参考:
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
-
Let
a
i,r = (
u -
u
i) / (
u
i+p-r+1 -
u
i )
- begin
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