将二次贝塞尔曲线(3点)转换为立方贝塞尔曲线(4点)的算法是什么?
答案 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 t²
三次贝塞尔曲线表示为:
C(t)= C 0 (1-t)³+ 3 C 1 (1-t)²t + 3 C 2 (1-t)t²+ C 3 t³
要使这两个多项式相等,它们的所有多项式系数必须相等。多项式系数通过以下表达式获得(例如:(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)
}
}