如何在 Android Google Maps API v2 中将 LatLng 和半径转换为 LatLngBounds?
Posted
技术标签:
【中文标题】如何在 Android Google Maps API v2 中将 LatLng 和半径转换为 LatLngBounds?【英文标题】:How to convert a LatLng and a radius to a LatLngBounds in Android Google Maps API v2? 【发布时间】:2013-02-25 11:58:26 【问题描述】:我认为这是最近的 Google Maps API v2 的限制。他们最近添加了在地面上绘制圆圈的功能 - 但如果您想定位相机以使其显示整个圆圈,则没有办法这样做。
可以调用 CameraUpdateFactory#newLatLngBounds(bounds, padding),其中“bounds”是 LatLngBounds,“padding”是以像素为单位的距离。问题是无法在 LatLngBounds 中创建 LatLng 和半径。
LatLngBounds 的构造函数只接受 2 个 LatLng 实例并生成一个矩形,其中这些是 NW 和 SE 角。
【问题讨论】:
【参考方案1】:就像提到的Risadinha 一样,您可以使用android-maps-utils
轻松实现这一目标。只需添加:
compile 'com.google.maps.android:android-maps-utils:0.4.4'
到你的 gradle 依赖,使用下面的代码:
public LatLngBounds toBounds(LatLng center, double radiusInMeters)
double distanceFromCenterToCorner = radiusInMeters * Math.sqrt(2.0);
LatLng southwestCorner =
SphericalUtil.computeOffset(center, distanceFromCenterToCorner, 225.0);
LatLng northeastCorner =
SphericalUtil.computeOffset(center, distanceFromCenterToCorner, 45.0);
return new LatLngBounds(southwestCorner, northeastCorner);
编辑:
我们的目标是计算两个点 (LatLngs
):
southwestCorner
和
northeastCorner
从SphericalUtil
的javadoc 中,您可以看到225
和45
是heading
值,而distanceFromCenterToCorner
是distance
。下图中数值的进一步解释:
【讨论】:
什么是 225 和 45 ?为什么需要 sqrt? 仅供参考,如果其他人想知道(和我一样),distance
,因此radius
,以米为单位。
为什么要乘以sqrt(2)。第二个参数不是以米为单位的距离吗?
@RobertDolca 因为你想计算从中心到右上角(或左下角)角的距离,所以它被相乘了。如果你没有将它乘以sqrt(2)
,你会得到从中心到顶部(或底部)edge的距离。
最新的是:compile 'com.google.maps.android:android-maps-utils:0.4.4'【参考方案2】:
使用 javascript 库,您可以绘制一个具有中心和半径的圆,然后获取它的边界。
centerSfo = new google.maps.LatLng(37.7749295, -122.41941550000001);
circle = new google.maps.Circle(radius: 5000, center: centerSfo);
bounds = circle.getBounds();
您可以使用 android api 来做同样的事情。
【讨论】:
是的,这可能是我能在这里得到的最佳答案。只是小更新: var circle = new window.google.maps.Circle(center:这是完全可行的。
LatLng 是您的圆心吗?你想要做的是在LatLngBounds
内写上你的圆圈(圆圈内的正方形问题),这样整个东西就会显示在地图上。
如果您在纸上绘制此图,您会发现您拥有计算LatLngBounds
所需的一切。
还记得怎么find the lengths of the sides of a right triangle吗?
a² + b² = c²
如果你从你的圆心画一条线到西北(左上)角,再画一条直线到正方形的西墙(从中心到左边的直线)你有一个三角形。现在您可以使用上面的等式求解c
,因为您知道三角形其他边的长度(圆的半径)。
所以现在你的方程变成了
r² + r² = c²
减少到
2r² = c²
进一步简化为
c = squareRoot(2) * r
现在你有距离了。这当然是过于简单化了,因为地球不是平的。如果距离不是很大,您可以使用上面相同的等式,但修改为将球形地球投影到平面上:
http://en.wikipedia.org/wiki/Geographical_distance#Flat-surface_formulae
请注意,这也使用Pythagorean theorem,与我们在上面所做的相同。
接下来,您需要根据给定方位的中心点和上面找到的距离计算端点(西北角和东南角)。
这篇文章可能会有所帮助:Calculate endpoint given distance, bearing, starting point
使用上面链接中的公式时,不要忘记将度数转换为弧度! (度数乘以pi/180
)
【讨论】:
@EmilAdz 目前有点不正确,因为距离方程正在计算平面值,而它应该计算测地线值。除非读者是Flat-Earther,否则应该没问题。 感谢@ChristopherPerry,但我有点希望通过现有的 Android API 找到某种方法来做到这一点。虽然您的解决方案是正确的(对于足够小的圆圈),但需要重写大量容易出错的逻辑。 好吧,对于 X 框架没有提供的东西,我不得不多次滚动自己的代码。为什么不做一些 TDD 并编写一些测试来驱动代码,然后你就会知道它的工作方式是你所期望的?它不应该是一个大函数,它可以分解为多个部分,并且每个部分都单独测试,因此如果出现错误,您将确切知道在哪里查看或改进您的算法。 嗨@ChristopherPerry,我可以从这个答案中获得一些信息以满足我的需要。我想为“X”缩放级别的半径计算设备上的像素数。基本上我在地图上覆盖了自己的圆圈来创建区域。现在我想根据缩放级别调整圆圈的宽度。你能帮我一个线索吗? 嗨@ChristopherPerry,我刚刚在这里发布了问题***.com/questions/35295605/…【参考方案4】:Google 提供了一个实用程序库:
http://googlemaps.github.io/android-maps-utils/
由 Google 推荐用于此任务和示例代码: http://code.google.com/p/gmaps-api-issues/issues/detail?id=5704
【讨论】:
【参考方案5】:虽然Bartek Lipinski's 的答案是正确的,如果您的 LatLngBounds 定义了一个正方形,大多数 LatLngBounds 定义了矩形,因此,东北点和西南点与中心的方位角并不总是 45 度和 255 度.
因此,如果您希望从任何四边形的中心获取半径的 LatLngBounds,请像这样使用初始 bounds.northeast
和 bounds.southwest
的坐标(使用 SphericalUtils):
LatLng northEast = SphericalUtil.computeOffset(center, radius * Math.sqrt(2.0), SphericalUtil.computeHeading(center, bounds.northeast));
LatLng southWest = SphericalUtil.computeOffset(center, radius * Math.sqrt(2.0), (180 + (180 + SphericalUtil.computeHeading(center, bounds.southwest))));
(180 + (180 + x))
从中心顺时针计算西南点的方位角。
【讨论】:
以上是关于如何在 Android Google Maps API v2 中将 LatLng 和半径转换为 LatLngBounds?的主要内容,如果未能解决你的问题,请参考以下文章
com.google.android.maps 在 Android Studio 中不存在
用户如何通过点击 google maps android 添加标记?
如何在 Google Maps Android SDK 的折线上添加形状
如何设置 Android Google Maps API v2 地图以显示全球地图?