最小圆覆盖模板

实际上是找三个点:
如果第一个点没找对的话,以后遇到正确的点会不包含,如果第二个点没找对的话,以后遇到正确的点会不包含,如果第三个点没找对的话,以后遇到正确的点会不包含。所以,只有以后不出现不包含的情况,就是找对了。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
 
using namespace std;
const double eps=1e-8;
 
struct Point
{
	double x,y;
};
 
Point p[505];
 
double dist(Point A,Point B)
{
	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
 
/***返回三角形的外心 */
Point circumcenter(Point A,Point B,Point C)
{
	Point ret;
	double a1=B.x-A.x,b1=B.y-A.y,c1=(a1*a1+b1*b1)/2;
	double a2=C.x-A.x,b2=C.y-A.y,c2=(a2*a2+b2*b2)/2;
	double d=a1*b2-a2*b1;
	ret.x=A.x+(c1*b2-c2*b1)/d;
	ret.y=A.y+(a1*c2-a2*c1)/d;
	return ret;
}
 
/***c为圆心,r为半径 */
void min_cover_circle(Point *p,int n,Point &c,double &r)
{
	random_shuffle(p,p+n);
	c=p[0]; r=0;
	for(int i=1;i<n;i++)
	{
		if(dist(p[i],c)>r+eps)   //第一个点
		{
			c=p[i]; r=0;
			for(int j=0;j<i;j++)
				if(dist(p[j],c)>r+eps)  //第二个点
				{
					c.x=(p[i].x+p[j].x)/2;
					c.y=(p[i].y+p[j].y)/2;
					r=dist(p[j],c);
					for(int k=0;k<j;k++)
						if(dist(p[k],c)>r+eps)  //第三个点
						{   //求外接圆圆心,三点必不共线
							c=circumcenter(p[i],p[j],p[k]);
							r=dist(p[i],c);
						}
				}
		}
	}
}
 
int main()
{
	int n;
	Point c;
	double r;
	while(~scanf("%d",&n)&&n)
	{
		for(int i=0;i<n;i++)
			scanf("%lf%lf",&p[i].x,&p[i].y);
		min_cover_circle(p,n,c,r);
		printf("%.2lf %.2lf %.2lf\n",c.x,c.y,r);
	}
	return 0;
}
### 使用CGAL库实现二维点集的最小外接圆计算 CGAL(Computational Geometry Algorithms Library)是一个强大的计算几何库,提供了多种算法和数据结构来解决复杂的几何问题。对于二维点集的最小外接圆计算,可以利用`Min_circle_2<Traits>`类[^1]。 #### 实现步骤说明 以下是基于CGAL库的一个具体示例代码,展示如何计算给定二维点集的最小外接圆: ```cpp #include <iostream> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Min_circle_2.h> #include <CGAL/Min_circle_2_traits_2.h> typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Min_circle_2_traits_2<K> Traits; typedef CGAL::Min_circle_2<Traits> Min_circle; int main() { const int n = 10; // 假设有10个点 K::Point_2 P[n]; // 随机生成一些点 for (int i = 0; i < n; ++i) { P[i] = K::Point_2((double)(rand() % 100), (double)(rand() % 100)); } // 计算最小外接圆 Min_circle min_circle(P, P + n, true); // 输出结果 std::cout << "Circle: "; if (min_circle.is_degenerate()) { // 如果退化,则所有点共线或重合 std::cout << "Degenerate circle." << std::endl; } else { std::cout << "(" << min_circle.center().x() << ", " << min_circle.center().y() << "); r=" << min_circle.radius() << std::endl; } return 0; } ``` 上述代码实现了以下功能: - **点集初始化**:通过随机数生成器创建了一个包含10个点的集合。 - **调用`Min_circle_2`**:使用这些点计算其最小包围圆,并验证是否存在退化解。 - **输出结果**:打印出最小外接圆的中心坐标及其半径。 #### 关键特性解析 1. `Min_circle_2<Traits>` 是专门用来求解最小外接圆的模板类。其中参数 `Traits` 提供了几何基本操作的支持。 2. 函数接受两个指针范围 `[P, P+n)` 表示输入点集;布尔值控制是否启用精确模式,默认开启以提高准确性。 3. 方法 `.is_degenerate()` 判断当前情况是否属于特殊情况——比如所有的点都在同一直线上或者完全相同的位置上形成单一位置的情况。 #### 应用场景扩展 除了基础的应用之外,在某些特定领域还可以做更多深入探讨: - 在地理信息系统(GIS),可用于分析区域内的最远可达范围; - 工业布局规划中帮助确定设施的最佳摆放位置使得服务覆盖最大化的同时减少成本投入; - 图像处理技术里辅助目标物体轮廓提取后的形态学描述等等[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值