将二次贝塞尔曲线转换为立方贝塞尔曲线

时间:2010-07-02 00:59:02

标签: c++ c algorithm graphics vector

将二次贝塞尔曲线(3点)转换为立方贝塞尔曲线(4点)的算法是什么?

3 个答案:

答案 0 :(得分:44)

来自http://fontforge.sourceforge.net/bezier.html

  

任何二次样条可以表示为立方(其中立方项为零)。立方体的终点与二次方的终点相同。

     

CP 0 = QP 0
  CP 3 = QP 2

     

立方体的两个控制点是:

     

CP 1 = QP 0 + 2/3 *(QP 1 -QP 0
  CP 2 = QP 2 + 2/3 *(QP 1 -QP 2

     

...由于四舍五入而引入了一个小错误,但它不太可能引人注意。

答案 1 :(得分:2)

只需给出已接受答案的证明即可。

二次贝塞尔曲线表示为:

Q(t)= Q 0 (1-t)²+ 2 Q 1 (1-t)t + Q 2

三次贝塞尔曲线表示为:

C(t)= C 0 (1-t)³+ 3 C 1 (1-t)²t + 3 C 2 (1-t)t²+ C 3

要使这两个多项式相等,它们的所有多项式系数必须相等。多项式系数通过以下表达式获得(例如:(1-t)²= 1-2t +t²),然后将1,t,t²和t³中的所有项分解为因子:

Q(t)= Q 0 +(-2Q 0 + 2Q 1 )t +(Q 0 -2Q 1 + Q 2 )t²

C(t)= C 0 +(-3C 0 + 3C 1 )t +(3C 0 -6C 1 + 3C 2 )t²+(-C 0 + 3C 1 -3C 2 + C 3 )t³

因此,我们得到以下4个方程:

C 0 = Q 0

-3C 0 + 3C 1 = -2Q 0 + 2Q 1

3C 0 -6C 1 + 3C 2 = Q 0 -2Q 1 + Q 2

-C 0 + 3C 1 -3C 2 + C 3 = 0

我们可以通过在第二行中用Q 0 替换C 0 来求解C 1 ,这样得出:

C 1 = Q 0 +(2/3)(Q 1 -Q 0 )< / p>

然后,我们可以继续替换以求解C 2 然后是C 3 ,或者简单地说“对称”,得出结论:

C 0 = Q 0

C 1 = Q 0 +(2/3)(Q 1 -Q 0 )< / p>

C 2 = Q 2 +(2/3)(Q 1 -Q 2 )< / p>

C 3 = Q 2

答案 2 :(得分:0)

作为参考,我基于Owen's answer above为NSBezierPath(macOS Swift 4)实现了addQuadCurve

extension NSBezierPath {
    public func addQuadCurve(to qp2: CGPoint, controlPoint qp1: CGPoint) {
        let qp0 = self.currentPoint
        self.curve(to: qp2,
            controlPoint1: qp0 + (2.0/3.0)*(qp1 - qp0),
            controlPoint2: qp2 + (2.0/3.0)*(qp1 - qp2))
    }
}

extension CGPoint {
    // Vector math
    public static func +(left: CGPoint, right: CGPoint) -> CGPoint {
        return CGPoint(x: left.x + right.x, y: left.y + right.y)
    }
    public static func -(left: CGPoint, right: CGPoint) -> CGPoint {
        return CGPoint(x: left.x - right.x, y: left.y - right.y)
    }
    public static func *(left: CGFloat, right: CGPoint) -> CGPoint {
        return CGPoint(x: left * right.x, y: left * right.y)
    }
}