计算几何Word文件下载.docx
《计算几何Word文件下载.docx》由会员分享,可在线阅读,更多相关《计算几何Word文件下载.docx(50页珍藏版)》请在冰豆网上搜索。
=(constPOINT&
return!
(fabs(x-_P.x)<
=EPSILON);
booloperator<
(constPOINT&
if(y!
=_P.y)returny<
_P.y;
elsereturnx<
_P.x;
};
POINToperator+(constPOINT&
returnPOINT(x+_P.x,y+_P.y);
POINToperator-(constPOINT&
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)<
if(x1>
0.0)return0.0;
elsereturn180.0;
doubleangle=ArcTan(fabs(y1/x1));
0)
returny1>
0?
angle:
360.0-angle;
else
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
doubleA,B,C;
LINE(POINT_a,POINT_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)<
fabs(A*_L.C-_L.A*C)<
fabs(B*_L.C-_L.B*C)<
//叉乘,右手螺旋向上为正
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&
b,constPOINT&
o)
return(a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
intSign_Cross(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);
//点到直线的垂足
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;
if(P.x<
max(S.a.x,S.b.x)+EPSILON&
P.x>
min(S.a.x,S.b.x)-EPSILON&
P.y<
max(S.a.y,S.b.y)+EPSILON&
P.y>
min(S.a.y,S.b.y)-EPSILON&
fabs(Cross(S.b,P,S.a))<
returntrue;
returnfalse;
//点到线段的最近点
POINTNearest_Point_To_Segment(constPOINT&
P,constSEGMENT&
LINEL(S.a,S.b);
POINTI=Pedal_Point(P,L);
if(Is_On_Segment(I,S))
returnI;
doublet1=Distance(P,S.a);
doublet2=Distance(P,S.b);
returnt1<
t2?
S.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);
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);
boolIs_Touch(constSEGMENT&
v)
=min(v.a.x,v.b.x)-EPSILON)&
=min(u.a.x,u.b.x)-EPSILON)&
=min(v.a.y,v.b.y)-EPSILON)&
=min(u.a.y,u.b.y)-EPSILON))
if(t1*t2==0)
return(t3*t4>
=0);
elsereturn(t1*t2>
0&
t3*t4==0);
//判断线断P和直线Q是否相交,端点重合算相交
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>
}
//判断两条直线是否平行
boolIs_Parallel(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)<
//判断两条直线是否相交
boolIs_Intersect(constLINE&
(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)<
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&
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&
doublex1=S.b.x-S.a.x;
doubley1=S.b.y-S.a.y;
0.0)return0.5*PI;
elsereturn1.5*PI;
elsereturnPI;
doubleangle=atan(fabs(y1/x1));
2.0*PI-angle;
PI-angle:
PI+angle;
//线段s1与s2的夹角
doubleAngle_Between(constSEGMENT&
s1,constSEGMENT&
//注意误差,若太接近,就另为0
doubleangle=Angle(s2)-Angle(s1);
if(fabs(angle)<
EPSILON)angle=0.0;
if(angle>
2.0*PI)angle=0.0;
elseif(angle<
0.0)angle+=2.0*PI;
returnangle;
//返回两线段的重合部分
vector<
SEGMENT>
Coincidence_With_Segment(constSEGMENT&
vector<
S;
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);
Is_On_Segment(s1.a,s2)&
s2.a!
=s1.a)
s.a=s2.a;
s.b=s1.a;
elseif(Is_On_Segment(s1.a,s2))
s.a=s1.a;
elseif(Is_On_Segment(s2.a,s1))
s.b=s2.a;
returnS;
//////////////////////////////////////////////////////////////////////////////
//圆
structCIRCLE
POINTC;
doubleR;
CIRCLE(){}
CIRCLE(POINT_P,double_R)
C=_P;
R=_R;
booloperator==(constCIRCLE&
_C)const
returnfabs(R-_C.R)<
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:
A;
doubleD=Distance(M.C,N.C);
if((D<
M.R+N.R)&
(D>
M.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