#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const int maxn = 5E2 + 10;
struct Point
{
double x, y;
Point(double x = 0, double y = 0): x(x), y(y) {}
};
typedef Point Vector;
//typedef vector<Point> Polygon;
Vector operator +(Vector A, Vector B)//
{
return Vector(A.x + B.x, A.y + B.y);
}
Vector operator -(Point A, Point 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);
}
bool operator <(const Point &a, const Point &b)//有修改
{
return a.x < b.x;
}
const double eps = 1e-10;
int dcmp(double x)//
{
if (fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
bool operator ==(const Point &a, const Point &b)//
{
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 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;
}
Vector Rotate(Vector A, double rad) //
{
return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
}
struct Line
{
Point P;
Vector v;
double ang;
Line() {};
Line(Point P, Vector v): P(P), v(v) {ang = atan2(v.y, v.x);}
bool operator < (const Line& L) const
{
return ang < L.ang;
}
};
Point GetLineIntersection(const Line &A, const Line &B) //
{
Vector u = A.P - B.P;
double t = Cross(B.v, u) / Cross(A.v, B.v);
return A.P + A.v * t;
}
struct Circle
{
Point c;
double r;
Circle(Point c = 0, double r = 0): c(c), r(r) {}
Point point(double a)
{
return Point(c.x + cos(a) * r, c.y + sin(a) * r);
}
};
//过点作圆形的切线
int getTangents(Point p, Circle C, Vector *v)
{
Vector u = C.c - p;
double dist = Length(u);
if (dist < C.r) return 0;
else if (dcmp(dist - C.r) == 0)
{
v[0] = Rotate(u, PI / 2);
return 1;
}
else
{
double ang = asin(C.r / dist);
v[0] = Rotate(u, -ang);
v[1] = Rotate(u, +ang);
return 2;
}
}
Point read_point()
{
double X, Y;
scanf("%lf%lf", &X, &Y);
return Point(X, Y);
}
int n;
double R;
Point P, A[maxn];
Circle C[maxn];
int main(int argc, char const *argv[])
{
while (~scanf("%d", &n) && n)
{
Point P = read_point();
for (int i = 0; i < n; i++)
{
Point t = read_point();
scanf("%lf", &R);
C[i] = Circle(t, R);
}
Line L = Line(Point(0, 0), Point(1, 0) - Point(0, 0));
for (int i = 0; i < n; i++)
{
Vector V[2];
int m = getTangents(P, C[i], V);
Line L1 = Line(P, V[0]), L2 = Line(P, V[1]);
Point p1 = GetLineIntersection(L, L1), p2 = GetLineIntersection(L, L2);
if (p2 < p1) swap(p1, p2);
A[i].x = p1.x, A[i].y = p2.x;
}
sort(A, A + n);
A[n].x = INF, A[n].y = INF;
double left = A[0].x , right = A[0].y;
for (int i = 1; i <= n; i++)
{
if (A[i].x > right)
{
printf("%.2lf %.2lf\n", left, right);
left = A[i].x, right = A[i].y;
}
if (A[i].y > right) right = A[i].y;
}
printf("\n");
}
return 0;
}
要注意好点的覆盖问题,只有断开时才要输出。