点Pから円に引いた2本の接線が求まるが、その2つの接点を求めよ (polar) "Tangent to a Circle" AOJ

f:id:peroon:20200925053205p:plain

typedef complex<ld> C;

// ベクトルの長さ
ld length(C v){
  return sqrt(v.real()*v.real() + v.imag()*v.imag());
}

// 2点間の距離
ld distance_between_two_points(C a, C b){
  return length(a-b);
}

// 単位ベクトル
C unit_vector(C v){
  return v / length(v);
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    // input
    ld px,py;cin>>px>>py;
    C p = {px,py};

    ld cx,cy,r;cin>>cx>>cy>>r;
    C c = {cx,cy};

    // p-c間距離
    ld d = distance_between_two_points(p,c);
    ld sin_theta = r / d;
    ld theta = asin(sin_theta); // ※radianです

    C v = c-p;
    v *= polar(1.0, (double)theta); // ※radianです
    auto u = unit_vector(v);
    auto ans0 = p + u * d * cos(theta);

    theta *= -1;
    v = c-p;
    v *= polar(1.0, (double)theta);
    u = unit_vector(v);
    auto ans1 = p + u * d * cos(theta);

    vector<pair<ld,ld>> V;
    V.push_back({ans0.real(), ans0.imag()});
    V.push_back({ans1.real(), ans1.imag()});
    sort(ALL(V));

    rep(i,2){
      ld x = V[i].first;
      ld y = V[i].second;
      printf("%.10Lf %.10Lf\n", x, y);
    }
    
    return 0;
}