您的位置:首页 > 其它

poj 1375

2014-04-15 11:04 288 查看
题目: Click here

题意:给出一个光源,给出一些圆,求投影区间。 就是求切线。

0 0 主要是最近在做几何的模版。所以贴一下。。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const double inf = 1e12;
const int N = 11111;
struct point{
double x,y;
point(){x=0,y=0;}
point(double _x,double _y){x=_x; y=_y;}
}light;
struct circle{
point o;
double r;
}Cir
;
struct line{
point p1,p2;
line(){};
line(point _p1,point _p2){
p1 = _p1,p2 =_p2;
}
};
bool equal(double x,double y){
if( y-x < eps && x - y < eps)
return true;
else return false;
}
struct node{
double l, r;
bool operator < (const node &tmp) const{
if( (l<tmp.l) || (equal(l,tmp.l) && r<tmp.r)) return true;
return false;
};
}tp
;
int n;
//通过圆外一点,求出两个切点pOn1,pOn2
void CalcQieDian(point pCenter, double r, point pOut,point &pOn1,point &pOn2)
{
point E,F,G;
//1. 坐标平移到圆心ptCenter处,求园外点的新坐标E
E.x= pOut.x-pCenter.x;
E.y= pOut.y-pCenter.y; //平移变换到E

//2. 求园与OE的交点坐标F, 相当于E的缩放变换
double t= r / sqrt (E.x * E.x + E.y * E.y); //得到缩放比例
F.x= E.x * t; F.y= E.y * t; //缩放变换到F

//3. 将E旋转变换角度a到切点G,其中cos(a)=r/OF=t, 所以a=arccos(t);
double a1=acos(t),a2=-acos(t); //得到旋转角度
//double a=-acos(t); 得到另一个点
G.x=F.x*cos(a1) -F.y*sin(a1);
G.y=F.x*sin(a1) +F.y*cos(a1); //旋转变换到G
//5. 返回H
pOn1 = point(G.x+pCenter.x,G.y+pCenter.y);
//在计算一次
G.x=F.x*cos(a2) -F.y*sin(a2);
G.y=F.x*sin(a2) +F.y*cos(a2); //旋转变换到G
pOn2 = point(G.x+pCenter.x,G.y+pCenter.y);
//6. 实际应用过程中,只要一个中间变量E,其他F,G,H可以不用。
}
//通过圆外一点,求两条切线
void CalcQieLine(circle &o,point &out,line &l1,line &l2){
point pOn1,pOn2;
CalcQieDian(o.o,o.r,out,pOn1,pOn2);
if(pOn2.x < pOn1.x){
swap(pOn2,pOn1);
}
l1=line(out,pOn1);
l2=line(out,pOn2);
}
//当y已经知道的时候,通过直线的y推导出x
double CalcPointUseLine(line &l,double y){
return l.p2.x - (l.p2.y-y)*(l.p2.x-l.p1.x)/(l.p2.y-l.p1.y);
}
//返回投影的两个点
void CalcTouYing(circle &o,point &out,node &ans){
line l1,l2;
CalcQieLine(o,out,l1,l2);
ans.l = CalcPointUseLine(l1,0.0);
ans.r = CalcPointUseLine(l2,0.0);
}
int main(){
while(scanf("%d",&n) && n){
cin >> light.x >> light.y;
for(int i = 0;i < n;i++){
cin >> Cir[i].o.x >> Cir[i].o.y >> Cir[i].r;
}
for(int i = 0;i < n;i++){
CalcTouYing(Cir[i],light,tp[i]);
}
sort(tp,tp+n);
double L=tp[0].l,R=tp[0].r;
for(int i = 1;i < n;i++){
if(R < tp[i].l){
printf("%.2lf %.2lf\n",L,R);
L = tp[i].l, R = tp[i].r;
}else{
R = max(R,tp[i].r);
}
}printf("%.2lf %.2lf\n\n",L,R);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息