判斷點是否在封閉區域裏面

一、判斷點在不在區域裏面方法

     1.判斷點在不在區域裏面,作點水平向左的線段(這個水平線段儘量的達到X軸負方向),看與圖形(代指區域)的交點是否是奇數個,如果是奇數個就是在圖形裏面。 關於交點特殊情況的判斷,如果水平向左的線段與圖形的線段重合,則記爲2個交點(或者0個),水平向左的線段與圖形的線段的交點是圖形線段的端點的情況,這個端點是圖形線段的高點則交點加一(高點即線段兩點Y軸座標大的那個點),否則不加。

源代碼如下

 

package chu.anywhere;

import java.awt.geom.Line2D;
import java.awt.geom.Point2D;

 

public class TestPP {
 //判斷點在不在圖形內 (此圖形只能在正座標)
  Boolean IsPointInPolygon(Point2D P,Point2D[] V)
  {
   int count=0;
   Point2D p2=new Point2D.Double(-1,P.getY());
   Line2D l2=new Line2D.Double(p2,P);
   for(int j=0;j<V.length-1;j++)
   {
   if(PinL(P,new Line2D.Double(V[j],V[j+1]))) 
   {
    return true;
   }
   }
    if(PinL(P,new Line2D.Double(V[0],V[V.length-1]))) 
   {
    return true;
   }
   for(int i=0;i<V.length-1;i++)
   {
   //如果平行就忽略
    if(llll(l2,new Line2D.Double(V[i],V[i+1])))
    {
     
    }else//如果不平行就判斷線段是否相交
    {
     if(java.awt.geom.Line2D.linesIntersect(l2.getX1(),l2.getY1(),l2.getX2(),l2.getY2(),V[i].getX(),V[i].getY(),V[i+1].getX(),V[i+1].getY()))
     {
      if(p(l2,new Line2D.Double(V[i],V[i+1])))
      {
      if(high(l2,new Line2D.Double(V[i],V[i+1])))
      {
      count++;
      }
      }else{
       count++;
      }
     }
    }
   
    
   }
   if(llll(l2,new Line2D.Double(V[V.length-1],V[0])))
   {
    
   }else
   {
    if(java.awt.geom.Line2D.linesIntersect(l2.getX1(),l2.getY1(),l2.getX2(),l2.getY2(),V[V.length-1].getX(),V[V.length-1].getY(),V[0].getX(),V[0].getY()))
    {
     if(p(l2,new Line2D.Double(V[V.length-1],V[0])))
     {
     if(high(l2,new Line2D.Double(V[V.length-1],V[0])))
     {
     count++;
     }
     }else{
      count++;
     }
    }
   }
   if(count%2==1)
   {
    return true;
   }else
   {
    return false;
   }
   
   
   
  }
 //判斷點在不在直線上
  public boolean PinL(Point2D p1,Line2D l1)
  {
   if(((p1.getY()-l1.getY1())*(p1.getX()-l1.getX2()))==((p1.getX()-l1.getX1())*(p1.getY()-l1.getY2()))&&(((p1.getY()<=l1.getY1())&&(p1.getY()>=l1.getY2()))||((p1.getY()>=l1.getY1())&&(p1.getY()<=l1.getY2())))&&(((p1.getX()<=l1.getX1())&&(p1.getX()>=l1.getX2()))||((p1.getX()>=l1.getX1())&&(p1.getX()<=l1.getX2()))))
   {
    return true;
   }else
   {
    return false;
   }
  }
  //判斷兩個線段是否平行
  public boolean llll(Line2D l1,Line2D l2)
  {
   if(((l1.getY2()-l1.getY1())*(l2.getX2()-l2.getX1()))==((l1.getX2()-l1.getX1())*(l2.getY2()-l2.getY1())))
   {
    return true;
   }
   return false;
   
  }
  public boolean high(Line2D l1,Line2D l2)
  {
   if(l2.getY1()>l2.getY2())
   {
   if(Pequals(getcrossPoint(l1.getP1(),l1.getP2(),l2.getP1(),l2.getP2()),l2.getP1()))
   {
    return true;
   }
    
   }
   if(l2.getY1()<l2.getY2())
   {
   if(Pequals(getcrossPoint(l1.getP1(),l1.getP2(),l2.getP1(),l2.getP2()),l2.getP2()))
   {
    return true;
   }
    
   }
   
   return false;
   
  }
  //判斷兩個直線相交是不是端點
  public boolean p(Line2D l1,Line2D l2)
  {
   if(Pequals(getcrossPoint(l1.getP1(),l1.getP2(),l2.getP1(),l2.getP2()),l2.getP1()))
   {
    return true;
   }
   
   if(Pequals(getcrossPoint(l1.getP1(),l1.getP2(),l2.getP1(),l2.getP2()),l2.getP2()))
   {
    return true;
   }
   return false;
   
  }
  //返回兩個線段的交點
  public  Point2D getcrossPoint(Point2D p1,Point2D p2,Point2D q1,Point2D q2)
  {   double crossPointy;
   double tempLeft=(q2.getX()-q1.getX())*(p1.getY()-p2.getY())-(p2.getX()-p1.getX())*(q1.getY()-q2.getY());
   double temRight=(p1.getY()-q1.getY())*(p2.getX()-p1.getX())*(q2.getX()-q1.getX())+
   q1.getX()*(q2.getY()-q1.getY())*(p2.getX()-p1.getX())-p1.getX()*(p2.getY()-p1.getY())*(q2.getX()-q1.getX());
   double crossPointx;
   if(Pequals(p1,q1))
   {
    return p1;
   }
   if(Pequals(p1,q2))
   {
    return p1;
   }
   if(Pequals(p2,q1))
   {
    return p2;
   }
   if(Pequals(p2,q2))
   {
    return p2;
   }
   
   if(tempLeft==0)
   {
    if(LPequals(p1,new Line2D.Double(q1,q2)))
    {
     return p1;
    }else if(LPequals(p2,new Line2D.Double(q1,q2)))
    {
     return p2;
    }
    else
    {
     return null;
    }
   }else
   {
    crossPointx=temRight/tempLeft;
   }
   if(p2.getX()-p1.getX()==0)
   {
    crossPointy=q1.getY();
   }
   else{
    crossPointy=(p2.getY()-p1.getY())/(p2.getX()-p1.getX())*(crossPointx-p1.getX())+p1.getY();
   }
    
   Point2D crossPoint=new Point2D.Double.Double(crossPointx,crossPointy);
   return crossPoint;
 }
  //判斷點是不是直線的端點
  public boolean LPequals(Point2D p1,Line2D line2D)
  {
   if(Pequals(p1,line2D.getP1()))
   {
    return true;
   }else if(Pequals(p1,line2D.getP2()))
   {
    return true;
   }else{
    return false;
   }
  }
  //判斷兩點是否重合
  public  boolean Pequals(Point2D point,Point2D anotherPoint)
  {
   if(point.getX()==anotherPoint.getX()&&point.getY()==anotherPoint.getY())
   {
    return true;
   }
   return false;
  }
  public static void main(String[] args) {
   TestPP l3=new TestPP();
   //構造一個由(110,110),(150,150),(110,130),(150,130)圍城的封閉區域
   Point2D p1=new Point2D.Double(110,110);
   Point2D p2=new Point2D.Double(150,150);
   Point2D p3=new Point2D.Double(110,130);
   Point2D p4=new Point2D.Double(150,130);
   Point2D p5=new Point2D.Double(120,120);
   Point2D p6=new Point2D.Double(170,120);
    Point2D[] pszcopy=new Point2D[4];
    pszcopy[0]=p1;
    pszcopy[1]=p2;
    pszcopy[2]=p3;
    pszcopy[3]=p4;
    //判斷點p5在不在區域裏面
    if(l3.IsPointInPolygon(p5,pszcopy))
    {
      System.out.println("點在區域裏面 ");
    }else
    {
     System.out.println("點不在區域裏面 ");
    }
    //同理判斷點p6在不在 區域裏面
    if(l3.IsPointInPolygon(p6,pszcopy))
    {
      System.out.println("點在區域裏面 ");
    }else
    {
     System.out.println("點不在區域裏面 ");
    }
    
  }

}



代碼可以跑起來,裏面的方法有些與常規想法略有區別,那是因爲這個類在運算ArcGIS網格的時候,數據比較棘手,多了一些判斷,只是把情況考慮的更爲清楚,對需要判斷點在不在區域這個方法不影響,後續的我會發表ArcGIS網格計算的其他代碼,本人代碼不夠優化,希望有人指出,我會一一回復的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章