最近在看recast&detour源码的时候有遇到许多数学上的算法问题,特此记录,以便以后查看。
推导过程
问题:
求点p1 p2 p3三点确定的圆的 圆心c 和 半径r 。
思路:
为了方便求解,将坐标系原点平移到p1点。
即新的p1坐标为(0,0),即p2 p3坐标同时减去p1坐标,假设新的p2新的坐标为(x2, y2),新的p3新的坐标(x3, y3)。
再最后求得的圆心c的坐标以后,再加上原来p1的坐标即可。
推导圆心方程:

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

源码
使用的公式即为上面推导的公式。
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
















