求最小外接圆(采用WelZl算法)

 链接:洛谷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]);
			}
		}
	}
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值