我如何知道一个 Lat,Lng 点是不是包含在一个圆圈内?

Posted

技术标签:

【中文标题】我如何知道一个 Lat,Lng 点是不是包含在一个圆圈内?【英文标题】:How do I know if a Lat,Lng point is contained within a circle?我如何知道一个 Lat,Lng 点是否包含在一个圆圈内? 【发布时间】:2011-05-26 17:18:54 【问题描述】:

好的,不言自明。我正在使用谷歌地图,我试图找出一个经纬度点是否在半径为 x 的圆内(x 由用户选择)。

边界框不适用于此。我已经尝试过使用以下代码:

distlatLng = new google.maps.LatLng(dist.latlng[0],dist.latlng[1]);
var latLngBounds = circle.getBounds();
if(latLngBounds.contains(distlatLng))
      dropPins(distlatLng,dist.f_addr);

这仍然会导致标记位于圆圈之外。

我猜这是一些需要计算曲率或面积的简单数学,但我不确定从哪里开始。有什么建议吗?

【问题讨论】:

This SO 帖子可能会为您提供所需的见解。 【参考方案1】:

带有可拖动中心标记的工作解决方案

你试过contains吗?看看LatLngBounds 构造函数。

我写了一篇关于它的文章,其中包含指向有效JSFiddle.net example 的链接。


Updated version.

【讨论】:

@zavidovych 这是一个已知的错误。它已经消失了一段时间,我猜是 v3.9 回来了。我已经提交了错误报告。还有一种方法,我会在有时间的时候发布。 很好的解决方案。当我需要它时不可用:) 很好的解决方案。到目前为止,包含似乎正在工作。 这个例子在demo.developerextensions.com/answers/…的修改版本,它也使用自定义函数检查距离,可以在没有google lib的情况下使用 @surindersingh 那是一个伟大的!谢谢!您可能想将其添加到答案中(请提交edit)。【参考方案2】:

这很简单。您只需要计算中心和给定点之间的距离并将其与半径进行比较。您可以从 here获取帮助计算两个纬度之间的距离

【讨论】:

虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review 感谢@fasteque 的信息 :) @fasteque 他提到的解决方案很简单。最好在您的问题/建议中包含更多详细信息,说明您到底想要什么或正在寻找什么。 @NBhargav 最好包含外部链接的相关部分,或者如果无法访问,请提供代码示例。回答指南中清楚地写了:***.com/help/how-to-answer【参考方案3】:

不幸的是,毕达哥拉斯对球体没有帮助。因此 Stuart Beard 的回答是不正确的;经度差异与米没有固定的比例,而是取决于纬度。

正确的方法是使用大圆距离公式。假设一个球形地球,一个很好的近似值是这样的(在 C++ 中):

/** Find the great-circle distance in metres, assuming a spherical earth, between two lat-long points in degrees. */
inline double GreatCircleDistanceInMeters(double aLong1,double aLat1,double aLong2,double aLat2)
    
    aLong1 *= KDegreesToRadiansDouble;
    aLat1 *= KDegreesToRadiansDouble;
    aLong2 *= KDegreesToRadiansDouble;
    aLat2 *= KDegreesToRadiansDouble;
    double cos_angle = sin(aLat1) * sin(aLat2) + cos(aLat1) * cos(aLat2) * cos(aLong2 - aLong1);

    /*
    Inaccurate trig functions can cause cos_angle to be a tiny amount
    greater than 1 if the two positions are very close. That in turn causes
    acos to give a domain error and return the special floating point value
    -1.#IND000000000000, meaning 'indefinite'. Observed on VS2008 on 64-bit Windows.
    */
    if (cos_angle >= 1)
        return 0;

    double angle = acos(cos_angle);
    return angle * KEquatorialRadiusInMetres;
    

在哪里

const double KPiDouble = 3.141592654;
const double KDegreesToRadiansDouble = KPiDouble / 180.0;

/**
A constant to convert radians to metres for the Mercator and other projections.
It is the semi-major axis (equatorial radius) used by the WGS 84 datum (see http://en.wikipedia.org/wiki/WGS84).
*/
const int32 KEquatorialRadiusInMetres = 6378137;

【讨论】:

完全同意这是正确的。然而,当时并不要求 100% 的准确度。 您仍然选择了一个在两极附近有危险错误的答案,@StuartBeard,我完全赞成在适当的情况下进行近似,但我认为您在非笛卡尔空间中选择笛卡尔距离因为“答案”是不负责任的。【参考方案4】:

使用 Google Maps API 几何库计算圆心与标记之间的距离,然后将其与半径进行比较。

var pointIsInsideCircle = google.maps.geometry.spherical.computeDistanceBetween(circle.getCenter(), point) <= circle.getRadius();

【讨论】:

【参考方案5】:

以下代码适用于我:我的标记不能拖到圆圈外,而是挂在其边缘(在任何方向)并保留最后一个有效位置。

该函数是标记“拖动”事件的事件处理程序。

_markerDragged : function() 
    var latLng = this.marker.getPosition();
    var center = this.circle.getCenter();
    var radius = this.circle.getRadius();
    if (this.circleBounds.contains(latLng) &&
        (google.maps.geometry.spherical.computeDistanceBetween(latLng, center) <= radius)) 
        this.lastMarkerPos = latLng;
        this._geocodePosition(latLng);
     else 
        // Prevent dragging marker outside circle
        // see (comments of) http://unserkaiser.com/code/google-maps-marker-check-if-in-circle/
        // see http://www.mvjantzen.com/blog/?p=3190 and source code of http://mvjantzen.com/cabi/trips4q2012.html
        this.marker.setPosition(this.lastMarkerPos);
    
,

感谢http://unserkaiser.com/code/google-maps-marker-check-if-in-circle/ 和http://www.mvjantzen.com/blog/?p=3190。

【讨论】:

【参考方案6】:

我真的有点傻。考虑一下我们可以使用毕达哥拉斯定理。

我们与一个点的最大距离(X 英里),以及两个纬度和两个经度。如果我们使用这些形成一个三角形,那么我们可以求解到该点的距离。

假设我们知道point1 坐标为lat1,lng1 是圆的中心,point2 坐标为lat2,lng2 是我们试图确定的点是否在圆内。

我们使用由point1point2 确定的点形成一个直角三角形。这,point3 将有坐标lat1,lng2lat2,lng1(哪个没关系)。然后我们计算差异(或者如果您愿意)距离 - latDiff = lat2-lat1lngDiff = lng2-lng1

然后我们使用毕达哥拉斯计算距中心的距离 - dist=sqrt(lngDiff^2+latDiff^2)

我们必须将所有内容都转换为米,以便它可以在谷歌地图上正常工作,因此英里乘以 1609(大约),纬度/经度乘以 111000(大约)。这并不完全准确,但它做得很好。

希望一切都有意义。

【讨论】:

在这里聚会有点晚了,但您有没有考虑到使用的地图投影会扭曲物体的形状和距离? 这完全忽略了地图投影。纬度和经度不等间距!它在北纬或南纬根本行不通。只在赤道附近。这是错误的。 @CarlF。是的,这是对的。使用地图时有更好的解决方案。看到这个答案***.com/a/10428729/1202145 @NBhargav,您的链接非常接近正确答案!它可能仍然存在问题。我没有检查数学,但要注意将弧近似为直线。可以使澳大利亚悉尼看起来更接近美国波士顿。

以上是关于我如何知道一个 Lat,Lng 点是不是包含在一个圆圈内?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 StandaloneSearchBox 获取 Lat 和 Lng?

RestKit 将包含 lat & lng 的数组映射到 CoreData

如何对两个属性而不是 [ lng, lat ] 数组进行地理搜索?

在图像上绘制 lat/lng 点

使用空间点类型在 MySQL 中存储 Lat Lng 值

如何通过 SQL 连接选择使用 lat/lng 半径