UVA12304_2D Geometry 110 in 1!

各种点线与圆的关系。

1、三角形外接圆:求各边中垂线交点;

2、三角形内切圆:定比分点构造等腰三角形求角平分线,求两角平分线交点;

3、定点到圆切线:点到圆心斜率加减切线夹角,处理结果的表示范围;

4、切直线、过定点的圆:点在线上是两个对称的圆,否则圆在点线确定的双曲线上,利用双曲线性质构造直角梯形,然后利用向量与定比分点求;

5、与两相交直线相切的圆:分别将直线朝不同方向平移半径距离求交点;

6、两相离圆的公共外切圆:三圆心连线构成三角形,所求圆心做三角形的高,余弦定理+定比分点求出各项数据。

特殊情况进行特判求值。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<math.h>
  5 #include<algorithm>
  6 using namespace std;
  7 const double eps = 1e-10;
  8 const double pi = acos(-1.0);
  9 char buf[100];
 10 char task[6][100] = {
 11     "CircumscribedCircle",
 12     "InscribedCircle",
 13     "TangentLineThroughPoint",
 14     "CircleThroughAPointAndTangentToALineWithRadius",
 15     "CircleTangentToTwoLinesWithRadius",
 16     "CircleTangentToTwoDisjointCirclesWithRadius"
 17     };
 18 inline double Sqr(double x)
 19 {return x * x;}
 20 inline int dcmp(double x)
 21 {
 22     if(x > eps) return 1;
 23     return x < -eps ? -1 : 0;
 24 }
 25 inline double pz(double x)
 26 {return dcmp(x) ? x : 0;}
 27 struct Point
 28 {
 29     double x, y;
 30     Point(){x = y = 0;}
 31     Point(double a, double b)
 32     {x = a, y = b;}
 33     Point operator-(const Point &b)const
 34     {return Point(x - b.x, y - b.y);}
 35     Point operator+(const Point &b)const
 36     {return Point(x + b.x, y + b.y);}
 37     Point operator-()
 38     {return Point(-x, -y);}
 39     Point operator*(const double &b)const
 40     {return Point(x * b, y * b);}
 41     double dot(const Point &b)const
 42     {return x * b.x + y * b.y;}
 43     double cross(const Point &b, const Point &c)const
 44     {return (b.x - x) * (c.y - y) - (c.x - x) * (b.y - y);}
 45     double Dis(const Point &b)const
 46     {return sqrt((*this - b).dot(*this - b));}
 47     bool operator<(const Point &b)const
 48     {
 49         if(!dcmp(x - b.x)) return y < b.y;
 50         return x < b.x;
 51     }
 52     bool operator>(const Point &b)const
 53     {return b < *this;}
 54 };
 55 inline double min(double a, double b)
 56 {return a < b ? a : b;}
 57 inline double max(double a, double b)
 58 {return a > b ? a : b;}
 59 inline Point min(Point a, Point b)
 60 {return a < b ? a : b;}
 61 inline Point max(Point a, Point b)
 62 {return a > b ? a : b;}
 63 Point CrossPoint(Point a, Point b, Point c, Point d)
 64 {
 65     double u = a.cross(b, c), v = b.cross(a, d);
 66     return Point((c.x * v + d.x * u) / (u + v), (c.y * v + d.y * u) / (u + v));
 67 }
 68 int Task(char *s)
 69 {
 70     for(int i = 0; i < 6; ++ i)
 71         if(!strcmp(s, task[i])) return i;
 72 }
 73 
 74 void CC()   //外接圆
 75 {
 76     Point a, b, c, ab, ac, r;
 77     scanf("%lf%lf%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y, &c.x, &c.y);
 78     ab = (a + b) * 0.5, ac = (a + c) * 0.5;
 79     r = CrossPoint(ab, Point(ab.x + a.y - b.y, ab.y + b.x - a.x), 
 80         ac, Point(ac.x + a.y - c.y, ac.y + c.x - a.x));
 81     printf("(%.6f,%.6f,%.6f)\n", 
 82         eps + pz(r.x), eps + pz(r.y), eps + pz(r.Dis(a)));
 83 }
 84 void IC()   //内切圆
 85 {
 86     Point a, b, c, apf, bpf, r;
 87     scanf("%lf%lf%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y, &c.x, &c.y);
 88     double la = b.Dis(c), lb = a.Dis(c), lc = a.Dis(b), p = (la + lb + lc) * 0.5;
 89     apf = (c + a + (b - a) * (lb / lc)) * 0.5;
 90     bpf = (c + b + (a - b) * (la / lc)) * 0.5;
 91     r = CrossPoint(a, apf, b, bpf);
 92     printf("(%.6f,%.6f,%.6f)\n", eps + pz(r.x), eps + pz(r.y), 
 93         eps + pz(sqrt(p * (p - la) * (p - lb) * (p - lc)) * 2 / (la + lb + lc)));
 94 }
 95 double ManageDeg(double x)
 96 {
 97     while(x < -eps) x += pi;
 98     while(x > pi - eps) x -= pi;
 99     return x;
100 }
101 void TLTP() //点到圆切线
102 {
103     Point a, r;
104     double R, ang, ang1, ang2;
105     scanf("%lf%lf%lf%lf%lf", &r.x, &r.y, &R, &a.x, &a.y);
106     ang = atan2(r.y - a.y, r.x - a.x);
107     switch(dcmp(a.Dis(r) - R))
108     {
109         case 0:
110             printf("[%.6f]\n", eps + pz(ManageDeg(ang + pi * 0.5) / pi * 180));
111             break;
112         case 1:
113             ang1 = ManageDeg(ang + asin(R / a.Dis(r))) / pi * 180;
114             ang2 = ManageDeg(ang - asin(R / a.Dis(r))) / pi * 180;
115             printf("[%.6f,%.6f]\n", eps + pz(min(ang1, ang2)), 
116                 eps + pz(max(ang1, ang2)));
117             break;
118         default:
119             printf("[]\n");
120     }
121 }
122 void CTAPATTAWR()//切直线且经定点、半径定值的圆
123 {
124     Point p, a, b, pcl, pcz, r1, r2, xl;
125     double R, rcp;
126     scanf("%lf%lf%lf%lf%lf%lf%lf", &p.x, &p.y, &a.x, &a.y, &b.x, &b.y, &R);
127     pcl = Point(p.x + a.y - b.y, p.y + b.x - a.x);//pcl-p 垂线向量
128     pcz = CrossPoint(p, pcl, a, b);//垂足
129     if(!dcmp(p.cross(a, b)))
130     {
131         r1 = p + (pcl - p) * (R / p.Dis(pcl));
132         r2 = p - (pcl - p) * (R / p.Dis(pcl));
133         printf("[(%.6f,%.6f),", eps + pz(min(r1, r2).x), eps + pz(min(r1, r2).y));
134         printf("(%.6f,%.6f)]\n", eps + pz(max(r1, r2).x), eps + pz(max(r1, r2).y));
135     }
136     else if(!dcmp(R - p.Dis(pcz) * 0.5))
137     {
138         r1 = (p + pcz) * 0.5;
139         printf("[(%.6f,%.6f)]\n", eps + pz(r1.x), eps + pz(r1.y));
140     }
141     else if(dcmp(R - p.Dis(pcz) * 0.5) > 0)//利用双曲线性质,构造直角梯形求解。
142     {
143         rcp = sqrt(R * R - Sqr(R - p.Dis(pcz)));//直角梯形的高。。。
144         r1 = pcz + (a - b) * (rcp / (a.Dis(b))) + (p - pcz) * (R / p.Dis(pcz));
145         r2 = pcz - (a - b) * (rcp / (a.Dis(b))) + (p - pcz) * (R / p.Dis(pcz));
146         printf("[(%.6f,%.6f),", eps + pz(min(r1, r2).x), eps + pz(min(r1, r2).y));
147         printf("(%.6f,%.6f)]\n", eps + pz(max(r1, r2).x), eps + pz(max(r1, r2).y));
148     }
149     else printf("[]\n");
150 
151 }
152 void CTTTLWR()//与两相交直线相切的圆
153 {
154     Point a, b, c, d, A, B, C, D, jd, xl1, xl2, r[4];
155     double R, R_, ang, l1, l2;
156     scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf", 
157         &a.x, &a.y, &b.x, &b.y, &c.x, &c.y, &d.x, &d.y, &R);
158     xl1 = Point(a.y - b.y, b.x - a.x); xl1 = xl1 * (R / sqrt(xl1.dot(xl1)));
159     xl2 = Point(c.y - d.y, d.x - c.x); xl2 = xl2 * (R / sqrt(xl2.dot(xl2)));
160     r[0] = CrossPoint(a + xl1, b + xl1, c + xl2, d + xl2);
161     r[1] = CrossPoint(a + xl1, b + xl1, c - xl2, d - xl2);
162     r[2] = CrossPoint(a - xl1, b - xl1, c + xl2, d + xl2);
163     r[3] = CrossPoint(a - xl1, b - xl1, c - xl2, d - xl2);
164     sort(r, r + 4);
165     printf("[");
166     for(int i = 0; i < 4; ++ i)
167     {
168         if(i)printf(",");
169         printf("(%.6f,%.6f)", eps + pz(r[i].x), eps + pz(r[i].y));
170     }
171     printf("]\n");
172 }
173 void CTTTDCWR()//两相离圆的公共外切圆
174 {
175     Point r1, r2, r[2], zd, xl;
176     double R1, R2, R, len;
177     scanf("%lf%lf%lf%lf%lf%lf%lf", &r1.x, &r1.y, &R1, &r2.x, &r2.y, &R2, &R);
178     if(!dcmp(R + R1 + R + R2 - r1.Dis(r2)))
179     {
180         r[0] = r1 + (r2 - r1) * ((R + R1) / (R + R1 + R + R2));
181         printf("[(%.6f,%.6f)]\n", eps + pz(r[0].x), eps + pz(r[0].y));
182     }
183     else if(dcmp(R + R1 + R + R2 - r1.Dis(r2)) > 0)
184     {
185         zd = r1 + (r2 - r1) * (((R + R1) * (Sqr(R + R1) + Sqr(r1.Dis(r2)) - Sqr(R + R2)) * 
186             0.5 / (R + R1) / r1.Dis(r2)) / r1.Dis(r2));//对称圆心的中点
187         len = sqrt(Sqr(R + R1) - Sqr(zd.Dis(r1)));//zd到所求圆心距离
188         xl = Point(r1.y - r2.y, r2.x - r1.x);//zd到所求圆心的向量
189         r[0] = zd + xl * (len / sqrt(xl.dot(xl)));
190         r[1] = zd - xl * (len / sqrt(xl.dot(xl)));
191         sort(r, r + 2);
192         printf("[(%.6f,%.6f),(%.6f,%.6f)]\n", 
193             eps + pz(r[0].x), eps + pz(r[0].y), eps + pz(r[1].x), eps + pz(r[1].y));
194     }
195     else printf("[]\n");
196 }
197 int main()
198 {
199     while(scanf("%s", buf) != EOF)
200     {
201         switch(Task(buf))
202         {
203             case 0: CC();break;
204             case 1: IC();break;
205             case 2: TLTP();break;
206             case 3: CTAPATTAWR();break;
207             case 4: CTTTLWR();break;
208             case 5: CTTTDCWR();break;
209         }
210     }
211     return 0;
212 }

 

转载于:https://www.cnblogs.com/CSGrandeur/archive/2012/09/03/2668532.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值