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 }

 

你可能感兴趣的:(try)