判斷點在多邊形內部

2021-06-05 02:58:13 字數 4027 閱讀 7466

微博:

文中所指的多邊形均為凸多邊形,一些描述可能有誤,歡迎指正。

在開始之前,我們需要先構建好測試環境。

我構建了乙個比較特殊的多邊形,如下。

從最上面的頂點順時針座標(螢幕座標系)分別為:(40,10) (60,30)(60,50) (20,50) (20,30)

根據對多邊形的了解,我們可以得出如下結論:

如果乙個點在多邊形內部,任意角度做射線肯定會與多邊形要麼有乙個交點,要麼有與多邊形邊界線重疊。

如果乙個點在多邊形外部,任意角度做射線要麼與多邊形有乙個交點,要麼有兩個交點,要麼沒有交點,要麼有與多邊形邊界線重疊。

利用上面的結論,我們只要判斷這個點與多邊形的交點個數,就可以判斷出點與多邊形的位置關係了。

首先羅列下注意事項:

l 射線跟多邊形的邊界線重疊的情況

l 區別內部點和外部點的射線在有乙個交點時的情況

對於第乙個注意事項,可以將射線角度設為零度,這樣子只需要判斷兩個相鄰頂點的y

值是否相等即可。然後再判斷這個點的

x值方位。

對於第二個注意事項,網上許多文章都說到做射線以後交點為奇數則表示在多邊形內部,這是乙個錯誤的觀點,不僅對於凹多邊形不成立,對於凸多邊形也不成立。

例如:從外部點做射線剛好經過一頂點,這樣子交點個數就為奇數,但是該點卻不在多邊形內部。

至於要如何區分這兩種情況呢,我能想到了乙個不完美的方法,外部點的射線跟多邊形有乙個交點的時候,該交點肯定為頂點,如果該射線上移一位或者下移一位,要麼變成有兩個交點要麼沒有交點。當然為了安全起見,這裡把射線盡量往相鄰點中心移動。這樣子就能夠判斷出是外部點的射線跟多邊形有乙個交點。

不過這個方法並不完美,因為有了移位操作,可能會把內部點移動出外部。而且如果判斷點在(60,30)位置,判斷的時候先遇到

(20,30)

,然後移位操作,就判斷就出錯了。

為了解決這些問題,我在起初先掃瞄一次判斷點是否在頂點上雖然影響了一點效率,而且當判定點距離多邊形乙個單位時,判斷可能會有誤。不過只要不是需要高精度的話,這個方法還是很有效的。

**如下:

bool insidepolygon1( pointd *polygon,int n,pointd pt )

}while (redo)}}

else

if ( pt.y == polygon[i].y)

}else

if ( polygon[i].y == polygon[j].y && //

在水平的邊界線上

pt.y == polygon[i].y &&

( (polygon[i].x < pt.x && pt.x < polygon[j].x) ||

(polygon[j].x < pt.x && pt.x < polygon[i].x) ) )}}

return inside;

}

複製**

角度和判別法就是判定點與多邊形所有相鄰頂點組成的角的角度和來判斷點與多邊形的位置關係。

如果點在多邊形內部,只要該點不在邊界線或者頂點上,則角度和為三百六十度。

如果在邊界線上,則角度和為一百八十度。

如果點在多邊形外部,則角度和無法達到三百六十度。但是角度和可能會達到一百八十度,比如判斷點在(60,10)。

**如下:

//

根據需要不判斷頂點

bool ispointinline( const pointd &pt,const pointd &pt1,const pointd &pt2 )

else

if (pt.x == pt1.x &&

pt1.x == pt2.x &&

((pt1.y < pt.y && pt.y < pt2.y) ||

(pt2.y < pt.y && pt.y < pt1.y)) )

else

if ( ((pt1.y < pt.y && pt.y < pt2.y) ||

(pt2.y < pt.y && pt.y < pt1.y)) &&

((pt1.x < pt.x && pt.x < pt2.x) ||

(pt2.x < pt.x && pt.x < pt1.x)) )

}return inside;

}bool insidepolygon2( pointd *polygon,int n,pointd p )

else

if (ispointinline(p,polygon[i],polygon[j])) //

是否在邊界線上

double x1,y1,x2,y2;

x1 = polygon[i].x - p.x;

y1 = polygon[i].y - p.y;

x2 = polygon[j].x - p.x;

y2 = polygon[j].y - p.y;

double radian = atan2(y1,x1) - atan2(y2,x2);

radian = abs(radian);

if (radian > m_pi) radian = 2* m_pi - radian;

angle += radian; //

計算角度和

}if ( fabs(6.28318530717958647692 - angle) < 1e-7 )

inside = true;

return inside;

}

複製**

有的人管角度和判別法叫做轉角法,還有乙個類似的方法叫弧長法。

根據角度和判別法,我們可以繼續演化,可以得出如下結論:

如果乙個點在多邊形內部,該點與多邊形所有相鄰頂點組成的三角形面積和為多邊形面積。反之不成立。

求三角形面積:

已知三角形a

(x1,y1)b

(x2,y2)c

(x3,y3

),則面積公式為:

|x1  x2  x3|   

s(a,b,c) = |y1  y2  y3| * 0.5 (當三點為逆時針時為正,順時針則為負的

)   

|1   1   1 |  

= ( x1*y2 - x1*y3 - x2*y1 + x2*y3 + x3*y1 - x3*y2 ) * 0.5

求多邊形面積:

根據上面求三角形的方法,

已知多邊形a1a2a3...an

(順或逆時針都可以),設平面上有任意的一點

p,則面積公式為:   

s(a1,a2,a3...an)   

=  s(p,a1,

a2)+ s(p,a2

,a3)+...+s(p,an,a1)

既然p是可以任取,為了方便用

(0,0)

好了。

**如下:

bool insidepolygon3( pointd *polygon,int n,pointd pt )

trigon_area *= 0.5;

polygon_area = abs(polygon_area * 0.5);

if ( fabs(trigon_area - polygon_area) < 1e-7 )

inside = true;

return inside;

}

複製**

多邊形面積計算

行列式如何展開

經網友glshader

提示,新增了這個方法。

如果判斷點在所有邊界線的同側,就能判定該點在多邊形內部。

判斷方法就是判斷兩條同起點射線斜率差。

**如下:

bool insidepolygon4( pointd *polygon,int n,pointd p )

if (0 == count1 ||

0 == count2)

return inside;

}

複製**

總結了四種判別法,雖然很多原理都很簡單,但是實際操作起來,發現很多細節還是值得推敲的。

判斷點在多邊形內部

用的是射線法,我的 取的是向右的射線 這題沒有點在邊上的情況,但是還是要考慮很多 比如射線覆蓋邊,射線交短點的情況,為了區分各種狀況 我分成了6中相交情況 唉 有點多了 不過比較清晰 不知道別人是怎麼做的 include struct edge struct point 儲存邊 edge e 105...

判斷點在多邊形內部

文中所指的多邊形均為凸多邊形,一些描述可能有誤,歡迎指正。在開始之前,我們需要先構建好測試環境。我構建了乙個比較特殊的多邊形,如下。從最上面的頂點順時針座標 螢幕座標系 分別為 40,10 60,30 60,50 20,50 20,30 根據對多邊形的了解,我們可以得出如下結論 如果乙個點在多邊形內...

判斷點在多邊形內演算法

點和多邊形關係的演算法實現 好了,現在我們已經了解了向量叉積的意義,以及判斷直線段是否有交點的演算法,現在回過頭看看文章開始部分的討論的問題 如何判斷乙個點是否在多邊形內部?根據射線法的描述,其核心是求解從p點發出的射線與多邊形的邊是否有交點。注意,這裡說的是射線,而我們前面討論的都是線段,好像不適...