/** * 判斷點是否在多邊形內 * @param point 檢測點 * @param pts 多邊形的頂點 * @return 點在多邊形內返回true,不然返回false */ public static boolean IsPtInPoly(Point2D.Double point, List<Point2D.Double> pts){ int N = pts.size(); boolean boundOrVertex = true; //若是點位於多邊形的頂點或邊上,也算作點在多邊形內,直接返回true int intersectCount = 0;//cross points count of x double precision = 2e-10; //浮點類型計算時候與0比較時候的容差 Point2D.Double p1, p2;//neighbour bound vertices Point2D.Double p = point; //當前點 p1 = pts.get(0);//left vertex for(int i = 1; i <= N; ++i){//check all rays if(p.equals(p1)){ return boundOrVertex;//p is an vertex } p2 = pts.get(i % N);//right vertex if(p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)){//ray is outside of our interests p1 = p2; continue;//next ray left point } if(p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)){//ray is crossing over by the algorithm (common part of) if(p.y <= Math.max(p1.y, p2.y)){//x is before of ray if(p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)){//overlies on a horizontal ray return boundOrVertex; } if(p1.y == p2.y){//ray is vertical if(p1.y == p.y){//overlies on a vertical ray return boundOrVertex; }else{//before ray ++intersectCount; } }else{//cross point on the left side double xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;//cross point of y if(Math.abs(p.y - xinters) < precision){//overlies on a ray return boundOrVertex; } if(p.y < xinters){//before ray ++intersectCount; } } } }else{//special case when ray is crossing through the vertex if(p.x == p2.x && p.y <= p2.y){//p crossing over p2 Point2D.Double p3 = pts.get((i+1) % N); //next vertex if(p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)){//p.x lies between p1.x & p3.x ++intersectCount; }else{ intersectCount += 2; } } } p1 = p2;//next ray left point } if(intersectCount % 2 == 0){//偶數在多邊形外 return false; } else { //奇數在多邊形內 return true; } }
測試:ide
// 測試一個點是否在多邊形內 public static void main(String[] args) { Point2D.Double point = new Point2D.Double(116.404072, 39.916605); List<Point2D.Double> pts = new ArrayList<Point2D.Double>(); pts.add(new Point2D.Double(116.395, 39.910)); pts.add(new Point2D.Double(116.394, 39.914)); pts.add(new Point2D.Double(116.403, 39.920)); pts.add(new Point2D.Double(116.402, 39.914)); pts.add(new Point2D.Double(116.410, 39.913)); if(IsPtInPoly(point, pts)){ System.out.println("點在多邊形內"); }else{ System.out.println("點在多邊形外"); } }