【问题标题】:Convert a quadratic bezier to a cubic one将二次贝塞尔曲线转换为三次贝塞尔曲线
【发布时间】:2011-03-10 21:51:37
【问题描述】:

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

【问题讨论】:

    标签: c++ c algorithm graphics vector


    【解决方案1】:

    来自https://fontforge.org/docs/techref/bezier.html#converting-truetype-to-postscript

    任何二次样条都可以表示为三次(三次项为零)。三次方的端点将与二次方的端点相同。

    CP0 = QP0
    CP3 = QP2

    三次方的两个控制点是:

    CP1 = QP0 + 2/3 *(QP1-QP0)
    CP2 = QP2 + 2/3 *(QP1-QP2)

    ...由于四舍五入而引入了轻微错误,但不太可能引起注意。

    【讨论】:

    • Flavius 建议使用CP2 = CP1 + 1/3*(QP1-QP2)。但从我的数学来看,这似乎给出了不同的结果。 (拿点QP0=(0,0)QP1=(1,2)QP2=(3,0);我的公式得到CP2=(5/3, 4/3),弗拉维乌斯的得到CP2=(0,2)。)我通过将三次系数设置为0 并求解其余部分来验证我的公式。 Flavius,你的配方是从哪里来的?
    • QP2 是二次方的句柄/锚点还是 QP1 是二次方的句柄/锚点?人们在我读到关于贝塞尔的每一个地方都会改变这些的顺序,当人们不指定时,要跟踪是很痛苦的。
    • QP1是中间的控制点,QP2是终点。
    【解决方案2】:

    作为参考,我基于 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)
        }
    }
    

    【讨论】:

      【解决方案3】:

      只是为接受的答案提供证明。

      二次贝塞尔曲线表示为:

      Q(t) = Q0 (1-t)² + 2 Q1 (1-t) t + Q2

      三次贝塞尔曲线表示为:

      C(t) = C0 (1-t)³ + 3 C1 (1-t)² t + 3 C2 sub> (1-t) t² + C3

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

      Q(t) = Q0 + (-2Q0 + 2Q1) t + (Q0 sub> - 2Q1 + Q2) t²

      C(t) = C0 + (-3C0 + 3C1) t + (3C0 sub> - 6C1 + 3C2) t² + (-C0 + 3C1 -3C2 + C3) t³

      因此,我们得到以下 4 个等式:

      C0 = Q0

      -3C0 + 3C1 = -2Q0 + 2Q1

      3C0 - 6C1 + 3C2 = Q0 - 2Q1子> + Q2

      -C0 + 3C1 -3C2 + C3 = 0

      我们可以通过在第二行简单地将 C0 替换为 Q0 来求解 C1,得到:

      C1 = Q0 + (2/3) (Q1 - Q0)

      那么,我们可以继续代入求解C2然后C3,或者更优雅地注意变量变化下原方程的对称性t' = 1-t,得出结论:

      C0 = Q0

      C1 = Q0 + (2/3) (Q1 - Q0)

      C2 = Q2 + (2/3) (Q1 - Q2)

      C3 = Q2

      【讨论】:

        猜你喜欢
        • 2016-10-05
        • 1970-01-01
        • 1970-01-01
        • 2012-07-27
        • 2012-01-19
        • 1970-01-01
        • 2015-06-15
        • 1970-01-01
        • 2011-08-03
        相关资源
        最近更新 更多