JS 绘制 Cardinal 样条曲线

Cardinal 曲线

根据定义,给定点集 {Pk1,Pk,Pk+1,Pk+2} , 则 PkPk+1 之间的 Cardinal 曲线可以由如下方程生成:

P(u)=au3+bu2+cu+dd=Pkc=s(Pk+1Pk1)b=3(Pk+1Pk)s(Pk+2Pk)2ca=(Pk+1Pk)cb

其中,s 用于控制曲线的松紧,取值范围为 [0, 1]。 0 表示最紧绷 (无平滑转角);1 表示最松弛。

绘制思路

根据公式,则只需将 u 从 0 到 1 采样并依据公式计算坐标即可。不过,由于不好把握 u 的采样间隔,这里并不打算采用这种方案。

我的思路是:

  1. 先计算两点之间 x, y 方向的差值
  2. 取差值绝对值较大的那个值,按预设精度进行细分,计算出 u 的步长
  3. 根据 u 的步长,计算方程的增量 ΔP
  4. 采用前向差分法,依次计算中间点坐标
    a. 如果中间点到上一线段的距离小于预设精度,抛弃该点

前向差分

设有一个三次样条曲线,其表达式如下:

P(u)=au3+bu2+cu+d

如果将 u 的取值范围细分为具有固定大小 h 的子区间,则相邻两点 x 坐标为:

xk=x(uk)xk+1=x(uk+h)

可计算出前向差分为:

Δ1xk=xk+1xk=3ahuk2+(3ah2+2bh)uk+(ah3+bh2+ch)

由于 Δ1xk 是关于 u 的多项式,计算复杂,所以也可以计算出 Δ1xk 的增量 Δ2xk,这样即可用加法计算出 Δ1xk 的值。不断重复计算增量的过程,直到增量为常数。最终可以得到:

Δ1xk=3ahuk2+(3ah2+2bh)uk+(ah3+bh2+ch)Δ2xk=6ah2uk+6ah3+2bh2Δ3xk=6ah3

根据以上公式,从 u0=0 开始,步长为 hx 坐标的迭代过程为:

k Δ3xk Δ2xk Δ1xk xk
0 6ah3 6ah3+2bh2 ah3+bh2+ch d
1 6ah3 Δ2x0+Δ3x0 Δ1x0+Δ2x0 x0+Δ1x0
k 6ah3 Δ2xk1+Δ3xk1 Δ1xk1+Δ2xk1 xk1+Δxk1
可以看到,每次迭代只需计算 3 次加法。

成果

最终效果如下图,也可以点击此处查看演示效果及源代码。

Cardinal 样条曲线

看起来效果还是不错的。不过,根据算法描述可以发现,如果两个点相距很近,就会因为中间点不够多而走样。

其它生成方法

当然还其它方法也可以绘制。比如,二分迭代法。每次计算出曲线的中点,将曲线按中点分为两部分,然后迭代这个过程。还可以先把曲线转换为 Bezier 曲线,然后进行绘制。

posted @   1bite  阅读(80)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示