过圆外⼀点与圆的切线⽅程()
Sample Input
6
300 450
70 50 30
120 20 20
270 40 10
250 85 20
220 30 30
380 100 100
1
300 300
300 150 90
1
300 300
390 150 90
Sample Output
0.72 78.86
88.50 133.94
181.04 549.93
75.00 525.00
300.00 862.50
题意:在天花板上给出⼀盏灯,下⾯放有n个圆柱形钢管,问下⾯有⼏段阴影部分,且输出阴影段的两个端点
分析:对于每个圆形,和圆外⼀点P,P与该圆的两条切线与X轴的交点就是阴影段的两个端点,先求出所有圆形对应的阴影段,因为有重合的,然后⼀遍扫描即可求出结果:
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"queue"
#include"algorithm"
#include"string.h"
#include"string"
#include"math.h"
#include"vector"
#include"stack"
#include"map"
#define eps 1e-4
#define inf 0x3f3f3f3f
#define M 609
#define PI acos(-1.0)
using namespace std;
struct node//⼆维点坐标
{
double x,y;
double x,y;
node(){};
node(double xx,double yy)
{
x=xx;
y=yy;
}
node operator+(node b)
{
return node(x+b.x,y+b.y);
}
node operator-(node b)
{
return node(x-b.x,y-b.y);
}
node operator*(double b)
{
return node(x*b,y*b);
}
double operator*(node b)
{
return x*b.x+y*b.y;
}
double operator^(node b)
{
return x*b.y-y*b.x;
}
}P;
struct Circle//定义圆⼼和半径
{
node center;
double r;
}p[M];
struct Line//定义直线⼀般式的三个参数ABC {
double A,B,C;
};
double len(node a)
{
return sqrt(a*a);
}
double dis(node a,node b)
{
return len(a-b);
}
double cross(node a,node b,node c)
{
return (b-a)^(c-a);
}
double dot(node a,node b,node c)
{
return (b-a)*(c-a);
}
Circle Inver(node p,double R,Circle c)
{
Circle ret;
double pc=dis();
ret.r=R*R/2*(1/(pc-c.r)-1/(pc+c.r));
double pc0=R*R/(pc+c.r)+ret.r;
}
Line line(node a,node b)
{
Line l;
Line l;
l.A=b.y-a.y;
l.B=a.x-b.x;
l.C=b.x*a.y-a.x*b.y;
return l;
}
node Ratate(node a,double rad)//向量逆时针旋转rad的⾓度
{
return node(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
Line PointCutCircle(node p,Circle c,int clock)//过圆外⼀点p且与圆的切线,clock代表两个不同的切线{
Line ret;
node she;
-p;
double pc=,p);
double rad=asin(c.r/pc);
if(clock==-1)//逆时针旋转
{
node she1=Ratate(she,rad);
ret.A=she1.y;
ret.B=-she1.x;
ret.C=she1.x*p.y-p.x*she1.y;
}
if(clock==1)//顺时针旋转
{
node she1=Ratate(she,-rad);
ret.A=she1.y;
ret.B=-she1.x;
ret.C=she1.x*p.y-p.x*she1.y;
}
return ret;
}
struct st
{
double l,r;
}s[M];
int cmp(st a,st b)
{
if(a.l!=b.l)
return a.l<b.l;
el
return a.r<b.r;
}
int main()
{
int n,i,kk=0;
while(scanf("%d",&n),n)
{
scanf("%lf%lf",&P.x,&P.y);
for(i=1;i<=n;i++)
scanf("%lf%lf%lf",&p[i].center.x,&p[i].center.y,&p[i].r);
for(i=1;i<=n;i++)
{
Line L1=PointCutCircle(P,p[i],1);
Line L2=PointCutCircle(P,p[i],-1);
s[i].l=-L1.C/L1.A;
s[i].r=-L2.C/L2.A;
}
if(kk)
printf("\n");
kk++;
sort(s+1,s+n+1,cmp);
double L=s[1].l;
double R=s[1].r;
for(i=2;i<=n;i++)
for(i=2;i<=n;i++)
{
if(s[i].l<=R)
{
R=max(R,s[i].r);
}
el
{
printf("%.2lf %.2lf\n",L,R); L=s[i].l;
R=s[i].r;
}
}
printf("%.2lf %.2lf\n",L,R);
}
return 0;
}