[轉] 射線法判斷點是否在多邊形內(C#)
阿新 • • 發佈:2019-01-09
//解題思想用射線法
//該題思想是向由點P向x正方向發射一個射線,穿過多邊形線段上的個數為奇數則在多邊形內,偶數則在多邊形外
//具體方法是:點的Y值大於等於多邊形上某個線段的最小值且小於該線段上的最大值,在該線段上取一個y值為點P.y的點P1。如果P.x<P1.x ,則計數器加1,若計數器為奇數則在多邊形內,若為偶數則在多邊形外
private bool PointInFences(point pnt1, point[] fencePnts)
{
int j=0, cnt = 0;
for (int i = 0; i < fencePnts.Length; i++)
{
j = (i == fencePnts.Length - 1) ? 0 : j + 1;
if ((fencePnts[i].y!=fencePnts[j].y)&&(((pnt1.y >= fencePnts[i].y) && (pnt1.y < fencePnts[j].y)) || ((pnt1.y >= fencePnts[j].y) && (pnt1.y < fencePnts[i].y))) && (pnt1.x < (fencePnts[j].x - fencePnts[i].x) * (pnt1.y - fencePnts[i].y) / (fencePnts[j].y
- fencePnts[i].y) + fencePnts[i].x)) cnt++;
}
return (cnt%2>0)?true:false;
}
我的一哥們寫的比較精煉的一個小程式。原程式沒有考慮到點P與多邊形上的某個平行x軸的線段的兩個端點三點共線問題。我加了一個先決判斷條件就是到線段不平行於x軸。 該方法構思巧妙: 1、向X軸正方向發射射線,先判斷是否與多邊形的線段相交,若相交點的X值大於P的x值,則計數器加1. 2、通過大於等於線段兩個端點的最小Y值,小於線段兩個端點的最大Y值,判斷出射線與線段是否相交。——避免了P線上段的延長線上的情況對計算結果的困擾。 順便用javascript重寫了一下,當點在邊上的時候也算在圖形內: function checkPoint(curPoint, points) {
//
var counter = 0;
for (var i = 0, p1, p2; i < points.length; i++) {
p1 = points[i];
p2 = points[(i + 1) % points.length];
if (p1.y == p2.y) {
continue;
}
if (curPoint.y <= Math.min(p1.y, p2.y)) {
continue;
}
if (curPoint.y >= Math.max(p1.y, p2.y)) {
continue;
}
var x = (curPoint.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
if (x > curPoint.x) counter++;
}
return counter % 2;
}
我的一哥們寫的比較精煉的一個小程式。原程式沒有考慮到點P與多邊形上的某個平行x軸的線段的兩個端點三點共線問題。我加了一個先決判斷條件就是到線段不平行於x軸。 該方法構思巧妙: 1、向X軸正方向發射射線,先判斷是否與多邊形的線段相交,若相交點的X值大於P的x值,則計數器加1. 2、通過大於等於線段兩個端點的最小Y值,小於線段兩個端點的最大Y值,判斷出射線與線段是否相交。——避免了P線上段的延長線上的情況對計算結果的困擾。 順便用javascript重寫了一下,當點在邊上的時候也算在圖形內: function checkPoint(curPoint, points) {
//
var counter = 0;
for (var i = 0, p1, p2; i < points.length; i++) {
p1 = points[i];
p2 = points[(i + 1) % points.length];
if (p1.y == p2.y) {
continue;
}
if (curPoint.y <= Math.min(p1.y, p2.y)) {
continue;
}
if (curPoint.y >= Math.max(p1.y, p2.y)) {
continue;
}
var x = (curPoint.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
if (x > curPoint.x) counter++;
}
return counter % 2;
}