Computational Geometry Template (二)

2014-11-23 23:18:23 · 作者: · 浏览: 14
t(p2,l.b)))>eps; } //判两点在线段异侧,点在线段上返回0,不共面无意义 bool opposite_side(point3 p1,point3 p2,line3 l) { return dmult(xmult(subt(l.a,l.b),subt(p1,l.b)),xmult(subt(l.a,l.b),subt(p2,l.b)))<-eps; } //判两点在平面同侧,点在平面上返回0 bool same_side(point3 p1,point3 p2,plane3 s) { return dmult(pvec(s),subt(p1,s.a))*dmult(pvec(s),subt(p2,s.a))>eps; } bool same_side(point3 p1,point3 p2,point3 s1,point3 s2,point3 s3) { return dmult(pvec(s1,s2,s3),subt(p1,s1))*dmult(pvec(s1,s2,s3),subt(p2,s1))>eps; } //判两点在平面异侧,点在平面上返回0 bool opposite_side(point3 p1,point3 p2,plane3 s) { return dmult(pvec(s),subt(p1,s.a))*dmult(pvec(s),subt(p2,s.a))<-eps; } bool opposite_side(point3 p1,point3 p2,point3 s1,point3 s2,point3 s3) { return dmult(pvec(s1,s2,s3),subt(p1,s1))*dmult(pvec(s1,s2,s3),subt(p2,s1))<-eps; } //判两直线平行 bool parallel(line3 u,line3 v) { return vlen(xmult(subt(u.a,u.b),subt(v.a,v.b))) #include #define eps 1e-8 #define zero(x) (((x)>0 (x):-(x))
eps; } //判两点在线段异侧,点在线段上返回0 bool opposite_side(point p1,point p2,line l) { return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)<-eps; } //判两直线平行 bool parallel(line u,line v) { return zero((u.a.x-u.b.x)*(v.a.y-v.b.y)-(v.a.x-v.b.x)*(u.a.y-u.b.y)); } //判两直线垂直 bool perpendicular(line u,line v) { return zero((u.a.x-u.b.x)*(v.a.x-v.b.x)+(u.a.y-u.b.y)*(v.a.y-v.b.y)); } //判两线段相交,包括端点和部分重合 bool intersect_in(line u,line v) { if (!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b)) return !same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u); return dot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u); } //判两线段相交,不包括端点和部分重合 bool intersect_ex(line u,line v) { return opposite_side(u.a,u.b,v)&&opposite_side(v.a,v.b,u); } //计算两直线交点,注意事先判断直线是否平行! //线段交点请另外判线段相交(同时还是要判断是否平行!) point intersection(line u,line v) { point ret=u.a; double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x)) /((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x)); ret.x+=(u.b.x-u.a.x)*t; ret.y+=(u.b.y-u.a.y)*t; return ret; } point intersection(point u1,point u2,point v1,point v2) { point ret=u1; double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x)) /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x)); ret.x+=(u2.x-u1.x)*t; ret.y+=(u2.y-u1.y)*t; return ret; } //点到直线上的最近点 point ptoline(point p,line l) { point t=p; t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x; return intersection(p,t,l.a,l.b); } //点到直线距离 double disptoline(point p,line l) { return fabs(xmult(p,l.a,l.b))/distance(l.a,l.b); } //点到线段上的最近点 point ptoseg(point p,line l) { point t=p; t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x; if (xmult(l.a,t,p)*xmult(l.b,t,p)>eps) return distance(p,l.a)eps) return distance(p,l.a)=pi+pi) dlng-=pi+pi; if (dlng>pi) dlng=pi+pi-dlng; lat1*=pi/180,lat2*=pi/180; return acos(cos(lat1)*cos(lat2)*cos(dlng)+sin(lat1)*sin(lat2)); } //计算距离,r 为球半径 double line_dist(double r,double lng1,double lat1,double lng2,double lat2) { double dlng=fabs(lng1-lng2)*pi/180; while (dlng>=pi+pi) dlng-=pi+pi; if (dlng>pi) dlng=pi+pi-dlng; lat1*=pi/180,lat2*=pi/180; return r*sqrt(2-2*(cos(lat1)*cos(lat2)*cos(dlng)+sin(lat1)*sin(lat2))); } //计算球面距离,r 为球半径 inline double sphere_dist(double r,double lng1,double lat1,double lng2,double lat2) { return r*angle(lng1,lat1,lng2,lat2); } //外心 point circumcenter(point a,point b,point c) { line u,v; u.a.x=(a.x+b.x)/2; u.a.y=(a.y+b.y)/2; u.b.x=u.a.x-a.y+b.y; u.b.y=u.a.y+a.x-b.x; v.a.x=(a.x+c.x)/2; v.a.y=(a.y+c.y)/2; v.b.x=v.a.x-a.y+c.y; v.b.y=v.a.y+a.x-c.x; return intersection(u,v); } //内心 point incenter(point a,point b,point c) { line u,v; double m,n; u.a=a; m=atan2(b.y-a.y,b.x-a.x); n=atan2(c.y-a.y,c.x-a.x); u.b.x=u.a.x+cos((m+n)/2); u.b.y=u.a.y+sin((m+n)/2); v.a=b; m=atan2(a.y-b.y,a.x-b.x); n=atan2(c.y-b.y,c.x-b.x); v.b.x=v.a.x+cos((m+n)/2); v.b.y=v.a.y+sin((m+n)/2); return intersection(u,v); } //垂心 point perpencenter(point a,point b,point c) { line u,v; u.a=c; u.b.x=u.a.x-a.y+b.y; u.b.y=u.a.y+a.x-b.x; v.a=b; v.b.x=v.a.x-a.y+c.y; v.b.y=v.a.y+a.x-c.x; return intersection(u,v); } //重心 //到三角形三顶点距离的平方和最小的点 //三角形内到三边距离之积最大的点 point barycenter(point a,point b,point c) { line u,v; u.a.x=(a.x+b.x)/2; u.a.y=(a.y+b.y)/2; u.b=c; v.a.x=(a.x+c.x)/2; v.a.y=(a.y+c.y)/2; v.b=b; return intersection(u,v); } //费马点 //到三角形三顶点距离之和最小的点 point fermentpoint(point a,point b,point c) { point u,v; double step=fabs(a.x)+fabs(a.y)+fabs(b.x)+fabs(b.y)+fabs(c.x)+fabs(c.y); int i,j,k; u.x=(a.x+b.x+c.x)/3; u.y=(a.y+b.y+c.y)/3; while (step>1e-10) { for (k=0; k<10; step/=2,k++) { for (i=-1; i<=1; i++) { for (j=-1; j<=1; j++) { v.x=u.x+step*i; v.y=u.y+step*j; if(distance(u,a)+distance(u,b)+distance(u,c)>distance(v,a)+distance(v,b)+distance(v,c)) { u=v; } } } } } return u; } //矢量差 U - V point3 subt(point3 u,point3 v) { point3 ret; ret.x=u.x-v.x; ret.y=u.y-v.y; ret.z=u.z-v.z; return ret; } //取平面法向量 point3 pvec(plane3 s) { return xmult(subt(s.a,s.b),subt(s.b,s.c)); } point3 pvec(point3 s1,point3 s2,point3 s3) { return xmult(subt(s1,s2),subt(s2,s3)); } //两点距离,单参数取向量大小 double distance(point3 p1,point3 p2) { return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.