1. 程式人生 > >[轉] 射線法判斷點是否在多邊形內(C#)

[轉] 射線法判斷點是否在多邊形內(C#)

//解題思想用射線法 //該題思想是向由點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;
}