Owe*_* S. 47
来自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)...由于四舍五入引入了一个小错误,但它不太可能引人注意.
只是为已接受的答案提供证明。
二次贝塞尔曲线表示为:
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 )
那么,我们可以继续代入求解 C 2然后 C 3,或者更优雅地注意到变量t' = 1-t变化下原始方程的对称性,并得出结论:
C 0 = Q 0
C 1 = Q 0 + (2/3) (Q 1 - Q 0 )
C 2 = Q 2 + (2/3) (Q 1 - Q 2 )
C 3 = Q 2
作为参考,我addQuadCurve根据上面 Owen 的答案实现了 NSBezierPath (macOS Swift 4) 。
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)
}
}
Run Code Online (Sandbox Code Playgroud)