POJ 2986 A Triangle and a Circle

POJ 2986 A Triangle and a Circle

题目链接:POJ 2986


/*
	POJ 2986 三角形和圆的公共面积
	题意:给出三角形的三个点的坐标和圆的坐标、半径
	斯特瓦尔特定理
	设已知△ABC及其底边上B、C两点间的一点D,则有
	AB^2·DC+AC^2·BD-AD²·BC=BC·DC·BD。
*/
#include<cstdio>
#include<cmath>

#define eps 1e-8
#define PI acos(-1.0)

struct point 
{
	double x,y;
};

double xmult(point p1,point p2,point p0)
{
	return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
double dmult(point p1,point p2,point p0)
{
	return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}

double tirarea(double a,double b,double c)
{
	double l=(a+b+c)/2;
	return sqrt(l*(l-a)*(l-b)*(l-c));
}

double distance(point p1,point p2)
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double root(double a,double b,double c)//
{
	if(a==0)return -c/b;
	return (-b+sqrt(b*b-4*a*c))/(2*a);
}
double slove(point pa,point pb,point po,double r)//圆与三角形求交
{
	double a,b,c,x,y;
	double area=xmult(pa,pb,po)/2;
	a=distance(po,pb);
	b=distance(po,pa);
	c=distance(pa,pb);
	if(a<=r&&b<=r)//1
	{
		return area;
	}
	else if(a<r&&b>=r)//2
	{
		//斯特瓦特公式与海伦公式推出
		x=(dmult(pa,po,pb)+sqrt(c*c*r*r-xmult(pa,po,pb)*xmult(pa,po,pb)))/c;
		return asin(area*(c-x)*2/c/b/r)*r*r/2+area*x/c;
	}
	else if(a>=r&&b<r)//3
	{
		y=(dmult(pb,po,pa)+sqrt(c*c*r*r-xmult(pb,po,pa)*xmult(pb,po,pa)))/c;
		return asin(area*(c-y)*2/c/a/r)*r*r/2+area*y/c;
	}
	else
		if(fabs(2*area) >=r*c||dmult(pb,po,pa)<=0
			||dmult(pa,po,pb)<=0)//4
		{
			if(dmult(pa,pb,po)<0)
			{
				if(xmult(pa,pb,po)<0)
				{
					return (-PI-asin(area*2/a/b))*r*r/2;
				}
				else return (PI-asin(area*2/a/b))*r*r/2;
			}
			else return asin(area*2/a/b)*r*r/2;
		}
		else //5
		{
			x=(dmult(pa,po,pb)+sqrt(c*c*r*r-xmult(pa,po,pb)*xmult(pa,po,pb)))/c;
			y=(dmult(pb,po,pa)+sqrt(c*c*r*r-xmult(pb,po,pa)*xmult(pb,po,pa)))/c;
			return (asin(area*(1-x/c)*2/r/b)
				+asin(area*(1-y/c)*2/r/a))*r*r/2
				+area*((y+x)/c-1);
		}
}

int main()
{
	point p[4],cen;
	double r;
	while(scanf("%lf%lf %lf%lf %lf%lf %lf%lf%lf"
		,&p[0].x,&p[0].y,&p[1].x,&p[1].y,&p[2].x,&p[2].y,&cen.x,&cen.y,&r)!=EOF)
	{
		if(xmult(p[0],p[1],p[2])==0)
		{
			printf("0.00\n");continue;
		}
		p[3]=p[0];
		double res=0;
		for(int i=0;i<3;i++)
			res+=slove(p[i],p[i+1],cen,r);
		printf("%.2lf\n",fabs(res));
	}
	return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值