判断点在多边形内的多种写法.docx
- 文档编号:28102918
- 上传时间:2023-07-08
- 格式:DOCX
- 页数:22
- 大小:48.05KB
判断点在多边形内的多种写法.docx
《判断点在多边形内的多种写法.docx》由会员分享,可在线阅读,更多相关《判断点在多边形内的多种写法.docx(22页珍藏版)》请在冰豆网上搜索。
判断点在多边形内的多种写法
判断点在多边形内的多种写法(射线算法)
(2010-10-0917:
04:
24)
转载▼
标签:
计算几何
射线法
杂谈
分类:
经验总结
*******************************************
* 射线算法一 *
*******************************************
1. 已知点point(x,y)和多边形Polygon(x1,y1;x2,y2;….xn,yn;);
2. 以point为起点,以无穷远为终点作平行于X轴的直线line(x,y;-∞,y);
3. 循环取得(for(i=0;i 4. 同时判断point(x,y)是否在side上,如果是,则返回1(点在多边形 上),否则继续下面的判断; 5. 判断线side与line是否有交点,如果有则count++,否则,i++。 6. 判断交点的总数,如果为奇数则返回0(点在多边形内),偶数则返回2(点在多边形外)。 代码: constdoubleINFINITY=1e10; constdoubleESP=1e-5; constintMAX_N=1000; structPoint { doublex,y; }; structLineSegment { Pointpt1,pt2; }; typedefvector // 计算叉乘 |P0P1| × |P0P2| doubleMultiply(Pointp1,Pointp2,Pointp0) { return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y)); } // 判断线段是否包含点point boolIsOnline(Pointpoint,LineSegmentline) { return((fabs(Multiply(line.pt1,line.pt2,point)) ((point.x-line.pt1.x)*(point.x-line.pt2.x)<=0)&& ((point.y-line.pt1.y)*(point.y-line.pt2.y)<=0)); } // 判断线段相交 boolIntersect(LineSegmentL1,LineSegmentL2) { return((max(L1.pt1.x,L1.pt2.x)>=min(L2.pt1.x,L2.pt2.x))&& (max(L2.pt1.x,L2.pt2.x)>=min(L1.pt1.x,L1.pt2.x))&& (max(L1.pt1.y,L1.pt2.y)>=min(L2.pt1.y,L2.pt2.y))&& (max(L2.pt1.y,L2.pt2.y)>=min(L1.pt1.y,L1.pt2.y))&& (Multiply(L2.pt1,L1.pt2,L1.pt1)*Multiply(L1.pt2,L2.pt2,L1.pt1)>=0)&& (Multiply(L1.pt1,L2.pt2,L2.pt1)*Multiply(L2.pt2,L1.pt2,L2.pt1)>=0) ); } // 判断点在多边形内 boolInPolygon(constPolygon&polygon,Pointpoint) { intn=polygon.size(); intcount=0; LineSegmentline; line.pt1=point; line.pt2.y=point.y; line.pt2.x=-INFINITY; for(inti=0;i { // 得到多边形的一条边 LineSegmentside; side.pt1=polygon[i]; side.pt2=polygon[(i+1)%n]; if(IsOnline(point,side)) { return1; } // 如果side平行x轴则不作考虑 if(fabs(side.pt1.y-side.pt2.y) { continue; } if(IsOnline(side.pt1,line)) { if(side.pt1.y>side.pt2.y)count++; } elseif(IsOnline(side.pt2,line)) { if(side.pt2.y>side.pt1.y)count++; } elseif(Intersect(line,side)) { count++; } } if(count%2==1){return0;} else{return2;} } } ******************************************* * 射线算法二 * ******************************************* 本文是采用射线法判断点是否在多边形内的C语言程序。 多年前,我自己实现了这样一个算法。 但是随着时间的推移,我决定重写这个代码。 参考周培德的《计算几何》一书,结合我的实践和经验,我相信,在这个算法的实现上,这是你迄今为止遇到的最优的代码。 这是个C语言的小算法的实现程序,本来不想放到这里。 可是,当我自己要实现这样一个算法的时候,想在网上找个现成的,考察下来竟然一个符合需要的也没有。 我对自己大学读书时写的代码没有信心,所以,决定重新写一个,并把它放到这里,以飨读者。 也增加一下BLOG的点击量。 首先定义点结构如下: 以下是引用片段: typedefstruct { doublex,y; }vertex_t; 本算法里所指的多边形,是指由一系列点序列组成的封闭简单多边形。 它的首尾点可以是或不是同一个点(不强制要求首尾点是同一个点)。 这样的多边形可以是任意形状的,包括多条边在一条绝对直线上。 因此,定义多边形结构如下: 以下是引用片段: typedefstruct { intnum_vertices; vertex_t*vertex; }vertexlist_t; 为加快判别速度,首先计算多边形的外包矩形(rect_t),判断点是否落在外包矩形内,只有满足落在外包矩形内的条件的点,才进入下一步的计算。 为此,引入外包矩形结构rect_t和求点集合的外包矩形内的方法vertices_get_extent,代码如下: 以下是引用片段: typedefstruct { doublemin_x,min_y,max_x,max_y; }rect_t; voidvertices_get_extent(constvertex_t*vl,intnp, rect_t*rc) { inti; 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; } for(i=1;i { if(vl[i].x if(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)相交;以下是引用片段: staticintis_same(constvertex_t*l_start,constvertex_t*l_end, constvertex_t*p, constvertex_t*q) { doubledx=l_end->x-l_start->x; doubledy=l_end->y-l_start->y; doubledx1=p->x-l_start->x; doubledy1=p->y-l_start->y; doubledx2=q->x-l_end->x; doubledy2=q->y-l_end->y; return((dx*dy1-dy*dx1)*(dx*dy2-dy*dx2)>0? 1: 0); } staticintis_intersect(constvertex_t*s1_start,constvertex_t*s1_end, constvertex_t*s2_start,constvertex_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)内的程序: 以下是引用片段: intpt_in_poly(constvertex_t*vl,intnp, constvertex_t*v) { inti,j,k1,k2,c; rect_trc; vertex_tw; if(np<3) return0; vertices_get_extent(vl,np,&rc); if(v->x return0; w.x=rc.max_x+DBL_EPSILON; w.y=v->y; c=0; for(i=0;i { j=(i+1)%np; if(is_intersect(vl+i,vl+j,v,&w)) { C++; } elseif(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; } } returnc%2; } 判断点在多边形内的多种写法(射线算法) (2010-10-0917: 04: 24) 转载▼ 标签: 计算几何 射线法 杂谈 分类: 经验总结 ******************************************* * 射线算法一 * ******************************************* 1. 已知点point(x,y)和多边形Polygon(x1,y1;x2,y2;….xn,yn;); 2. 以point为起点,以无穷远为终点作平行于X轴的直线line(x,y;-∞,y); 3. 循环取得(for(i=0;i 4. 同时判断point(x,y)是否在side上,如果是,则返回1(点在多边形 上),否则继续下面的判断; 5. 判断线side与line是否有交点,如果有则count++,否则,i++。 6. 判断交点的总数,如果为奇数则返回0(点在多边形内),偶数则返回2(点在多边形外)。 代码: constdoubleINFINITY=1e10; constdoubleESP=1e-5; constintMAX_N=1000; structPoint { doublex,y; }; structLineSegment { Pointpt1,pt2; }; typedefvector // 计算叉乘 |P0P1| × |P0P2| doubleMultiply(Pointp1,Pointp2,Pointp0) { return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y)); } // 判断线段是否包含点point boolIsOnline(Pointpoint,LineSegmentline) { return((fabs(Multiply(line.pt1,line.pt2,point)) ((point.x-line.pt1.x)*(point.x-line.pt2.x)<=0)&& ((point.y-line.pt1.y)*(point.y-line.pt2.y)<=0)); } // 判断线段相交 boolIntersect(LineSegmentL1,LineSegmentL2) { return((max(L1.pt1.x,L1.pt2.x)>=min(L2.pt1.x,L2.pt2.x))&& (max(L2.pt1.x,L2.pt2.x)>=min(L1.pt1.x,L1.pt2.x))&& (max(L1.pt1.y,L1.pt2.y)>=min(L2.pt1.y,L2.pt2.y))&& (max(L2.pt1.y,L2.pt2.y)>=min(L1.pt1.y,L1.pt2.y))&& (Multiply(L2.pt1,L1.pt2,L1.pt1)*Multiply(L1.pt2,L2.pt2,L1.pt1)>=0)&& (Multiply(L1.pt1,L2.pt2,L2.pt1)*Multiply(L2.pt2,L1.pt2,L2.pt1)>=0) ); } // 判断点在多边形内 boolInPolygon(constPolygon&polygon,Pointpoint) { intn=polygon.size(); intcount=0; LineSegmentline; line.pt1=point; line.pt2.y=point.y; line.pt2.x=-INFINITY; for(inti=0;i { // 得到多边形的一条边 LineSegmentside; side.pt1=polygon[i]; side.pt2=polygon[(i+1)%n]; if(IsOnline(point,side)) { return1; } // 如果side平行x轴则不作考虑 if(fabs(side.pt1.y-side.pt2.y) { continue; } if(IsOnline(side.pt1,line)) { if(side.pt1.y>side.pt2.y)count++; } elseif(IsOnline(side.pt2,line)) { if(side.pt2.y>side.pt1.y)count++; } elseif(Intersect(line,side)) { count++; } } if(count%2==1){return0;} else{return2;} } } ******************************************* * 射线算法二 * ******************************************* 本文是采用射线法判断点是否在多边形内的C语言程序。 多年前,我自己实现了这样一个算法。 但是随着时间的推移,我决定重写这个代码。 参考周培德的《计算几何》一书,结合我的实践和经验,我相信,在这个算法的实现上,这是你迄今为止遇到的最优的代码。 这是个C语言的小算法的实现程序,本来不想放到这里。 可是,当我自己要实现这样一个算法的时候,想在网上找个现成的,考察下来竟然一个符合需要的也没有。 我对自己大学读书时写的代码没有信心,所以,决定重新写一个,并把它放到这里,以飨读者。 也增加一下BLOG的点击量。 首先定义点结构如下: 以下是引用片段: typedefstruct { doublex,y; }vertex_t; 本算法里所指的多边形,是指由一系列点序列组成的封闭简单多边形。 它的首尾点可以是或不是同一个点(不强制要求首尾点是同一个点)。 这样的多边形可以是任意形状的,包括多条边在一条绝对直线上。 因此,定义多边形结构如下: 以下是引用片段: typedefstruct { intnum_vertices; vertex_t*vertex; }vertexlist_t; 为加快判别速度,首先计算多边形的外包矩形(rect_t),判断点是否落在外包矩形内,只有满足落在外包矩形内的条件的点,才进入下一步的计算。 为此,引入外包矩形结构rect_t和求点集合的外包矩形内的方法vertices_get_extent,代码如下: 以下是引用片段: typedefstruct { doublemin_x,min_y,max_x,max_y; }rect_t; voidvertices_get_extent(constvertex_t*vl,intnp, rect_t*rc) { inti; 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; } for(i=1;i { if(vl[i].x if(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在
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 判断 多边形 多种 写法
![提示](https://static.bdocx.com/images/bang_tan.gif)