TileProvider 方法 getTile - 需要将 x 和 y 转换为纬度/经度 [英] TileProvider method getTile - need to translate x and y to lat/long

查看:51
本文介绍了TileProvider 方法 getTile - 需要将 x 和 y 转换为纬度/经度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将 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:

  1. 如何确定由 x、y 和缩放表示的图块是否包含热图项目的纬度/经度?
  2. 如何将热图项目的经纬度转换为位图的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆