需要将x和y转换为纬度/长度



我正在将一个iOS应用移植到Android上,并且使用Google Maps Android API v2. .应用程序需要在地图上绘制热图覆盖。

到目前为止,看起来最好的选择是使用TileOverlay并实现自定义TileProvider。在方法getTile中,我的方法被给定x、y和zoom,并且需要以Tile的形式返回位图。到目前为止,一切顺利。

我有一组热图项,我将使用它们在位图上绘制径向梯度,每个都有一个lat/long。我在完成以下两个任务时遇到了困难:

  1. 我如何确定由x, y和缩放表示的tile是否包含热图项目的纬度/长度?
  2. 如何将热图项的纬度/长度转换为位图的x/y坐标。

谢谢你的帮助!

感谢MaciejGórski下面的答案,以及marcin的实现,我能够得到我问题的前半部分的答案,但我仍然需要第二部分的帮助。为了澄清,我需要一个函数来返回指定lat/long的贴图的x/y坐标。我试过逆转MaciejGórski和marcin的答案的计算,但没有运气。

public static Point fromLatLng(LatLng latlng, int zoom){
    int noTiles = (1 << zoom);
    double longitudeSpan = 360.0 / noTiles;
    double mercator = fromLatitude(latlng.latitude);
    int y = ((int)(mercator / 360 * noTiles)) + 180;
    int x = (int)(latlng.longitude / longitudeSpan) + 180;
    return new Point(x, y);
}

任何帮助都是感激的!

这对我有用:

double n = Math.pow(2, zoom);
double longitudeMin = x/n * 360 -180;
double lat_rad = Math.atan(Math.sinh(Math.PI * (1 - 2 * y/n)));
double latitudeMin = lat_rad * 180/Math.PI;
double longitudeMax = (x + 1)/n * 360 -180;
lat_rad = Math.atan(Math.sinh(Math.PI * (1 - 2 * (y + 1)/n)));
double latitudeMax = lat_rad * 180/Math.PI;

引用:http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames

在缩放级别0上,只有一个贴图(x=0,y=0)。在下一个缩放级别,瓷砖的数量是原来的四倍(x和y的两倍)。

这意味着在缩放级别W上,x可能是范围<0,1 <<W) .

从文档:

瓷砖的坐标是从地图的左上角(西北角)测量的。在缩放级别N下,贴图坐标的x值范围从0到2N - 1,从西向东递增,y值范围从0到2N - 1,从北到南递增。

你可以通过简单的计算来实现。

对于经度,这很简单:

double longitudeMin = (((double) x) / (1 << zoom)) * 360 - 180;
double longitudeMax = (((double) x + 1) / (1 << zoom)) * 360 - 180;
longitudeMax = Double.longBitsToDouble(Double.doubleToLongBits(longitudeMax) - 1); // adjust

这里x首先缩放为<0,1),然后缩放为<-180,180)。

最大值被调整,所以它不会与下一个区域重叠。你可以跳过这个。

对于纬度,这将有点困难,因为谷歌地图使用墨卡托投影。

首先缩放y,就像它在<-180,180范围内一样。注意,值需要反转。

double mercatorMax = 180 - (((double) y) / (1 << zoom)) * 360;
double mercatorMin = 180 - (((double) y + 1) / (1 << zoom)) * 360;

现在你使用一个神奇的函数来做墨卡托投影(来自SphericalMercator.java):

public static double toLatitude(double mercator) {
    double radians = Math.atan(Math.exp(Math.toRadians(mercator)));
    return Math.toDegrees(2 * radians) - 90;
}
latitudeMax = SphericalMercator.toLatitude(mercatorMax);
latitudeMin = SphericalMercator.toLatitude(mercatorMin);
latitudeMin = Double.longBitsToDouble(Double.doubleToLongBits(latitudeMin) + 1);

这是从内存中键入的,没有以任何方式进行测试,所以如果有错误,请发表评论,我会修复它。

MaciejGórski如果你不介意(如果你不介意,我会删除这篇文章),我将你的代码编译成准备使用的方法:

private LatLngBounds boundsOfTile(int x, int y, int zoom) {
    int noTiles = (1 << zoom);
    double longitudeSpan = 360.0 / noTiles;
    double longitudeMin = -180.0 + x * longitudeSpan;
    double mercatorMax = 180 - (((double) y) / noTiles) * 360;
    double mercatorMin = 180 - (((double) y + 1) / noTiles) * 360;
    double latitudeMax = toLatitude(mercatorMax);
    double latitudeMin = toLatitude(mercatorMin);
    LatLngBounds bounds = new LatLngBounds(new LatLng(latitudeMin, longitudeMin), new LatLng(latitudeMax, longitudeMin + longitudeSpan));
    return bounds;
}

相关内容

  • 没有找到相关文章

最新更新