B-spline , deBoor算法实现

参考:

http://blog.csdn.net/tuqu/article/details/4749586

http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/

http://en.wikipedia.org/wiki/De_Boor_algorithm


tuqu的就是翻译Dr. C. -K的文章加上部分个人理解

实现deBoor算法:

http://www.91r.net/ask/14258839.html  ,这个实现作者完全没验证!!!不靠谱

相对靠谱的实现(根据wekipedia实现的)  hi3x10.wordpress.com/2009/10/18/de-boor-algorithm-in-c

http://bbs.csdn.net/topics/380072374 (作者很粗暴就把算法贴出来,没做什么描述)


我是根据Dr. C.-K的文章来实现的,但是却出现了问题。

举例:

假设 6 个控制点 ,10 个节点 [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0],3 次曲线 . 我要插入的u值分别为 [0.15,0.25,0.35,0.45,0.55,0.65,0.75,0.85,0.95].

当 u=0.75, 其落在了[U6,U7)节点空间, 按照hi3x10.wordpress.com/2009/10/18/de-boor-algorithm-in-c

的写法,将返回ctrlPoints[6],但是已经超出数组范围了!!!同理Dr. C. -K的deBoor算法也是如此,若s=0,则i=k时也超出了控制点数组Pi范围了。

而在WikiPedia上也只给出了原理,没说明l(即u所在区间)如何计算。

那么要么是我设置u出现了问题,要么是计算i(chi3x10用i表示,而Dr. C. -K用k表示)就不对,哪里出错了呢?

也许控制点应该用u所在Ui对应的控制点P,比如U6对应最大的控制点P5,而不是P6.


昨天思考了下,觉得根据B-Spline曲线定义,确实不可能超出控制点范围,所以实现程序时忽略超出范围的控制点即可. 比如u=0.75以及之后的u计算就要全部忽略。

同时,对比了C.-K的实现与wikiPedia的描述,发现其实两者基本一致(就1点不同),C.-K做得更完整,即插入值时要考虑原始节点(即m=n+p+1中的m+1个节点)的重复度。

不过两篇文章实现都没管插入节点如何设计的问题。

因为按照我遇到的问题,插入节点如果落在了[Uk,Uk+1),则可知

曲线次数<=k<=最后的控制点index。

按照算法,k<曲线次数就无法递归下去,而k大于最后控制点index就没有意义。

所以设计插入节点值时也得考虑下。



附上Dr. C. -K的de Boor算法


Input: a value u
Output: the point on the curve, C(u)

If u lies in [uk,uk+1) andu !=uk, leth =p (i.e., insertingup times) ands = 0;
If u = uk and uk is a knot of multiplicitys, leth =p - s (i.e., insertingup - s times);
Copy the affected control points Pk-s, Pk-s-1, Pk-s-2, ...,Pk-p+1 andPk-p to a new array and rename them asPk-s,0,Pk-s-1,0,Pk-s-2,0, ...,Pk-p+1,0;

forr := 1 tohdo

  • for i := k-p+r to k-s do
    • begin
      • Let a i,r = ( u - u i) / ( u i+p-r+1 - u i )
        Let P i,r = (1 - a i,r) P i-1,r-1 + a i,r P i,r-1
      end

Pk-s,p-s is the point C(u).

问题:

C. -K在文章说到:if a knot u is insertedrepeatedly so that its multiplicity isp, the last generated new control point isthe point on the curve that corresponds tou.

但是Clamped曲线要求前后P+1个节点相等,P0=P1=..=Pp=u1 , Pm=Pm-1=..=Pm-p-1=u2。那我设计初始knot span时,如果u值等于U0=U1=U2是否有影响?因为如果U0=U1..=Up,那么我要插入的次数是 曲线次数P-u所在区间已有的重复度(即P+1次)=-1,即不插入。


另外,C. -k的算法里,如果k=0(此时曲线是C.-k称为的open曲线,其他人可能称为floating曲线),那如何计算P0,p-s?以为P0,p-s需要P-1,p-s才行,我该跳过还是该直接等于P0,r-1??这个问题同样适用于wikiPedia上deBoor算法的描述。


2013/10/18, 根据网络上http://course.cug.edu.cn/21cn/%BC%C6%CB%E3%BB%FA%CD%BC%D0%CE%D1%A7/Chapter3/CG_Txt_3_021.htm

关于B-Spline de boor算法的实现(如何弄到,嘿嘿),我发现了自己的bug。实现后完整地画出了B-Spline曲线(按照Dr. C. -K文章实现de boor是OK的)。

说实话,Xcode上debug相当痛苦啊。

目前网络上发现的中国教科书实现的算法都没有考虑u所在knot span已有的重复度。

同时考虑到中国这里知识共享的问题,我把实现的代码分享出来。部分代码有点傻,没有优化过,请需要的人自己优化。

免责声明:这段代码是利用Dr. C.-K的文章实现的,仅作为学习、交流使用,其他方面本人概不负责。

实现环境:

2013/10/18,Xcode4.6.1,OS X Mountain Lion,English

项目创建利用了Cocos2d2.1版


链接地址:http://pan.baidu.com/s/1BXi7R



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值