链接:洛谷P1742 最小圆覆盖(Welzl’s算法,三点求圆心的证明)_tomjobs的博客-CSDN博客

重点:

1.WelZl定理:

如果第i个点不在当前i-1个点求出的圆的范围内,则第i个点肯定在新圆上面。

三点圆公式,推导过程。

 

//判断点是否在圆形内
bool IsPointOnCirCle(const AcGePoint2d& centerPt,const double& radius, const AcGePoint2d& pt)
{
	//如果小于半径则在圆内
	if ((centerPt.distanceTo(pt) - radius)<DTE)
	{
		return true;
	}
	return false;
}

//三点圆求解公式
void GetCircleCenterPt(const AcGePoint2d& p0, const AcGePoint2d& p1, const AcGePoint2d& p2, AcGePoint2d& cp)
{
	double a1 = p1.x - p0.x, b1 = p1.y - p0.y, c1 = (p1.x * p1.x - p0.x * p0.x + p1.y * p1.y - p0.y * p0.y) / 2;
	double a2 = p2.x - p0.x, b2 = p2.y - p0.y, c2 = (p2.x * p2.x - p0.x * p0.x + p2.y * p2.y - p0.y * p0.y) / 2;
	cp.x = (b2 * c1 - b1 * c2) / (a1 * b2 - a2 * b1);
	cp.y = (a2 * c1 - a1 * c2) / (a2 * b1 - a1 * b2);
}

//输入多个点获取最小覆盖圆,采用WelZl算法
void GetCircleByWelZl(const vector<AcGePoint2d>& pts,double& radius, AcGePoint2d& centerPt)
{
	if (pts.size()<2)
	{
		return;
	}
	radius = 0.0;
	centerPt = pts[0];
	for (int i = 1; i < pts.size(); ++i)
	{
		//如果在圆内
		if (IsPointOnCirCle(centerPt, radius, pts[i]))
		{
			continue;
		}
		//如果不在,则以此点为圆心
		centerPt = pts[i];
		radius = 0.0;
		for (int j = 0; j < i; ++j)
		{
			//如果在圆内
			if (IsPointOnCirCle(centerPt, radius, pts[j]))
			{
				continue;
			}
			//获取两点圆心和半径
			centerPt = AcGePoint2d((pts[i].x + pts[j].x) / 2, (pts[i].y + pts[j].y) / 2);
			radius = centerPt.distanceTo(pts[j]);
			for (int k = 0; k < j; ++k)
			{
				//如果在圆内
				if (IsPointOnCirCle(centerPt, radius, pts[k]))
				{
					continue;
				}
				//不在,则根据三点圆求解公式
				GetCircleCenterPt(pts[i], pts[j], pts[k], centerPt);
				radius = centerPt.distanceTo(pts[k]);
			}
		}
	}
}


 

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐