EasyGIS.NET
EasyGIS.NET copied to clipboard
Tile XYZ to WMS
Hi! How can I convert the XYZ Tile format to WMS Tile format? I see many maps on web using this format and I would like to use them.
URL sample: https://ies-ows.jrc.ec.europa.eu/gwis?service=WMS&request=GetMap&layers=admin.countries_borders&styles=&format=image%2Fpng&transparent=true&version=1.1.1&singletile=false&width=2048&height=2048&srs=EPSG%3A3857&bbox=0,5009377.085697314,2504688.5428486555,7514065.628545967
I did some things, like:
Tile URL
Since I'm using the TileCollection class from EGIS sample (with some mods) I changed the parameter format to check and replace later:
https://ies-ows.jrc.ec.europa.eu/gwis?service=WMS&request=GetMap&layers=admin.countries_borders&styles=&format=image%2Fpng&transparent=true&version=1.1.1&singletile=false&width=256&height=256&srs=EPSG%3A3857&bbox={bbLeft},{bbBottom},{bbRight},{bbTop}
Extend converter
This class provide the conversion from XYZ to a extended long/lat. I tryed to use the TileUtil.GetTileLatLonBounds method but I could't make it work:
public static class xnGeoUtilsLongLat
{
public class Extend
{
public double Left { get; set; }
public double Right { get; set; }
public double Bottom { get; set; }
public double Top { get; set; }
public double Res { get; set; }
public Extend()
{ }
}
public class Tile
{
public double X { get; set; }
public double Y { get; set; }
public int Z { get; set; }
public double Top { get; set; }
public double Left { get; set; }
public Tile()
{ }
}
// web mercator projection extent
static Extend ProjExtent = new Extend
{
Left = -20037508.342789244,
Right = 20037508.342789244,
Bottom = -20037508.342789244,
Top = 20037508.342789244
};
//tile seize
static int TileSize = 256;
// resolutions
static double[] Resolutions = new double[] {
156543.03392804097, 78271.51696402048, 39135.75848201024,
19567.87924100512, 9783.93962050256, 4891.96981025128, 2445.98490512564,
1222.99245256282, 611.49622628141, 305.748113140705, 152.8740565703525,
76.43702828517625, 38.21851414258813, 19.109257071294063, 9.554628535647032,
4.777314267823516, 2.388657133911758, 1.194328566955879, 0.5971642834779395,
0.29858214173896974, 0.14929107086948487, 0.07464553543474244,
0.03732276771737122, 0.01866138385868561 };
static List<Tile> GetTiles(Extend extent, int z)
{
//coordinated in pixel
var lx = Math.Floor((extent.Left - ProjExtent.Left) / Resolutions[z]);
var rx = Math.Floor((extent.Right - ProjExtent.Left) / Resolutions[z]);
var by = Math.Floor((ProjExtent.Top - extent.Bottom) / Resolutions[z]);
var ty = Math.Floor((ProjExtent.Top - extent.Top) / Resolutions[z]);
// tile numbers
var lX = Math.Floor(lx / TileSize);
var rX = Math.Floor(rx / TileSize);
var bY = Math.Floor(by / TileSize);
var tY = Math.Floor(ty / TileSize);
//top left tile position of top-left tile with respect to window/div
var top = (tY * TileSize) - ty;
var topStart = top;
var left = (lX * TileSize) - lx;
var tiles = new List<Tile>();
for (var i = lX; i <= rX; i++)
{
top = topStart;
for (var j = tY; j <= bY; j++)
{
tiles.Add(new Tile
{
X = i,
Y = j,
Z = z,
Top = top,
Left = left
});
top += TileSize;
}
left += TileSize;
}
return tiles;
}
public static Extend TileExtent(double x, double y, int z)
{
return TileExtent(new xnGeoUtilsLongLat.Tile()
{
X = x,
Y = y,
Z = z
});
}
public static Extend TileExtent(Tile tile)
{
var right = ProjExtent.Left + tile.X * TileSize * Resolutions[tile.Z];
var left = right - TileSize * Resolutions[tile.Z];
var bottom = ProjExtent.Top - tile.Y * TileSize * Resolutions[tile.Z];
var top = bottom + TileSize * Resolutions[tile.Z];
return new Extend()
{
Left = left,
Right = right,
Bottom = bottom,
Top = top,
Res = Resolutions[tile.Z]
};
}
}
CreateBitmap code
Here the CreateBitmap method that was changed to check if imageUrlFormat contains "{bbLeft}". Case yes then use WMS format else keep using XYZ.
private System.Drawing.Bitmap CreateBitmap()
{
try
{
string strUrl = "";
if (imageUrlFormat.Contains("{bbLeft}"))
{
//force dot as decimal separator
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ".";
var _ext = xnGeoUtilsLongLat.TileExtent(this.x, this.y, this.zoomLevel);
imageUrlFormat = imageUrlFormat
.Replace("{bbLeft}", "{0}")
.Replace("{bbBottom}", "{1}")
.Replace("{bbRight}", "{2}")
.Replace("{bbTop}", "{3}");
strUrl = string.Format(imageUrlFormat, _ext.Left.ToString(nfi), _ext.Bottom.ToString(nfi), _ext.Right.ToString(nfi), _ext.Top.ToString(nfi));
}
else
strUrl = string.Format(imageUrlFormat, this.zoomLevel, this.x, this.y);
Console.WriteLine(strUrl);
var bitmapStream = GetFromCache(strUrl);
if (bitmapStream != null)
{
bitmapStream.Seek(0, System.IO.SeekOrigin.Begin);
using (Image img = Bitmap.FromStream(bitmapStream))
{
//copy the returned image to a new bitmap. If we don't do this then the transparency may not
//display properly
Bitmap bm = new Bitmap(img.Width, img.Height);
using (Graphics g = Graphics.FromImage(bm))
{
g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
}
return bm;
}
}
//request not in local cache - retrieve asyncronously
//dont await this call!
GetBitmapAsync(strUrl);
Bitmap blankBitmap = new Bitmap(256, 256);
using (Graphics g = Graphics.FromImage(blankBitmap))
{
g.Clear(Color.LightGray);
}
return blankBitmap;
}
catch (Exception ex)
{
Bitmap blankBitmap = new Bitmap(256, 256);
using (Graphics g = Graphics.FromImage(blankBitmap))
{
g.Clear(Color.LightGray);
}
return blankBitmap;
}
}
It's working in part. Tiles is loaded, but it's not on the right position.
At moment I'm stuck on this and I can't go ahead. Can someone help me with this?