JAVA射线_用射线法实现判断点是否在多边形内部
最近工作中遇到了這個問題,檢索之后發現這種實現方式挺有意思的,無論是凸多邊形還是凹多邊形都可以判斷。
射線法是用被測點向任意方向(通常為了好算,使其射向右側)做一條射線,判斷射線與多邊形的交點。如果交點的數量為奇數,則被測點在多邊形內;如果交點的數量為偶數,則被測點在多邊形以外。
期間,有些特殊情況需要判斷,比如:
1. 射線剛好經過凸多邊形兩條相鄰邊的交點上的情況會導致重復判斷;
2.射線和多邊形的邊重合的情況。
先上js代碼。
functionisDotInPolygon(point, polygonPoints) {var flag = false,
p1,
p2;for(var i = 0, j = polygonPoints.length - 1; i < polygonPoints.length; j = i++) {
p1=polygonPoints[i];
p2=polygonPoints[j];//這里判斷是否剛好被測點在多邊形的邊上
if(isDotInLineSegment(point, p1, p2)) return true;if((p1.y > point.y != p2.y > point.y) && (point.x < (point.y - p1.y) * (p1.x - p2.x) / (p1.y - p2.y) +p1.x)) {
flag= !flag;
}
}returnflag;
}
判斷點是否在線段上的 isDotInLineSegment 的函數我懶得寫了,這個很好實現。
關鍵點在于判斷射線與多邊形邊相交的部分,這段代碼原理不是我想出來的,它實現的方式很是精妙。
首先咱們看 表達式1:? p1.y > point.y != p2.y > point.y
表面上看,表達式1是用了一個類似于異或的判斷,要求被測點的y坐標在循環中多邊形當前邊的y軸投影范圍內;
它其實還隱藏了另外一層條件,可以過濾掉前面提到的特殊情況1 和 2。 舉個例子,多邊形相鄰的倆個邊所在線段(p1, p2)和 (p2, p3),為了解釋方便,咱們假設其中p3.y > p2.y > p1.y。 如果從被測點發射出來的射線經過了p2 ,那么上面這段表達式1其實在判斷(p1, p2)時為false,判斷(p2, p3)時為true,這樣就巧妙地避免了重復計數的問題。? ?而如果是個凹多邊形,存在p3.y >?p2.y < p1.y , 那么表達式1 在判斷(p1, p2)與(p2, p3)時都為true, 可以正確地計數兩次。
然后看 表達式2 :?point.x < (point.y - p1.y) * (p1.x - p2.x) / (p1.y - p2.y) + p1.x
同樣為了解釋方便,咱們假設其中p2.y >?point.y > p1.y, 表達式2 等同于 (point.x - p1.x) /?(point.y - p1.y) < (p1.x - p2.x) / (p1.y - p2.y)? ,其中??(p1.x - p2.x) / (p1.y - p2.y) 可以理解為是線段(p1, p2)斜率的倒數,?(point.x - p1.x) /?(point.y - p1.y) 則是線段 (p1, point) 斜率的倒數。如果線段(p1, p2)的斜率的倒數要大于線段 (p1, point) 的斜率的倒數,則點point就只能在線段(p1, p2)的左側。這樣就確保了射線與線段(p1, p2)的相交。
這段看起來有點復雜,其實拿動筆畫一畫就很容易明白(沒錯,我又懶得上圖了)。
總結
以上是生活随笔為你收集整理的JAVA射线_用射线法实现判断点是否在多边形内部的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OPENGL 射线拾取法
- 下一篇: 射线