Map control and Web Map Service

10 posts, 0 answers
  1. Thomas Dahl Pedersen
    Thomas Dahl Pedersen avatar
    3 posts
    Member since:
    Apr 2010

    Posted 28 May 2010 Link to this post

    Hi.

    Can I use an OGC Web Map Service as datasource for the WPF Map control?

    /Thomas
  2. Andrey
    Admin
    Andrey avatar
    1681 posts

    Posted 28 May 2010 Link to this post

    Hi Thomas,

    You can use a custom map provider to display a map using WMS-based map server.
    I have attached the CustomEnvinsaMapProvider class. You should change the TileUrlFormat template at top of this class before you can use it.

    Best wishes,
    Andrey Murzov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  3. UI for WPF is Visual Studio 2017 Ready
  4. Barry
    Barry avatar
    1 posts
    Member since:
    Jun 2012

    Posted 28 Sep 2011 Link to this post

    Is there an updated example for a WMS implementation using the new TileMapSource and TiledProvider classes?
  5. Andrey
    Admin
    Andrey avatar
    1681 posts

    Posted 03 Oct 2011 Link to this post

    Hi Barry,

    I have attached new version of WMS custom provider which inherits the TileMapSource and TiledProvider classes.

    Greetings,
    Andrey Murzov
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  6. Jose
    Jose avatar
    14 posts
    Member since:
    Sep 2011

    Posted 16 Mar 2012 Link to this post

    Hello,
    I'm using the latest example code for connecting to a Spanish WMS.
    Everything works fine except that when the zoom is great, the calculations performed for the BBOX (XMIN, YMIN, XMAX, YMAX) is flawed and that WMS does not give me the right images.
    You might say it does not return the correct values ​​when the zoom is great?
    If you want to test the WMS I use, TileUrlFormat is:


    http://www1.sedecatastro.gob.es/Cartografia/WMS/ServidorWMS.aspx?SERVICE=WMS&REQUEST=GetMap&SRS=EPSG:4326&BBOX={0},{1},{2},{3}&WIDTH={4}&HEIGHT={4}&Layers=Catastro&TRANSPARENT=TRUE&STYLES=PositionStyle&FORMAT=image/png

     

    To view the map should be located in Spain.

    Thanks and sorry for my English

  7. Jose
    Jose avatar
    14 posts
    Member since:
    Sep 2011

    Posted 19 Mar 2012 Link to this post

    I found the solution!
    I use another function found in http://alastaira.wordpress.com/2011/01/07/accessing-a-wms-tile-server-from-bing-maps-v7/ to convert the QuadKey in BBox
    The final class will read:


    public class WMSCustomSource : TiledMapSource
        {
             
            private const string TileUrlFormat = @"http://www1.sedecatastro.gob.es/Cartografia/WMS/ServidorWMS.aspx?SERVICE=WMS&REQUEST=GetMap&SRS=EPSG:4326&BBOX={0}&WIDTH={1}&HEIGHT={1}&Layers=Catastro&TRANSPARENT=TRUE&STYLES=PositionStyle&FORMAT=image/png";
            private const int TileSize = 256;
     
            /// <summary>
            /// Earth Circumference.
            /// </summary>
            private double earthCircumference;
            private double halfEarthCircumference;
            private double earthRadius;
     
            /// <summary>
            /// Initializes a new instance of the OSMCustomSource class.
            /// </summary>
            public WMSCustomSource(ISpatialReference spatialReference)
                : base(1, 20, TileSize, TileSize)
            {
                this.earthRadius = spatialReference.SpheroidRadius;
                this.earthCircumference = this.earthRadius * 2 * Math.PI;
                this.halfEarthCircumference = this.earthCircumference / 2d;
            }
     
            /// <summary>
            /// Initialize provider.
            /// </summary>
            public override void Initialize()
            {
                // Raise provider intialized event.
                this.RaiseIntializeCompleted();
            }
     
     
     
            public string QuadKeyToBBox(string quadKey)
            {
     
                int zoom = quadKey.Length;
                int x = 0, y = 0;
                // Work out the x and y position of this tile
     
                for (int i = zoom; i > 0; i--)
                {
                    int mask = 1 << (i - 1);
                    switch (quadKey[zoom - i])
                    {
                        case '0':
                            break;
                        case '1':
                            x |= mask;
                            break;
                        case '2':
                            y |= mask;
                            break;
                        case '3':
                            x |= mask;
                            y |= mask;
                            break;
                        default:
                            throw new ArgumentException("Invalid QuadKey digit sequence.");
                    }
                }
                // From the grid position and zoom, work out the min and max Latitude / Longitude values of this tile
                double W = (float)(x * TileSize) * 360 / (float)(TileSize * Math.Pow(2, zoom)) - 180;
     
                double N = (float)Math.Asin((Math.Exp((0.5 - (y * TileSize) / (TileSize) / Math.Pow(2, zoom)) * 4 * Math.PI) - 1) / (Math.Exp((0.5 - (y * TileSize) / 256 / Math.Pow(2, zoom)) * 4 * Math.PI) + 1)) * 180 / (float)Math.PI;
     
                double E = (float)((x + 1) * TileSize) * 360 / (float)(TileSize * Math.Pow(2, zoom)) - 180;
                double S = (float)Math.Asin((Math.Exp((0.5 - ((y + 1) * TileSize) / (TileSize) / Math.Pow(2, zoom)) * 4 * Math.PI) - 1) / (Math.Exp((0.5 - ((y + 1) * TileSize) / 256 / Math.Pow(2, zoom)) * 4 * Math.PI) + 1)) * 180 / (float)Math.PI;
     
                double[] bounds = new double[] { W, S, E, N };
     
                // Return a comma-separated string of the bounding coordinates
                return string.Join(",", Array.ConvertAll(bounds, s => s.ToString().Replace(',','.')));
            }
     
     
            /// <summary>
            /// Converts radians to degrees
            /// </summary>
            /// <param name="d"></param>
            /// <returns></returns>
            private double RadiansToDegrees(double radians)
            {
                return radians / Math.PI * 180d;
            }
     
            /// <summary>
            /// Converts a grid row to Latitude
            /// </summary>
            /// <param name="y"></param>
            /// <param name="zoom"></param>
            /// <returns></returns>
            private double ConvertYToLatitude(int y, int zoom)
            {
                double arc = this.earthCircumference / ((double)(1 << zoom) * (double)TileSize);
                double metersY = this.halfEarthCircumference - ((double)y * (double)TileSize * arc);
                double a = Math.Exp(metersY * 2d / this.earthRadius);
                double result = RadiansToDegrees(Math.Asin((a - 1d) / (a + 1d)));
                return result;
            }
     
            /// <summary>
            /// Converts a grid column to Longitude
            /// </summary>
            /// <param name="x"></param>
            /// <param name="zoom"></param>
            /// <returns></returns>
            private double ConvertXToLongitude(int x, int zoom)
            {
                double arc = this.earthCircumference / ((double)(1 << zoom) * (double)TileSize);
                double metersX = ((double)x * (double)TileSize * arc) - this.halfEarthCircumference;
                double result = RadiansToDegrees(metersX / this.earthRadius);
                return result;
            }
     
            private static string GetQuadKey(int tileX, int tileY, int levelOfDetail)
            {
                var quadKey = new StringBuilder();
                for (int i = levelOfDetail; i > 0; i--)
                {
                    char digit = '0';
                    int mask = 1 << (i - 1);
                    if ((tileX & mask) != 0)
                    {
                        digit++;
                    }
     
                    if ((tileY & mask) != 0)
                    {
                        digit++;
                        digit++;
                    }
     
                    quadKey.Append(digit);
                }
     
                return quadKey.ToString();
            }
     
            /// <summary>
            /// Gets the image URI.
            /// </summary>
            /// <param name="tileLevel">Tile level.</param>
            /// <param name="tilePositionX">Tile X.</param>
            /// <param name="tilePositionY">Tile Y.</param>
            /// <returns>URI of image.</returns>
            protected override Uri GetTile(int tileLevel, int tilePositionX, int tilePositionY)
            {
                int zoomLevel = ConvertTileToZoomLevel(tileLevel);
     
                string quadKey = GetQuadKey(tilePositionX, tilePositionY, zoomLevel);
     
                string bbox = QuadKeyToBBox(quadKey);
                 
                string url = string.Format(CultureInfo.InvariantCulture, TileUrlFormat, bbox, TileSize);
     
                return new Uri(url);
            }
     
            
        }
  8. Andrey
    Admin
    Andrey avatar
    1681 posts

    Posted 21 Mar 2012 Link to this post

    Hi Jose,

    The tiles which can be used in custom provider should be compatible with the DeepZoom concept. The tiles should have the same size for different zoom levels. Also one tile from the previous zoom level should be covered by FOUR tiles from next zoom level. i.e. it should be 1 tile for level 0, 4 tiles for level 1 and etc.
    It looks like the tile images on this server for levels 1-4 have not been generated according to these rules.
    You can restrict the zooming using the RadMap.MinZoomLevel property. For more information you can take a look at the following documentation topic:
    http://www.telerik.com/help/silverlight/radmap-howto-limit-panning-zooming-region.html

    All the best,
    Andrey Murzov
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
  9. David
    David avatar
    2 posts
    Member since:
    Jul 2010

    Posted 05 Apr 2013 Link to this post

    Hi Andrey,

    I am making use of the provider you supplied
     WMSCustomProvider.zip,

    However the tiles are marginally out of alignment see attached screenshot. It happens at all zoom levels.

    I'm hoping there is a quick fix for this...

    Thanks,
  10. Andrey
    Admin
    Andrey avatar
    1681 posts

    Posted 08 Apr 2013 Link to this post

    Hi David,

    It is quite difficult to say what is wrong with your tile server without URL which we can use to test provider. At the first glance the images on your server do not corresponds to the Mercator projection.

    If you provide us with URI to access your WMS server then we can try it and check what is wrong. Also, the code you are using is quite old. There is built in implementation of the WMS map provider in the RadMap which uses another approach to get tiles. Could you, please, try it with your server?

    Regards,
    Andrey Murzov
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  11. David
    David avatar
    2 posts
    Member since:
    Jul 2010

    Posted 08 Apr 2013 Link to this post

    Thanks Andrey,

    I will log a ticket through the help centre as the URI contains sensitive access details.

Back to Top
UI for WPF is Visual Studio 2017 Ready