This is a migrated thread and some comments may be shown as answers.

Map control and Web Map Service

9 Answers 262 Views
Map
This is a migrated thread and some comments may be shown as answers.
Thomas Dahl Pedersen
Top achievements
Rank 1
Thomas Dahl Pedersen asked on 28 May 2010, 10:59 AM
Hi.

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

/Thomas

9 Answers, 1 is accepted

Sort by
0
Andrey
Telerik team
answered on 28 May 2010, 04:03 PM
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.
0
Barry
Top achievements
Rank 1
answered on 28 Sep 2011, 04:41 PM
Is there an updated example for a WMS implementation using the new TileMapSource and TiledProvider classes?
0
Andrey
Telerik team
answered on 03 Oct 2011, 08:19 AM
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 >>

0
Jose
Top achievements
Rank 1
answered on 16 Mar 2012, 05:40 PM

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

0
Jose
Top achievements
Rank 1
answered on 19 Mar 2012, 01:29 PM

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);
        }
 
        
    }
0
Andrey
Telerik team
answered on 21 Mar 2012, 08:59 AM
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 >>
0
David
Top achievements
Rank 1
answered on 05 Apr 2013, 12:40 PM
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,
0
Andrey
Telerik team
answered on 08 Apr 2013, 12:26 PM
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.

0
David
Top achievements
Rank 1
answered on 08 Apr 2013, 03:01 PM
Thanks Andrey,

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

Tags
Map
Asked by
Thomas Dahl Pedersen
Top achievements
Rank 1
Answers by
Andrey
Telerik team
Barry
Top achievements
Rank 1
Jose
Top achievements
Rank 1
David
Top achievements
Rank 1
Share this question
or