【问题标题】:Test of Point inside polygon in AndroidAndroid中多边形内点的测试
【发布时间】:2013-03-26 20:45:41
【问题描述】:

前几天我在 Java 中做了一个课程来计算 point(X,Y) 是否在多边形内。 (XYdouble,因为它们是地理坐标)。

我知道 Java 有 Polygon 类,但我不得不使用 Path2DPoint2D,因为 Polygon 不允许 double 的,只有整数 :(

一旦我在Path2D 中完成了多边形,我就使用了contains 的方法(Path2D 有它),我的问题就解决了。

但是现在,我想导入到Android,问题就出在这里,因为Path2D需要导入:

import java.awt.geom.Path2D;
import java.awt.geom.Point2D;

并且在Android中不存在awt,所以我不能使用。

那么,有没有类似Path2D 的类有contains 方法?还是我自己计算?

这是我在 Java 中使用 Path2D 所做的:

private void ConstructPolygon(Vector<Point2D> coodinates)
{       
    this.polygon.moveTo(coodinates.get(0).getX(), coodinates.get(0).getY());        

    //System.out.println(coodinates.get(0).getX() + "   " + coodinates.get(0).getY());
    //System.out.println("asda");

    for(int i = 1; i < this.num_points; i++)
    {
        //System.out.println(coodinates.get(i).getX() + "   " + coodinates.get(i).getY());
        this.polygon.lineTo(coodinates.get(i).getX(), coodinates.get(i).getY());
    }
    this.polygon.closePath();
}
public boolean InsideCity(Point2D punto)
{
    return this.polygon.contains(punto);                
}

【问题讨论】:

  • 也许您可以将所有 double 值乘以 10,000 并将它们与 Java Polygon 类一起使用?

标签: java android polygon point


【解决方案1】:

您可以完全使用我的简单库:https://github.com/snatik/polygon-contains-point

准备多边形:

Polygon polygon = Polygon.Builder()
    .addVertex(new Point(1, 3))
    .addVertex(new Point(2, 8))
    .addVertex(new Point(5, 4))
    .addVertex(new Point(5, 9))
    .addVertex(new Point(7, 5))
    .addVertex(new Point(6, 1))
    .addVertex(new Point(3, 1))
    .build();

并检查该点是否在多边形内:

Point point = new Point(4.5f, 7);
boolean contains = polygon.contains(point);

它适用于浮点类型和包含孔的多边形:)

【讨论】:

  • 嗨@sromku!我有一个问题,我必须读取一个 KML 文件才能获得坐标,但这可能超过 100 个点……那么我怎样才能将 Builder 用于所有这些点?因为我的想法是读取kml,获取向量中的点(例如),然后构建多边形......所以......我不知道如何以你的方式使用:(你能帮我吗? 谢谢!!(代码完美!)
  • 请注意,此代码未通过测试用例,您碰巧用它使用的奇怪倾斜射线直接击中顶点。
  • 这个库即使是最简单的形状也有问题,在考虑之前检查问题列表。 github.com/sromku/polygon-contains-point/issues
  • @KaveeshKanwal 是的,会的
  • @sromku 在地图坐标的情况下,正确的顺序是 new Point(lat , lon) 吗?或新点(经度,纬度)?
【解决方案2】:

您可以使用 Google Maps PolyUtil:

import com.google.maps.android.PolyUtil;

boolean inside = PolyUtil.containsLocation(new LatLng(...), poly, true);

【讨论】:

    【解决方案3】:

    这是我在 Android 中的做法。 它基于这个java程序(光线投射算法): https://gis.stackexchange.com/questions/42879/check-if-lat-long-point-is-within-a-set-of-polygons-using-google-maps/46720#46720

        public boolean pointInPolygon(LatLng point, Polygon polygon) {
            // ray casting alogrithm http://rosettacode.org/wiki/Ray-casting_algorithm
            int crossings = 0;
            List<LatLng> path = polygon.getPoints();
            path.remove(path.size()-1); //remove the last point that is added automatically by getPoints()
    
            // for each edge
            for (int i=0; i < path.size(); i++) {
                LatLng a = path.get(i);
                int j = i + 1;
                //to close the last edge, you have to take the first point of your polygon
                if (j >= path.size()) {
                    j = 0;
                }
                LatLng b = path.get(j);
                if (rayCrossesSegment(point, a, b)) {
                    crossings++;
                }
            }
    
            // odd number of crossings?
            return (crossings % 2 == 1);
         }
    
        public boolean rayCrossesSegment(LatLng point, LatLng a,LatLng b) {
                    // Ray Casting algorithm checks, for each segment, if the point is 1) to the left of the segment and 2) not above nor below the segment. If these two conditions are met, it returns true
                    double px = point.longitude,
                    py = point.latitude,
                    ax = a.longitude,
                    ay = a.latitude,
                    bx = b.longitude,
                    by = b.latitude;
                if (ay > by) {
                    ax = b.longitude;
                    ay = b.latitude;
                    bx = a.longitude;
                    by = a.latitude;
                }
                // alter longitude to cater for 180 degree crossings
                if (px < 0 || ax <0 || bx <0) { px += 360; ax+=360; bx+=360; }
                // if the point has the same latitude as a or b, increase slightly py
                if (py == ay || py == by) py += 0.00000001;
    
    
                // if the point is above, below or to the right of the segment, it returns false
                if ((py > by || py < ay) || (px > Math.max(ax, bx))){ 
                    return false;
                }
                // if the point is not above, below or to the right and is to the left, return true
                else if (px < Math.min(ax, bx)){ 
                    return true;
                }
                // if the two above conditions are not met, you have to compare the slope of segment [a,b] (the red one here) and segment [a,p] (the blue one here) to see if your point is to the left of segment [a,b] or not
                else {
                    double red = (ax != bx) ? ((by - ay) / (bx - ax)) : Double.POSITIVE_INFINITY;
                    double blue = (ax != px) ? ((py - ay) / (px - ax)) : Double.POSITIVE_INFINITY;
                    return (blue >= red);
                }
    
         }
    

    【讨论】:

    • 请分享链接以获取多边形类
    【解决方案4】:

    对不起@sromku 我问过自己(我从来没有用过这种东西)

    如果有人有同样的问题,我就是这样解决的

    Builder poly2 = new Polygon.Builder();
        for(int i = 0; i< xpoints.length;i++){
            poly2.addVertex(new Point(xpoints[i],ypoints[i]));
        }
        Polygon polygon2 = poly2.build();
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多