POJ - 1375

相关知识:圆外一点引两条切线,求切点,
相似三角形求投影

#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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值