计算几何.docx
《计算几何.docx》由会员分享,可在线阅读,更多相关《计算几何.docx(50页珍藏版)》请在冰豆网上搜索。
计算几何
//计算几何(二维)
#include
#include
#include
#include
usingnamespacestd;
constdoubleEPSILON=1e-8;
constdoubleINFINITY=1e10;
constdoublePI=3.14159265358979323846;
inlinedoubleDegToRad(doubledeg){return(deg*PI/180.0);}
inlinedoubleRadToDeg(doublerad){return(rad*180.0/PI);}
inlinedoubleSin(doubledeg){returnsin(DegToRad(deg));}
inlinedoubleCos(doubledeg){returncos(DegToRad(deg));}
inlinedoubleTan(doubledeg){returntan(DegToRad(deg));}
inlinedoubleArcSin(doubleval){returnRadToDeg(asin(val));}
inlinedoubleArcCos(doubleval){returnRadToDeg(acos(val));}
inlinedoubleArcTan(doubleval){returnRadToDeg(atan(val));}
structPOINT
{
doublex,y;
POINT(){};
POINT(double_x,double_y)
{
x=_x;
y=_y;
}
booloperator==(constPOINT&_P)const
{
returnfabs(x-_P.x)<=EPSILON&&fabs(y-_P.y)<=EPSILON;
}
booloperator!
=(constPOINT&_P)const
{
return!
(fabs(x-_P.x)<=EPSILON&&fabs(y-_P.y)<=EPSILON);
}
booloperator<(constPOINT&_P)const
{
if(y!
=_P.y)returny<_P.y;
elsereturnx<_P.x;
};
POINToperator+(constPOINT&_P)const
{
returnPOINT(x+_P.x,y+_P.y);
}
POINToperator-(constPOINT&_P)const
{
returnPOINT(x-_P.x,y-_P.y);
}
doubleAngle(constPOINT&O)//返回点关于O点的极坐标
{
doublex1=x-O.x;
doubley1=y-O.y;
if(fabs(x1)<=EPSILON)
{
if(y1>0.0)return90.0;
elsereturn270.0;
}
if(fabs(y1)<=EPSILON)
{
if(x1>0.0)return0.0;
elsereturn180.0;
}
doubleangle=ArcTan(fabs(y1/x1));
if(x1>0)
{
returny1>0?
angle:
360.0-angle;
}
else
{
returny1>0?
180.0-angle:
180.0+angle;
}
}
doubleAngle()//默认O点为(0,0)
{
returnAngle(POINT(0,0));
}
};
inlinedoubleDistance(constPOINT&a,constPOINT&b)
{
returnsqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
structSEGMENT
{
POINTa,b;
SEGMENT(){};
SEGMENT(POINT_a,POINT_b)
{
a=_a;
b=_b;
};
booloperator==(constSEGMENT&_SEGMENT)const
{
returna==_SEGMENT.a&&b==_SEGMENT.b;
};
};
//Ax+By+C=0
structLINE
{
POINTa,b;
doubleA,B,C;
LINE(POINT_a,POINT_b)
{
a=_a;
b=_b;
A=b.y-a.y;
B=a.x-b.x;
C=b.x*a.y-a.x*b.y;
};
LINE(double_A,double_B,double_C)
{
A=_A;
B=_B;
C=_C;
};
booloperator==(constLINE&_L)const
{
returnfabs(A*_L.B-_L.A*B)<=EPSILON&&
fabs(A*_L.C-_L.A*C)<=EPSILON&&
fabs(B*_L.C-_L.B*C)<=EPSILON;
};
};
//叉乘,右手螺旋向上为正
doubleCross(constSEGMENT&p,constSEGMENT&q)
{
return(p.b.x-p.a.x)*(q.b.y-q.a.y)-(q.b.x-q.a.x)*(p.b.y-p.a.y);
}
doubleCross(constPOINT&a,constPOINT&b,constPOINT&o)
{
return(a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
intSign_Cross(constSEGMENT&p,constSEGMENT&q)//返回叉乘的符号
{
doublet=Cross(p,q);
if(t>EPSILON)return1;
elseif(t<-EPSILON)return-1;
elsereturn0;
}
intSign_Cross(constPOINT&a,constPOINT&b,constPOINT&o)//返回叉乘的符号
{
doublet=Cross(a,b,o);
if(t>EPSILON)return1;
elseif(t<-EPSILON)return-1;
elsereturn0;
}
//点到直线的垂足
POINTPedal_Point(constPOINT&P,constLINE&L)
{
if(fabs(L.B)<=EPSILON)//如果直线平行Y轴
{
returnPOINT(-L.C/L.A,P.y);
}
elseif(fabs(L.A)<=EPSILON)//如果直线平行X轴
{
returnPOINT(P.x,-L.C/L.B);
}
else
{
doublek1=-L.A/L.B;
doublek2=-1/k1;
doubleb1=-L.C/L.B;
doubleb2=P.y-k2*P.x;
doublex=(b2-b1)/(k1-k2);
doubley=k2*x+b2;
returnPOINT(x,y);
}
}
//p点关于直线L的对称点
POINTSymmetrical_Point_Of_Line(POINTP,LINEL)
{
POINT_P;
doubled;
d=L.A*L.A+L.B*L.B;
_P.x=(L.B*L.B*P.x-L.A*L.A*P.x-
2.0*L.A*L.B*P.y-2.0*L.A*L.C)/d;
_P.y=(L.A*L.A*P.y-L.B*L.B*P.y-
2.0*L.A*L.B*P.x-2.0*L.B*L.C)/d;
return_P;
}
boolIs_On_Segment(constPOINT&P,constSEGMENT&S)
{
if(P==S.a||P==S.b)returntrue;
else
{
if(P.xP.x>min(S.a.x,S.b.x)-EPSILON&&
P.yP.y>min(S.a.y,S.b.y)-EPSILON&&
fabs(Cross(S.b,P,S.a))<=EPSILON)
{
returntrue;
}
}
returnfalse;
}
//点到线段的最近点
POINTNearest_Point_To_Segment(constPOINT&P,constSEGMENT&S)
{
LINEL(S.a,S.b);
POINTI=Pedal_Point(P,L);
if(Is_On_Segment(I,S))
{
returnI;
}
else
{
doublet1=Distance(P,S.a);
doublet2=Distance(P,S.b);
returnt1S.a:
S.b;
}
}
//直线相交的交点
POINTIntersection_Point(constLINE&L1,constLINE&L2)
{
POINTI;
I.x=-(L2.B*L1.C-L1.B*L2.C)/(L1.A*L2.B-L2.A*L1.B);
I.y=(L2.A*L1.C-L1.A*L2.C)/(L1.A*L2.B-L2.A*L1.B);
returnI;
}
POINTIntersection_Point(constSEGMENT&s1,constSEGMENT&s2)
{
LINEl1(s1.a,s1.b);
LINEl2(s2.a,s2.b);
returnIntersection_Point(l1,l2);
}
boolIs_Intersect(constSEGMENT&u,constSEGMENT&v)
{
if((max(u.a.x,u.b.x)>min(v.a.x,v.b.x)-EPSILON)&&
(max(v.a.x,v.b.x)>min(u.a.x,u.b.x)-EPSILON)&&
(max(u.a.y,u.b.y)>min(v.a.y,v.b.y)-EPSILON)&&
(max(v.a.y,v.b.y)>min(u.a.y,u.b.y)-EPSILON))
{
intt1=Sign_Cross(v.a,u.b,u.a);
intt2=Sign_Cross(u.b,v.b,u.a);
intt3=Sign_Cross(u.a,v.b,v.a);
intt4=Sign_Cross(v.b,u.b,v.a);
return(t1*t2>0)&&(t3*t4>0);
}
returnfalse;
}
boolIs_Touch(constSEGMENT&u,constSEGMENT&v)
{
if((max(u.a.x,u.b.x)>=min(v.a.x,v.b.x)-EPSILON)&&
(max(v.a.x,v.b.x)>=min(u.a.x,u.b.x)-EPSILON)&&
(max(u.a.y,u.b.y)>=min(v.a.y,v.b.y)-EPSILON)&&
(max(v.a.y,v.b.y)>=min(u.a.y,u.b.y)-EPSILON))
{
intt1=Sign_Cross(v.a,u.b,u.a);
intt2=Sign_Cross(u.b,v.b,u.a);
intt3=Sign_Cross(u.a,v.b,v.a);
intt4=Sign_Cross(v.b,u.b,v.a);
if(t1*t2==0)
{
return(t3*t4>=0);
}
elsereturn(t1*t2>0&&t3*t4==0);
}
returnfalse;
}
//判断线断P和直线Q是否相交,端点重合算相交
boolIs_Intersect(constSEGMENT&p,constLINE&q)
{
SEGMENTp1,p2,q0;
p1.a=q.a;p1.b=p.a;
p2.a=q.a;p2.b=p.b;
q0.a=q.a;q0.b=q.b;
intt1=Sign_Cross(p1,q0);
intt2=Sign_Cross(q0,p2);
return(t1*t2>=0);
}
//判断两条直线是否平行
boolIs_Parallel(constLINE&L1,constLINE&L2)
{
//共线不算平行
//return(L1.A*L2.B==L2.A*L1.B)&&
//((L1.A*L2.C!
=L2.A*L1.C)||(L1.B*L2.C!
=L2.B*L1.C));
//共线算平行
return(fabs(L1.A*L2.B-L2.A*L1.B)<=EPSILON);
}
//判断两条直线是否相交
boolIs_Intersect(constLINE&L1,constLINE&L2)
{
return!
(L1==L2)&&!
(Is_Parallel(L1,L2));
}
//角(AOB)的平分线
LINEAngle_Bisector(POINTA,constPOINT&O,POINTB)
{
doubleangle1=A.Angle(O);
doubleangle2=B.Angle(O);
doubleangle3=(angle2-angle1)/2.0+angle1;
if(fabs(angle3-90.0)<=EPSILON||fabs(angle3-270.0)<=EPSILON)
{
POINTP1(O.x,O.y+1.0);
returnLINE(P1,O);
}
doublek=Tan(angle3);
POINTP2(O.x+1.0,O.y+k);
returnLINE(P2,O);
}
//线段的垂直平分线
LINESEGMENT_Bisector(constSEGMENT&S)
{
POINTO((S.a.x+S.b.x)/2.0,(S.a.y+S.b.y)/2.0);
returnAngle_Bisector(S.a,O,S.b);
}
//从X轴旋转到S的角度
doubleAngle(constSEGMENT&S)
{
doublex1=S.b.x-S.a.x;
doubley1=S.b.y-S.a.y;
if(fabs(x1)<=EPSILON)
{
if(y1>0.0)return0.5*PI;
elsereturn1.5*PI;
}
if(fabs(y1)<=EPSILON)
{
if(x1>0.0)return0.0;
elsereturnPI;
}
doubleangle=atan(fabs(y1/x1));
if(x1>0)
{
returny1>0?
angle:
2.0*PI-angle;
}
else
{
returny1>0?
PI-angle:
PI+angle;
}
}
//线段s1与s2的夹角
doubleAngle_Between(constSEGMENT&s1,constSEGMENT&s2)
{
//注意误差,若太接近,就另为0
doubleangle=Angle(s2)-Angle(s1);
if(fabs(angle)if(angle>2.0*PI)angle=0.0;
elseif(angle<0.0)angle+=2.0*PI;
returnangle;
}
//返回两线段的重合部分
vectorCoincidence_With_Segment(constSEGMENT&s1,constSEGMENT&s2)
{
vectorS;
SEGMENTs;
if(Is_Touch(s1,s2))
{
if(Is_On_Segment(s1.a,s2)&&Is_On_Segment(s1.b,s2))
{
S.push_back(s1);
}
elseif(Is_On_Segment(s2.a,s1)&&Is_On_Segment(s2.b,s1))
{
S.push_back(s2);
}
elseif(Is_On_Segment(s2.b,s1)&&Is_On_Segment(s1.b,s2)&&s2.b!
=s1.b)
{
s.a=s2.b;
s.b=s1.b;
S.push_back(s);
}
elseif(Is_On_Segment(s2.a,s1)&&Is_On_Segment(s1.a,s2)&&s2.a!
=s1.a)
{
s.a=s2.a;
s.b=s1.a;
S.push_back(s);
}
elseif(Is_On_Segment(s1.a,s2))
{
s.a=s1.a;
s.b=s1.a;
S.push_back(s);
}
elseif(Is_On_Segment(s2.a,s1))
{
s.a=s2.a;
s.b=s2.a;
S.push_back(s);
}
}
returnS;
}
//////////////////////////////////////////////////////////////////////////////
//圆
//////////////////////////////////////////////////////////////////////////////
structCIRCLE
{
POINTC;
doubleR;
CIRCLE(){}
CIRCLE(POINT_P,double_R)
{
C=_P;
R=_R;
}
booloperator==(constCIRCLE&_C)const
{
returnfabs(R-_C.R)<=EPSILON&&C==_C.C;
}
doubleArea()
{
returnPI*R*R;
}
};
//两个圆的公共面积
doubleTwo_Circle_Common_Area(constCIRCLE&A,constCIRCLE&B)
{
doublearea=0.0;
CIRCLEM=(A.R>B.R)?
A:
B;
CIRCLEN=(A.R>B.R)?
B:
A;
doubleD=Distance(M.C,N.C);
if((DM.R-N.R))
{
doublecosM=(M.R*M.R+D*D-N.R*N.R)/(2.0*M.R*D);
doublecosN=(N.R*N.R+D*D-M.R*M.R)/(2.0*N.R*D);
doublealpha=2.0*ArcCos(cosM);
doublebeta=2.0*ArcCos(cosN);
doubleTM=0.5*M.R*M.R*Sin(alpha);
doubleTN=0.5*N.R*N.R*Sin(beta);
doubleFM=(alpha/360.0)*M.Area();
doubleFN=(beta/360.0)*N.Area();
area=FM+FN-TM-TN;
}
elseif(D<=M.R-N.R)
{
area=N.Ar