样条之贝塞尔(Bezier)

      我曾经发过两篇关于贝塞尔的文章:数学图形(1.47)贝塞尔(Bézier)曲线数学图形之贝塞尔(Bézier)曲面。那是使用我自己定义的脚本语言生成贝塞尔图形。由于我自己定义的脚本语法功能有限,所以最多只能支持5次贝塞尔函数,而这里将实现N次。

      N阶贝塞尔曲线可如下推断:

      给定点P0P1、…、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 <assert.h>
 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 // --------------------------------------------------------------------------------------

 图像:

相关软件的下载地址为:https://files.cnblogs.com/WhyEngine/TestSpline.zip

posted on 2014-10-13 18:24  叶飞影  阅读(4264)  评论(1编辑  收藏  举报