计算几何之线段、直线、圆
1
#include
<
stdio.h
>
2 #include < math.h >
3
4 const double eps = 1e - 6 ;
5
6 // 点(x,y)
7 typedef struct
8 {
9 double x,y;
10} Point;
11
12 // 直线方程ax+by+c=0
13 typedef struct
14 {
15 double a,b,c;
16} Line;
17
18 // 圆的标准方程(x-center.x)^2+(y-center.y)^2=r^2
19 typedef struct
20 {
21 Point center;
22 double r;
23} Circle;
24
25 // 浮点数符号函数
26 int DblCmp( double d)
27 {
28 if(fabs(d)<eps) return 0;
29 else return d>0?1:-1;
30}
31
32 // 线段AB的中点C
33 Point MidPoint(Point A,Point B)
34 {
35 Point C;
36 C.x=(A.x+B.x)/2;
37 C.y=(A.y+B.y)/2;
38 return C;
39}
40
41 // 点A到点B的距离
42 double Dist(Point A,Point B)
43 {
44 return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
45}
46
47 // ∠ACB的弧度值
48 double Angle(Point A,Point B,Point C)
49 {
50 double a,b,c;
51 a=Dist(B,C);
52 b=Dist(A,C);
53 c=Dist(A,B);
54 return acos((a*a+b*b-c*c)/(2*a*b));
55}
56
57 // 二维向量a=(x1,y1)与b=(x2,y2)的叉积的数值
58 double Det( double x1, double y1, double x2, double y2)
59 {
60 return x1*y2-x2*y1;
61}
62
63 // 二维向量的叉积AB*AC的数值
64 double Cross(Point A,Point B,Point C)
65 {
66 return Det(B.x-A.x,B.y-A.y,C.x-A.x,C.y-A.y);
67}
68
69 // 二维向量a=(x1,y1)与b=(x2,y2)的点积
70 double DotDet( double x1, double y1, double x2, double y2)
71 {
72 return x1*x2+y1*y2;
73}
74
75 // 二维向量的点积AB·AC
76 double Dot(Point A,Point B,Point C)
77 {
78 return DotDet(B.x-A.x,B.y-A.y,C.x-A.x,C.y-A.y);
79}
80
81 // 点A与B或C重合时为0,点A在BC内部时为-1,点A在BC外部时为1
82 int BetweenCmp(Point A,Point B,Point C)
83 {
84 return DblCmp(Dot(A,B,C));
85}
86
87 // 线段AB,CD规范相交则返回1,并求交点P;不规范相交则返回2;没有交点则返回0
88 int SegsCross(Point A,Point B,Point C,Point D,Point & P)
89 {
90 double s1,s2,s3,s4;
91 int d1,d2,d3,d4;
92 d1=DblCmp(s1=Cross(A,B,C));
93 d2=DblCmp(s2=Cross(A,B,D));
94 d3=DblCmp(s3=Cross(C,D,A));
95 d4=DblCmp(s4=Cross(C,D,B));
96 if(((d1^d2)==-2)&&((d3^d4)==-2))
97 {
98 P.x=(C.x*s2-D.x*s1)/(s2-s1);
99 P.y=(C.y*s2-D.y*s1)/(s2-s1);
100 return 1;
101 }
102 if(((d1==0)&&(BetweenCmp(C,A,B)<=0))||
103 ((d2==0)&&(BetweenCmp(D,A,B)<=0))||
104 ((d3==0)&&(BetweenCmp(A,C,D)<=0))||
105 ((d4==0)&&(BetweenCmp(B,C,D)<=0)))
106 return 2;
107 else return 0;
108}
109
110 // 直线L1,L2相交则返回1,并求交点P;重合则返回2,平行则返回0;
111 int LinesCross(Line L1,Line L2,Point & P)
112 {
113 double d1=Det(L1.a,L1.b,L2.a,L2.b),d2=Det(L1.b,L1.c,L2.b,L2.c),d3=Det(L1.a,L1.c,L2.a,L2.c);
114 int x=DblCmp(d1),y=DblCmp(d2);
115 if(x==0&&y==0) return 2;
116 else if(x==0&&y!=0) return 0;
117 else
118 {
119 P.x=d2/d1;
120 P.y=-d3/d1;
121 return 1;
122 }
123}
124
125 // 两点式:AB构造直线L
126 Line LineFromSegs(Point A,Point B)
127 {
128 Line L;
129 L.a=B.y-A.y;
130 L.b=A.x-B.x;
131 L.c=B.x*A.y-A.x*B.y;
132 return L;
133}
134
135 // 点斜式:A及方位向量dir构造直线L
136 Line LineFromPointAndSlope(Point A,Point dir)
137 {
138 Line L;
139 if(dir.x==0)
140 {
141 L.a=1;
142 L.b=0;
143 L.c=-A.x;
144 }
145 else
146 {
147 double k=dir.y/dir.x;
148 L.a=k;
149 L.b=-1;
150 L.c=A.y-k*A.x;
151 }
152 return L;
153}
154
155 // 两点A,B构造垂直平分线L
156 Line PerbisecFromSegs(Point A,Point B)
157 {
158 Line AB=LineFromSegs(A,B),L;
159 Point C=MidPoint(A,B),dir;
160 dir.x=B.y-A.y;dir.y=A.x-B.x;
161 L=LineFromPointAndSlope(C,dir);
162 return L;
163}
164
165 // 三点A,B,C构造圆O
166 Circle CirFromPoints(Point A,Point B,Point C)
167 {
168 Circle O;
169 double c=Dist(A,B),ACB=Angle(A,B,C);
170 O.r=c/(2*sin(ACB));
171 Line DO=PerbisecFromSegs(A,B),EO=PerbisecFromSegs(B,C);
172 Point P;
173 if(LinesCross(DO,EO,P)==1) O.center=P;
174 return O;
175}
2 #include < math.h >
3
4 const double eps = 1e - 6 ;
5
6 // 点(x,y)
7 typedef struct
8 {
9 double x,y;
10} Point;
11
12 // 直线方程ax+by+c=0
13 typedef struct
14 {
15 double a,b,c;
16} Line;
17
18 // 圆的标准方程(x-center.x)^2+(y-center.y)^2=r^2
19 typedef struct
20 {
21 Point center;
22 double r;
23} Circle;
24
25 // 浮点数符号函数
26 int DblCmp( double d)
27 {
28 if(fabs(d)<eps) return 0;
29 else return d>0?1:-1;
30}
31
32 // 线段AB的中点C
33 Point MidPoint(Point A,Point B)
34 {
35 Point C;
36 C.x=(A.x+B.x)/2;
37 C.y=(A.y+B.y)/2;
38 return C;
39}
40
41 // 点A到点B的距离
42 double Dist(Point A,Point B)
43 {
44 return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
45}
46
47 // ∠ACB的弧度值
48 double Angle(Point A,Point B,Point C)
49 {
50 double a,b,c;
51 a=Dist(B,C);
52 b=Dist(A,C);
53 c=Dist(A,B);
54 return acos((a*a+b*b-c*c)/(2*a*b));
55}
56
57 // 二维向量a=(x1,y1)与b=(x2,y2)的叉积的数值
58 double Det( double x1, double y1, double x2, double y2)
59 {
60 return x1*y2-x2*y1;
61}
62
63 // 二维向量的叉积AB*AC的数值
64 double Cross(Point A,Point B,Point C)
65 {
66 return Det(B.x-A.x,B.y-A.y,C.x-A.x,C.y-A.y);
67}
68
69 // 二维向量a=(x1,y1)与b=(x2,y2)的点积
70 double DotDet( double x1, double y1, double x2, double y2)
71 {
72 return x1*x2+y1*y2;
73}
74
75 // 二维向量的点积AB·AC
76 double Dot(Point A,Point B,Point C)
77 {
78 return DotDet(B.x-A.x,B.y-A.y,C.x-A.x,C.y-A.y);
79}
80
81 // 点A与B或C重合时为0,点A在BC内部时为-1,点A在BC外部时为1
82 int BetweenCmp(Point A,Point B,Point C)
83 {
84 return DblCmp(Dot(A,B,C));
85}
86
87 // 线段AB,CD规范相交则返回1,并求交点P;不规范相交则返回2;没有交点则返回0
88 int SegsCross(Point A,Point B,Point C,Point D,Point & P)
89 {
90 double s1,s2,s3,s4;
91 int d1,d2,d3,d4;
92 d1=DblCmp(s1=Cross(A,B,C));
93 d2=DblCmp(s2=Cross(A,B,D));
94 d3=DblCmp(s3=Cross(C,D,A));
95 d4=DblCmp(s4=Cross(C,D,B));
96 if(((d1^d2)==-2)&&((d3^d4)==-2))
97 {
98 P.x=(C.x*s2-D.x*s1)/(s2-s1);
99 P.y=(C.y*s2-D.y*s1)/(s2-s1);
100 return 1;
101 }
102 if(((d1==0)&&(BetweenCmp(C,A,B)<=0))||
103 ((d2==0)&&(BetweenCmp(D,A,B)<=0))||
104 ((d3==0)&&(BetweenCmp(A,C,D)<=0))||
105 ((d4==0)&&(BetweenCmp(B,C,D)<=0)))
106 return 2;
107 else return 0;
108}
109
110 // 直线L1,L2相交则返回1,并求交点P;重合则返回2,平行则返回0;
111 int LinesCross(Line L1,Line L2,Point & P)
112 {
113 double d1=Det(L1.a,L1.b,L2.a,L2.b),d2=Det(L1.b,L1.c,L2.b,L2.c),d3=Det(L1.a,L1.c,L2.a,L2.c);
114 int x=DblCmp(d1),y=DblCmp(d2);
115 if(x==0&&y==0) return 2;
116 else if(x==0&&y!=0) return 0;
117 else
118 {
119 P.x=d2/d1;
120 P.y=-d3/d1;
121 return 1;
122 }
123}
124
125 // 两点式:AB构造直线L
126 Line LineFromSegs(Point A,Point B)
127 {
128 Line L;
129 L.a=B.y-A.y;
130 L.b=A.x-B.x;
131 L.c=B.x*A.y-A.x*B.y;
132 return L;
133}
134
135 // 点斜式:A及方位向量dir构造直线L
136 Line LineFromPointAndSlope(Point A,Point dir)
137 {
138 Line L;
139 if(dir.x==0)
140 {
141 L.a=1;
142 L.b=0;
143 L.c=-A.x;
144 }
145 else
146 {
147 double k=dir.y/dir.x;
148 L.a=k;
149 L.b=-1;
150 L.c=A.y-k*A.x;
151 }
152 return L;
153}
154
155 // 两点A,B构造垂直平分线L
156 Line PerbisecFromSegs(Point A,Point B)
157 {
158 Line AB=LineFromSegs(A,B),L;
159 Point C=MidPoint(A,B),dir;
160 dir.x=B.y-A.y;dir.y=A.x-B.x;
161 L=LineFromPointAndSlope(C,dir);
162 return L;
163}
164
165 // 三点A,B,C构造圆O
166 Circle CirFromPoints(Point A,Point B,Point C)
167 {
168 Circle O;
169 double c=Dist(A,B),ACB=Angle(A,B,C);
170 O.r=c/(2*sin(ACB));
171 Line DO=PerbisecFromSegs(A,B),EO=PerbisecFromSegs(B,C);
172 Point P;
173 if(LinesCross(DO,EO,P)==1) O.center=P;
174 return O;
175}