起点-终点-弧度 三参数 定位圆弧
无脑推导
符号说明
- \(o\) 圆心
- \(p_1\) 圆弧起点
- \(p_2\) 圆弧终点
- \(a\) 弧度(逆时针方向)
- \(a_1\) 以圆心为原点建轴,圆弧起点到正半轴的弧度
- \(a_2\) 以圆心为原点建轴,圆弧终点到正半轴的弧度
推导过程
\[\begin{gather}
p_1-o=r\{cos(a_1),sin(a_1)\} \\
p_2-o=r\{cos(a_2),sin(a_2)\} \\
a_2-a_1=a \\
p_2-p_1=r\{cos(a_2)-cos(a_1),sin(a_2)-sin(a_1)\} \\
dx=r(cos(a_2)-cos(a_1)) \\
dy=r(sin(a_2)-sin(a_1)) \\
\dfrac{dx}{dy}=\dfrac{cos(a+a_1)-cos(a_1)}{sin(a+a_1)-sin(a_1)} \\
\dfrac{dx}{dy}=\dfrac{cos(a)cos(a_1)-sin(a)sin(a_1)-cos(a_1)}{sin(a)cos(a_1)+cos(a)sin(a_1)-sin(a_1)} \\
\dfrac{dx}{dy}=\dfrac{(cos(a)-1)cos(a_1)-sin(a)sin(a_1)}{(cos(a)-1)sin(a_1)+sin(a)cos(a_1)} \\
((cos(a)-1)dx+sin(a)dy)sin(a_1)=((cos(a)-1)dy-sin(a)dx)cos(a_1) \\
tan(a_1)=\dfrac{sin(a_1)}{cos(a_1)}=\dfrac{(cos(a)-1)dy-sin(a)dx}{(cos(a)-1)dx+sin(a)dy}
\end{gather}\]
Qt 实现
细节处理
由于 Qt 窗口坐标系与标准笛卡尔坐标系存在上下翻转的差异,故为了保证实际绘制效果与理论效果一致,需要进行顺逆时针的翻转变换。
进行翻转变换后,计算结果同样是变换过后的值,并非理论的计算值。如果需要对所确定的圆弧参数进行下一步计算,需对结果进行逆变换或在一开始便不进行翻转变换。
源码
void drawArc(QPainter* painter, const QPointF& p1, const QPointF& p2, double radian) {
//! 翻转起点、终点
const auto& q1 = p2;
const auto& q2 = p1;
const auto dx = q2.x() - q1.x();
const auto dy = q2.y() - q1.y();
const auto u = cos(radian) - 1;
const auto v = sin(radian);
const auto a1 = atan2(u * dy - v * dx, u * dx + v * dy);
const auto a2 = a1 + radian;
const auto r = fabs(dx) < 1e-6 ? dy / (sin(a2) - sin(a1)) : dx / (cos(a2) - cos(a1));
const auto ox = q1.x() - r * cos(a1);
const auto oy = q1.y() - r * sin(a1);
const auto bb = QRectF(ox - r, oy - r, r * 2, r * 2);
//! 翻转圆弧角度
const auto start = -qRadiansToDegrees(a1) * 16;
const auto span = -qRadiansToDegrees(radian) * 16;
painter->drawArc(bb, start, span);
}