一:已知两点坐标和两点之间的夹角,求圆点
1:代数推导
2:几何推导
3:代码部分
Matrix 是一个矩阵类,引入了高等数学库方便计算:Eigen
//保存圆的参数
struct _arcConfig{
double raio;//保存半径
QPointF center;//保存圆心
QPointF center2;//保存圆心2
};
//获取圆的中心和半径,---两点和两点之间的角度 -- 代数推导
_arcConfig GlobleFunction::get_ArcCenter2(QPointF point1,QPointF point2,double rad)
{
/* 存在两个解:
* 解1:
* (1-cosβ)a + sinβ*b = x2 - x1*cosβ + y1*sinβ
* sinβ*a + (cosβ-1)b = -y2 + x1*sinβ + y1*cosβ
* 解2:
* * (1-cosβ)a + sinβ*b = x1 - x2*cosβ + y2*sinβ
* sinβ*a + (cosβ-1)b = -y1 + x2*sinβ + y2*cosβ
* 利用克拉默法则解行列式
* 求center(a,b)
*
*/
QPointF center,center2;
_arcConfig config;
Matrix<double,2,2> matD,matD1,matD2,matD3,matD4;
matD<<(1 - qCos(rad)),qSin(rad),
qSin(rad),(qCos(rad)-1);
matD1<<point2.x() - (point1.x()*qCos(rad))+(point1.y()*qSin(rad)) , qSin(rad),
point1.x()*qSin(rad) + point1.y()*qCos(rad) -point2.y() , (qCos(rad)-1);
matD2<<(1 - qCos(rad )),point2.x() - (point1.x()*qCos(rad))+(point1.y()*qSin(rad)),
qSin(rad ),point1.x()*qSin(rad) + point1.y()*qCos(rad) -point2.y() ;
matD3<<point1.x() - (point2.x()*qCos(rad))+(point2.y()*qSin(rad)) , qSin(rad),
point2.x()*qSin(rad) + point2.y()*qCos(rad) -point1.y() , (qCos(rad)-1);
matD4<<(1 - qCos(rad )),point1.x() - (point2.x()*qCos(rad))+(point2.y()*qSin(rad)),
qSin(rad ),point2.x()*qSin(rad) + point2.y()*qCos(rad) -point1.y() ;
double D = matD.determinant();
double D1 = matD1.determinant();
double D2 = matD2.determinant();
double D3 = matD3.determinant();
double D4 = matD4.determinant();
center.setX(D1 / D);
center.setY(D2 / D);
center2.setX(D3 / D);
center2.setY(D4 / D);
double raio = qSqrt(qPow(point1.x()-center.x(),2)+qPow(point1.y()-center.y(),2));
config.raio =raio;
config.center = center;
config.center2 = center2;
return config;
}
//获取圆的中心和半径,---两点和两点之间的角度 -- 几何推导
_arcConfig GlobleFunction::get_ArcCenter3(QPointF point1,QPointF point2,double rad)
{
/* 存在两个解:
* 解1:
* x = (x1+x2)/2 + (y1-y2) / 2tan(β/2)
* y = (y1+y2)/2 + (x2-x1) / 2tan(β/2)
* 解2:
* x = (x1+x2)/2 - (y1-y2) / 2tan(β/2)
* y = (y1+y2)/2 - (x2-x1) / 2tan(β/2)
*
* 直接求解
*
*/
QPointF center,center2;
_arcConfig config;
center.setX((point1.x() + point2.x()) / 2 + (point1.y()-point2.y()) / (2*qTan(rad/2)));
center.setY((point1.y() + point2.y()) / 2 + (point2.x()-point1.x()) / (2*qTan(rad/2)));
center2.setX((point1.x() + point2.x()) / 2 - (point1.y()-point2.y()) / (2*qTan(rad/2)));
center2.setY((point1.y() + point2.y()) / 2 - (point2.x()-point1.x()) / (2*qTan(rad/2)));
double raio = qSqrt(qPow(point1.x()-center.x(),2)+qPow(point1.y()-center.y(),2));
config.raio =raio;
config.center = center;
config.center2 = center2;
return config;
}
二:已知三点坐标,求圆点
1:代数推导
2:代码部分
//获取圆的中心和半径,---三点拟合圆 -- 代数推导
_arcConfig GlobleAlgorithm::get_ArcCenter3(QPointF point1,QPointF point2,QPointF point3)
{
/* 存在两个解:
* 解1:
* R² = (x - x0)² + (y - y0)²
* 展开可得:
* R² = x² - 2xx0 + x0² + y² - 2yy0 + y0²
* 即:x0 = a / 2; y0 = b/2
* 变换后:x² + y² - ax - by + c = 0 ==> ax + by - c = x² + y²
* 利用克拉默法则解行列式 求:a, b, c
* 求center(x0,y0)
*
*/
_arcConfig config;
QPointF center;
Matrix<double,3,3> matD,matDa,matDb,matDc;
matD<<point1.x(),point1.y(),-1,
point2.x(),point2.y(),-1,
point3.x(),point3.y(),-1;
matDa<<qPow(point1.x(),2) + qPow(point1.y(),2),point1.y(),-1,
qPow(point2.x(),2) + qPow(point2.y(),2),point2.y(),-1,
qPow(point3.x(),2) + qPow(point3.y(),2),point3.y(),-1;
matDb<<point1.x(),qPow(point1.x(),2) + qPow(point1.y(),2),-1,
point2.x(),qPow(point2.x(),2) + qPow(point2.y(),2),-1,
point3.x(),qPow(point3.x(),2) + qPow(point3.y(),2),-1;
matDc<<point1.x(),point1.y(),qPow(point1.x(),2) + qPow(point1.y(),2),
point2.x(),point2.y(),qPow(point2.x(),2) + qPow(point2.y(),2),
point3.x(),point3.y(),qPow(point3.x(),2) + qPow(point3.y(),2);
//求行列式解
double D = matD.determinant();
double Da = matDa.determinant();
double Db = matDb.determinant();
double Dc = matDc.determinant();
double a =Da / D;
double b =Db / D;
double c =Dc / D;
center.setX(a / 2);
center.setY(b / 2);
//半径
double raio = 0.5 * qSqrt(qPow(a,2)+qPow(b,2) - 4*c);
config.raio =raio;
config.center = center;
return config;
}
三:适用场合
相机做旋转标定求圆心