方法一 算法 : public int isLeft(Point P0, Point P1,Point P2)
{
int abc= ((P1.X - P0.X) * (P2.Y - P0.Y) - (P2.X - P0.X) * (P1.Y - P0.Y));
return abc;
}
private bool PointInFences(Point pnt1, Point[] fencePnts)
{
int wn = 0,j=0; //wn 計數器 j第二個點指針
for (int i = 0; i < fencePnts.Length; i++)
{//開始循環
if (i == fencePnts.Length - 1)
j = 0;//如果 循環到最后一點 第二個指針指向第一點
else
j = j + 1; //如果不是 ,則找下一點
if (fencePnts[i].Y <= pnt1.Y) // 如果多邊形的點 小於等於 選定點的 Y 坐標
{
if (fencePnts[j].Y > pnt1.Y) // 如果多邊形的下一點 大於於 選定點的 Y 坐標
{
if (isLeft(fencePnts[i], fencePnts[j], pnt1) > 0)
{
wn++;
}
}
}
else
{
if (fencePnts[j].Y <= pnt1.Y)
{
if (isLeft(fencePnts[i], fencePnts[j], pnt1) < 0)
{
wn--;
}
}
}
}
if (wn == 0)
return false;
else
return true;
}
方法二 c#內置函數:
GraphicsPath myGraphicsPath = new GraphicsPath();
Region myRegion=new Region();
myGraphicsPath.Reset();
Point inputponint = new Point(inputx, inputy);
myGraphicsPath.AddPolygon(points);//points);
myRegion.MakeEmpty();
myRegion.Union(myGraphicsPath);
//返回判斷點是否在多邊形里
bool myPoint= myRegion.IsVisible(inputponint);
this.lblx.Text = myPoint.ToString();
圖形算法:
1,面積法。就是看所有邊和目標點組成的三角形面積和是否等於總的多邊形面積,如果相等,則在內部。反之在外部。這種方法計算量較大,用到的主要計算是查乘。
2,夾角和法。參見三樓,判斷所有邊和目標點的夾角和是否為360度。計算量比上面這種方法稍微小點,用到主要是點乘和求模計算。
3,引射線法。就是從該點出發引一條射線,看這條射線和所有邊的交點數目。如果有奇數個交點,則說明在內部,如果有偶數個交點,則說明在外部。這是所有方法中計算量最小的方法,在光線追蹤算法中有大量的應用。
在C#中的話,有一個Region類,可以直接調用IsVisible判斷是否在這個區域內部,我估計內部的實現應該是上面說的第三種方法。主要看你的需求是哪種輸入了,如果在C#中,你完全可以用Region類來隱藏內部實現。
另外一種解決方法:
1. 已知點point(x,y)和多邊形Polygon(x1,y1;x2,y2;….xn,yn;);
2. 以point為起點,以無窮遠為終點作平行於X軸的直線line(x,y; -∞,y);
3. 循環取得(for(i=0;i<n;i++))多邊形的每一條邊side(xi,yi;xi+1,yi+1),且判斷是否平行於X軸,如果平行continue,否則,i++;
4. 同時判斷point(x,y)是否在side上,如果是,則返回1(點在多邊形
上),否則繼續下面的判斷;
5. 判斷線side與line是否有交點,如果有則count++,否則,i++。
6. 判斷交點的總數,如果為奇數則返回0(點在多邊形內),偶數則返回2(點在多邊形外)。
代碼:
/*射線法判斷點q與多邊形polygon的位置關系,要求polygon為簡單多邊形,頂點逆時針排列
如果點在多邊形內:返回0
如果點在多邊形邊上:返回1
如果點在多邊形外:返回2
*/
const double INFINITY = 1e10;
const double ESP = 1e-5;
const int MAX_N = 1000;
struct Point {
double x, y;
};
struct LineSegment {
Point pt1, pt2;
};
typedef vector<Point> Polygon;
//計算叉乘|P0P1|×|P0P2|
double Multiply(Point p1, Point p2, Point p0)
{
return ( (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y) );
}
//判斷線段是否包含點point
bool IsOnline(Point point, LineSegment line)
{
return( ( fabs(Multiply(line.pt1, line.pt2, point)) < ESP ) &&
( ( point.x - line.pt1.x ) * ( point.x - line.pt2.x ) <= 0 ) &&
( ( point.y - line.pt1.y ) * ( point.y - line.pt2.y ) <= 0 ) );
}
//判斷線段相交
bool Intersect(LineSegment L1, LineSegment L2)
{
return( (max(L1.pt1.x, L1.pt2.x) >= min(L2.pt1.x, L2.pt2.x)) &&
(max(L2.pt1.x, L2.pt2.x) >= min(L1.pt1.x, L1.pt2.x)) &&
(max(L1.pt1.y, L1.pt2.y) >= min(L2.pt1.y, L2.pt2.y)) &&
(max(L2.pt1.y, L2.pt2.y) >= min(L1.pt1.y, L1.pt2.y)) &&
(Multiply(L2.pt1, L1.pt2, L1.pt1) * Multiply(L1.pt2, L2.pt2, L1.pt1) >= 0) &&
(Multiply(L1.pt1, L2.pt2, L2.pt1) * Multiply(L2.pt2, L1.pt2, L2.pt1) >= 0)
);
}
//判斷點在多邊形內
bool InPolygon(const Polygon& polygon, Point point)
{
int n = polygon.size();
int count = 0;
LineSegment line;
line.pt1 = point;
line.pt2.y = point.y;
line.pt2.x = - INFINITY;
for( int i = 0; i < n; i++ ) {
//得到多邊形的一條邊
LineSegment side;
side.pt1 = polygon[i];
side.pt2 = polygon[(i + 1) % n];
if( IsOnline(point, side) ) {
return1 ;
}
//如果side平行x軸則不作考慮
if( fabs(side.pt1.y - side.pt2.y) < ESP ) {
continue;
}
if( IsOnline(side.pt1, line) ) {
if( side.pt1.y > side.pt2.y ) count++;
} else if( IsOnline(side.pt2, line) ) {
if( side.pt2.y > side.pt1.y ) count++;
} else if( Intersect(line, side) ) {
count++;
}
}
if ( count % 2 == 1 ) {return 0;}
else { return 2;}
}
}
