起点-终点-弧度 三参数 定位圆弧

无脑推导

符号说明

  • \(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);
}
posted @ 2023-03-01 20:35  周上行Ryer  阅读(133)  评论(0编辑  收藏  举报