前几天我在Java上做了一个类来计算point(X,Y)
是否在多边形内。 (X
和Y
为double
,因为它们是地理坐标。)
我知道Java有类Polygon
,但我必须使用Path2D
和Point2D
,因为Polygon
不允许double
,只是整数:(
在Path2D
完成多边形后,我使用方法contains
(Path2D
得到了它),我的问题就解决了。
但是现在,我想导入到Android,问题出在这里,因为Path2D
需要导入:
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
并且在Android中不存在awt,所以我无法使用。
那么,是否有类似于Path2D
的类具有contains
方法?或者我必须自己计算?
以下是我使用Path2D
在Java中的表现:
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);
}
答案 0 :(得分:31)
您可以完全使用我的简单库: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);
它适用于float类型和包含孔的多边形:)
答案 1 :(得分:14)
您可以使用Google Maps PolyUtil:
import com.google.maps.android.PolyUtil;
boolean inside = PolyUtil.containsLocation(new LatLng(...), poly, true);
答案 2 :(得分:6)
以下是我在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);
}
}
答案 3 :(得分: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();