最近在做一个ai算法,只检测划定的区域内的物体,所以需要判断某点是否在所绘制的区域内,整理了一下,具体代码如下(基本可以直接用)
1.编写点的实体类
//点的实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Point {
//x坐标
private Double lngx;
//y坐标
private Double laty;
}
2.编写检测算法
public class CheckIsInPolygons {
/**
* 判断当前位置是否在多边形区域内
*
* @param checkPoint 当前经纬度
* @param areaAround 围栏范围
* @return
*/
public static boolean checkIsInPolygon(Point checkPoint, List<Point> areaAround) {
Point2D.Double point = new Point2D.Double(checkPoint.getLaty(), checkPoint.getLngx());
List<Point2D.Double> pointList = new ArrayList<>();
for (Point everyPoint : areaAround) {
Point2D.Double polygonPoint = new Point2D.Double(everyPoint.getLaty(), everyPoint.getLngx());
pointList.add(polygonPoint);
}
return checkIsPtInPoly(point, pointList);
}
/**
* 判断点是否在多边形内,如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
*
* @param point 检测点
* @param pts 多边形的顶点
* @return 点在多边形内返回true, 否则返回false
*/
public static boolean checkIsPtInPoly(Point2D.Double point, List<Point2D.Double> pts) {
int N = pts.size();
//如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
boolean boundOrVertex = true;
//cross points count of x
int intersectCount = 0;
//浮点类型计算时候与0比较时候的容差
double precision = 2e-10;
//neighbour bound vertices
Point2D.Double p1, p2;
//当前点
Point2D.Double p = point;
//left vertex
p1 = pts.get(0);
//check all rays
for (int i = 1; i <= N; ++i) {
if (p.equals(p1)) {
//p is an vertex
return boundOrVertex;
}
//right vertex
p2 = pts.get(i % N);
//ray is outside of our interests
if (p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)) {
p1 = p2;
//next ray left point
continue;
}
//ray is crossing over by the algorithm (common part of)
if (p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)) {
//x is before of ray
if (p.y <= Math.max(p1.y, p2.y)) {
//overlies on a horizontal ray
if (p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)) {
return boundOrVertex;
}
//ray is vertical
if (p1.y == p2.y) {
//overlies on a vertical ray
if (p1.y == p.y) {
return boundOrVertex;
//before ray
} else {
++intersectCount;
}
} else {
//cross point on the left side
//cross point of y
double xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;
//overlies on a ray
if (Math.abs(p.y - xinters) < precision) {
return boundOrVertex;
}
//before ray
if (p.y < xinters) {
++intersectCount;
}
}
}
} else {
//special case when ray is crossing through the vertex
//p crossing over p2
if (p.x == p2.x && p.y <= p2.y) {
//next vertex
Point2D.Double p3 = pts.get((i + 1) % N);
//p.x lies between p1.x & p3.x
if (p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)) {
++intersectCount;
} else {
intersectCount += 2;
}
}
}
//next ray left point
p1 = p2;
}
//偶数在多边形外
if (intersectCount % 2 == 0) {
return false;
} else {
//奇数在多边形内
return true;
}
}
// 测试算法,返回true,则代表在区域内,返回false,代表不在区域内
public static void main(String[] args) {
//待检测的点的坐标
Point checkPoint=new Point();
checkPoint.setLngx(3.0);
checkPoint.setLaty(2.1);
//区域坐标
List<Point> areaAround=new ArrayList<>();
Point areaPoint01=new Point();
areaPoint01.setLngx(1.0);
areaPoint01.setLaty(0.0);
areaAround.add(areaPoint01);
Point areaPoint02=new Point();
areaPoint02.setLngx(3.0);
areaPoint02.setLaty(0.0);
areaAround.add(areaPoint02);
Point areaPoint03=new Point();
areaPoint03.setLngx(3.0);
areaPoint03.setLaty(2.0);
areaAround.add(areaPoint03);
Point areaPoint04=new Point();
areaPoint04.setLngx(1.0);
areaPoint04.setLaty(2.0);
areaAround.add(areaPoint04);
Boolean res=checkIsInPolygon(checkPoint,areaAround);
System.out.println(res);
}
}