【问题标题】:Calculate the control points for cubic Bézier curve from an arc从弧计算三次贝塞尔曲线的控制点
【发布时间】:2015-12-25 22:19:45
【问题描述】:

我有一个由两个端点(P0 = x1,y1 和 P4 = x2,y2)和半径 R 或圆弧中心(C = xc, yc)定义的几何圆弧。我需要在javascript中计算三次贝塞尔曲线的两个控制点P2、P3。在我的特殊情况下,弧角将小于 90 度。

我已经搜索了互联网和 stackoverflow,但任何解决方案都是不完整的,不能概括为不确定角度的弧,或者太复杂以至于我无法理解。

有没有任何 javascript 代码或伪代码可以提供帮助?我之前问过一个类似的问题,但当我需要三次贝塞尔曲线时,我不恰当地将贝塞尔曲线称为二次曲线。

【问题讨论】:

    标签: javascript math geometry bezier


    【解决方案1】:

    圆弧的三次贝塞尔近似,由起点和终点的坐标、圆心和半径定义 – (x1,y1) = P0, (x2,y2) = P3, C = (cx,cy), R.
    (arс的近似值,由角度定义,可以找到here

    贝塞尔曲线的控制点应该在圆上给定点的切线上。一种可能的近似方法——(对称)曲线的中点应位于圆上。
    (注意,为了好的近似弧角不能很大)

    给定点的半径向量:

    V1 = (x1-cx, y1 - cy)
    V2 = (x2-cx, y2 - cy)
    

    切向量:

    T1 = (cy – y1, x1 – cx)
    T2 = (y2 - cy, cx – x2)
    

    控制点坐标(k - 未知因子):

    P1 = P0 + k * T1
    P2 = P3 + k * T2
    

    贝塞尔曲线的中点:

    MB = B(1/2) = P0 * 1/8 + P1 * 3/8 + P2 * 3/8 + P3 * 1/8 = 
    P0 * 1/8 + P0 * 3/8  + k * T1 * 3/8 + P3 * 3/8 + k * T2 * 3/8 +  P3 * 1/8 =
    (P0 + P3)/2 + k * 3/8 * (T1 +T2)
    

    现在根据 k 因子求解方程

    (MB.X – cx)^2 + (MB.Y – cy)^2 = R^2
    

    有两种可能的解决方案——如果输入点的顺序正确,我们需要正的一种(通常情况下对于弧

    Delphi 代码(不检查输入数据,不处理额外情况)及其结果:

      procedure BezierArcByPoints(x1, y1, x2, y2, cx, cy, R: Integer;
        var Pts: array of TPoint);
      var
        t1x, t1y, t2x, t2y, dx, dy, k, tx, ty, D, a, b, c: Double;
      begin
        t1x := cy - y1;
        t1y := x1 - cx;
        t2x := y2 - cy;
        t2y := cx - x2;
        dx := (x1 + x2) / 2 - cx;
        dy := (y1 + y2) / 2 - cy;
        tx := 3 / 8 * (t1x + t2x);
        ty := 3 / 8 * (t1y + t2y);
        a := tx * tx + ty * ty;
        b := dx * tx + dy * ty;
        c := dx * dx + dy * dy - R * R;
        D := b * b - a * c;
        if D > 0 then begin
          k := (Sqrt(D) - b) / a;
          Pts[0] := Point(x1, y1);
          Pts[3] := Point(x2, y2);
          Pts[1] := Point(x1 + Round(k * t1x), y1 + Round(k * t1y));
          Pts[2] := Point(x2 + Round(k * t2x), y2 + Round(k * t2y));
        end;
      end;
    
    var
      Pts: array [0 .. 3] of TPoint;
      an1, an2: Double;
    begin
      an1 := 0;
      an2 := Pi / 2;
      Canvas.Pen.Color := clBlue;
      Canvas.Pen.Width := 1;
      Canvas.Ellipse(100, 100, 301, 301);
      BezierArcByPoints(200 + Round(100 * Cos(an1)), 
                       200 + Round(100 * Sin(an1)),
                       200 + Round(100 * Cos(an2)), 
                       200 + Round(100 * Sin(an2)), 
                       200, 200, 100, Pts);
      Canvas.Pen.Color := clRed;
      Canvas.Pen.Width := 3;
      Canvas.PolyBezier(Pts);
    end;
    

    【讨论】:

    • 谢谢 MBo,这正是我想要的。转换为 javascript 很简单,而且效果很好。很抱歉我之前的帖子造成了混乱。
    • 对于更通用的解释,另请参阅pomax.github.io/bezierinfo/#circles_cubic,它给出了基于已知弧角 φ 的控制点的直接公式
    • 弧线不平怎么办,像螺旋线?
    • @WDUK 3d 曲线段可以近似为 d 贝塞尔曲线,曲线
    • 按 d 贝塞尔曲线曲线?你这是什么意思?
    猜你喜欢
    • 2016-06-24
    • 1970-01-01
    • 2011-08-03
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    相关资源
    最近更新 更多