Pat*_*Pat 2 javascript math geometry bezier
我有一个由两个端点(P0 = x1,y1 和 P4 = x2,y2)以及半径 R 或圆弧中心(C = xc, yc)定义的几何弧。我需要在javascript中计算三次B\xc3\xa9zier曲线的两个控制点P2、P3。在我的特定情况下,弧角将小于 90 度。
\n\n我搜索过互联网和 stackoverflow,任何解决方案都是不完整的,没有针对不确定角度的弧进行概括,或者太复杂而我无法理解。
\n\n有谁有任何 javascript 代码或伪代码可以提供帮助吗?我之前问过类似的问题,但当我需要三次 B\xc3\xa9zier 曲线时,错误地将 B\xc3\xa9zier 曲线称为二次曲线。
\n圆弧的三次贝塞尔近似,由圆的起点和终点坐标、圆心和半径 \xe2\x80\x93 定义(x1,y1) = P0, (x2,y2) = P3, C = (cx,cy), R。\n(由角度定义的 ar\xd1\x81 的近似值可以在此处
找到)
贝塞尔曲线的控制点应该位于圆上给定点的切线上。一种可能的近似方法 \xe2\x80\x93 (对称)曲线的中点应位于圆上。
\n(请注意,为了获得良好的近似,弧角不能太大)
给定点的半径向量:
\n\nV1 = (x1-cx, y1 - cy)\nV2 = (x2-cx, y2 - cy)\nRun Code Online (Sandbox Code Playgroud)\n\n切向量:
\n\nT1 = (cy \xe2\x80\x93 y1, x1 \xe2\x80\x93 cx)\nT2 = (y2 - cy, cx \xe2\x80\x93 x2)\nRun Code Online (Sandbox Code Playgroud)\n\n控制点坐标(k \xe2\x80\x93 未知但因素):
\n\nP1 = P0 + k * T1\nP2 = P3 + k * T2\nRun Code Online (Sandbox Code Playgroud)\n\n贝塞尔曲线的中点:
\n\nMB = B(1/2) = P0 * 1/8 + P1 * 3/8 + P2 * 3/8 + P3 * 1/8 = \nP0 * 1/8 + P0 * 3/8 + k * T1 * 3/8 + P3 * 3/8 + k * T2 * 3/8 + P3 * 1/8 =\n(P0 + P3)/2 + k * 3/8 * (T1 +T2)\nRun Code Online (Sandbox Code Playgroud)\n\n现在针对 k 因子求解方程
\n\n(MB.X \xe2\x80\x93 cx)^2 + (MB.Y \xe2\x80\x93 cy)^2 = R^2\nRun Code Online (Sandbox Code Playgroud)\n\n有两种可能的解决方案 \xe2\x80\x93 如果输入点的顺序正确(通常情况下,弧 < Pi - 具有最小量级),我们需要正解
\n\nDelphi 代码(不检查输入数据,不处理额外情况)及其结果:\n
procedure BezierArcByPoints(x1, y1, x2, y2, cx, cy, R: Integer;\n var Pts: array of TPoint);\n var\n t1x, t1y, t2x, t2y, dx, dy, k, tx, ty, D, a, b, c: Double;\n begin\n t1x := cy - y1;\n t1y := x1 - cx;\n t2x := y2 - cy;\n t2y := cx - x2;\n dx := (x1 + x2) / 2 - cx;\n dy := (y1 + y2) / 2 - cy;\n tx := 3 / 8 * (t1x + t2x);\n ty := 3 / 8 * (t1y + t2y);\n a := tx * tx + ty * ty;\n b := dx * tx + dy * ty;\n c := dx * dx + dy * dy - R * R;\n D := b * b - a * c;\n if D > 0 then begin\n k := (Sqrt(D) - b) / a;\n Pts[0] := Point(x1, y1);\n Pts[3] := Point(x2, y2);\n Pts[1] := Point(x1 + Round(k * t1x), y1 + Round(k * t1y));\n Pts[2] := Point(x2 + Round(k * t2x), y2 + Round(k * t2y));\n end;\n end;\n\nvar\n Pts: array [0 .. 3] of TPoint;\n an1, an2: Double;\nbegin\n an1 := 0;\n an2 := Pi / 2;\n Canvas.Pen.Color := clBlue;\n Canvas.Pen.Width := 1;\n Canvas.Ellipse(100, 100, 301, 301);\n BezierArcByPoints(200 + Round(100 * Cos(an1)), \n 200 + Round(100 * Sin(an1)),\n 200 + Round(100 * Cos(an2)), \n 200 + Round(100 * Sin(an2)), \n 200, 200, 100, Pts);\n Canvas.Pen.Color := clRed;\n Canvas.Pen.Width := 3;\n Canvas.PolyBezier(Pts);\nend;\nRun Code Online (Sandbox Code Playgroud)\n