【问题标题】:Splitting a bezier curve分割贝塞尔曲线
【发布时间】:2011-12-03 17:25:44
【问题描述】:

我正在为 iPhone 开发一款游戏,它会在你移动时在你的角色之后创建一条路径(移动类似于蛇,但在转向方面是弯曲的)。我现在这样做的方法是将玩家所在的所有顶点保存在一个数组中,然后在每一帧的每个顶点上画一个圆圈。

我想继续使用贝塞尔曲线。我已经阅读了很多关于它们的内容,并且我非常了解它们,但我对数学并不是很擅长。我已经明白我应该使用 DeCasteljau 的算法在特定的 t 处分割曲线,但我还没有找到要使用的公式以及如何在代码中实现这一点。

所以我目前拥有的是 t=1 处曲线的所有控制点。现在我只想获取 t

【问题讨论】:

    标签: math ios4 split bezier


    【解决方案1】:

    我设法让它工作,实际上非常简单的数学。只需计算贝塞尔曲线的所有切线即可得到分数。

    这里有一些蟒蛇:

    def sliceBezier(points, t):
        x1, y1 = points[0]
        x2, y2 = points[1]
        x3, y3 = points[2]
        x4, y4 = points[3]
    
        x12 = (x2-x1)*t+x1
        y12 = (y2-y1)*t+y1
    
        x23 = (x3-x2)*t+x2
        y23 = (y3-y2)*t+y2
    
        x34 = (x4-x3)*t+x3
        y34 = (y4-y3)*t+y3
    
        x123 = (x23-x12)*t+x12
        y123 = (y23-y12)*t+y12
    
        x234 = (x34-x23)*t+x23
        y234 = (y34-y23)*t+y23
    
        x1234 = (x234-x123)*t+x123
        y1234 = (y234-y123)*t+y123
    
        return [(x1, y1), (x12, y12), (x123, y123), (x1234, y1234)]
    

    称之为:

    sliceBezier([(point1_x, point1_y),(controlpoint1_x, controlpoint1_y),(controlpoint2_x, controlpoint2_y),(point2_x, point2_y)], 0.23);
    

    【讨论】:

    • 有了上面的解决方案,我不明白如何将新找到的点合并到原始列表中。如果我从四个点的列表开始,我希望拆分后的最终列表是七个点。但是,我看不到您的返回值在原始列表中的位置。
    • @Brannon 此方法在这里返回拆分的第一部分(因此只有 4 个点),因此如果您想要另一部分,您只需执行相同的操作,但 t = 1-t。我认为这应该有效。否则,我认为只是颠倒积分顺序应该是另一种方式。我写这篇文章已经有一段时间了:)
    • 是的,1-t 点的倒序确实可以计算另一边。我在 stackoverflow 上的另一篇文章中发现了这个建议。
    • 您可以通过返回 [(x1,y1),(x12,y12),(x123,y123),(x1234,y1234),(x234,y234),(x34,y34 ),(x4,y4)] 由于贝塞尔曲线定义中的对称性。
    【解决方案2】:

    我实现了类似的东西,如果你有一个现代浏览器take a look here。它是用 javascript 实现的,并且还支持更高阶的贝塞尔曲线。

    【讨论】:

    • +1 可在您的网站上提供非常漂亮的可视化和解释。对我来说,不仅解决方案很重要。我也想知道,为什么解决方案有效。谢谢!
    • 感谢您的赞许。我还实现了一种将贝塞尔曲线转换为一组顶点的算法。 (www.iscriptdesign.com/?sketch=iPath/polybezier.jsvg)。我仍在寻找将贝塞尔曲线转换为一组弧线的实现。
    【解决方案3】:

    这是使用 Apple 的 SIMD api 的解决方案。它简洁并返回两条细分曲线。

    void SplitBezier(float t,
                     simd_float2 cv[4],
                     simd_float2 a[4],
                     simd_float2 b[4]) {
    
      a[0] = cv[0];
      b[3] = cv[3];
    
      a[1] = simd_mix(cv[0], cv[1], t);
      b[2] = simd_mix(cv[2], cv[3], t);
    
      auto b12 = simd_mix(cv[1], cv[2], t);
    
      a[2] = simd_mix(a[1], b12, t);
      b[1] = simd_mix(b12, b[2], t);
    
      a[3] = b[0] = simd_mix(a[2], b[1], t);
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-12
      • 1970-01-01
      • 2011-03-10
      • 1970-01-01
      • 1970-01-01
      • 2013-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多