相关知识:圆外一点引两条切线,求切点,
相似三角形求投影
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <cmath>
using namespace std;
struct point
{
double x, y;
}sta[510];
double r[510];
struct Line
{
point s, e;
Line(){};
Line(point a, point b)
{
s = a, e = b;
}
}L[510];
point Rotate(point p, double angle)
{
point res;
res.x = p.x*cos(angle) - p.y*sin(angle);
res.y = p.x*sin(angle) + p.y*cos(angle);
return res;
}
void TangentPoint_PC(point poi, point o, double r, point &res1, point &res2)
{
double line = sqrt((poi.x - o.x)*(poi.x - o.x) + (poi.y - o.y)*(poi.y - o.y));
double angle = acos(r/line);
point unitvector, lin;
lin.x = poi.x - o.x;
lin.y = poi.y - o.y;
unitvector.x = lin.x/sqrt(lin.x*lin.x+lin.y*lin.y)*r;
unitvector.y = lin.y/sqrt(lin.x*lin.x+lin.y*lin.y)*r;
res1=Rotate(unitvector,-angle);
res2=Rotate(unitvector,angle);
res1.x += o.x;
res1.y += o.y;
res2.x += o.x;
res2.y += o.y;
return ;
}
void relf(point &res, point source)
{
double xx = source.x - res.x;
double yy = source.y - res.y;
if(xx == 0)
{
res.x = res.x;
res.y = 0;
}
else
{
double k = yy/xx;
double b = source.y - k*source.x;
res.y = 0;
res.x = -b/k;
}
}
int cmp(Line a, Line b)
{
if(a.s.x != b.s.x)
return a.s.x < b.s.x;
return a.e.x < b.e.x;
}
int main()
{
int n;
while(scanf("%d",&n) != EOF&&n)
{
point p;
scanf("%lf%lf",&p.x, &p.y);
for( int i = 0; i < n; i++)
scanf("%lf%lf%lf",&sta[i].x, &sta[i].y, &r[i]);
for( int i = 0; i < n; i++)
{
point r1, r2;
TangentPoint_PC(p,sta[i], r[i], r1, r2);
// cout<<r1.x<<" -- "<<r1.y<<endl;
// cout<<r2.x<<" -- "<<r2.y<<endl;
if(r1.x > r2.x) swap(r1, r2);
L[i] = Line(r1, r2);
relf(L[i].s, p);
relf(L[i].e, p);
}
sort(L, L+n, cmp);
printf("%.2f ",L[0].s.x);
double last = L[0].e.x;
for( int i = 1; i<n; i++)
{
if(L[i].s.x <= last && L[i].e.x > last)
last = L[i].e.x;
else if(L[i].s.x > last)
{
printf("%.2f\n%.2f ",last, L[i].s.x);
last = L[i].e.x;
}
}
printf("%.2f\n\n",last);
}
return 0;
}