OSDN Git Service

style: format markdown files with remark-lint
author24OI-bot <15963390+24OI-bot@users.noreply.github.com>
Sat, 5 Oct 2019 02:19:33 +0000 (22:19 -0400)
committer24OI-bot <15963390+24OI-bot@users.noreply.github.com>
Sat, 5 Oct 2019 02:19:33 +0000 (22:19 -0400)
docs/geometry/inverse.md

index e26af75..0921964 100644 (file)
@@ -86,121 +86,149 @@ author: hyp1231
     #include <vector>
     using namespace std;
     
-    const double EPS = 1e-8;         //精度系数
-    const double PI = acos(-1.0);    //π
+    const double EPS = 1e-8;       //精度系数
+    const double PI = acos(-1.0);  //π
     const int N = 4;
     
     struct Point {
-        double x, y;
-        Point(double x = 0, double y = 0) :x(x), y(y) {}
-        const bool operator < (Point A)const {
-            return x == A.x ? y < A.y : x < A.x;
-        }
+      double x, y;
+      Point(double x = 0, double y = 0) : x(x), y(y) {}
+      const bool operator<(Point A) const { return x == A.x ? y < A.y : x < A.x; }
     };  //点的定义
     
-    typedef Point Vector;   //向量的定义
+    typedef Point Vector;  //向量的定义
     
-    Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }    //向量加法
-    Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); }    //向量减法
-    Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }        //向量数乘
-    Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y / p); }    //向量数除
+    Vector operator+(Vector A, Vector B) {
+      return Vector(A.x + B.x, A.y + B.y);
+    }  //向量加法
+    Vector operator-(Vector A, Vector B) {
+      return Vector(A.x - B.x, A.y - B.y);
+    }  //向量减法
+    Vector operator*(Vector A, double p) {
+      return Vector(A.x * p, A.y * p);
+    }  //向量数乘
+    Vector operator/(Vector A, double p) {
+      return Vector(A.x / p, A.y / p);
+    }  //向量数除
     
     int dcmp(double x) {
-        if (fabs(x) < EPS)return 0; else return x < 0 ? -1 : 1;
-    }   //与0的关系
+      if (fabs(x) < EPS)
+        return 0;
+      else
+        return x < 0 ? -1 : 1;
+    }  //与0的关系
     
-    double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }    //向量点乘
-    double Length(Vector A) { return sqrt(Dot(A, A)); }     //向量长度
-    double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }    //向量叉乘
+    double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }  //向量点乘
+    double Length(Vector A) { return sqrt(Dot(A, A)); }               //向量长度
+    double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }  //向量叉乘
     
     Point GetLineProjection(Point P, Point A, Point B) {
-        Vector v = B - A;
-        return A + v*(Dot(v, P - A) / Dot(v, v));
-    }   //点在直线上投影
+      Vector v = B - A;
+      return A + v * (Dot(v, P - A) / Dot(v, v));
+    }  //点在直线上投影
     
     struct Circle {
-        Point c;
-        double r;
-        Circle() :c(Point(0, 0)), r(0) {}
-        Circle(Point c, double r = 0) :c(c), r(r) {}
-        Point point(double a) { return Point(c.x + cos(a)*r, c.y + sin(a)*r); }    //输入极角返回点坐标
-    };  //圆
+      Point c;
+      double r;
+      Circle() : c(Point(0, 0)), r(0) {}
+      Circle(Point c, double r = 0) : c(c), r(r) {}
+      Point point(double a) {
+        return Point(c.x + cos(a) * r, c.y + sin(a) * r);
+      }  //输入极角返回点坐标
+    };   //圆
     
     // a[i] 和 b[i] 分别是第i条切线在圆A和圆B上的切点
     int getTangents(Circle A, Circle B, Point* a, Point* b) {
-        int cnt = 0;
-        if (A.r < B.r) { swap(A, B); swap(a, b); }
-        double d2 = (A.c.x - B.c.x)*(A.c.x - B.c.x) + (A.c.y - B.c.y)*(A.c.y - B.c.y);
-        double rdiff = A.r - B.r;
-        double rsum = A.r + B.r;
-        if (dcmp(d2 - rdiff * rdiff) < 0) return 0;    //内含
-        
-        double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);
-        if (dcmp(d2) == 0 && dcmp(A.r - B.r) == 0)return -1;    //无限多条切线
-        if (dcmp(d2 - rdiff*rdiff) == 0) {                //内切,一条切线
-            a[cnt] = A.point(base); b[cnt] = B.point(base); ++cnt;
-            return 1;
-        }
-        //有外公切线
-        double ang = acos(rdiff / sqrt(d2));
-        a[cnt] = A.point(base + ang); b[cnt] = B.point(base + ang); ++cnt;
-        a[cnt] = A.point(base - ang); b[cnt] = B.point(base - ang); ++cnt;
-        if (dcmp(d2 - rsum*rsum) == 0) {                  //一条内公切线
-            a[cnt] = A.point(base); b[cnt] = B.point(PI + base); ++cnt;
-        } else if (dcmp(d2 - rsum*rsum) > 0) {            //两条内公切线
-            double ang = acos(rsum / sqrt(d2));
-            a[cnt] = A.point(base + ang); b[cnt] = B.point(PI + base + ang); ++cnt;
-            a[cnt] = A.point(base - ang); b[cnt] = B.point(PI + base - ang); ++cnt;
-        }
-        return cnt;
-    }   // 两圆公切线 返回切线的条数,-1表示无穷多条切线
+      int cnt = 0;
+      if (A.r < B.r) {
+        swap(A, B);
+        swap(a, b);
+      }
+      double d2 =
+          (A.c.x - B.c.x) * (A.c.x - B.c.x) + (A.c.y - B.c.y) * (A.c.y - B.c.y);
+      double rdiff = A.r - B.r;
+      double rsum = A.r + B.r;
+      if (dcmp(d2 - rdiff * rdiff) < 0) return 0;  //内含
+    
+      double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);
+      if (dcmp(d2) == 0 && dcmp(A.r - B.r) == 0) return -1;  //无限多条切线
+      if (dcmp(d2 - rdiff * rdiff) == 0) {                   //内切,一条切线
+        a[cnt] = A.point(base);
+        b[cnt] = B.point(base);
+        ++cnt;
+        return 1;
+      }
+      //有外公切线
+      double ang = acos(rdiff / sqrt(d2));
+      a[cnt] = A.point(base + ang);
+      b[cnt] = B.point(base + ang);
+      ++cnt;
+      a[cnt] = A.point(base - ang);
+      b[cnt] = B.point(base - ang);
+      ++cnt;
+      if (dcmp(d2 - rsum * rsum) == 0) {  //一条内公切线
+        a[cnt] = A.point(base);
+        b[cnt] = B.point(PI + base);
+        ++cnt;
+      } else if (dcmp(d2 - rsum * rsum) > 0) {  //两条内公切线
+        double ang = acos(rsum / sqrt(d2));
+        a[cnt] = A.point(base + ang);
+        b[cnt] = B.point(PI + base + ang);
+        ++cnt;
+        a[cnt] = A.point(base - ang);
+        b[cnt] = B.point(PI + base - ang);
+        ++cnt;
+      }
+      return cnt;
+    }  // 两圆公切线 返回切线的条数,-1表示无穷多条切线
     
     Circle Inversion_C2C(Point O, double R, Circle A) {
-        double OA = Length(A.c - O);
-        double RB = 0.5 * ((1 / (OA - A.r)) - (1 / (OA + A.r))) * R * R;
-        double OB = OA * RB / A.r;
-        double Bx = O.x + (A.c.x - O.x) * OB / OA;
-        double By = O.y + (A.c.y - O.y) * OB / OA;
-        return Circle(Point(Bx, By), RB);
-    }   // 点 O 在圆 A 外,求圆 A 的反演圆 B,R 是反演半径
+      double OA = Length(A.c - O);
+      double RB = 0.5 * ((1 / (OA - A.r)) - (1 / (OA + A.r))) * R * R;
+      double OB = OA * RB / A.r;
+      double Bx = O.x + (A.c.x - O.x) * OB / OA;
+      double By = O.y + (A.c.y - O.y) * OB / OA;
+      return Circle(Point(Bx, By), RB);
+    }  // 点 O 在圆 A 外,求圆 A 的反演圆 B,R 是反演半径
     
     Circle Inversion_L2C(Point O, double R, Point A, Vector v) {
-        Point P = GetLineProjection(O, A, A + v);
-        double d = Length(O - P);
-        double RB = R * R / (2 * d);
-        Vector VB = (P - O) / d * RB;
-        return Circle(O + VB, RB);
-    }   // 直线反演为过 O 点的圆 B,R 是反演半径
+      Point P = GetLineProjection(O, A, A + v);
+      double d = Length(O - P);
+      double RB = R * R / (2 * d);
+      Vector VB = (P - O) / d * RB;
+      return Circle(O + VB, RB);
+    }  // 直线反演为过 O 点的圆 B,R 是反演半径
     
     bool theSameSideOfLine(Point A, Point B, Point S, Vector v) {
-        return dcmp(Cross(A - S, v)) * dcmp(Cross(B - S, v)) > 0;
-    }   // 返回 true 如果 A B 两点在直线同侧
+      return dcmp(Cross(A - S, v)) * dcmp(Cross(B - S, v)) > 0;
+    }  // 返回 true 如果 A B 两点在直线同侧
     
     int main() {
-        int T;
-        scanf("%d", &T);
-        while (T--) {
-            Circle A, B;
-            Point P;
-            scanf("%lf%lf%lf", &A.c.x, &A.c.y, &A.r);
-            scanf("%lf%lf%lf", &B.c.x, &B.c.y, &B.r);
-            scanf("%lf%lf", &P.x, &P.y);
-            Circle NA = Inversion_C2C(P, 10, A);
-            Circle NB = Inversion_C2C(P, 10, B);
-            Point LA[N], LB[N];
-            Circle ansC[N];
-            int q = getTangents(NA, NB, LA, LB), ans = 0;
-            for (int i = 0; i < q; ++i) if (theSameSideOfLine(NA.c, NB.c, LA[i], LB[i] - LA[i])) {
-                if (!theSameSideOfLine(P, NA.c, LA[i], LB[i] - LA[i])) continue;
-                ansC[ans++] = Inversion_L2C(P, 10, LA[i], LB[i] - LA[i]);
-            }
-            printf("%d\n", ans);
-            for (int i = 0; i < ans; ++i) {
-                printf("%.8f %.8f %.8f\n", ansC[i].c.x, ansC[i].c.y, ansC[i].r);
-            }
+      int T;
+      scanf("%d", &T);
+      while (T--) {
+        Circle A, B;
+        Point P;
+        scanf("%lf%lf%lf", &A.c.x, &A.c.y, &A.r);
+        scanf("%lf%lf%lf", &B.c.x, &B.c.y, &B.r);
+        scanf("%lf%lf", &P.x, &P.y);
+        Circle NA = Inversion_C2C(P, 10, A);
+        Circle NB = Inversion_C2C(P, 10, B);
+        Point LA[N], LB[N];
+        Circle ansC[N];
+        int q = getTangents(NA, NB, LA, LB), ans = 0;
+        for (int i = 0; i < q; ++i)
+          if (theSameSideOfLine(NA.c, NB.c, LA[i], LB[i] - LA[i])) {
+            if (!theSameSideOfLine(P, NA.c, LA[i], LB[i] - LA[i])) continue;
+            ansC[ans++] = Inversion_L2C(P, 10, LA[i], LB[i] - LA[i]);
+          }
+        printf("%d\n", ans);
+        for (int i = 0; i < ans; ++i) {
+          printf("%.8f %.8f %.8f\n", ansC[i].c.x, ansC[i].c.y, ansC[i].r);
         }
-        
-        return 0;
+      }
+    
+      return 0;
     }
     ```