C#判斷點(diǎn)的位置(區(qū)域內(nèi)或外)
C#判斷點(diǎn)的位置方法一
- 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ì)數(shù)器 j第二個(gè)點(diǎn)指針
- for (int i = 0; i < fencePnts.Length; i++)
- {//開始循環(huán)
- if (i == fencePnts.Length - 1)
- j = 0;//如果 循環(huán)到最后一點(diǎn) 第二個(gè)指針指向第一點(diǎn)
- else
- j = j + 1; //如果不是 ,則找下一點(diǎn)
- if (fencePnts[i].Y < = pnt1.Y) // 如果多邊形的點(diǎn) 小于等于 選定點(diǎn)的 Y 坐標(biāo)
- {
- if (fencePnts[j].Y > pnt1.Y) // 如果多邊形的下一點(diǎn) 大于于 選定點(diǎn)的 Y 坐標(biāo)
- {
- 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#判斷點(diǎn)的位置方法二——c#內(nèi)置函數(shù):
- 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);
- //返回判斷點(diǎn)是否在多邊形里
- bool myPoint= myRegion.IsVisible(inputponint);
- this.lblx.Text = myPoint.ToString();
圖形算法:
1,面積法。就是看所有邊和目標(biāo)點(diǎn)組成的三角形面積和是否等于總的多邊形面積,如果相等,則在內(nèi)部。反之在外部。這種方法計(jì)算量較大,用到的主要計(jì)算是查乘。
2,夾角和法。參見三樓,判斷所有邊和目標(biāo)點(diǎn)的夾角和是否為360度。計(jì)算量比上面這種方法稍微小點(diǎn),用到主要是點(diǎn)乘和求模計(jì)算。
3,引射線法。就是從該點(diǎn)出發(fā)引一條射線,看這條射線和所有邊的交點(diǎn)數(shù)目。如果有奇數(shù)個(gè)交點(diǎn),則說明在內(nèi)部,如果有偶數(shù)個(gè)交點(diǎn),則說明在外部。這是所有方法中計(jì)算量最小的方法,在光線追蹤算法中有大量的應(yīng)用。
在C#中的話,有一個(gè)Region類,可以直接調(diào)用IsVisible判斷是否在這個(gè)區(qū)域內(nèi)部,我估計(jì)內(nèi)部的實(shí)現(xiàn)應(yīng)該是上面說的第三種方法。主要看你的需求是哪種輸入了,如果在C#中,你完全可以用Region類來隱藏內(nèi)部實(shí)現(xiàn)。
C#判斷點(diǎn)的位置的另外一種解決方法:
1.已知點(diǎn)point(x,y)和多邊形Polygon(x1,y1;x2,y2;….xn,yn;);
2.以point為起點(diǎn),以無窮遠(yuǎn)為終點(diǎn)作平行于X軸的直線line(x,y; -∞,y);
3.循環(huán)取得(for(i=0;i< n;i++))多邊形的每一條邊side(xi,yi;xi+1,yi+1),且判斷是否平行于X軸,如果平行continue,否則,i++;
4. 同時(shí)判斷point(x,y)是否在side上,如果是,則返回1(點(diǎn)在多邊形
上),否則繼續(xù)下面的判斷;
5.判斷線side與line是否有交點(diǎn),如果有則count++,否則,i++。
6.判斷交點(diǎn)的總數(shù),如果為奇數(shù)則返回0(點(diǎn)在多邊形內(nèi)),偶數(shù)則返回2(點(diǎn)在多邊形外)。
代碼:
- /* 射線法判斷點(diǎn)q與多邊形polygon的位置關(guān)系,要求polygon為簡(jiǎn)單多邊形,頂點(diǎn)逆時(shí)針排列
- 如果點(diǎn)在多邊形內(nèi): 返回0
- 如果點(diǎn)在多邊形邊上: 返回1
- 如果點(diǎn)在多邊形外: 返回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;
- // 計(jì)算叉乘 |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) );
- }
- // 判斷線段是否包含點(diǎn)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)
- );
- }
- // 判斷點(diǎn)在多邊形內(nèi)
- 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;}
- }
- }
【編輯推薦】