数学基础计算几何算法实现_第1页
数学基础计算几何算法实现_第2页
数学基础计算几何算法实现_第3页
数学基础计算几何算法实现_第4页
数学基础计算几何算法实现_第5页
已阅读5页,还剩8页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、计算几何几何函数库导引1.2.3.常量定义和包含文件基本数据结构精度控制 点的基本运算 1.2.3.4.5.6.7.平面上两点之间距离判断两点是否重合 矢量叉乘矢量点乘判断点是否段上求一点饶某点旋转后的坐标求矢量夹角 线段及直线的基本运算 1.2.3.4.5.6.7.8.9.点与线段的关系求点到线段所在直线垂线的垂足点到线段的最近点点到线段所在直线的距离点到折线集的最近距离 判断圆是否在多边形内 求矢量夹角余弦求线段之间的夹角判断线段是否相交判断线段是否相交但不交在端点处求点关于某直线的对称点判断两条直线是否相交及求直线交点判断线段是否相交,如果相交返回交点 多边形常用算法模块 1.2.3.4

2、.5.7.8.9.判断多边形是否简单多边形检查多边形顶点的凸凹性 判断多边形是否凸多边形 求多边形面积判断多边形顶点的排列方向射判断点是否在多边形内判断点是否在凸多边形内寻找点集的 graham 算法10.寻找点集凸包的卷法凸包 MelkMan 算法的实现凸多边形的直径求凸多边形的重心=导引/* 需要包含的头文件 */#include /* 常量定义 */const double INF = 1E200; const double EP = 1E-10;constMAXV = 300;const doubl= 3.14159265;/* 基本几何结构 */struct POdouble x;

3、double y;PO(double a=0, doub=0) x=a; y=b;struct LIPO PO LI LI;/ 直线的struct LINEGs;e;G(PO G() a, POb) s=a; e=b;方程 a*x+b*y+c=0为表示,约定 a= 0double a;doub;double c;LINE(double d1=1, double d2=-1, double d3=0) a=d1; b=d2; c=d3;/线段树struct LINETREE/浮点误差的处理dblcmp(double d)ibs(d)0) ?1 :-1 ;点的基本运算/ 返回两点之间欧氏距离dou

4、ble dist(POp1,POp2)return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) );/ 判断两个点是否重合bool equal_po(POp1,POp2)return ( (abs(p1.x-p2.x)EP)&(abs(p1.y-p2.y)0:sp 在矢量 op ep 的顺时针方向;r=0:op sp ep 三点共线;r0: sp 在矢量 op ep 的逆时针方向 */double multiply(POsp,POep,POop)return(sp.x-op.x)*(ep.y-op.y) - (ep.x-op

5、.x)*(sp.y-op.y);double amultiply(POsp,POep,POop)return fabs(sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y);/*矢量(p1-op)和(p2-op)的点积r=dotmultiply(p1,p2,op),得到矢量(p1-op)和(p2-op)的点积如果两个矢量都非零矢量r 0:两矢量夹角为钝角 */double dotmultiply(POp1,POp2,POp0)return (p1.x-p0.x)*(p2.x-p0.x) + (p1.y-p0.y)*(p2.y-p0.y);/* 判断点p

6、是否段 l 上条件:(p段 l 所在的直线上)& (点 p 在以线段 l 为对角线的矩形内) */bool online(LIG l,POp)return (multiply(l.e,p,l.s)=0)& ( ( (p.x-l.s.x) * (p.x-l.e.x) =0 ) & ( (p.y-l.s.y)*(p.y-l.e.y) =1.0 ) return 0;if (cosfi 0) return fi;/ 说明矢量 os 在矢量 oe 的顺时针方向return -fi;线段及直线的基本运算/* 判断点C段 AB 所在的直线 l 上垂足 P 的与线段 AB 的关系本函数是根据下面的公式写的,

7、P 是点 C 到线段 AB 所在直线的垂足AC dot ABr =|AB|2(Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)=L2r has the following meaning:r=0 r=1 r1 0r1P = A P = BP is on the backward exten P is on the forward extenP iserior to ABof AB of AB*/double relation(POc,LIG l)LItl.s=l.s; tl.e=c;G tl;return dotmultiply(tl.e,l.e,l.s)/(dist(l.s,l.

8、e)*dist(l.s,l.e);/ 求点 C 到线段 AB 所在直线的垂足 PPOpendicular(POp,LIG l)double r=relation(p,l);POtp;tp.x=l.s.x+r*(l.e.x-l.s.x);tp.y=l.s.y+r*(l.e.y-l.s.y); return tp;/* 求点 p 到线段 l 的最短距离返回线段上距该点最近的点 np注意:np 是线段 l 上到点 p 最近的点,不一定是垂足*/double ptoligdist(POp,LIG l,PO&np)double r=relation(p,l); if(r1)np=l.e;return d

9、ist(p,l.e);np=pendicular(p,l);return dist(p,np);/ 求点 p 到线段 l 所在直线的距离/请注意本函数与上个函数的区别double ptoldist(POp,LIG l)return abs(multiply(p,l.e,l.s)/dist(l.s,l.e);/* 计算点到折线集的最近距离,并返回最近点.注意:调用的是 ptolig()函数 */vcount, POdouble ptopoi;set(poset, POp, PO&q)double cd=double(INF),td;LIG l;POtq,cq;for(i=0;ivcount-1;

10、i+)l.s=po l.e=po td=ptoli if(tdcd)cd=td; cq=tq;seti;seti+1;gdist(p,l,tq);q=cq; return cd;/* 判断圆是否在多边形内*/bool CircleInsidePolygon(vcount,POcenter,double radius,POpolygon)POq;double d; q.x=0;q.y=0; d=ptoposet(vcount,polygon,center,q);if(dradius|fabs(d-radius)=min(v.s.x,v.e.x)&(max(v.s.x,v.e.x)=min(u.s

11、.x,u.e.x)&(max(u.s.y,u.e.y)=min(v.s.y,v.e.y)&(max(v.s.y,v.e.y)=min(u.s.y,u.e.y)&(multiply(v.s,u.e,u.s)*multiply(u.e,v.e,u.s)=0)&(multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)=0);/排斥实验/跨立实验/ 判断线段 u 和 v 相交(不包括双方的端点)boolersect_A(LIG u,LIG v)return (ersect(u,v) &(!online(u,v.s)(!online(u,v.e)(!online(v,u.

12、e)(!online(v,u.s);& & &/ 判断线段 v 所在直线与线段 u 相交方法:判断线段 u 是否跨立线段 vboolersect_l(LIG u,LIG v)return multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)=0;/ 根据已知两点坐标,求过这两点的直线方程: a*x+b*y+c = 0(a = 0)LINE makeline(POLINE tl;sign = 1; tl.a=p2.y-p1.y; if(tl.a0)sign = -1; tl.a=sign*tl.a;p1,POp2)tl.b=sign*(p1.x-p2.x); t

13、l.c=sign*(p1.y*p2.x-p1.x*p2.y); return tl;/ 根据直线方程返回直线的斜率 k,水平线返回0,竖直线返回 1e200double slope(LINE l)if(abs(l.a) 1e-20)return 0; if(abs(l.b) 1e-20)return INF; return -(l.a/l.b);/ 返回直线的倾斜角 alpha ( 0 - pi)/ 注意:atan()返回的是 -PI/2 PI/2double alpha(LINE l)if(abs(l.a) EP)return 0; if(abs(l.b)0)return a);elsere

14、turn PI+a);/ 求点 p 关于直线 l 的对称点POsymmetry(LINE l,POp)POtp;tp.x=(l.b*l.b-l.a*l.a)*p.x-2*l.a*l.b*p.y-2*l.a*l.c)/(l.a*l.a+l.b*l.b);tp.y=(l.a*l.a-l.b*l.b)*p.y-2*l.a*l.b*p.x-2*l.b*l.c)/(l.a*l.a+l.b*l.b); return tp;/ 如果两条直线 l1(a1*x+b1*y+c1 = 0), l2(a2*x+b2*y+c2 = 0)相交,返回 true,且返回交点 pbool lineersect(LINE l1,

15、LINE l2,PO&p) / 是 L1,L2double d=l1.a*l2.b-l2.a*l1.b; if(abs(d)EP) / 不相交return false;p.x = (l2.c*l1.b-l1.c*l2.b)/d;p.y = (l2.a*l1.c-l1.a*l2.c)/d; return true;/ 如果线段 l1 和 l2 相交,返回 true 且交点由(er)返回,否则返回 falseboolersection(LIG l1,LIG l2,PO&er)LINE ll1,ll2; ll1=makeline(l1.s,l1.e); ll2=makeline(l2.s,l2.e)

16、;if(lineersect(ll1,ll2,er) return online(l1,er);else return false; 多边形常用算法模块如果无特别说明,输入多边形顶点要求按逆时针排列/ 返回多边形面积(signed);/ 输入顶点按逆时针排列时,返回正值;否则返回负值double area_of_polygon(i; double s;if (vcount3) return 0;vcount,POpolygon)s=polygon0.y*(polygonvcount-1.x-polygon1.x); for (i=1;i0;/*射判断点 q 与多边形 polygon 的位置关系

17、要求 polygon 为简单多边形,顶点时针排列如果点在多边形内: 返回 0如果点在多边形边上:返回 1如果点在多边形外: 返回 2 */insidepolygon(POq)c=0,i,n;G l1,l2;LIl1.s=q; l1.e=q;l1.e.x=double(INF); n=vcount;for (i=0;il2.e.y)c+;/l2 的一个端点在 l1 上且该端点是两端点中纵坐标较大的那个if(!online(l1,l2.e)& online(l1,l2.s) & l2.e.yl2.e.y) c+;/忽略平行边if(c%2 = 1)return 0; elsereturn 2;/判断

18、点 q 在凸多边形 polygon 内/ 点 q 是凸多边形 polygon 内包括边上时,返回 true/ 注意:多边形 polygon 一定要是凸多边形bool InsideConvexPolygon(vcount,POpolygon,POq)PO LIp;G l;i;p.x=0; p.y=0;for(i=0;ivcount;i+) / 寻找一个肯定在多边形 polygon 内的点 p:多边形顶点平均值p.x+=polygoni.x; p.y+=polygoni.y;p.x /= vcount;p.y /= vcount;for(i=0;ivcount;i+)l.s=polygoni; l

19、.e=polygon(i+1)%vcount; if(multiply(p,l.e,l.s)*multiply(q,l.e,l.s)0)/* 点 p 和点 q 在边 l 的两侧,说明点 q 肯定在多边形外return false;return true;*/*寻找凸包的 graham 扫描法PoSet 为输入的点集;ch 为输出的凸包上的点集,按照逆时针方向排列;n 为 PoSet 中的点的数目len 为输出的凸包上的点的个数 */void Graham_scan(POi,j,k=0,top=2;PoSet,POch,n,&len)POtmp;/ 选取 PoSet 中 y 坐标最小的点 PoS

20、etk,如果这样的点有多个,则取最左边的一个for(i=1;in;i+)if ( PoSeti.yPoSetk.y | (PoSeti.y=PoSetk.y)& (PoSeti.xPoSetk.x) ) k=i;tmp=PoSet0;Po PoSet0=PoSetk;Setk=tmp; / 现在 PoSet 中 y 坐标最小的点在 PoSet0for (i=1;in-1;i+) /* 对顶点按照相对 PoSet0的极角从小到大进行排序,极角相同的按照距离 Pok=i;Set0从近到远进行排序 */for (j=i+1;j0 |/ 极角更小(multiply(PoSetj,PoSetk,PoSe

21、t0)=0)&/* 极角相等,距离更短 */dist(PoSet0,Po k=j;Setj)dist(PoSet0,PoSetk) )tmp=PoSeti;Po PoSeti=Po Setk=tmp;Setk;ch0=Po ch1=Po ch2=PoSet0;Set1;Set2;for (i=3;i=0) top-;ch+top=PoSeti;len=top+1;/ 卷法求点集凸壳,参数说明同 graham 算法void ConvexClosure(POtop=0,i,index,PoSet,POch,n,&len);double curmax,curcos,curdis;PO LItmp;G l1,l2;bool useMAXV; tmp=Po Set0; index=0;/ 选取 y 最小点,如果多于一个,则选取最左点for(i=1;in;i+)if(PoSeti.ytmp.y|PoSeti.y = tmp.y&PoSeti.xtmp.x)index=i;usei=false;tmp=PoSetindex;=index; useindex=true;index=-1; chtop+=tmp; tmp.x-=100; l1.s=tmp; l1.e=ch0;l2.s=ch0;while(index!=)curmax=-100; curdis=0;/ 选

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论