c语言实现点在多边形内部,C语言中实现 点在多边形内 算法
來源:
天極網
作者:
若水
2008-05-15/01:29
本文是采用射線法判斷點是否在多邊形內的C語言程序。多年前,我自己實現了這樣一個算法。但是隨著時間的推移,我決定重寫這個代碼。參考周培德的《計算幾何》一書,結合我的實踐和經驗,我相信,在這個算法的實現上,這是你迄今為止遇到的最優的代碼。
這是個C語言的小算法的實現程序,本來不想放到這里。可是,當我自己要實現這樣一個算法的時候,想在網上找個現成的,考察下來竟然一個符合需要的也沒有。我對自己大學讀書時寫的代碼沒有信心,所以,決定重新寫一個,并把它放到這里,以饗讀者。也增加一下BLOG的點擊量。
首先定義點結構如下:
以下是引用片段:
/*?Vertex?structure?*/
typedef?struct
{
double?x,?y;
}?vertex_t;
本算法里所指的多邊形,是指由一系列點序列組成的封閉簡單多邊形。它的首尾點可以是或不是同一個點(不強制要求首尾點是同一個點)。這樣的多邊形可以是任意形狀的,包括多條邊在一條絕對直線上。因此,定義多邊形結構如下:
以下是引用片段:
/*?Vertex?list?structure?–?polygon?*/
typedef?struct
{
int?num_vertices;?/*?Number?of?vertices?in?list?*/
vertex_t?*vertex;?/*?Vertex?array?pointer?*/
}?vertexlist_t;
為加快判別速度,首先計算多邊形的外包矩形(rect_t),判斷點是否落在外包矩形內,只有滿足落在外包矩形內的條件的點,才進入下一步的計算。為此,引入外包矩形結構rect_t和求點集合的外包矩形內的方法vertices_get_extent,代碼如下:
以下是引用片段:
/*?bounding?rectangle?type?*/
typedef?struct
{
double?min_x,?min_y,?max_x,?max_y;
}?rect_t;
/*?gets?extent?of?vertices?*/
void?vertices_get_extent?(const?vertex_t*?vl,?int?np,?/*?in?vertices?*/
rect_t*?rc?/*?out?extent*/?)
{
int?i;
if?(np?>?0){
rc->min_x?=?rc->max_x?=?vl[0].x;?rc->min_y?=?rc->max_y?=?vl[0].y;
}else{
rc->min_x?=?rc->min_y?=?rc->max_x?=?rc->max_y?=?0;?/*?=0???no?vertices?at?all?*/
}
for(i=1;?i
{
if(vl[i].x?min_x)?rc->min_x?=?vl[i].x;
if(vl[i].y?min_y)?rc->min_y?=?vl[i].y;
if(vl[i].x?>?rc->max_x)?rc->max_x?=?vl[i].x;
if(vl[i].y?>?rc->max_y)?rc->max_y?=?vl[i].y;
}
}
當點滿足落在多邊形外包矩形內的條件,要進一步判斷點(v)是否在多邊形(vl:np)內。本程序采用射線法,由待測試點(v)水平引出一條射線B(v,w),計算B與vl邊線的交點數目,記為c,根據奇內偶外原則(c為奇數說明v在vl內,否則v不在vl內)判斷點是否在多邊形內。
具體原理就不多說。為計算線段間是否存在交點,引入下面的函數:
(1)is_same判斷2(p、q)個點是(1)否(0)在直線l(l_start,l_end)的同側;
(2)is_intersect用來判斷2條線段(不是直線)s1、s2是(1)否(0)相交;
#p#分頁標題#e#以下是引用片段:
/*?p,?q?is?on?the?same?of?line?l?*/
static?int?is_same(const?vertex_t*?l_start,?const?vertex_t*?l_end,?/*?line?l?*/
const?vertex_t*?p,
const?vertex_t*?q)
{
double?dx?=?l_end->x?-?l_start->x;
double?dy?=?l_end->y?-?l_start->y;
double?dx1=?p->x?-?l_start->x;
double?dy1=?p->y?-?l_start->y;
double?dx2=?q->x?-?l_end->x;
double?dy2=?q->y?-?l_end->y;
return?((dx*dy1-dy*dx1)*(dx*dy2-dy*dx2)?>?0??1?:?0);
}
/*?2?line?segments?(s1,?s2)?are?intersect??*/
static?int?is_intersect(const?vertex_t*?s1_start,?const?vertex_t*?s1_end,
const?vertex_t*?s2_start,?const?vertex_t*?s2_end)
{
return?(is_same(s1_start,?s1_end,?s2_start,?s2_end)==0?&&
is_same(s2_start,?s2_end,?s1_start,?s1_end)==0)??1:?0;
}
下面的函數pt_in_poly就是判斷點(v)是(1)否(0)在多邊形(vl:np)內的程序:
以下是引用片段:
int?pt_in_poly?(?const?vertex_t*?vl,?int?np,?/*?polygon?vl?with?np?vertices?*/
const?vertex_t*?v)
{
int?i,?j,?k1,?k2,?c;
rect_t?rc;
vertex_t?w;
if?(np?
return?0;
vertices_get_extent(vl,?np,?&rc);
if?(v->x?x?>?rc.max_x?||?v->y?y?>?rc.max_y)
return?0;
/*?Set?a?horizontal?beam?l(*v,?w)?from?v?to?the?ultra?right?*/
w.x?=?rc.max_x?+?DBL_EPSILON;
w.y?=?v->y;
c?=?0;?/*?Intersection?points?counter?*/
for(i=0;?i
{
j?=?(i+1)?%?np;
if(is_intersect(vl+i,?vl+j,?v,?&w))
{
c++;
}
else?if(vl[i].y==w.y)
{
k1?=?(np+i-1)%np;
while(k1!=i?&&?vl[k1].y==w.y)
k1?=?(np+k1-1)%np;
k2?=?(i+1)%np;
while(k2!=i?&&?vl[k2].y==w.y)
k2?=?(k2+1)%np;
if(k1?!=?k2?&&?is_same(v,?&w,?vl+k1,?vl+k2)==0)
c++;
if(k2?<=?i)
break;
i?=?k2;
}
}
return?c%2;
}
本想配些插圖說明問題,但是,CSDN的文章里放圖片我還沒用過。以后再試吧!實踐證明,本程序算法的適應性極強。但是,對于點正好落在多邊形邊上的極端情形,有可能得出2種不同的結果。
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的c语言实现点在多边形内部,C语言中实现 点在多边形内 算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 农商银行交社保流程
- 下一篇: c语言双链表是什么意思,双链表的表示和实