java Android中多边形内点的测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15816928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 20:57:42  来源:igfitidea点击:

Test of Point inside polygon in Android

javaandroidpolygonpoint

提问by Shudy

The other day I did a class in Java to calculate if a point(X,Y)is inside a polygon. (Xand Yare double, because will be geo-coordinates).

前几天我用 Java 做了一门课来计算 apoint(X,Y)是否在多边形内。(XYdouble,因为将是地理坐标)。

I know that Java has the class Polygon, but I had to use Path2Dand Point2D, because Polygondon't allow double's, just integers :(

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

Once I have the polygon done in Path2D, I used the method contains(Path2Dhad it), and my problem was solved.

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

But now, I want to import to Android, and the problem is here, because Path2Dneeds to import:

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

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

and in Android don't exist awt, so I can't use.

而在Android中不存在awt,所以我无法使用。

So, is there any class similar to Path2Dthat had containsmethod? or I have to calculate by myself?

那么,有没有类似于Path2D那个 hadcontains方法的类?还是我必须自己计算?

Here is how I did in Java using Path2D:

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

回答by sromku

You can use my simple library exactly for this: https://github.com/snatik/polygon-contains-point.

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

Prepare polygon:

准备多边形:

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();

And check whereas the point is inside the polygon:

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

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

It works with float types and with polygons that contain holes :)

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

回答by fnieto - Fernando Nieto

You can use Google Maps PolyUtil:

您可以使用 Google 地图 PolyUtil:

import com.google.maps.android.PolyUtil;

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

回答by ylag75

Here is how I did it in Android. It is based on this java program (ray casting algorithm) : https://gis.stackexchange.com/questions/42879/check-if-lat-long-point-is-within-a-set-of-polygons-using-google-maps/46720#46720

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

     }

回答by Shudy

Sorry @sromku I asked my self (I never used this type of things)

抱歉@sromku 我问我自己(我从来没有用过这种类型的东西)

That's how I solved if anyone have the same question

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

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();