TileProvider 方法 getTile - 需要将 x 和 y 转换为纬度/经度 [英] TileProvider method getTile - need to translate x and y to lat/long
问题描述
我正在将 iOS 应用移植到 Android,并使用 Google Maps Android API v2.
该应用需要在地图上绘制热图叠加层.
I’m porting an iOS app to Android, and using Google Maps Android API v2.
The application needs to draw a heatmap overlay onto the map.
到目前为止,看起来最好的选择是使用 TileOverlay
并实现自定义 TileProvider
.在方法getTile
中,我的方法被赋予了x、y和zoom,需要返回一个Tile
形式的位图.到现在为止还挺好.
So far, it looks like the best option is to use a TileOverlay
and implement a custom TileProvider
. In the method getTile
, my method is given x, y, and zoom, and needs to return a bitmap in the form of a Tile
. So far, so good.
我有一组热图项目,我将用它们在位图上绘制径向渐变,每个项目都有一个纬度/经度.我在执行以下两项任务时遇到问题:
I have an array of heatmap items that I will use to draw radial gradients onto the bitmap, each with a lat/long. I am having trouble with the following two tasks:
- 如何确定由 x、y 和缩放表示的图块是否包含热图项目的纬度/经度?
- 如何将热图项目的经纬度转换为位图的 x/y 坐标.
感谢您的帮助!
更新
感谢下面 MaciejGórski 的回答和 marcin 的实现,我能够回答我问题的第一部分,但我仍然需要第二部分的帮助.为了澄清,我需要一个函数来返回指定纬度/经度的图块的 x/y 坐标.我试过在没有运气的情况下反转 MaciejGórski 和 marcin 的答案的计算.
Thanks to MaciejGórski's answer below, and marcin's implementation I was able to get the 1st half of my question answered, but I still need help with the 2nd part. To clarify, I need a function to return the x/y coordinates of the tile for a specified lat/long. I've tried reversing the calculations of MaciejGórski's and marcin's answer with no luck.
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);
}
感谢任何帮助!
推荐答案
在缩放级别 0 上,只有一个图块 (x=0,y=0).在下一个缩放级别,图块数量翻了四倍(x 和 y 翻了一番).
On zoom level 0, there is only one tile (x=0,y=0). On next zoom level number of tiles are quadrupled (doubled on x and y).
这意味着在缩放级别 W
上,x 可能是范围 <0, 1 <<<;W).
This means on zoom level W
, x may be a value in range <0, 1 << W).
来自文档:
图块的坐标是从地图的左上角(西北角)开始测量的.在缩放级别 N 下,瓦片坐标的 x 值范围为 0 到 2N - 1,从西到东增加,y 值范围从 0 到 2N - 1,从北到南增加.
The coordinates of the tiles are measured from the top left (northwest) corner of the map. At zoom level N, the x values of the tile coordinates range from 0 to 2N - 1 and increase from west to east and the y values range from 0 to 2N - 1 and increase from north to south.
您可以使用简单的计算来实现这一点.
You can achieve this using simple calculations.
对于经度,这很简单:
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)
Here x is first scaled into <0,1), then into <-180,180).
最大值被调整,所以它不会与下一个区域重叠.你可以跳过这个.
The max value is adjusted, so it doesn't overlap with the next area. You may skip this.
对于纬度,这会有点困难,因为 Google 地图使用墨卡托投影.
For latitude this will be a bit harder, because Google Maps use Mercator projection.
首先你缩放 y,就像它在 <-180,180 的范围内一样).请注意,这些值需要反转.
First you scale y just like it was in range <-180,180). Note that the values need to be reversed.
double mercatorMax = 180 - (((double) y) / (1 << zoom)) * 360;
double mercatorMin = 180 - (((double) y + 1) / (1 << zoom)) * 360;
现在你使用一个神奇的函数来进行墨卡托投影(来自 SphericalMercator.java):
Now you use a magical function that does Mercator projection (from 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);
这是从内存中输入的,并没有以任何方式进行测试,所以如果那里有错误,请发表评论,我会修复它.
This was was typed from memory and was not tested in any way, so if there is an error there, please put a comment and I will fix it.
这篇关于TileProvider 方法 getTile - 需要将 x 和 y 转换为纬度/经度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!