zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    【Linux】5.5 Shell运算符
    【Linux】5.4 Shell数组
    【Linux】5.3 Shell字符串
    【Linux】5.2 Shell变量
    【Linux】5.1 Shell简介
    【Linux】3.11 包管理工具(RPM和YUM)
    【Linux】3.10 进程管理(重点)
    【Linux】3.9 网络配置
    【Linux】3.8 Linux磁盘分区、挂载
    【Linux】3.7 定时任务调度
  • 原文地址:https://www.cnblogs.com/CSGrandeur/p/2668532.html
Copyright © 2011-2022 走看看