一、判斷點在不在區域裏面方法
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網格計算的其他代碼,本人代碼不夠優化,希望有人指出,我會一一回復的。