获取到经纬度范围后,我们需要计算出瓦片的范围。
本文涉及的地图瓦片都以左上角为原点开始编号的,从左至右为 x 轴, 从上到下为 y轴。
为保证地图是方形,基于 Web 墨卡托投影的地图左上角经纬度坐标为(180°,85.0511 °),右下角经纬度为(-180°,-85.0511°)。纬度范围是[-85.0511, 85.0511 ]。
假设z为需要拼接的图层的层数,设n=2的z次方,lon为经度,lat为维度,则经纬度、层级和瓦片的坐标x、y的关系为:
TileX =(lon+180)÷360×n;
TileY = (1-(log(tan(lat))+sec(lat)))÷2×n;
在C#中,Math函数的三角参数要求为弧度,所以纬度值牵扯到三角函数的还需要×PI÷180。两个函数如下:
/// <summary>
/// 计算瓦片所在X值
/// </summary>
/// <param name="lng"></param>
/// <param name="zoom"></param>
/// <returns></returns>
public static double getTileX(double lng, int zoom)
{
double tileX = (lng + 180.0) / 360 * Math.Pow(2, zoom);
return tileX;
}
/// <summary>
/// 墨卡托投影下,通过维度计算瓦片所在Y值
/// </summary>
/// <param name="lat"></param>
/// <param name="zoom"></param>
/// <returns></returns>
public static double getTileY(double lat, int zoom)
{
if (lat > 90)
lat = lat - 180;
if (lat < -90)
lat = lat + 180;
double tileY = Math.Pow(2, zoom) / 2 * (1 - (Math.Log(Math.Tan(Math.PI * lat / 180) + 1 / Math.Cos(Math.PI * lat / 180))) / Math.PI);
return tileY;
}
前面将下载图片的函数已在第三章中写好,直接通过xyz和瓦片地址下载图片,然后使用GDI+拼接即可。
这里有一个很严重的问题,就是受GDI+技术限制,图幅过大可能拼接失败。一般10000像素×10000像素以内为妥。所以,过大范围的需求,只能拼接为系统承受范围内的大小了。我们做一个参数,可以设置这个值,最大到10240像素。用户最终在ps里再量力而行的拼接了。
写一个类DownloadWork,用于在线程里展开下载任务,在构造函数中声明下载范围和下载图片的参数。
GetArea(WorkArg arg)用