Android:如何将地图视图的缩放级别设置为当前位置周围 1 公里半径?
我想将地图视图设置为缩放至 1 公里半径,但不知道如何设置?
该文档表示,缩放级别 1 会将地球赤道映射到 256 像素。那么如何计算需要设置哪个缩放级别才能使地图视图显示 1KM 半径内的区域?
更新:
阅读了几篇博客文章后,我编写了以下代码:
private int calculateZoomLevel() {
double equatorLength = 6378140; // in meters
double widthInPixels = screenWidth;
double metersPerPixel = equatorLength / 256;
int zoomLevel = 1;
while ((metersPerPixel * widthInPixels) > 2000) {
metersPerPixel /= 2;
++zoomLevel;
}
Log.i("ADNAN", "zoom level = "+zoomLevel);
return zoomLevel;
}
这个想法是,首先我在缩放级别 1 中计算每像素米,根据谷歌的说法,它使用 256 像素显示地球赤道。现在,每个后续缩放级别都会放大 2 级,因此每个缩放级别的每个像素米数减半。我这样做,直到我得到一个缩放级别,其中每像素米乘以屏幕宽度得到小于2000,即2公里宽。
但我不认为我得到的缩放级别显示的是 2 公里半径的地图。有人可以告诉我我在这里做错了什么吗?
I want to set the map view zoomed to 1km radius but cant figure out how?
The doc says that the zoom level 1 will map earths equator to 256 pixels. So how do I calculate which zoom level I need to set so that the map view shows area in 1KM radius?
UPDATE:
After reading a few blog posts I wrote the following code:
private int calculateZoomLevel() {
double equatorLength = 6378140; // in meters
double widthInPixels = screenWidth;
double metersPerPixel = equatorLength / 256;
int zoomLevel = 1;
while ((metersPerPixel * widthInPixels) > 2000) {
metersPerPixel /= 2;
++zoomLevel;
}
Log.i("ADNAN", "zoom level = "+zoomLevel);
return zoomLevel;
}
The idea is that first I calculate Meters per pixel in the zoom level 1, which according to google shows equator of earth using 256 pixels. Now every subsequent zoom level magnifies by a level of 2 so I half the meters per pixel for every zoom level. I do this until I have a zoom level where meters per pixel multiplied by the screen width gives me less than 2000 i.e 2 Km across.
But I dont think that the zoom level I am getting is showing the map of 2Km radius. Can some one tell me what I am doing wrong here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
虽然这个答案是合乎逻辑的,而且我发现它有效,但结果不准确,我不知道为什么,但我厌倦了这种方法,而且这种技术要准确得多。
1) 在对象上以所需半径画一个圆
2) 将该对象传递给此函数并设置缩放级别
这是链接
although this answer is logical and i find it working but the results are not accurate i dont know why but i tired this approach and this technique is far more accurate.
1) Make a circle on object with desired radius
2) Pass that object to this function and set the zoom level
Here's a link
下面的代码是最终使用的。给定屏幕宽度,并且在缩放级别 1 时,地球赤道长 256 像素,并且每个后续缩放级别都会使表示地球赤道所需的像素数加倍,以下函数返回屏幕将显示区域的缩放级别2公里宽。
The following code is what ended up using. Given the screen width and the fact that at zoom level 1 the equator of Earth is 256 pixels long and every subsequent zoom level doubles the number of pixels needed to represent earths equator, the following function returns the zoom level where the screen will show an area of 2Km width.
我最终使用了以下实用程序:
https://github.com/googlemaps/android-maps-utils
我从库中提取了类,因此您不需要整个库。
您无需设置缩放级别,而是使用边界。结果是一样的。
精确显示 1 公里的代码:
从库中提取的类(略有更改):
I ended up using the utils from:
https://github.com/googlemaps/android-maps-utils
I extracted the class from the lib, so you don't need the whole library.
Instead of setting zoom level, you use bounds. The result is the same.
Code to show exactly 1 kilometer:
The class extracted (slightly changed) from the lib:
最终工作解决方案:
ps 使用 @sho 答案和 @Lionel Briand 评论
FINAL working solution:
p.s. Using @sho answer and @Lionel Briand comment
谷歌地图似乎与英里/像素密切相关。当缩放 = 13 时,1 英里 = 100 像素。 2 英里 = 200 像素。每个变焦级别增加或减少 2 倍。因此,在变焦 14 时,1 英里 = 200 像素,在变焦 12 时,1 英里 = 50 像素。
Google maps seems to work closely to miles/pixel. At zoom=13, 1 mile= 100 pixels. 2 miles = 200 pixels. Each zoom leven increases or decreases by a factor of 2. Therefore, at Zoom 14, 1 mile = 200 pixels and at zoom 12, 1 mile = 50 pixels.
使用循环来计算缩放级别是非常幼稚的。
使用数学会更好。
这里是函数(返回类型:float)
示例调用:
计算缩放级别的数学公式是:
这就是全部! :-)
注意:上面的解决方案作为接受的答案仅适用于赤道附近的缩放级别。
如果您想要一个适用于所有纬度的解决方案,您需要与要计算的缩放级别相同纬度的纬线长度。
calcZoom
方法更改为其中
this.calcParallelLegth(atLatitude)
返回atLatitude
纬度处纬线的长度。您可以使用一些库自己计算长度(最好使用 Vincenty 公式)。
或者
如果您没有这样的库(或者您不搜索库,或者您只想要完整的代码有效)在这个答案的底部,您可以找到整个工作代码,其中包含使用表格(使用 Vincenty Formulae 计算)的
double calcParallelLegth(double atLatitude)
的实现所有纬度的平行长度,公差为 3%。注意:
只有当您理解公式(或检查公式是否正确)时,才需要阅读下面的内容
下面的公式解释:
用简单的方式表达!
让我们将问题分为两部分。
第 1 部分
计算 256x256 尺寸图像的缩放
第 2 部分
针对不同尺寸的图像调整缩放
解决第 1 部分
图像尺寸为 256x256。
缩放级别 0 显示整个赤道。
随后的每个缩放级别都让我看到之前的一半。
赤道长 40,075,016 米(根据 WGS-84 (*1) 和
Vincenty 公式 (*2))
正如您在上面看到的,每个后续缩放级别让我看到之前的一半。
zoom 是所需的 Zoom_level。
visible_distance 是图像水平显示的米数。
如果您想要 1 公里,则必须使用 visible_distance=1000 计算缩放,
让我们找出缩放公式。
这就是数学发挥其魔力的地方(“无聊”的魔力)。
256x256 图像的缩放级别公式为:
第 1 部分完成!!
解决第 2 部分
将缩放调整为所需的图像尺寸。
每当图像宽度加倍时,看到整个赤道所需的变焦就会增加一倍。
示例:
在 512x512 的图像中,看到整个赤道所需的缩放倍数为 1。
在 1024x1024 的图像中,看到整个赤道所需的缩放倍数为 2。
在 2048x2048 的图像中,看到整个赤道所需的缩放倍数为 3。
也就是说
......
宽度->宽度/256 = 2^x -> Zoom=x(需要看到整个赤道)
这意味着(zoom_level 是
何时需要x 来调整缩放所需的图像尺寸。
中提取 x 的问题
所以,这是从Let's do it
现在我们有了 x 公式,
WIDTHxHEIGHT 图像的缩放级别公式为:
因此,如果您希望在 512x512 图像中可见 1km,那么
它必须是整数
完成!
这是计算每个纬度图像宽度的缩放级别的完整代码。
Using loop to calculate zoom level is very naive.
It is way long better to use math.
Here the function (return type: float)
example call:
The math formulae to calculate the zoom level is:
That's all folks! :-)
ATTENTION: The solution above as the accepted answer only works for zoom levels next to the equator.
If you want a solution that works with all latitudes you need the length of the parallel at the same latitude of the zoom level you want to compute. The
calcZoom
method changes toWhere
this.calcParallelLegth(atLatitude)
returs the length of the parallel at theatLatitude
latitude.You can compute the length yourself with some library (preferably using Vincenty formulae).
Alternatively
If you don't have such a library (or you don't search for a library, or you just want a complete code that works) at the bottom of this answer you can find the whole working code with an implementation of
double calcParallelLegth(double atLatitude)
that uses a table (computed using Vincenty Formulae) with parallel length at all latitudes with 3% tollerance.NOTE:
YOU NEED TO READ BELOW ONLY IF YOU AND TO UNDERSTAND THE FORMULA (OR CHECK IF THE FORMULA IS RIGHT)
Formulae explanation below :
Putting it in a simple way!
Let's split the problem in two parts.
Part 1
calc the zoom for an 256x256 size image
Part 2
adapt the zoom for an image with a different size
Resolving Part 1
Image size is 256x256.
Zoom level 0 shows the whole equator.
each subsequent zoom level let me see half then before.
Equator is 40,075,016 meters long (according WGS-84 (*1) and
Vincenty formulae (*2))
As you can see above, each subsequent zoom level let me see half then before.
zoom is the zoom_level wanted.
visible_distance is how many meters the image shows horizontally.
if you want 1km than you have to calculate zoom with visible_distance=1000
Let's find out the zoom formulae.
Here is where math do it's magic ("boring" magic stuff).
the zoom level formulae for an 256x256 image is:
Part 1 DONE!!
Resolving Part 2
Adapt the zoom to the wanted image size.
Every time that the image width doubles, the zoom needed to see the whole equator increases of one.
Example:
In an image 512x512 the zoom needed to see the whole equator is 1.
In an image 1024x1024 the zoom needed to see the whole equator is 2.
In an image 2048x2048 the zoom needed to see the whole equator is 3.
That said
...
width -> width/256 = 2^x -> zoom=x (needed to see the whole equator)
this means that (zoom_level is
Whe need x to adapt the zoom the the wanted image size.
So, it is a matter of extract x from
Let's do it
Now we have the x formula.
the zoom level formulae for an WIDTHxHEIGHT image is:
So, if you want 1km visible in an 512x512 image than
If it must be integer
DONE!
Here is the complete code that computes the zoom level at every latitude ed image width.
我已将接受的答案转换为返回双精度值,因为 Android Google 地图库使用浮点缩放级别,并且还考虑了远离赤道的纬度。
顺便说一句,为了在 Android 上获得最佳结果,不要传递视图的实际像素数,而是根据设备的像素密度缩放的尺寸。
希望这对某人有帮助。
I've converted the accepted answer to return a double value, since the Android Google Maps library uses floating point zoom levels, and also account for latitudes away from the equator.
As an aside, for best results on Android don't pass the view's real pixel count, but the dimension scaled for the device's pixel density.
Hope this helps someone.
我确信有很多方法可以找到它我使用这种技术来计算缩放级别
I am sure there are many methods to find it I use this technique to calculate zoom level