使用圆心、半径和圆上的 3 个点计算圆弧上的点
Calculate points on an arc of a circle using center, radius and 3 points on the circle
给定圆心、半径和圆上的 3 个点,我想通过指定开始绘制的角度和数量来绘制从第一个点开始,通过第二个点并在第三个点结束的圆弧要旋转的角度。为此,我需要计算圆弧上的点。我希望计算出的点数是可变的,这样我就可以调整计算出的弧的精度,所以这意味着我可能需要一个循环来计算每个点,在它计算出一个点后稍微旋转一下。这个问题Draw arc with 2 points and center of the circle的答案我看过了,但是只是解决了计算角度的问题,因为我不知道'canvas.drawArc'是怎么实现的。
这个问题分为两部分:
- 如何求两点之间通过第三点的弧?
- 如何在找到的圆弧上生成一组点?
让我们从第一部分开始。给定 (O, r)
圆上的三个点 A
、B
和 C
,我们想要找到 A
和 C
之间穿过 B
。要找到圆弧的内角,我们需要计算 AB
和 AC
圆弧的 oriented angles。如果 AB
的角度大于 AC
,则方向错误:
Va.x = A.x - O.x;
Va.y = A.y - O.y;
Vb.x = B.x - O.x;
Vb.y = B.y - O.y;
Vc.x = C.x - O.x;
Vc.y = C.y - O.y;
tb = orientedAngle(Va.x, Va.y, Vb.x, Vb.y);
tc = orientedAngle(Va.x, Va.y, Vc.x, Vc.y);
if tc<tb
tc = tc - 2 * pi;
end
function t = orientedAngle(x1, y1, x2, y2)
t = atan2(x1*y2 - y1*x2, x1*x2 + y1*y2);
if t<0
t = t + 2 * pi;
end
end
现在是第二部分。你说:
I probably need a loop that calculates each point by rotating a little
after it has calculated a point.
但问题是,有多少?由于圆的周长随着半径的增加而增加,因此您无法以固定的角度达到固定的精度。换句话说,要绘制两条角度相同但半径不同的圆弧,我们需要的点数不同。我们可以假设[几乎]不变的是这些点之间的距离,或者我们为模拟弧线而绘制的线段的长度:
segLen = someConstantLength;
arcLen = abs(tc)*r;
segNum = ceil(arcLen/segLen);
segAngle = tc / segNum;
t = atan2(Va.y, Va.x);
for i from 0 to segNum
P[i].x = O.x + r * cos(t);
P[i].y = O.y + r * sin(t);
t = t + segAngle;
end
注意,虽然在这个方法中A
和C
肯定会被创建,但是点B
不一定是创建的点之一。但是这个点离最近的线段的距离会很小
给定圆心、半径和圆上的 3 个点,我想通过指定开始绘制的角度和数量来绘制从第一个点开始,通过第二个点并在第三个点结束的圆弧要旋转的角度。为此,我需要计算圆弧上的点。我希望计算出的点数是可变的,这样我就可以调整计算出的弧的精度,所以这意味着我可能需要一个循环来计算每个点,在它计算出一个点后稍微旋转一下。这个问题Draw arc with 2 points and center of the circle的答案我看过了,但是只是解决了计算角度的问题,因为我不知道'canvas.drawArc'是怎么实现的。
这个问题分为两部分:
- 如何求两点之间通过第三点的弧?
- 如何在找到的圆弧上生成一组点?
让我们从第一部分开始。给定 (O, r)
圆上的三个点 A
、B
和 C
,我们想要找到 A
和 C
之间穿过 B
。要找到圆弧的内角,我们需要计算 AB
和 AC
圆弧的 oriented angles。如果 AB
的角度大于 AC
,则方向错误:
Va.x = A.x - O.x;
Va.y = A.y - O.y;
Vb.x = B.x - O.x;
Vb.y = B.y - O.y;
Vc.x = C.x - O.x;
Vc.y = C.y - O.y;
tb = orientedAngle(Va.x, Va.y, Vb.x, Vb.y);
tc = orientedAngle(Va.x, Va.y, Vc.x, Vc.y);
if tc<tb
tc = tc - 2 * pi;
end
function t = orientedAngle(x1, y1, x2, y2)
t = atan2(x1*y2 - y1*x2, x1*x2 + y1*y2);
if t<0
t = t + 2 * pi;
end
end
现在是第二部分。你说:
I probably need a loop that calculates each point by rotating a little after it has calculated a point.
但问题是,有多少?由于圆的周长随着半径的增加而增加,因此您无法以固定的角度达到固定的精度。换句话说,要绘制两条角度相同但半径不同的圆弧,我们需要的点数不同。我们可以假设[几乎]不变的是这些点之间的距离,或者我们为模拟弧线而绘制的线段的长度:
segLen = someConstantLength;
arcLen = abs(tc)*r;
segNum = ceil(arcLen/segLen);
segAngle = tc / segNum;
t = atan2(Va.y, Va.x);
for i from 0 to segNum
P[i].x = O.x + r * cos(t);
P[i].y = O.y + r * sin(t);
t = t + segAngle;
end
注意,虽然在这个方法中A
和C
肯定会被创建,但是点B
不一定是创建的点之一。但是这个点离最近的线段的距离会很小