码迷,mamicode.com
首页 > 其他好文 > 详细

uva 12304

时间:2015-10-11 22:47:52      阅读:305      评论:0      收藏:0      [点我收藏+]

标签:

题意:要求解答6个关于圆的问题。
1.给出三角形坐标求外接圆
2.给出三角形坐标求内切圆
3.给出一个圆心和半径已知的圆,求过点(x,y)的所有和这个圆相切的直线
4.求所有和已知直线相切的过定点(x,y)的已知半径的圆的圆心
5.给出两个不平行的直线,求所有半径为r的同时和这两个直线相切的圆
6.给定两个相离的圆,求出所有和这两个圆外切的半径为r的圆。

比较恶心的计算几何模板题,直接模板吧。。。。

技术分享
  1 #include<cstdio>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<memory.h>
  7 #include<cstdlib>
  8 #include<vector>
  9 #define clc(a,b) memset(a,b,sizeof(a))
 10 #define LL long long int
 11 #define up(i,x,y) for(i=x;i<=y;i++)
 12 #define w(a) while(a)
 13 using namespace std;
 14 const int inf=0x3f3f3f3f;
 15 const int N = 110;
 16 const int maxn = 50;
 17 const double eps = 1e-10;        //调到1e-6以上第4问就可以用delta判断切线,但《训练指南》建议,尽量不要调eps
 18 const double pi = acos(-1);
 19 
 20 char type[maxn];
 21 
 22 int dcmp(double x)
 23 {
 24     return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);
 25 }
 26 
 27 struct Point
 28 {
 29     double x;
 30     double y;
 31 
 32     Point(double x = 0, double y = 0):x(x), y(y) {}
 33 
 34     bool operator < (const Point& e) const
 35     {
 36         return dcmp(x - e.x) < 0 || (dcmp(x - e.x) == 0 && dcmp(y - e.y) < 0);
 37     }
 38 
 39     bool operator == (const Point& e) const
 40     {
 41         return dcmp(x - e.x) == 0 && dcmp(y - e.y) == 0;
 42     }
 43 
 44     int read()
 45     {
 46         return scanf("%lf%lf", &x, &y);
 47     }
 48 } p[3];
 49 
 50 typedef Point Vector;
 51 
 52 Vector operator + (Point A, Point B)
 53 {
 54     return Vector(A.x + B.x, A.y + B.y);
 55 }
 56 
 57 Vector operator - (Point A, Point B)
 58 {
 59     return Vector(A.x - B.x, A.y - B.y);
 60 }
 61 
 62 Vector operator * (Point A, double p)
 63 {
 64     return Vector(A.x * p, A.y * p);
 65 }
 66 
 67 Vector operator / (Point A, double p)
 68 {
 69     return Vector(A.x / p, A.y / p);
 70 }
 71 
 72 struct Line
 73 {
 74     Point p;
 75     Point v;
 76 
 77     Line() {}
 78     Line(Point p, Point v):p(p), v(v) {}
 79 
 80     int read()
 81     {
 82         return scanf("%lf%lf%lf%lf", &p.x, &p.y, &v.x, &v.y);
 83     }
 84 
 85     Point point(double t)
 86     {
 87         return p + v * t;
 88     }
 89 };
 90 
 91 struct Circle
 92 {
 93     Point c;
 94     double r;
 95 
 96     Circle() {}
 97     Circle(Point c, double r):c(c), r(r) {}
 98 
 99     int read()
100     {
101         return scanf("%lf%lf%lf", &c.x, &c.y, &r);
102     }
103 
104     Point point(double a)
105     {
106         return Point(c.x + r * cos(a), c.y + r * sin(a));
107     }
108 };
109 
110 double Dot(Vector A, Vector B)
111 {
112     return A.x * B.x + A.y * B.y;
113 }
114 
115 double Cross(Vector A, Vector B)
116 {
117     return A.x * B.y - B.x * A.y;
118 }
119 
120 double Length(Vector A)
121 {
122     return sqrt(Dot(A, A));
123 }
124 
125 Vector Rotate(Vector A, double rad)
126 {
127     return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
128 }
129 
130 Vector Normal(Vector A)
131 {
132     double L = Length(A);
133     return Vector(-A.y / L, A.x / L);
134 }
135 
136 double DistanceToLine(Point P, Point A, Point B)        //点到直线的距离
137 {
138     Vector v1 = B - A;
139     Vector v2 = P - A;
140     return fabs(Cross(v1, v2) / Length(v1));
141 }
142 
143 double angle(Vector v)      //求向量的极角
144 {
145     return atan2(v.y, v.x);
146 }
147 
148 Point GetLineIntersection(Line l1, Line l2)         //求两直线的交点(前提:相交)
149 {
150     Vector u = l1.p - l2.p;
151     double t = Cross(l2.v, u) / Cross(l1.v, l2.v);
152     return l1.point(t);
153 }
154 
155 int getLineCircleIntersection(Line l, Circle C, double& t1, double& t2, vector<Point>& sol)         //求直线与圆的交点
156 {
157     double a = l.v.x;
158     double b = l.p.x - C.c.x;
159     double c = l.v.y;
160     double d = l.p.y - C.c.y;
161     double e = a * a + c * c;
162     double f = 2 * (a * b + c * d);
163     double g = b * b + d * d - C.r * C.r;
164     double delta = f * f - 4 * e * g;
165     double dist = DistanceToLine(C.c, l.p, l.p+l.v);
166     if(dcmp(dist - C.r) == 0)       //相切,此处需特殊判断,不能用delta
167     {
168         t1 = t2 = -f / (2 * e);
169         sol.push_back(l.point(t1));
170         return 1;
171     }
172     if(dcmp(delta) < 0) return 0;       //相离
173     else        //相交
174     {
175         t1 = (-f - sqrt(delta)) / (2 * e);
176         sol.push_back(l.point(t1));
177         t2 = (-f + sqrt(delta)) / (2 * e);
178         sol.push_back(l.point(t2));
179         return 2;
180     }
181 }
182 
183 int GetCircleCircleIntersection(Circle C1, Circle C2, vector<Point>& sol)       //求圆与圆的交点
184 {
185     double d = Length(C1.c - C2.c);
186     if(dcmp(d) == 0)
187     {
188         if(dcmp(C1.r - C2.r) == 0) return -1;       //两圆重合
189         return 0;       //同心圆但不重合
190     }
191     if(dcmp(C1.r + C2.r - d) < 0) return 0;     //外离
192     if(dcmp(fabs(C1.r - C2.r) - d) > 0) return 0;       //内含
193     double a = angle(C2.c - C1.c);
194     double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d));
195     Point p1 = C1.point(a + da);
196     Point p2 = C1.point(a - da);
197     sol.push_back(p1);
198     if(p1 == p2) return 1;      //外切
199     sol.push_back(p2);
200     return 2;
201 }
202 
203 Circle CircumscribedCircle(Point p1, Point p2, Point p3)        //求三角形的外心
204 {
205     double Bx = p2.x - p1.x, By = p2.y - p1.y;
206     double Cx = p3.x - p1.x, Cy = p3.y - p1.y;
207     double D = 2 * (Bx * Cy - By * Cx);
208     double cx = (Cy * (Bx * Bx + By * By) - By * (Cx * Cx + Cy * Cy)) / D + p1.x;
209     double cy = (Bx * (Cx * Cx + Cy * Cy) - Cx * (Bx * Bx + By * By)) / D + p1.y;
210     Point p(cx, cy);
211     return Circle(p, Length(p1-p));
212 }
213 
214 Circle InscribedCircle(Point p1, Point p2, Point p3)        //求三角形的内切圆
215 {
216     double a = Length(p3 - p2);
217     double b = Length(p3 - p1);
218     double c = Length(p2 - p1);
219     Point p = (p1 * a + p2 * b + p3 * c) / (a + b + c);
220     return Circle(p, DistanceToLine(p, p2, p3));
221 }
222 
223 int TangentLineThroughPoint(Point p, Circle C, Vector *v)       //求点到圆的直线
224 {
225     Vector u = C.c - p;
226     double dist = Length(u);
227     if(dcmp(dist - C.r) < 0) return 0;
228     else if(dcmp(dist - C.r) < eps)
229     {
230         v[0] = Rotate(u, pi / 2);
231         return 1;
232     }
233     else
234     {
235         double ang = asin(C.r / dist);
236         v[0] = Rotate(u, ang);
237         v[1] = Rotate(u, -ang);
238         return 2;
239     }
240 }
241 
242 void CircleThroughAPointAndTangentToALineWithRadius(Point p, Point p1, Point p2, double r)
243 {
244     Vector AB = p2 - p1;
245     Vector change1 = Rotate(AB, pi / 2) / Length(AB) * r;
246     Vector change2 = Rotate(AB, -pi / 2) / Length(AB) * r;
247     Line l1(p1 + change1, AB);
248     Line l2(p1 + change2, AB);
249     vector<Point> sol;
250     sol.clear();
251     double t1, t2;
252     int cnt1 = getLineCircleIntersection(l1, Circle(p, r), t1, t2, sol);
253     int cnt2 = getLineCircleIntersection(l2, Circle(p, r), t1, t2, sol);
254     int cnt = cnt1 + cnt2;
255     if(cnt) sort(sol.begin(), sol.end());
256     printf("[");
257     for(int i = 0; i < cnt; i++)
258     {
259         printf("(%.6f,%.6f)", sol[i].x, sol[i].y);
260         if(cnt == 2 && !i) printf(",");
261     }
262     puts("]");
263 }
264 
265 void CircleTangentToTwoLinesWithRadius(Point A, Point B, Point C, Point D, double r)
266 {
267     Vector AB = B - A;
268     Vector change = Normal(AB) * r;
269     Point newA1 = A + change;
270     Point newA2 = A - change;
271     Vector CD = D - C;
272     Vector update = Normal(CD) * r;
273     Point newC1 = C + update;
274     Point newC2 = C - update;
275     Point p[5];
276     p[0] = GetLineIntersection(Line(newA1, AB), Line(newC1, CD));
277     p[1] = GetLineIntersection(Line(newA1, AB), Line(newC2, CD));
278     p[2] = GetLineIntersection(Line(newA2, AB), Line(newC1, CD));
279     p[3] = GetLineIntersection(Line(newA2, AB), Line(newC2, CD));
280     sort(p, p + 4);
281     printf("[");
282     printf("(%.6f,%.6f)", p[0].x, p[0].y);
283     for(int i = 1; i < 4; i++)
284     {
285         printf(",(%.6f,%.6f)", p[i].x, p[i].y);
286     }
287     puts("]");
288 }
289 
290 void CircleTangentToTwoDisjointCirclesWithRadius(Circle C1, Circle C2, double r)
291 {
292     Vector CC = C2.c - C1.c;
293     double rdist = Length(CC);
294     if(dcmp(2 * r - rdist + C1.r + C2.r) < 0) puts("[]");
295     else if(dcmp(2 * r - rdist + C1.r + C2.r) == 0)
296     {
297         double ang = angle(CC);
298         Point A = C1.point(ang);
299         Point B = C2.point(ang + pi);
300         Point ret = (A + B) / 2;
301         printf("[(%.6f,%.6f)]\n", ret.x, ret.y);
302     }
303     else
304     {
305         Circle A = Circle(C1.c, C1.r + r);
306         Circle B = Circle(C2.c, C2.r + r);
307         vector<Point> sol;
308         sol.clear();
309         GetCircleCircleIntersection(A, B, sol);
310         sort(sol.begin(), sol.end());
311         printf("[(%.6f,%.6f),(%.6f,%.6f)]\n", sol[0].x, sol[0].y, sol[1].x, sol[1].y);
312     }
313 }
314 
315 int main()
316 {
317     while(scanf("%s", type) == 1)
318     {
319         if(strcmp(type, "CircumscribedCircle") == 0)
320         {
321             Point p1, p2, p3;
322             p1.read();
323             p2.read();
324             p3.read();
325             Circle ret = CircumscribedCircle(p1, p2, p3);
326             printf("(%f,%f,%f)\n", ret.c.x, ret.c.y, ret.r);
327         }
328         else if(strcmp(type, "InscribedCircle") == 0)
329         {
330             Point p1, p2, p3;
331             p1.read();
332             p2.read();
333             p3.read();
334             Circle ret = InscribedCircle(p1, p2, p3);
335             printf("(%f,%f,%f)\n", ret.c.x, ret.c.y, ret.r);
336         }
337         else if(strcmp(type, "TangentLineThroughPoint") == 0)
338         {
339             Circle C;
340             Point p;
341             C.read();
342             p.read();
343             Vector v[3];
344             int cnt = TangentLineThroughPoint(p, C, v);
345             double ret[3];
346             for(int i = 0; i < cnt; i++)
347             {
348                 ret[i] = angle(v[i]);
349                 if(dcmp(ret[i] - pi) == 0) ret[i] = 0;
350                 if(dcmp(ret[i]) < 0) ret[i] += pi;
351             }
352             sort(ret, ret + cnt);
353             printf("[");
354             for(int i = 0; i < cnt; i++)
355             {
356                 printf("%.6f", ret[i] / pi * 180);
357                 if(cnt == 2 && !i) printf(",");
358             }
359             puts("]");
360         }
361         else if(strcmp(type, "CircleThroughAPointAndTangentToALineWithRadius") == 0)
362         {
363             Point p, p1, p2;
364             double r;
365             p.read();
366             p1.read();
367             p2.read();
368             scanf("%lf", &r);
369             CircleThroughAPointAndTangentToALineWithRadius(p, p1, p2, r);
370         }
371         else if(strcmp(type, "CircleTangentToTwoLinesWithRadius") == 0)
372         {
373             Point A, B, C, D;
374             double r;
375             A.read();
376             B.read();
377             C.read();
378             D.read();
379             scanf("%lf", &r);
380             CircleTangentToTwoLinesWithRadius(A, B, C, D, r);
381         }
382         else
383         {
384             Circle C1, C2;
385             double r;
386             C1.read();
387             C2.read();
388             scanf("%lf", &r);
389             CircleTangentToTwoDisjointCirclesWithRadius(C1, C2, r);
390         }
391     }
392     return 0;
393 }
View Code

 

uva 12304

标签:

原文地址:http://www.cnblogs.com/ITUPC/p/4870049.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!