【问题标题】:OSMBonusPack: Check whether my GeoPoint is inside Polygon or notOSMBonusPack:检查我的 GeoPoint 是否在多边形内
【发布时间】:2016-03-20 18:51:48
【问题描述】:

我在 android 中使用 osmdroid 以及 osmdroid 奖励包。我画了一个多边形。现在我想检查 GeoPoint(Latitude, longitude) 是否位于绘制的多边形内。我该怎么做?

这里我使用 contains 方法,它只接受 MotionEvent 对象并且它不起作用。有没有其他方法可以做到这一点?

我的代码如下。

GeoPoint gPt0 = new GeoPoint(23.215210, 72.648600);
GeoPoint gPt1 = new GeoPoint(23.216030, 72.648340);
GeoPoint gPt2 = new GeoPoint(23.217400, 72.649070);
GeoPoint gPt3 = new GeoPoint(23.216570, 72.650290);
GeoPoint gPt4 = new GeoPoint(23.214750, 72.649130);

List<GeoPoint> list = new ArrayList<>();
list.add(gPt0);
list.add(gPt1);
list.add(gPt2);
list.add(gPt3);
list.add(gPt4);
Polygon polygon = new Polygon(getApplication());
polygon.setPoints(list);
GeoPoint center = new GeoPoint(23.21612, 72.64933);
map.getOverlays().add(polygon);

MotionEvent event = MotionEvent.obtain(1, 1, MotionEvent.ACTION_HOVER_ENTER, (float)23.21602, (float) 72.64926, 1);

Log.e("CONTAINS", polygon.contains(event)+"");

【问题讨论】:

    标签: android osmdroid


    【解决方案1】:

    请尝试以下使用 Java 的算法

    class Point
    {
        int x, y;
     
        Point()
        {}
     
        Point(int p, int q)
        {
            x = p;
            y = q;
        }
    }
     
    public class Position_Point_WRT_Polygon
    {
     
        public static boolean onSegment(Point p, Point q, Point r)
        {
            if (q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x)
                    && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y))
                return true;
            return false;
        }
     
        public static int orientation(Point p, Point q, Point r)
        {
            int val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
     
            if (val == 0)
                return 0;
            return (val > 0) ? 1 : 2;
        }
     
        public static boolean doIntersect(Point p1, Point q1, Point p2, Point q2)
        {
     
            int o1 = orientation(p1, q1, p2);
            int o2 = orientation(p1, q1, q2);
            int o3 = orientation(p2, q2, p1);
            int o4 = orientation(p2, q2, q1);
     
            if (o1 != o2 && o3 != o4)
                return true;
     
            if (o1 == 0 && onSegment(p1, p2, q1))
                return true;
     
            if (o2 == 0 && onSegment(p1, q2, q1))
                return true;
     
            if (o3 == 0 && onSegment(p2, p1, q2))
                return true;
     
            if (o4 == 0 && onSegment(p2, q1, q2))
                return true;
     
            return false;
        }
     
        public static boolean isInside(Point polygon[], int n, Point p)
        {
            int INF = 10000;
            if (n < 3)
                return false;
     
            Point extreme = new Point(INF, p.y);
     
            int count = 0, i = 0;
            do
            {
                int next = (i + 1) % n;
                if (doIntersect(polygon[i], polygon[next], p, extreme))
                {
                    if (orientation(polygon[i], p, polygon[next]) == 0)
                        return onSegment(polygon[i], p, polygon[next]);
     
                    count++;
                }
                i = next;
            } while (i != 0);
     
            return (count & 1) == 1 ? true : false;
        }
     
        public static void main(String args[])
        {
            Point polygon1[] = { new Point(0, 0), new Point(10, 0),
                    new Point(10, 10),new Point(5, 5), new Point(0, 10) };
            int n = 5;
     
            Point p = new Point(5, 7);
            System.out.println("Point P(" + p.x + ", " + p.y
                    + ") lies inside polygon1: " + isInside(polygon1, n, p));
            p = new Point(11, 11);
            System.out.println("Point P(" + p.x + ", " + p.y
                    + ") lies inside polygon1: " + isInside(polygon1, n, p));
     
            Point polygon2[] = { new Point(0, 0), new Point(5, 5), new Point(5, 0) };
            n = 3;
     
            p = new Point(3, 3);
            System.out.println("Point P(" + p.x + ", " + p.y
                    + ") lies inside polygon2: " + isInside(polygon2, n, p));
            p = new Point(5, 1);
            System.out.println("Point P(" + p.x + ", " + p.y
                    + ") lies inside polygon2: " + isInside(polygon2, n, p));
            p = new Point(8, 1);
            System.out.println("Point P(" + p.x + ", " + p.y
                    + ") lies inside polygon2: " + isInside(polygon2, n, p));
     
            Point polygon3[] = { new Point(0, 0), new Point(10, 0),
                    new Point(10, 10), new Point(0, 10), new Point(5, 5) };
            n = 5;
     
            p = new Point(-1, 10);
            System.out.println("Point P(" + p.x + ", " + p.y
                    + ") lies inside polygon3: " + isInside(polygon3, n, p));
        }
    }

    【讨论】:

      【解决方案2】:

      当您定义一个新的运动事件时,X 和 Y 是屏幕中的位置(像素),而不是地图中的位置。此外,osmdroid 中的 java 文档中还有一些注意事项:

      /** Important note: this function returns correct results only if the Polygon has been drawn before, 
       * and if the MapView positioning has not changed. 
       * @param event
       * @return true if the Polygon contains the event position. 
       */
      public boolean contains(MotionEvent event)
      

      如果您看到该方法的源代码 (https://github.com/osmdroid/osmdroid/blob/master/osmdroid-android/src/main/java/org/osmdroid/bonuspack/overlays/Polygon.java),则仅使用 MotionEvent 内部的坐标:

      return region.contains((int)event.getX(), (int)event.getY());
      

      【讨论】:

      猜你喜欢
      • 2011-06-17
      • 2018-02-15
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多