uva 12304 2D Geometry 110 in 1! (Geometry)

uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3726

  新增加与圆有关的模板,过了这题。

  使用模板的时候犯了一个小错误,忘记了自己的点到直线的距离是一个有向距离,结果就把自己坑了。

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <set>
  5 #include <vector>
  6 #include <iostream>
  7 #include <algorithm>
  8 
  9 using namespace std;
 10 
 11 #define REP(i, n) for (int i = 0; i < (n); i++)
 12 
 13 struct Point {
 14     double x, y;
 15     Point() {}
 16     Point(double x, double y) : x(x), y(y) {}
 17 } ;
 18 template<class T> T sqr(T x) { return x * x;}
 19 inline double ptDis(Point a, Point b) { return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
 20 
 21 // basic calculations
 22 typedef Point Vec;
 23 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
 24 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
 25 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
 26 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
 27 
 28 const double eps = 1e-8;
 29 const double pi = acos(-1.0);
 30 inline int sgn(double x) { return fabs(x) < eps ? 0 : (x < 0 ? -1 : 1);}
 31 bool operator < (Point a, Point b) { return a.x < b.x || (a.x == b.x && a.y < b.y);}
 32 bool operator == (Point a, Point b) { return sgn(a.x - b.x) == 0 && sgn(a.y - b.y) == 0;}
 33 
 34 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
 35 inline double vecLen(Vec x) { return sqrt(sqr(x.x) + sqr(x.y));}
 36 inline double angle(Vec v) { return atan2(v.y, v.x);}
 37 inline double angle(Vec a, Vec b) { return acos(dotDet(a, b) / vecLen(a) / vecLen(b));}
 38 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
 39 inline double triArea(Point a, Point b, Point c) { return fabs(crossDet(b - a, c - a));}
 40 inline Vec vecUnit(Vec x) { return x / vecLen(x);}
 41 inline Vec rotate(Vec x, double rad) { return Vec(x.x * cos(rad) - x.y * sin(rad), x.x * sin(rad) + x.y * cos(rad));}
 42 Vec normal(Vec x) {
 43     double len = vecLen(x);
 44     return Vec(- x.y / len, x.x / len);
 45 }
 46 
 47 struct Line {
 48     Point s, t;
 49     Line() {}
 50     Line(Point s, Point t) : s(s), t(t) {}
 51     Point point(double x) {
 52         return s + (t - s) * x;
 53     }
 54 } ;
 55 typedef Line Seg;
 56 
 57 inline bool onSeg(Point x, Point a, Point b) { return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0;}
 58 inline bool onSeg(Point x, Seg s) { return onSeg(x, s.s, s.t);}
 59 
 60 // 0 : not intersect
 61 // 1 : proper intersect
 62 // 2 : improper intersect
 63 int segIntersect(Point a, Point c, Point b, Point d) {
 64     Vec v1 = b - a, v2 = c - b, v3 = d - c, v4 = a - d;
 65     int a_bc = sgn(crossDet(v1, v2));
 66     int b_cd = sgn(crossDet(v2, v3));
 67     int c_da = sgn(crossDet(v3, v4));
 68     int d_ab = sgn(crossDet(v4, v1));
 69     if (a_bc * c_da > 0 && b_cd * d_ab > 0) return 1;
 70     if (onSeg(b, a, c) && c_da) return 2;
 71     if (onSeg(c, b, d) && d_ab) return 2;
 72     if (onSeg(d, c, a) && a_bc) return 2;
 73     if (onSeg(a, d, b) && b_cd) return 2;
 74     return 0;
 75 }
 76 inline int segIntersect(Seg a, Seg b) { return segIntersect(a.s, a.t, b.s, b.t);}
 77 
 78 // point of the intersection of 2 lines
 79 Point lineIntersect(Point P, Vec v, Point Q, Vec w) {
 80     Vec u = P - Q;
 81     double t = crossDet(w, u) / crossDet(v, w);
 82     return P + v * t;
 83 }
 84 inline Point lineIntersect(Line a, Line b) { return lineIntersect(a.s, a.t - a.s, b.s, b.t - b.s);}
 85 
 86 // Warning: This is a DIRECTED Distance!!!
 87 double pt2Line(Point x, Point a, Point b) {
 88     Vec v1 = b - a, v2 = x - a;
 89     return crossDet(v1, v2) / vecLen(v1);
 90 }
 91 inline double pt2Line(Point x, Line L) { return pt2Line(x, L.s, L.t);}
 92 
 93 double pt2Seg(Point x, Point a, Point b) {
 94     if (a == b) return vecLen(x - a);
 95     Vec v1 = b - a, v2 = x - a, v3 = x - b;
 96     if (sgn(dotDet(v1, v2)) < 0) return vecLen(v2);
 97     if (sgn(dotDet(v1, v3)) > 0) return vecLen(v3);
 98     return fabs(crossDet(v1, v2)) / vecLen(v1);
 99 }
100 inline double pt2Seg(Point x, Seg s) { return pt2Seg(x, s.s, s.t);}
101 
102 struct Poly {
103     vector<Point> pt;
104     Poly() {}
105     Poly(vector<Point> pt) : pt(pt) {}
106     double area() {
107         double ret = 0.0;
108         int sz = pt.size();
109         for (int i = 1; i < sz; i++) {
110             ret += crossDet(pt[i], pt[i - 1]);
111         }
112         return fabs(ret / 2.0);
113     }
114 } ;
115 
116 struct Circle {
117     Point c;
118     double r;
119     Circle(Point c, double r) : c(c), r(r) {}
120     Point point(double a) {
121         return Point(c.x + cos(a) * r, c.y + sin(a) * r);
122     }
123 } ;
124 
125 int lineCircleIntersect(Line L, Circle C, double &t1, double &t2, vector<Point> &sol) {
126     double a = L.s.x, b = L.t.x - C.c.x, c = L.s.y, d = L.t.y - C.c.y;
127     double e = sqr(a) + sqr(c), f = 2 * (a * b + c * d), g = sqr(b) + sqr(d) - sqr(C.r);
128     double delta = sqr(f) - 4.0 * e * g;
129     if (sgn(delta) < 0) return 0;
130     if (sgn(delta) == 0) {
131         t1 = t2 = -f / (2.0 * e);
132         sol.push_back(L.point(t1));
133         return 1;
134     }
135     t1 = (-f - sqrt(delta)) / (2.0 * e);
136     sol.push_back(L.point(t1));
137     t2 = (-f + sqrt(delta)) / (2.0 * e);
138     sol.push_back(L.point(t2));
139     return 2;
140 }
141 
142 int lineCircleIntersect(Line L, Circle C, vector<Point> &sol) {
143     Vec dir = L.t - L.s, nor = normal(dir);
144     Point mid = lineIntersect(C.c, nor, L.s, dir);
145     double len = sqr(C.r) - sqr(ptDis(C.c, mid));
146     if (sgn(len) < 0) return 0;
147     if (sgn(len) == 0) {
148         sol.push_back(mid);
149         return 1;
150     }
151     Vec dis = vecUnit(dir);
152     len = sqrt(len);
153     sol.push_back(mid + dis * len);
154     sol.push_back(mid - dis * len);
155     return 2;
156 }
157 
158 // -1 : coincide
159 int circleCircleIntersect(Circle C1, Circle C2, vector<Point> &sol) {
160     double d = vecLen(C1.c - C2.c);
161     if (sgn(d) == 0) {
162         if (sgn(C1.r - C2.r) == 0) {
163             return -1;
164         }
165         return 0;
166     }
167     if (sgn(C1.r + C2.r - d) < 0) return 0;
168     if (sgn(fabs(C1.r - C2.r) - d) > 0) return 0;
169     double a = angle(C2.c - C1.c);
170     double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2.0 * C1.r * d));
171     Point p1 = C1.point(a - da), p2 = C1.point(a + da);
172     sol.push_back(p1);
173     if (p1 == p2) return 1;
174     sol.push_back(p2);
175     return 2;
176 }
177 
178 int tangent(Point p, Circle C, vector<Vec> &sol) {
179     Vec u = C.c - p;
180     double dist = vecLen(u);
181     if (dist < C.r) return 0;
182     if (sgn(dist - C.r) == 0) {
183         sol.push_back(rotate(u, pi / 2.0));
184         return 1;
185     }
186     double ang = asin(C.r / dist);
187     sol.push_back(rotate(u, -ang));
188     sol.push_back(rotate(u, ang));
189     return 2;
190 }
191 
192 // ptA : points of tangency on circle A
193 // ptB : points of tangency on circle B
194 int tangent(Circle A, Circle B, vector<Point> &ptA, vector<Point> &ptB) {
195     if (A.r < B.r) {
196         swap(A, B);
197         swap(ptA, ptB);
198     }
199     int d2 = sqr(A.c.x - B.c.x) + sqr(A.c.y - B.c.y);
200     int rdiff = A.r - B.r, rsum = A.r + B.r;
201     if (d2 < sqr(rdiff)) return 0;
202     double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);
203     if (d2 == 0 && A.r == B.r) return -1;
204     if (d2 == sqr(rdiff)) {
205         ptA.push_back(A.point(base));
206         ptB.push_back(B.point(base));
207         return 1;
208     }
209     double ang = acos((A.r - B.r) / sqrt(d2));
210     ptA.push_back(A.point(base + ang));
211     ptB.push_back(B.point(base + ang));
212     ptA.push_back(A.point(base - ang));
213     ptB.push_back(B.point(base - ang));
214     if (d2 == sqr(rsum)) {
215         ptA.push_back(A.point(base));
216         ptB.push_back(B.point(pi + base));
217     } else if (d2 > sqr(rsum)) {
218         ang = acos((A.r + B.r) / sqrt(d2));
219         ptA.push_back(A.point(base + ang));
220         ptB.push_back(B.point(pi + base + ang));
221         ptA.push_back(A.point(base - ang));
222         ptB.push_back(B.point(pi + base - ang));
223     }
224     return (int) ptA.size();
225 }
226 
227 /****************** template above *******************/
228 
229 const char *str[6] = { "CircumscribedCircle", "InscribedCircle", "TangentLineThroughPoint", "CircleThroughAPointAndTangentToALineWithRadius", "CircleTangentToTwoLinesWithRadius", "CircleTangentToTwoDisjointCirclesWithRadius"};
230 bool cmp(Circle x, Circle y) { return x.c < y.c || (x.c == y.c && x.r < y.r);}
231 
232 Circle work1(Point p1, Point p2, Point p3) {
233     Vec nor1 = normal(p1 - p2);
234     Vec nor2 = normal(p2 - p3);
235     Point mid1 = (p1 + p2) / 2.0;
236     Point mid2 = (p2 + p3) / 2.0;
237     Point O = lineIntersect(mid1, nor1, mid2, nor2);
238     double r = ptDis(O, p1);
239     return Circle(O, r);
240 }
241 
242 Circle work2(Point p1, Point p2, Point p3) {
243     Vec v11 = p2 - p1;
244     Vec v12 = p3 - p1;
245     Vec v21 = p1 - p2;
246     Vec v22 = p3 - p2;
247     double ang1 = (angle(v11) + angle(v12)) / 2.0;
248     double ang2 = (angle(v21) + angle(v22)) / 2.0;
249     Vec vec1 = Vec(cos(ang1), sin(ang1));
250     Vec vec2 = Vec(cos(ang2), sin(ang2));
251     Point O = lineIntersect(p1, vec1, p2, vec2);
252     double r = pt2Line(O, p1, p2);
253     return Circle(O, fabs(r));
254 }
255 
256 vector<double> work3(Circle C, Point p) {
257     vector<double> ret;
258     vector<Vec> tmp;
259     ret.clear();
260     int cnt = tangent(p, C, tmp);
261     for (int i = 0; i < cnt; i++) {
262         double ang = angle(tmp[i]);
263         if (ang < 0) ang += pi;
264         ang = fmod(ang, pi);
265         ret.push_back(ang * 180 / pi);
266     }
267     return ret;
268 }
269 
270 vector<Point> work4(Point p, Line l, double r) {
271     Vec vec = l.t - l.s;
272     Vec nor = normal(vec);
273     nor = nor / vecLen(nor) * r;
274     vector<Point> ret;
275     ret.clear();
276     lineCircleIntersect(Line(l.s + nor, l.s + nor + vec), Circle(p, r), ret);
277     lineCircleIntersect(Line(l.s - nor, l.s - nor + vec), Circle(p, r), ret);
278     return ret;
279 }
280 
281 vector<Point> work5(Line l1, Line l2, double r) {
282     Vec v1 = l1.t - l1.s;
283     Vec v2 = l2.t - l2.s;
284     Vec nor1 = normal(v1);
285     Vec nor2 = normal(v2);
286     nor1 = nor1 / vecLen(nor1) * r;
287     nor2 = nor2 / vecLen(nor2) * r;
288     vector<Point> ret;
289     ret.clear();
290     ret.push_back(lineIntersect(l1.s + nor1, v1, l2.s + nor2, v2));
291     ret.push_back(lineIntersect(l1.s + nor1, v1, l2.s - nor2, v2));
292     ret.push_back(lineIntersect(l1.s - nor1, v1, l2.s + nor2, v2));
293     ret.push_back(lineIntersect(l1.s - nor1, v1, l2.s - nor2, v2));
294     return ret;
295 }
296 
297 vector<Point> work6(Circle c1, Circle c2, double r) {
298     c1.r += r;
299     c2.r += r;
300     vector<Point> ret;
301     ret.clear();
302     circleCircleIntersect(c1, c2, ret);
303     return ret;
304 }
305 
306 char buf[100];
307 
308 int main() {
309 //    freopen("in", "r", stdin);
310 //    freopen("out", "w", stdout);
311     double x[10];
312     while (cin >> buf) {
313         if (!strcmp(str[0], buf)) {
314             for (int i = 0; i < 6; i++) {
315                 cin >> x[i];
316             }
317             Circle tmp = work1(Point(x[0], x[1]), Point(x[2], x[3]), Point(x[4], x[5]));
318             printf("(%.6f,%.6f,%.6f)\n", tmp.c.x, tmp.c.y, tmp.r);
319         } else if (!strcmp(str[1], buf)) {
320             for (int i = 0; i < 6; i++) {
321                 cin >> x[i];
322             }
323             Circle tmp = work2(Point(x[0], x[1]), Point(x[2], x[3]), Point(x[4], x[5]));
324             printf("(%.6f,%.6f,%.6f)\n", tmp.c.x, tmp.c.y, tmp.r);
325         } else if (!strcmp(str[2] ,buf)) {
326             for (int i = 0; i < 5; i++) {
327                 cin >> x[i];
328             }
329             vector<double> ans = work3(Circle(Point(x[0], x[1]), x[2]), Point(x[3], x[4]));
330             sort(ans.begin(), ans.end());
331             putchar('[');
332             for (int i = 0; i < ans.size(); i++) {
333                 if (i) putchar(',');
334                 printf("%.6f", ans[i]);
335             }
336             puts("]");
337         } else if (!strcmp(str[3], buf)) {
338             for (int i = 0; i < 7; i++) {
339                 cin >> x[i];
340             }
341             vector<Point> ans = work4(Point(x[0], x[1]), Line(Point(x[2], x[3]), Point(x[4], x[5])), x[6]);
342             sort(ans.begin(), ans.end());
343             putchar('[');
344             for (int i = 0; i < ans.size(); i++) {
345                 if (i) putchar(',');
346                 printf("(%.6f,%.6f)", ans[i].x, ans[i].y);
347             }
348             puts("]");
349         } else if (!strcmp(str[4], buf)) {
350             for (int i = 0; i < 9; i++) {
351                 cin >> x[i];
352             }
353             vector<Point> ans = work5(Line(Point(x[0], x[1]), Point(x[2], x[3])), Line(Point(x[4], x[5]), Point(x[6], x[7])), x[8]);
354             sort(ans.begin(), ans.end());
355             putchar('[');
356             for (int i = 0; i < ans.size(); i++) {
357                 if (i) putchar(',');
358                 printf("(%.6f,%.6f)", ans[i].x, ans[i].y);
359             }
360             puts("]");
361         } else if (!strcmp(str[5], buf)) {
362             for (int i = 0; i < 7; i++) {
363                 cin >> x[i];
364             }
365             vector<Point> ans = work6(Circle(Point(x[0], x[1]), x[2]), Circle(Point(x[3], x[4]), x[5]), x[6]);
366             sort(ans.begin(), ans.end());
367             putchar('[');
368             for (int i = 0; i < ans.size(); i++) {
369                 if (i) putchar(',');
370                 printf("(%.6f,%.6f)", ans[i].x, ans[i].y);
371             }
372             puts("]");
373         }
374     }
375     return 0;
376 }

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/uva_12304_Lyon.html