确定点是不是在多边形中

Posted

技术标签:

【中文标题】确定点是不是在多边形中【英文标题】:Identify if point is in the polygon确定点是否在多边形中 【发布时间】:2014-11-18 19:03:19 【问题描述】:

根据我的要求,我正在谷歌地图上绘制多边形,如下图所示。(使用地图 v2)

现在我需要在用户输入特定多边形时显示警报。

如何确定我当前的位置是否在多边形中。 (需要优化方式而不耗尽电池)

提前致谢。

【问题讨论】:

你在这里使用地理围栏了吗? 不。我刚刚使用 PolygonOptions 绘制了那个多边形。寻找识别当前位置是否在该多边形中的最佳方法。 您可以为此使用地理围栏。 developer.android.com/training/location/geofencing.html 我认为地理围栏是如果我们可以有一个位置并给出一个特定的半径,它会在用户进入该位置时发出警报。就我而言,我正在使用多个位置绘制一个多边形。 当你给一个位置一个radius时,geofence将每个点存储在radius包围的区域内。你的问题与这个有关。你可以在geofence中绘制poligon而不是circle。 【参考方案1】:

刚刚尝试了识别多边形中的点的光线投射算法。这很完美。

Ray-Casting论文参考http://en.wikipedia.org/wiki/Point_in_polygon

private boolean isPointInPolygon(LatLng tap, ArrayList<LatLng> vertices) 
        int intersectCount = 0;
        for (int j = 0; j < vertices.size() - 1; j++) 
            if (rayCastIntersect(tap, vertices.get(j), vertices.get(j + 1))) 
                intersectCount++;
            
        

        return ((intersectCount % 2) == 1); // odd = inside, even = outside;
    

    private boolean rayCastIntersect(LatLng tap, LatLng vertA, LatLng vertB) 

        double aY = vertA.latitude;
        double bY = vertB.latitude;
        double aX = vertA.longitude;
        double bX = vertB.longitude;
        double pY = tap.latitude;
        double pX = tap.longitude;

        if ((aY > pY && bY > pY) || (aY < pY && bY < pY)
                || (aX < pX && bX < pX)) 
            return false; // a and b can't both be above or below pt.y, and a or
                            // b must be east of pt.x
        

        double m = (aY - bY) / (aX - bX); // Rise over run
        double bee = (-aX) * m + aY; // y = mx + b
        double x = (pY - bee) / m; // algebra is neat!

        return x > pX;
    

【讨论】:

你的算法总是返回 false ,为什么? @Supriya 工作良好。谢谢你。如果可能,我请您解释相交是如何工作的。【参考方案2】:

我发现光线投射方法不可靠,但我最终使用了来自谷歌地图的PolyUtil

你需要依赖compile 'com.google.maps.android:android-maps-utils:0.5'

然后方法是这样的

PolyUtil.containsLocation(userLocation, polyPointsList, false);

编辑

这是源代码中对该方法的描述

计算给定点是否位于指定多边形内。无论最后一个点是否等于第一个点,多边形总是被认为是闭合的。内部被定义为不包含南极——南极总是在外部。如果测地线为真,则多边形由大圆段组成,否则由恒向(loxodromic)段组成。

【讨论】:

为什么最后一个参数是假的?那个参数是什么? 我已经添加了方法的描述,因为我在他们的源代码中找到了它 谢谢!很棒的答案! 这两项工作始终如一。我将它们都添加了,并将地图触摸侦听器作为唤起。没有问题。但这显然是更简洁的实现方式。【参考方案3】:

参考这个链接

Polygon Touch detection Google Map API V2

它的RayCasting算法,它可以帮助你:)

算法简介:

从你的点向右画一条水平线,如果它以奇数次与多边形的边相交,则该点在多边形内部,否则在外部:)

这些 wiki 链接将为您提供完整的想法:

http://en.wikipedia.org/wiki/Point_in_polygon

http://rosettacode.org/wiki/Ray-casting_algorithm

【讨论】:

试试这个。谢谢:) 为我的几个测试工作。检查其论文。 :) 谢谢【参考方案4】:

这是 Dart 中的代码,取自: https://github.com/KohlsAdrian/google_maps_utils/blob/master/lib/poly_utils.dart

  /// Checks if [point] is inside [polygon]
  static bool containsLocationPoly(Point point, List<Point> polygon) 
    num ax = 0;
    num ay = 0;
    num bx = polygon[polygon.length - 1].x - point.x;
    num by = polygon[polygon.length - 1].y - point.y;
    int depth = 0;

    for (int i = 0; i < polygon.length; i++) 
      ax = bx;
      ay = by;
      bx = polygon[i].x - point.x;
      by = polygon[i].y - point.y;

      if (ay < 0 && by < 0) continue; // both "up" or both "down"
      if (ay > 0 && by > 0) continue; // both "up" or both "down"
      if (ax < 0 && bx < 0) continue; // both points on left

      num lx = ax - ay * (bx - ax) / (by - ay);

      if (lx == 0) return true; // point on edge
      if (lx > 0) depth++;
    

    return (depth & 1) == 1;
  

【讨论】:

以上是关于确定点是不是在多边形中的主要内容,如果未能解决你的问题,请参考以下文章

如何确定一个点是不是在二维凸多边形内?

确定点是不是在多边形内

确定一个点是不是位于传单多边形内

如何在 N 时间内确定一个点是不是在 2D 凸多边形内

已知一个多边形的所有顶点坐标,如果确定一点是不是在这个多边形内?

如何判断一个指定的经纬度点是不是落在一个多边形区域内