我曾经发过两篇关于贝塞尔的文章:数学图形(1.47)贝塞尔(Bézier)曲线,数学图形之贝塞尔(Bézier)曲面,
样条之贝塞尔(Bezier)
。那是使用我自己定义的脚本语言生成贝塞尔图形。由于我自己定义的脚本语法功能有限,所以最多只能支持5次贝塞尔函数,而这里将实现N次。N阶贝塞尔曲线可如下推断:
给定点P0、P1、…、Pn,其贝塞尔曲线即
\mathbf{B}(t)=\sum_{i=0}^n {n\choose i}\mathbf{P}_i(1-t)^{n-i}t^i ={n\choose 0}\mathbf{P}_0(1-t)^nt^{0}+{n\choose 1}\mathbf{P}_1(1-t)^{n-1}t^{1}+\cdots+{n\choose n-1}\mathbf{P}_{n-1}(1-t)^{1}t^{n-1}+{n\choose n}\mathbf{P}_n(1-t)^{0}t^n \mbox{ , } t \in [0,1]
看其公式需要先为之生成一套杨辉三角形数组。
关于插值与样条的介绍请看:http://www.cnblogs.com/WhyEngine/p/4020294.html
.h文件
复制代码
1 /****************************************************************
2
3 File name : YcBezierSpline.h
4 Author : 叶峰
5 Version : 2.0
6 Create Date : 2014/08/18
7 Description : Bezier样条
8
9 *****************************************************************/
10
11 #ifndef __YcBezierSpline_H__
12 #define __YcBezierSpline_H__
13
14 // INCLUDES -----------------------------------------------------------------------------
15
16 #include "YicSpline.h"
17
18 // --------------------------------------------------------------------------------------
19
20 #define YD_MAX_BEZIER_CONTROL_VALUE 33
21
22 // --------------------------------------------------------------------------------------
23
24 class YcBezierSpline : public YicSpline
25 {
26 public:
27 YcBezierSpline();
28
29 ~YcBezierSpline();
30
31 // 设置输出样条值的数目
32 void SetSplineValuesCount(Yuint count);
33
34 // 获得输出样条值的数目
35 Yuint GetSplineValuesCount() const;
36
37 // 计算样条数值
38 bool BuildSpline(const void* ctrlValuesPtr, Yuint ctrlStride, Yuint ctrlCount,
39 void* splineValuesPtr, Yuint splineStride) const;
40
41 protected:
42 void ClearPowT();
43
44 void BuildPowT();
45
46 Yreal GetValueT(Yint t, Yint p) const
47 {
48 return m_pow_t[YD_MAX_BEZIER_CONTROL_VALUE*t + p];
49 }
50
51 protected:
52 Yuint m_valuesCount;
53 Yreal* m_pow_t;
54
55 protected:
56 static void BuildYanghuiTriangle();
57 static Yint m_yanghuiRowIndex[YD_MAX_BEZIER_CONTROL_VALUE];
58 static Yint m_yanghuiTriangle[(YD_MAX_BEZIER_CONTROL_VALUE+1)*YD_MAX_BEZIER_CONTROL_VALUE/2];
59 };
60
61 // --------------------------------------------------------------------------------------
62
63 #endif
复制代码
CPP文件
复制代码
1 /****************************************************************
2
3 File name : YcBezierSpline.cpp
4 Author : 叶峰
5 Version : 2.0
6 Create Date : 2014/08/18
7 Description :
8
9 *****************************************************************/
10
11 // INCLUDES -----------------------------------------------------------------------------
12
13 #include "..\..\YCommon_h\YSpline\YcBezierSpline.h"
14 #include
15
16 // --------------------------------------------------------------------------------------
17
18 Yint YcBezierSpline::m_yanghuiRowIndex[YD_MAX_BEZIER_CONTROL_VALUE] = {0};
19 Yint YcBezierSpline::m_yanghuiTriangle[(YD_MAX_BEZIER_CONTROL_VALUE+1)*YD_MAX_BEZIER_CONTROL_VALUE/2] = {0};
20
21 void YcBezierSpline::BuildYanghuiTriangle()
22 {
23 // 第0行
24 m_yanghuiRowIndex[0] = 0;
25 m_yanghuiTriangle[0] = 1;
26
27 Yint index = 1;
28 Yint t0,t1;
29 Yint* lastRow;
30 for (Yint i = 1; i < YD_MAX_BEZIER_CONTROL_VALUE; i++)
31 {
32 m_yanghuiRowIndex[i] = index;
33 m_yanghuiTriangle[index] = 1;
34 index++;
35
36 for (Yint j = 1; j <= i; j++)
37 {
38 lastRow = m_yanghuiTriangle + m_yanghuiRowIndex[i-1];
39 t0 = lastRow[j - 1];
40 t1 = (j < i) ? lastRow[j] : 0;
41
42 m_yanghuiTriangle[index] = t0 + t1;
43 index++;
44 }
45 }
46
47 assert(index == (YD_MAX_BEZIER_CONTROL_VALUE+1)*YD_MAX_BEZIER_CONTROL_VALUE/2);
48 }
49
50 // --------------------------------------------------------------------------------------
51
52 YcBezierSpline::YcBezierSpline()
53 {
54 if (m_yanghuiTriangle[0] == 0)
55 {
56 BuildYanghuiTriangle();
57 }
58
59 m_valuesCount = 0;
60 m_pow_t = NULL;
61
62 SetSplineValuesCount(100);
63 }
64
65 YcBezierSpline::~YcBezierSpline()
66 {
67 ClearPowT();
68 }
69
70 // 设置输出样条值的数目
71 void YcBezierSpline::SetSplineValuesCount(Yuint count)
72 {
73 if (count < 2)
74 {
75 count = 2;
76 }
77
78 if (count == m_valuesCount)
79 {
80 return;
81 }
82 m_valuesCount = count;
83 BuildPowT();
84 }
85
86 // 获得输出样条值的数目
87 Yuint YcBezierSpline::GetSplineValuesCount() const
88 {
89 return m_valuesCount;
90 }
91
92 void YcBezierSpline::ClearPowT()
93 {
94 if (m_pow_t)
95 {
96 free(m_pow_t);
97 m_pow_t = NULL;
98 }
99 }
100
101 void YcBezierSpline::BuildPowT()
102 {
103 ClearPowT();
104
105 m_pow_t = (Yreal*)malloc(m_valuesCount*YD_MAX_BEZIER_CONTROL_VALUE*sizeof(Yreal));
106 Yreal t;
107 for (Yuint i = 0; i < m_valuesCount; i++)
108 {
109 t = i/(m_valuesCount - 1.0f);
110
111 m_pow_t[i*YD_MAX_BEZIER_CONTROL_VALUE] = 1.0f;
112 for (Yint j = 1; j < YD_MAX_BEZIER_CONTROL_VALUE; j++)
113 {
114 m_pow_t[i*YD_MAX_BEZIER_CONTROL_VALUE + j] = m_pow_t[i*YD_MAX_BEZIER_CONTROL_VALUE + j - 1]*t;
115 }
116 }
117 }
118
119 // 计算样条数值
120 bool YcBezierSpline::BuildSpline(const void* ctrlValuesPtr, Yuint ctrlStride, Yuint ctrlCount,
121 void* splineValuesPtr, Yuint splineStride) const
122 {
123 if (ctrlCount < 2 || ctrlCount > YD_MAX_BEZIER_CONTROL_VALUE)
124 {
125 return false;
126 }
127
128 Yreal* destValue;
129 Yreal* srcValue;
130 Yreal v;
131 const Yint* yanghuiRow = m_yanghuiTriangle + m_yanghuiRowIndex[ctrlCount - 1];
132
133 for (Yuint i = 0; i < m_valuesCount; i++)
134 {
135 v = 0.0f;
136 for (Yuint j = 0; j < ctrlCount; j++)
137 {
138 srcValue = (Yreal*)((char*)ctrlValuesPtr + ctrlStride*j);
139 v += yanghuiRow[j] * (*srcValue) * GetValueT(i, j) * GetValueT(m_valuesCount - 1 - i, ctrlCount - 1 - j);
140 }
141
142 destValue = (Yreal*)((char*)splineValuesPtr + splineStride*i);
143 *destValue = v;
144 }
145
146 return true;
147 }
148
149 // --------------------------------------------------------------------------------------