【问题标题】:How to detect if a point is in a Circle?如何检测一个点是否在一个圆圈中?
【发布时间】:2013-01-13 22:33:00
【问题描述】:

如何测试 LatLng 点是否在圆的范围内? (谷歌地图 JavaScript v3)

getBounds() 方法返回圆的边界框,它是一个矩形,所以如果一个点落在圆之外但在边界框内,你会得到错误的答案。

【问题讨论】:

标签: javascript google-maps google-maps-api-3


【解决方案1】:

使用spherical geometry library(请务必将其包含在 API 中)

function pointInCircle(point, radius, center)
{
    return (google.maps.geometry.spherical.computeDistanceBetween(point, center) <= radius)
}

【讨论】:

    【解决方案2】:

    您可以手动进行距离比较,相当简单。

    (x1 - x2)^2 + (y1 - y2)^2 <= D^2 
    

    【讨论】:

    • 注意这并没有考虑到地球上的球面映射。 Lat/Lng 不相等,因此在两极附近这是错误的(但在赤道附近更准确)。
    • 另外,这没有考虑地球的曲率,也没有考虑使用的投影。
    【解决方案3】:

    您可以使用 Circle 对象来显示它;

    new google.maps.Circle({
                map : map,
                center : new google.maps.LatLng(lat,lng),
                strokeColor:'#00FFCC',
                strokeWeight:2,
                fillOpacity:0,
                radius:radiusm
            });
    

    并将勾股定理应用于坐标:但在这种情况下,要使其成为“真实”圆,因为纬度和经度之间的 1° 之间的比率会随纬度而变化, 你至少应该像这样调整它们:

    var kmRadius = 100; //(radius of 100 km)
    var lat_gap = kmRadius/111.1;
    var lng_gap = lat_gap / Math.cos(lat / (Math.PI/180));
    

    【讨论】:

      【解决方案4】:

      你为什么不简单地用Pythagorean theorem 来计算呢?你知道a²+b²=c²。如果 c 低于 r(半径),你就知道它在里面。

      var isInside=Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) >= r*r;
      

      【讨论】:

      • 谢谢,这就是我最终做的,使用 API 的内置函数。如果圆形对象有 containsLocation() 方法会更容易。 (我也喜欢 fitBounds() 方法!)您可以在此处查看代码:Circle Selection for Google Maps
      • 注意这并没有考虑到地球上的球面映射。 Lat/Lng 不相等,因此在两极附近这是错误的(但在赤道附近更准确)。
      • 另外,这没有考虑地球的曲率,也没有考虑使用的投影。
      【解决方案5】:

      这样的事情应该可以解决问题(代码未经测试):

      public boolean pointInCircle(Circle c, LatLng coord) {
        Rectangle r = c.getBounds();
        double rectX = r.getX();
        double rectY = r.getY();
        double rectWidth = r.getWidth();
        double rectHeight = r.getHeight();
      
        double circleCenterX = rectX + rectWidth/2;
        double circleCenterY = rectY + rectHeight/2;
      
        double lat = coord.getLatitude();
        double lon = coord.getLongitude();
      
        // Point in circle if (x−h)^2 + (y−k)^2 <= r^2
        double rSquared = Math.pow(rectWidth/2, 2);
        double point = Math.pow(lat - circleCenterX, 2) + Math.pow(lon - circleCenterY, 2);
      
        return (point <= rSquared) ? true : false;
      }
      

      【讨论】:

      • 注意这并没有考虑到地球上的球面映射。 Lat/Lng 不相等,因此在两极附近这是错误的(但在赤道附近更准确)。
      • 另外,这没有考虑地球的曲率,也没有考虑使用的投影。
      【解决方案6】:

      试试这个(Javascript):

      const toRadians = (val) => {
         return val * Math.PI / 180;
      }
      const toDegrees = (val) => {
         return val * 180 / Math.PI;
      }
      // Calculate a point winthin a circle
      // circle ={center:LatLong, radius: number} // in metres
      const pointInsideCircle = (point, circle) => {
          let center = circle.center;
          let distance = distanceBetween(point, center);
      
          return distance < circle.radius; // Use '<=' if you want to get all points in the border
      };
      
      const distanceBetween = (point1, point2) => {
          var R = 6371e3; // metres
          var φ1 = toRadians(point1.latitude);
          var φ2 = toRadians(point2.latitude);
          var Δφ = toRadians(point2.latitude - point1.latitude);
          var Δλ = toRadians(point2.longitude - point1.longitude);
      
          var a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
                  Math.cos(φ1) * Math.cos(φ2) *
                  Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
          var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
      
          return R * c;
      }
      

      参考:http://www.movable-type.co.uk/scripts/latlong.html

      这个 npm 帮助模块做同样的事情,并返回一个布尔值来判断该项目是否在圆圈中。

      https://www.npmjs.com/package/fencery

      【讨论】:

      • 既然你用的是es6:const toRadians = val =&gt; val * Math.PI / 180;const toDegrees = val =&gt; val * 180 / Math.PI;
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-25
      • 2012-11-12
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      • 1970-01-01
      相关资源
      最近更新 更多