12

前几天我在 Java 中做了一个类来计算 apoint(X,Y)是否在多边形内。(X并且Ydouble,因为将是地理坐标)。

我知道Java有类Polygon,但我不得不使用Path2Dand Point2D,因为Polygon不允许double's,只允许整数:(

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

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

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

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

那么,有没有类似Path2Dhadcontains方法的类呢?还是我必须自己计算?

这是我在 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);                
}
4

4 回答 4

36

您可以为此使用我的简单库: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);

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

于 2013-04-04T16:46:02.047 回答
26

您可以使用 Google 地图 PolyUtil:

import com.google.maps.android.PolyUtil;

boolean inside = PolyUtil.containsLocation(new LatLng(...), poly, true);
于 2016-07-09T09:03:30.640 回答
7

这是我在Android中的做法。它基于这个java程序(光线投射算法): https ://gis.stackexchange.com/questions/42879/check-if-lat-long-point-is-within-a-set-of-polygons-using -谷歌地图/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);
            }

     }
于 2014-09-14T12:54:31.603 回答
5

对不起@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();
于 2013-04-10T16:23:23.643 回答