Multiscaleimage

Dec 11, 2009 at 6:51 AM

Hi Guys,

this whole week i've been trying to display map tiles from my company's WMS server and i cant get it right. It doesnt do the whole Quadkey type thing that I know of. I dont know if its able to do the ZoomLevel, TileX, TileY thing. All I have to work with is the X and Y geo-coordinates. I worked out a math equation as to physically build the X Y tiles needed per zoom level. If im right it needs 4 tiles at Zoom 9, 16 at Zoom 10, 64 at zoom 11 etc. So I put the tiles it will need to display into an array [ZoomLevel][TileX][TileY]  and then added it to tileImageLayerSources . Trying to display it of course is an epic fail.  Its jumbled and whatnot. If anyone has any suggestions or anyting would appreciate it. My code is below if thats any help :S

 

protected override void GetTileLayers(int tileLevel, int tilePositionX, int tilePositionY, System.Collections.Generic.IListtileImageLayerSources) 
{ 
double MapX = 25.600000; 
double MapY = -26.600000; 
StringBuilder zoomKey = new StringBuilder(); 
int totalTiles = 1; int startDeepZoom = 0; 
double zoomLevel = 0; 
if ((tileLevel >= 0) && (tileLevel < 1)) 
{ zoomLevel = 20.48; } 
else if ((tileLevel >= 1) && (tileLevel < 2)) { zoomLevel = 10.24; } 
else if ((tileLevel >= 2) && (tileLevel < 3)) { zoomLevel = 5.12; } 
else if ((tileLevel >= 3) && (tileLevel < 4)) { zoomLevel = 2.56; } 
else if ((tileLevel >= 4) && (tileLevel < 5)) { zoomLevel = 1.28; } 
else if ((tileLevel >= 5) && (tileLevel < 6)) { zoomLevel = 0.64; }
else if ((tileLevel >= 6) && (tileLevel < 7)) { zoomLevel = 0.32; } 
else if ((tileLevel >= 7) && (tileLevel < 8)) { zoomLevel = 0.16; } 
else if ((tileLevel >= 8) && (tileLevel < 9)) { zoomLevel = 0.08; } 
else if ((tileLevel >= 9) && (tileLevel < 10)) { zoomLevel = 0.02; totalTiles = 4; startDeepZoom = 1; } 
else if ((tileLevel >= 10) && (tileLevel < 11)) { zoomLevel = 0.09; totalTiles = 16; startDeepZoom = 2; } 
else if ((tileLevel >= 11) && (tileLevel < 12)) { zoomLevel = 0.005; totalTiles = 64; startDeepZoom = 3; } 
else if ((tileLevel >= 12) && (tileLevel < 13)) { zoomLevel = 0.0025; totalTiles = 256; startDeepZoom = 4; } 
else if ((tileLevel >= 13) && (tileLevel < 14)) { zoomLevel = 0.00125; totalTiles = 1024; startDeepZoom = 5; } 
else if (tileLevel >= 14) { zoomLevel = 0.000625; totalTiles = 4096; startDeepZoom = 6; } double tilesBack = Math.Sqrt(Convert.ToDouble(totalTiles)); 
string[,,] map = new string[7,4096,4096]; 
int zoom; 
double minMapX; 
double minMapY; 
if (totalTiles == 1) { minMapX = MapX; minMapY = MapY; } 
else { minMapX = MapX - (zoomLevel / (tilesBack * 2)); 
minMapY = MapY + (zoomLevel / (tilesBack * 2)); 
} 
for (int x = 0; x < Math.Sqrt(Convert.ToDouble(totalTiles)); x++) 
{ 
	for (int y = 0; y < Math.Sqrt(Convert.ToDouble(totalTiles)); y++) 
	{ 
		map[startDeepZoom, x, y] = minMapY + "_" + minMapX + ".png"; 
		minMapY -= (zoomLevel * tilesBack);
	} 
	minMapX += (zoomLevel * tilesBack); 
} 
string VEUrl = "MAPSERVER/"+zoomLevel+"/"+map[startDeepZoom,tilePositionX,tilePositionY]; 
tileImageLayerSources.Add(new Uri(VEUrl)); 
} 
public VETileSource() : base(134217728, 134217728, 256, 256, 0) { }

Coordinator
Dec 14, 2009 at 2:08 AM

In the latest sourc code if you look at \trunk\Map\Services\WMS their is a working version but it isn't using the correct projection.

We have been working on this last week also, we're using ESRI ArcGIS as the WMS and need to set the projection to be Bing Maps, the offical EPSG is 3857 but it is so new you will likely not have it listed, 3785 and 900913 are identical, I had to load it manually:

900913;PROJCS["Mercator Spheric", GEOGCS["WGS84basedSpheric_GCS", DATUM["WGS84basedSpheric_Datum", SPHEROID["WGS84based_Sphere", 6378137, 0], TOWGS84[0, 0, 0, 0, 0, 0, 0]], PRIMEM["Greenwich", 0, AUTHORITY["EPSG", "8901"]], UNIT["degree", 0.0174532925199433, AUTHORITY["EPSG", "9102"]], AXIS["E", EAST], AXIS["N", NORTH]], PROJECTION["Mercator"], PARAMETER["False_Easting", 0], PARAMETER["False_Northing", 0], PARAMETER["Central_Meridian", 0], PARAMETER["Latitude_of_origin", 0], UNIT["metre", 1, AUTHORITY["EPSG", "9001"]], AXIS["East", EAST], AXIS["North", NORTH]]

The next issue you face is the co-ordinates then need to be supplied in XY meters from the orgin instead of lat/long WGS84. This is the method I used to convert:

       private static double[] MercatorEllipsoid(LatLong pos)
        {
            return new[] { LongitudeToX(pos.Longitude), LatitudeToY(pos.Latitude) };
        }

        private const double earthRadius = 6378137; //The radius of the earth - should never change!

        public static double LatitudeToY(double lat)
        {
            double sinLat = Math.Sin(DegToRad(lat));
            return earthRadius / 2 * Math.Log((1 + sinLat) / (1 - sinLat));
        }

        public static double LongitudeToX(double lon)
        {
            return earthRadius * DegToRad(lon);
        }

        private static double DegToRad(double d)
        {
            return d * Math.PI / 180.0;
        }