hdu 2892 area 有向面积 三角剖分运用 模板题

本文提供了一个复杂的计算几何问题解决方案,涉及线段与圆的相交判断、计算交点坐标及求解几何图形与圆的覆盖区域面积等核心内容。通过详细的代码实现,展示了如何处理点、线段和圆之间的复杂关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一次见到这种题,有想法,不会打。。。

代码太长了,有几个链接不错

http://www.xuebuyuan.com/1749999.html    //个人认为这个讲的最详细

http://blog.youkuaiyun.com/ch2010091/article/details/7786450

ac代码:

#include <iostream>
#include <cmath>
#include <cstdio>

using namespace std;

const int maxn = 100000 + 10;
const double eps = 1e-10;
typedef struct _point
{
	double x,y;
	_point (double x = 0, double y = 0):x(x),y(y) {}
}Point,Vector;
Point p[maxn];

typedef struct _circle
{
	Point c;
	double r;
}Circle;

typedef struct _line
{
	Point p;
	Vector v;
}Line;

Vector operator + (Vector a, Vector b) {return Vector(a.x + b.x, a.y + b.y);}
Vector operator - (Vector a, Vector b) {return Vector(a.x - b.x, a.y - b.y);}

double Dot (Vector a, Vector b) {return a.x * b.x + a.y * b.y;}
double Length (Vector a) {return sqrt (Dot (a, a));}
double Cross (Vector a, Vector b) {return a.x * b.y - a.y * b.x;}
double Distance (Point a, Point b) {return Length (a - b);}
double Angle (Vector a, Vector b) {return acos (Dot (a, b) / Length (a) / Length (b));}

int dcmp (double x)
{
	if (fabs (x) < eps) return 0;
	else return x < 0 ? -1 : 1;
}

int getLineCircleIntersection (Line L, Circle C, double& t1, double& t2)
{//返回线段和圆的交点个数
	double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
	double e = a * a + c * c, f = 2 * (a * b + c * d), g = b * b + d * d - C.r * C.r;
	double delta = f * f - 4 * e * g;		//判别式
	if (dcmp (delta) < 0) return 0;
	if (dcmp (delta) == 0)
	{
		t1 = t2 = -f / (2 * e);
		return 1;
	}
	t1 = (-f - sqrt (delta)) / (2 * e);
	t2 = (-f + sqrt (delta)) / (2 * e);
	return 2;
}

double slove (Circle r, int n)
{
	int i,j;
	double ans = 0;
	double x;
	for (i = 0; i < n; i++)
	{
		if (dcmp(Distance(p[i], r.c) - r.r) <= 0 && dcmp(Distance(p[(i + 1) % n], r.c) - r.r) <= 0)
		{//两个顶点都在圆内,直接求三角形面积
			ans += Cross (p[i] - r.c, p[(i + 1) % n] - r.c) / 2;
		}
		else if (dcmp(Distance(p[i], r.c) - r.r) <= 0 && dcmp(Distance(p[(i + 1) % n], r.c) - r.r) > 0)
		{//p[i]在圆内,p[i+1]在圆外,求与圆的交点
			double t1,t2;
			Line L;
			L.p = p[i];
			L.v = p[(i + 1) % n] - p[i];
			getLineCircleIntersection (L, r, t1, t2);
			t1 = t1 > 0 ? t1 : t2;
			Point inter;
			inter.x = L.p.x + L.v.x * t1; inter.y = L.p.y + L.v.y * t1;
			ans += Cross (p[i] - r.c, inter - r.c) / 2;		//三角形面积
			x = (Angle (inter - r.c, p[(i + 1) % n] - r.c) / 2.0) * r.r * r.r;		//扇形面积
			if (Cross (inter - r.c, p[(i + 1) % n] - r.c) < 0)
				ans -= x;
			else
				ans += x;
		}
		else if (dcmp(Distance(p[i], r.c) - r.r) > 0 && dcmp(Distance(p[(i + 1) % n], r.c) - r.r) <= 0)
		{//p[i]在圆外,p[i+1]在圆内
			double t1,t2;
			Line L;
			L.p = p[i];
			L.v = p[(i + 1) % n] - p[i];
			getLineCircleIntersection (L, r, t1, t2);
			t1 = t1 < t2 ? t1 : t2;
			Point inter;
			inter.x = L.p.x + L.v.x * t1; inter.y = L.p.y + L.v.y * t1;
			ans += Cross (inter - r.c, p[(i + 1) % n] - r.c) / 2;		//三角形面积
			x = (Angle (p[i] - r.c, inter - r.c) / 2.0) * r.r * r.r;		//扇形面积
			if (Cross (p[i] - r.c, inter - r.c) < 0)
				ans -= x;
			else
				ans += x;
		}
		else if (dcmp(Distance(p[i], r.c) - r.r) > 0 && dcmp(Distance(p[(i + 1) % n], r.c) - r.r) > 0)
		{//两个点都在圆外
			double t1,t2;
			Line L;
			L.p = p[i];
			L.v = p[(i + 1) % n] - p[i];
			if (getLineCircleIntersection (L, r, t1, t2) <= 1)
			{//只有一个或者没有交点
				x = (Angle (p[(i + 1) % n] - r.c, p[i] - r.c) / 2.0) * r.r * r.r;		//扇形面积
				if (Cross (p[i] - r.c, p[(i + 1) % n] - r.c) < 0)
					ans -= x;
				else
					ans += x;
			}
			else
			{
				Point inter1,inter2;
				if (t1 > t2)
					swap (t1,t2);
				inter1.x = L.p.x + L.v.x * t1; inter1.y = L.p.y + L.v.y * t1;
				inter2.x = L.p.x + L.v.x * t2; inter2.y = L.p.y + L.v.y * t2;
				ans += Cross (inter1 - r.c, inter2 - r.c) / 2;		//三角形面积
				x = (Angle (p[i] - r.c, inter1 - r.c) / 2.0) * r.r * r.r;		//扇形面积
				if (Cross (p[i] - r.c, inter1 - r.c) < 0)
					ans -= x;
				else
					ans += x;
				x = (Angle (inter2 - r.c, p[(i + 1) % n] - r.c) / 2.0) * r.r * r.r;
				if (Cross (inter2 - r.c, p[(i + 1) % n] - r.c) < 0)
					ans -= x;
				else
					ans += x;
			}
		}
	}
	return ans;
}

int main ()
{
	double h;
	Circle c;
	while (scanf ("%lf%lf%lf",&c.c.x, &c.c.y, &h) != EOF)
	{
		double x1,y1;
		scanf ("%lf%lf",&x1, &y1);
		//求圆心
		double t = sqrt (h / 5.0);
		c.c.x += x1 * t;
		c.c.y += y1 * t;
		scanf ("%lf",&c.r);
		
		int n;
		scanf ("%d",&n);
		int i,j;
		for (i = 0; i < n; i++)
		{
			scanf ("%lf%lf",&p[i].x,&p[i].y);
		}
		printf ("%.2lf\n",fabs (slove (c, n)));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值