在计算机图像图形学中,经常会用到求圆心或圆半径的情况,本文介绍一种已知三个点求圆心和圆半径的方法(当然三个点不能共线,共线的三个点不能构成圆)。
原理:相互连接三个点,选取其中的任意两条直线,通过对这两条直线的中心做垂线,两条垂线的交点就是圆心,以此点为圆心,以此点到任意一点的距离为半径画圆。
三个点分别计为pt1, pt2, pt3:取直线p1p2和p1p3(也可以取其他直线),直线的中点则分别为:
CvPoint midPt1, midPt2; midPt1.x = (pt2.x + pt1.x)/2; midPt1.y = (pt2.y + pt1.y)/2; midPt2.x = ( pt3.x + pt1.x)/2; midPt2.y = ( pt3.y + pt1.y)/2;由于p1p2和p1p3的垂线与其自身的斜率的乘积为-1,则其垂线的斜率分别为:
float k1 = -(pt2.x - pt1.x)/(pt2.y - pt1.y); float k2 = -(pt3.x - pt1.x)/(pt3.y - pt1.y);那么对应的垂线的直线可以表示为:
y - midPt1.y = k1( x - midPt1.x); y = midPt2.y = k2( x - midPt2.x);对上面两条直线表达式进行联解,则可以分别求出其交点x, y的值,其中:
center.x = (midPt2.y - midPt1.y- k2* midPt2.x + k1*midPt1.x)/(k1 - k2); center.y = midPt1.y + k1*( midPt2.y - midPt1.y - k2*midPt2.x + k2*midPt1.x)/(k1-k2);x、y就是圆的圆心。圆心与任意一个顶点的距离即为圆的半径,表达为:
float radius = sqrtf((center.x - pt1.x)*(center.x - pt1.x) + (center.y - pt1.y)*(center.y - pt1.y));完整的代码如下:
typedef struct { CvPoint center; int radius; }CircleData; CircleData findCircle( CvPoint pt1, CvPoint pt2, CvPoint pt3) { CvPoint midPt1, midPt2; midPt1.x = (pt2.x + pt1.x)/2; midPt1.y = (pt2.y + pt1.y)/2; midPt2.x = ( pt3.x + pt1.x)/2; midPt2.y = ( pt3.y + pt1.y)/2; float k1 = -(pt2.x - pt1.x)/(pt2.y - pt1.y); float k2 = -(pt3.x - pt1.x)/(pt3.y - pt1.y); CircleData CD; CD.center.x = (midPt2.y - midPt1.y- k2* midPt2.x + k1*midPt1.x)/(k1 - k2); CD.center.y = midPt1.y + k1*( midPt2.y - midPt1.y - k2*midPt2.x + k2*midPt1.x)/(k1-k2); CD.radius = sqrtf((CD.center.x - pt1.x)*(CD.center.x - pt1.x) + (CD.center.y - pt1.y)*(CD.center.y - pt1.y)); return CD; }测试效果如图所示:
作者:侯相,出处http://blog.csdn.net/kezunhai或http://www.feiyuntech.com/:欢迎转载或分享,但请务必声明文章出处。
原文地址:http://blog.csdn.net/kezunhai/article/details/39476691