/// <summary>
/// 经纬度与xy坐标转换工具类
/// </summary>
public class LatlngXYZConvertHelper
{
/// <summary>
/// 经纬度转xy
/// </summary>
/// <param name="lon">需要转换的经度</param>
/// <param name="lat">需要转换的纬度</param>
/// <param name="zoom">地图级别</param>
/// <param name="x">转换后的x坐标</param>
/// <param name="y">转换后的y坐标</param>
public static void LatlngToTile(double lon, double lat, int zoom, ref float x, ref float y)
{
x = (float)((lon + 180.0) / 360.0 * (1 << zoom));
y = (float)((1.0 - Math.Log(Math.Tan(lat * Math.PI / 180.0) +
1.0 / Math.Cos(lat * Math.PI / 180.0)) / Math.PI) / 2.0 * (1 << zoom));
}
/// <summary>
/// xy转经纬度
/// </summary>
/// <param name="tile_x">需要转换的x坐标</param>
/// <param name="tile_y">需要转换的y坐标</param>
/// <param name="zoom">地图级别</param>
/// <param name="lng">转换后的经度</param>
/// <param name="lat">转换后的纬度</param>
public static void TileToLatlng(double tile_x, double tile_y, int zoom, ref float lng, ref float lat)
{
double n = Math.PI - ((2.0 * Math.PI * tile_y) / Math.Pow(2.0, zoom));
lng = (float)((tile_x / Math.Pow(2.0, zoom) * 360.0) - 180.0);
lat = (float)(180.0 / Math.PI * Math.Atan(Math.Sinh(n)));
}
/// <summary>
/// 根据经纬度转为瓦片行列号
/// (验证与LatlngToTile方法结果相同)
/// </summary>
/// <param name="lat">纬度</param>
/// <param name="lon">经度</param>
/// <param name="zoom">地图级别</param>
/// <param name="x">x坐标</param>
/// <param name="y">y坐标</param>
public static void getTileNumber(double lat, double lon, int zoom, ref int x, ref int y)
{
try
{
int xtile = (int)Math.Floor((lon + 180) / 360 * (1 << zoom));
int ytile = (int)Math
.Floor((1 - Math.Log(Math.Tan(ToRadians(lat)) + 1 / Math.Cos(ToRadians(lat))) / Math.PI) / 2
* (1 << zoom));
if (xtile < 0)
xtile = 0;
if (xtile >= (1 << zoom))
xtile = ((1 << zoom) - 1);
if (ytile < 0)
ytile = 0;
if (ytile >= (1 << zoom))
ytile = ((1 << zoom) - 1);
x = xtile;
y = ytile;
}
catch (Exception ex)
{
throw new Exception("经纬度转为瓦片行列号失败:" + ex.Message);
}
}
/// <summary>
/// 角度转换为弧度
/// </summary>
/// <param name="degrees"></param>
/// <returns></returns>
private static double ToRadians(double degrees)
{
return (Math.PI / 180) * degrees;
}
}