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
Test of Point inside polygon in Android
提问by Shudy
The other day I did a class in Java to calculate if a point(X,Y)
is inside a polygon. (X
and Y
are double
, because will be geo-coordinates).
前几天我用 Java 做了一门课来计算 apoint(X,Y)
是否在多边形内。(X
和Y
是double
,因为将是地理坐标)。
I know that Java has the class Polygon
, but I had to use Path2D
and Point2D
, because Polygon
don't allow double
's, just integers :(
我知道 Java 有这个类Polygon
,但我不得不使用Path2D
and Point2D
,因为Polygon
不允许double
's,只有整数 :(
Once I have the polygon done in Path2D
, I used the method contains
(Path2D
had it), and my problem was solved.
一旦我在 中完成了多边形Path2D
,我就使用了该方法contains
(Path2D
拥有它),我的问题就解决了。
But now, I want to import to Android, and the problem is here, because Path2D
needs 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 Path2D
that had contains
method? 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();