java 实现电子围栏—判断点是否在指定区域内的方法
一、意义
通过实现电子围栏—判断点是否在指定区域内方法,可以方便地对点的位置判断,从而实现复杂的功能。
二、方法
package use;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
public class PolygonUtil {
/**
* 判断点是否在多边形内
* @Title: IsPointInPoly
* @Description:判断点是否在指定区域内
* @param point 测试点
* @param pts 多边形的点
* @return boolean
* @throws
*/
public static boolean isInPolygon(Point2D.Double point, List<Point2D.Double> pts, boolean bj){
int N = pts.size();
boolean boundOrVertex = bj;
int intersectCount = 0;//交叉点数量
double precision = 2e-10; //浮点类型计算时候与0比较时候的容差
Point2D.Double p1, p2;//临近顶点
Point2D.Double p = point; //当前点
p1 = pts.get(0);
for(int i = 1; i <= N; ++i){
if(p.equals(p1)){
return boundOrVertex;
}
p2 = pts.get(i % N);
if(p1.equals(p2)){
continue;
}
if(p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)){
p1 = p2;
continue;
}
//射线穿过算法
if(p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)){
if(p.y <= Math.max(p1.y, p2.y)){
if(p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)){
return boundOrVertex;
//return true;
}
if(p1.y == p2.y){
if(p1.y == p.y){
return boundOrVertex;
}else{
++intersectCount;
}
}else{
double xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;
if(Math.abs(p.y - xinters) < precision){
return boundOrVertex;
}
if(p.y < xinters){
++intersectCount;
}
}
}
}else{
if(p.x == p1.x && p.x == p2.x) {
if(p.y >= Math.min(p1.y, p2.y) && p.y <= Math.max(p1.y, p2.y)){
return boundOrVertex;
}
}
if(p.x == p2.x && p.y <= p2.y){
Point2D.Double p3 = p2;
for(int k = 1; k <= N; ++k) {
p3 = pts.get((i + k) % N);
if (p2.equals(p3)) {
continue;
}
break;
}
if (p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)) {
++intersectCount;
} else {
intersectCount += 2;
}
}
}
p1 = p2;
}
if(intersectCount % 2 == 0){//偶数在多边形外
return false;
} else { //奇数在多边形内
return true;
}
}
public static boolean isin(double x,double y,double [] xa,double [] ya)
{
Point2D.Double point = new Point2D.Double();
point.setLocation(x,y);
List<Point2D.Double> pts = new ArrayList<>();
int l = xa.length;
if(l==0)
{
return false;
}
for(int i=0;i<l;i++)
{
Point2D.Double pointa = new Point2D.Double();
pointa.setLocation(xa[i],ya[i]);
pts.add(pointa);
}
boolean is =isInPolygon(point,pts,true);
return is;
}
public static boolean isin1(double x,double y,double [][] z)
{
Point2D.Double point = new Point2D.Double();
point.setLocation(x,y);
List<Point2D.Double> pts = new ArrayList<>();
int l = z.length;
if(l==0)
{
return false;
}
for(int i=0;i<l;i++)
{
Point2D.Double pointa = new Point2D.Double();
pointa.setLocation(z[i][0],z[i][1]);
pts.add(pointa);
}
boolean is =isInPolygon(point,pts,true);
return is;
}
}
三、使用例子
public static void main(String[] args) {
double [] a = {1,1,0,0};
double [] b = {1,0,0,1};
double [][] c = {{1,1},{1,0},{0,0},{0,1}};
System.out.println(isin(0.1,0.1,a,b));
System.out.println(isin1(0.1,0.1,c));
System.out.println(isin(2,0.1,a,b));
System.out.println(isin1(2,0.1,c));
}
输出:
true
true
false
false
四、结尾
本方法经过本人多次分析与测试,如有更好的方法或者发现错误的地方欢迎大家评论与指正!