poj1375 解析几何 求点与圆切线在幕布上的映射(求切线)

题意:

给你一个光源 和n个圆形障碍物,现在光源向y = 0投影 问你被圆遮住的阴影区段有哪些?

思路:

图是偷的qaq 可以求出图中∠a和∠b 投影到下面幕布的区段: (b-a的正负不打紧,我们根据角度求映射距离,负角就变成了O.x+……了)

double OA = dis(O,a[i]);//圆心与光源的距离
double a = asin(a[i].r/OA);//R对角的角度
double b = asin((O.x-a[i].x)/OA);//圆心与y轴的角度
ans[i].L = O.x - O.y * tan(a+b);
ans[i].R = O.x - O.y * tan(b-a);

上代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>

using namespace std;
const int MaxN = 5e2 + 5;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;

int n;
struct Circle{
	double x,y,r;
	Circle(double x = 0,double y = 0,double r = 0) : x(x),y(y),r(r) {}
}a[MaxN],O;

struct Seg{//投影阴影区段
	double L,R;
}ans[MaxN];

bool cmp(Seg A,Seg B){
	return A.L < B.L;
}

double dis(Circle A,Circle B){
	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

int main()
{
	int cnt = 0;
	while(~scanf("%d",&n) && n){
		scanf("%lf%lf",&O.x,&O.y);
		for(int i = 1;i <= n; i++){
			scanf("%lf %lf %lf",&a[i].x,&a[i].y,&a[i].r);
			double OA = dis(O,a[i]);//圆心与光源的距离
			double aa = asin(a[i].r/OA);//R对角的角度
			double bb = asin((O.x-a[i].x)/OA);//圆心与y轴的角度
			double angle1 = aa + bb;
			double angle2 = bb - aa;
			ans[i].L = O.x - O.y * tan(angle1);
			ans[i].R = O.x - O.y * tan(angle2);
		}
		sort(ans + 1,ans + 1 + n,cmp);
		double beg = ans[1].L;
		double lst = ans[1].R;
		if(cnt) printf("\n");
		cnt++;
		for(int i = 2;i <= n; i++){
			if(ans[i].L > lst){
				printf("%.2f %.2f\n",beg,lst);
				beg = ans[i].L;
				lst = ans[i].R;
			}
			else lst = max(lst,ans[i].R);//或者sort再加一行
		}
		printf("%.2f %.2f\n",beg,lst);
	}
	return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值