C++求2个圆的交点

本文探讨了在计算机图形学中的conetracing中,如何通过求解二维圆和圆的相交问题作为简化步骤。作者详细介绍了求解过程,包括圆心坐标、半径和交点的计算,特别提到了特殊情况如圆心重合和3维到2维投影的问题。后续计划转向更简便的近似方法来估算相交面积。

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

最近,在看cone tracing中涉及求圆锥和立方体的相交的需要。发现这十分复杂,所以想退而求其次求圆锥和球体的相交,再做简化,求二维圆和圆的相交面积。

然而求二维圆和圆的相交面积,也有一些复杂。如果先求2个圆的交点,可以辅助相交面积的求解,所以先写了个程序验证2圆交点求解。

首先,根据圆的一般方程,我们如果有2个圆的中心坐标(c1x,c1y)、(c2x,c2y),以及2个圆的半径r1和r2,我们可以列出下面2个等式:

   1)

  2)

把2式减去1式,可以得到:

   3) 

这个公式项目较多,做一些变量替换,可以简化这个公式,令:

  4)

 5)

  6)

把式4、5、6代入3式,可以得到:

  7)

然后把7代入1:

  8)

整理一下,得式9:

9)

最后得到的这个关于x的1元2次方程就可以直接求解了,先提取一下系数:

  10)

  11)

  12)

根据求根公式,得到解x1和x2,如果根式里小于0,则没有解,即2圆不相交。解出x1、x2后代入7式,可以解得y1和y2,2个相交坐标点即可求出。

  13)

到这里,一般的求解推理就完成了,但是回顾式7,可以发现,这里可能会有个除零异常发生。即两圆的中心Y坐标相同(c1y=c2y)时,C为0,这时就不能按上述流程求解了。

不过(c1y=c2y)时,求解简化了,此时x只有1个解,从公式3,我们得出x的解为:

最后函数可以如下实现:

bool CircleIntersect(Vec2 c1, float r1, Vec2 c2, float r2, Vec2 *intersectP1, Vec2 *intersectP2)
{
	float centerD = c1.Distance(c2);
	if (centerD < r1 + r2){
		float A = r2 * r2 - r1 * r1 - c2.x * c2.x + c1.x * c1.x - c2.y * c2.y + c1.y * c1.y;
		float B = 2 * (c1.x - c2.x);
		float C = 2 * (c1.y - c2.y);
		if (C == 0){
			if (B == 0){  // center are the same
				return false;
			}
			else{
				float x = A / B;
				float a = 1;
				float b = -2 * c2.y;
				float c = x * x - 2 * c2.x * x + c2.x * c2.x + c2.y * c2.y - r2 * r2;

				float delta = b * b - 4 * a * c;
				if (delta >= 0.0f){
					float sqrtD = powf(delta, 0.5f);
					float y1 = (sqrtD - b) / (2 * a);
					float y2 = (-sqrtD - b) / (2 * a);
					*intersectP1 = Vec2(x, y1);
					*intersectP2 = Vec2(x, y2);
					return true;
				}
			}
		}
		else{
			float a = B * B / (C * C) + 1;
			float b = 2 * c1.y * B / C - 2 * c1.x - 2 * A * B / (C * C);
			float c = c1.x * c1.x + c1.y * c1.y + A * A / (C * C) - 2 * c1.y * A / C - r1 * r1;

			float delta = b * b - 4 * a * c;
			if (delta >= 0.0f){
				float sqrtD = powf(delta, 0.5f);
				float x1 = (sqrtD - b) / (2 * a);
				float x2 = (-sqrtD - b) / (2 * a);
				float y1 = (A - B * x1) / C;
				float y2 = (A - B * x2) / C;
				*intersectP1 = Vec2(x1, y1);
				*intersectP2 = Vec2(x2, y2);
				return true;
			}
		}
	}
	return false;
}

函数参数为2圆的中心和半径;如果2圆相交,返回true且把交点通过指针回传,没有相交则返回false。

注:如果2圆中心重合(B与C为0)则视为不相交(即使半径相等时会有无数个交点);另外如果两圆心距离小于半径之和才进入求交点计算,可以省下很多计算量。

讨论:计划计算2圆的相交面积,现在想到的方法是计算相交后得到的2个扇形面积减去扇形重合的区域。这个方法应该能精确计算出相交面积。但是要实施到cone tracing中,有1个问题:需要把3维2球体投射到2维平面上求解。这点不是很好克服,所以可能会转而使用一个近似的方法:计算2圆中心距离和2圆半径的关系。比如:当2圆分离时,2圆中心距离>2圆半径之和;当圆1包含圆2(圆1半径>圆2半径)时,圆1半径减2圆中心距离>圆2半径(见下图)。

本程序是两相交交点,输入信息为两心坐标和半径值。如有更好的算法,欢迎交流!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值