判斷點是否在多邊形內

有一個n邊形,頂點爲p1,p2,...,pn;給定一個已知點p,判斷p在此多邊形內還是外。

預備知識: 兩線段相交的定義,如果一條線段的兩端分別處在另一條線段的兩端,則此兩線段相交

判斷2點在線段的兩側可以用向量的叉乘實現!

基本步驟:

1,過p點垂直向上作一條射線

2,判斷此射線與n邊形n條邊的交點

3,把所有交點相加,如果是奇數則說明在多邊形內,否則在多邊形外

思路非常的簡單,另外說明一下幾種特殊的情況:

1,射線與多邊形的頂點相交;比如射線過多邊形的Pi點,則如果Pi-1和Pi+1在此射線的異側,此交點可以算一個,如果此兩點在射線的同側,則此交點不計。此結論非常簡單,畫個圖應該就能明白了

2,p點在多邊形的某一條邊上;也認爲p在多邊形中

3,p不在多邊形的邊上,但p的射線與多邊形的某一條邊重合;比如與Pi,Pi+1線段重合,則如果Pi-1和Pi+2在射線的兩側,此情況也算一個交點,否則此情況不計交點。跟一種的情況類似,畫個圖應該明白了!

順便提一下點在平面細圖中的判斷

平面細圖就是有m個多邊形構成,但任何兩個多邊形都沒有邊的相交,只有頂點的重合

這樣相當於就是調用m次點在多邊形中的算法

以上實現是非常簡單了,偶最近在看並行算法方面的東東,因此本篇主要是爲並行算法作準備的

還可參考:http://www.cppblog.com/w2001/archive/2007/09/06/31694.html
判斷點是否處於多邊形內的三種方法

1. 叉乘判別法 (只適用於凸多邊形)

想象一個凸多邊形,其每一個邊都將整個2D屏幕劃分成爲左右兩邊,連接每一邊的第一個端點和要測試的點得到一個矢量v,將兩個2維矢量擴展成3維的,然後將該邊與v叉乘,判斷結果3維矢量中Z分量的符號是否發生變化,進而推導出點是否處於凸多邊形內外。這裏要注意的是,多邊形頂點究竟是左手序還是右手序,這對具體判斷方式有影響。

2. 面積判別法 (只適用於凸多邊形)

第四點分別與三角形的兩個點組成的面積分別設爲S1,S2,S3,只要S1+S2+S3>原來的三角形面積就不在三角形範圍中.可以使用海倫公式 。推廣一下是否可以得到面向凸多邊形的算法?(不確定)

3. 角度和判別法 (適用於任意多邊形)

double angle = 0;
realPointList::iterator iter1 = points.begin();
for (realPointList::iterator iter2 = (iter1 + 1); iter2 < points.end(); ++iter1, ++iter2)
 {
   double x1 = (*iter1).x - p.x;  
   double y1 = (*iter1).y - p.y;  
   double x2 = (*iter2).x - p.x;
   double y2 = (*iter2).y - p.y;  
   angle += angle2D(x1, y1, x2, y2);
 }

if (fabs(angle - span::PI2) < 0.01) return true;
else return false;

另外,可以使用bounding box來加速。
if (p.x < (*iter)->boundingBox.left ||
   p.x > (*iter)->boundingBox.right ||
   p.y < (*iter)->boundingBox.bottom ||
   p.y > (*iter)->boundingBox.top) 。。。。。。

對於多邊形來說,計算bounding box非常的簡單。只需要把水平和垂直方向上的最大最小值找出來就可以了。

對於三角形:第四點分別與三角形的兩個點的交線組成的角度分別設爲j1,j2,j3,只要j1+j2+j3>360就不在三角形範圍中。

4. 水平/垂直交叉點數判別法
(適用於任意多邊形)

注意到如果從P作水平向左的射線的話,如果P在多邊形內部,那麼這條射線與多邊形的交點必爲奇數,如果P在多邊形外部,則交點個數必爲偶數(0也在內)。所以,我們可以順序考慮多邊形的每條邊,求出交點的總個數。還有一些特殊情況要考慮。假如考慮邊(P1,P2),
1)如果射線正好穿過P1或者P2,那麼這個交點會被算作2次,處理辦法是如果P的從座標與P1,P2中較小的縱座標相同,則直接忽略這種情況
2)如果射線水平,則射線要麼與其無交點,要麼有無數個,這種情況也直接忽略。
3)如果射線豎直,而P0的橫座標小於P1,P2的橫座標,則必然相交。
4)再判斷相交之前,先判斷P是否在邊(P1,P2)的上面,如果在,則直接得出結論:P再多邊形內部。

(引用 http://blog.sina.com.cn/s/blog_62986cd40100gjv2.html?retcode=0 )

實現:

語法:result=insidepolygon(Point *polygon,int N,Point p);
參數:
*polygon: 多邊形頂點數組
N: 多邊形頂點個數
p: 被判斷點
返回值: 0:點在多邊形內部;1:點在多邊形外部
注 意:  
  若p點在多邊形頂點或者邊上,返回值不確定,需另行判斷
  需要 math.h
源程序:  
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)

typedef struct {
    double x,y;
} Point;

int insidepolygon(Point *polygon,int N,Point p)
{
    int counter = 0;
    int i;
    double xinters;
    Point p1,p2;

    p1 = polygon[0];
    for (i=1;i<=N;i++) {
        p2 = polygon[i % N];
        if (p.y > MIN(p1.y,p2.y)) {
            if (p.y <= MAX(p1.y,p2.y)) {
                if (p.x <= MAX(p1.x,p2.x)) {
                    if (p1.y != p2.y) {
                        xinters = (p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
                        if (p1.x == p2.x || p.x <= xinters)
                            counter++;
                        }
                    }
                }
            }
            p1 = p2;
        }

    if (counter % 2 == 0)
        return(OUTSIDE);
    else
        return(INSIDE);
}

(引用:http://fengyan1974.blog.sohu.com/53913983.html)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章