Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #ifndef __SP_MATH_SPLINE_H__
00009 #define __SP_MATH_SPLINE_H__
00010
00011
00012 #include "Base/spMath.hpp"
00013 #include "Base/spInputOutput.hpp"
00014
00015 #include <vector>
00016
00017
00018 namespace sp
00019 {
00020 namespace math
00021 {
00022
00023
00024
00025
00026
00027
00028 template <class C> struct SSplinePolynom
00029 {
00030 SSplinePolynom() : a(0), b(0), c(0), d(0)
00031 {
00032 }
00033 ~SSplinePolynom()
00034 {
00035 }
00036
00037
00038 inline C calc(const C &t) const
00039 {
00040 return a + b*t + c*t*t + d*t*t*t;
00041 }
00042
00043
00044 C a, b, c, d;
00045 };
00046
00047
00049 template <class C, typename T, s32 Dimension> class SP_EXPORT Spline
00050 {
00051
00052 public:
00053
00054 Spline(T Expansion = T(1)) :
00055 PointCount_ (0 ),
00056 Polynom_ (0 ),
00057 Expansion_ (Expansion )
00058 {
00059 }
00060 ~Spline()
00061 {
00062 clear();
00063 }
00064
00065
00066
00067 bool create(const C* PointArray, u32 Count)
00068 {
00069 if (!PointArray || !Count)
00070 return false;
00071
00072
00073 clear();
00074
00075
00076 PointCount_ = Count;
00077 Polynom_ = new SSplinePolynom<C>[PointCount_];
00078
00079 update(PointArray);
00080
00081
00082 return true;
00083 }
00084
00085 void update(const C* PointArray)
00086 {
00087 if (PointArray && Polynom_)
00088 {
00089 for (s32 i = 0; i < Dimension; ++i)
00090 buildPolynom(PointArray, Polynom_, i);
00091 }
00092 }
00093
00094 void clear()
00095 {
00096
00097 PointCount_ = 0;
00098
00099
00100 MemoryManager::deleteBuffer(Polynom_);
00101 }
00102
00103
00104
00105 inline bool create(const std::vector<C> &PointList)
00106 {
00107 return PointList.size() ? create(&PointList[0], PointList.size()) : false;
00108 }
00109 inline void update(const std::vector<C> &PointList)
00110 {
00111 if (Polynom_ && PointList.size() == PointCount_)
00112 update(&PointList[0]);
00113 }
00114
00115 inline void setExpansion(T Expansion)
00116 {
00117 Expansion_ = Expansion;
00118 }
00119 inline T getExpansion() const
00120 {
00121 return Expansion_;
00122 }
00123
00124 inline u32 getPointCount() const
00125 {
00126 return PointCount_;
00127 }
00128
00129 inline SSplinePolynom<C>& getPolynom(const u32 Index)
00130 {
00131 return Polynom_[Index];
00132 }
00133 inline SSplinePolynom<C> getPolynom(const u32 Index) const
00134 {
00135 if (Index < PointCount_)
00136 return Polynom_[Index];
00137 return SSplinePolynom<C>();
00138 }
00139
00140 private:
00141
00142
00143
00144 void buildPolynom(const C* Points, SSplinePolynom<C>* f, s32 Comp)
00145 {
00146 T* s = new T[PointCount_];
00147 T* y = new T[PointCount_];
00148 T* v = new T[PointCount_];
00149 T* q = new T[PointCount_];
00150
00151 s32 i, Count = static_cast<s32>(PointCount_);
00152
00153 y[0] = 3 * (Points[1][Comp] - Points[0][Comp]);
00154
00155 for (i = 1; i < Count - 1; ++i)
00156 y[i] = 3 * (Points[i+1][Comp] - Points[i-1][Comp]);
00157
00158 y[Count - 1] = 3 * (Points[Count - 1][Comp] - Points[Count - 2][Comp]);
00159
00160 v[0] = T(0.5);
00161 q[0] = T(0.5) * y[0];
00162
00163 for (i = 1; i < Count - 1; ++i)
00164 {
00165 v[i] = T(1) / (4 - v[i - 1]);
00166 q[i] = Expansion_ * v[i] * (y[i] - q[i - 1]);
00167 }
00168
00169 q[Count - 1] = Expansion_ * (T(1) / (2 - v[Count - 2])) * (y[Count - 1] - q[Count - 2]);
00170
00171 s[Count - 1] = q[Count - 1];
00172
00173 for (i = Count - 2; i >= 0; --i)
00174 s[i] = q[i] - v[i]*s[i + 1];
00175
00176 for (i = 0; i < Count - 1; ++i)
00177 {
00178 f[i].a[Comp] = Points[i][Comp];
00179 f[i].b[Comp] = s[i];
00180 f[i].c[Comp] = 3*Points[i+1][Comp] - 3*Points[i ][Comp] - 2*s[i] - s[i+1];
00181 f[i].d[Comp] = 2*Points[i ][Comp] - 2*Points[i+1][Comp] + s[i] + s[i+1];
00182 }
00183
00184 delete [] s;
00185 delete [] y;
00186 delete [] v;
00187 delete [] q;
00188 }
00189
00190
00191
00192 u32 PointCount_;
00193 SSplinePolynom<C>* Polynom_;
00194 T Expansion_;
00195
00196 };
00197
00198 typedef Spline<dim::point2df, f32, 2> Spline2D;
00199 typedef Spline<dim::vector3df, f32, 3> Spline3D;
00200
00201
00202 }
00203
00204 }
00205
00206
00207 #endif
00208
00209
00210
00211