三点确定一个圆的计算方法

最近在看recast&detour源码的时候有遇到许多数学上的算法问题,特此记录,以便以后查看。

 

 

推导过程

问题:

求点p1 p2 p3三点确定的圆的 圆心c 和 半径r 。

思路:

为了方便求解,将坐标系原点平移到p1点。

即新的p1坐标为(0,0),即p2 p3坐标同时减去p1坐标,假设新的p2新的坐标为(x2, y2),新的p3新的坐标(x3, y3)。

再最后求得的圆心c的坐标以后,再加上原来p1的坐标即可。

推导圆心方程:

三点确定一个圆的计算方法_第1张图片

最后,(x0 y0)再加上原来的p1点的坐标值,即为最终要求的圆心坐标。

 

补充公式

 

三点确定一个圆的计算方法_第2张图片

源码

使用的公式即为上面推导的公式。

static bool circumCircle(const float* p1, const float* p2, const float* p3,
						 float* c, float& r)
{
	static const float EPS = 1e-6f;
	// Calculate the circle relative to p1, to avoid some precision issues. 避免精度问题?
	const float v1[3] = {0,0,0};
	float v2[3], v3[3];
	rcVsub(v2, p2,p1);
	rcVsub(v3, p3,p1);
	
	const float cp = vcross2(v1, v2, v3);
	if (fabsf(cp) > EPS)// 三点不能共线 组成圆的充要条件
	{
		const float v1Sq = vdot2(v1,v1);
		const float v2Sq = vdot2(v2,v2);
		const float v3Sq = vdot2(v3,v3);
		c[0] = (v1Sq*(v2[2]-v3[2]) + v2Sq*(v3[2]-v1[2]) + v3Sq*(v1[2]-v2[2])) / (2*cp);
		c[1] = 0;
		c[2] = (v1Sq*(v3[0]-v2[0]) + v2Sq*(v1[0]-v3[0]) + v3Sq*(v2[0]-v1[0])) / (2*cp);
		r = vdist2(c, v1);
		rcVadd(c, c, p1);
		return true;
	}
	
	rcVcopy(c, p1);
	r = 0;
	return false;
}

vcross2函数

p1指向p2的向量 和 p1指向p3的向量的 (把第三维的坐标看成0)

 i        j       k

u1     v1     0

u2     v2     0

 =  (u1v2 - v1u2)k

也就是二维矩阵的行列式的值。    

inline float vcross2(const float* p1, const float* p2, const float* p3)
{
	const float u1 = p2[0] - p1[0];
	const float v1 = p2[2] - p1[2];
	const float u2 = p3[0] - p1[0];
	const float v2 = p3[2] - p1[2];
	return u1 * v2 - v1 * u2;
}

参考

https://blog.csdn.net/liyuanbhu/article/details/52891868

 

 

你可能感兴趣的:(数学)