Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef BSPLINE_ND_H
00019 #define BSPLINE_ND_H
00020
00021
00022 #include <vector>
00023 #include <cmath>
00024 #include <assert.h>
00025
00026 #define BSPLINE_TINY 1e-20
00027
00028
00036 template <class PointND>
00037 class BSplineND
00038 {
00039 public:
00040
00041 BSplineND();
00042
00043 ~BSplineND();
00044
00045 void setCtrlPoints(const std::vector<PointND>& ctrlPointVec );
00046
00047
00048 bool ipoWithConstSampleDist(double dIpoDist, std::vector<PointND>& ipoVec);
00049
00050 bool ipoWithNumSamples(int iNumPts, std::vector<PointND>& ipoVec);
00051
00052 void eval(double dPos, PointND& point);
00053
00054 double getMaxdPos() const { return m_dLength; }
00055
00056 private:
00057
00058 double m_iGrad;
00059
00060
00061 std::vector<PointND> m_CtrlPointVec;
00062
00063 std::vector<double> m_KnotVec;
00064
00065 double m_dLength;
00066
00067
00068 double evalBasis(double t, unsigned int i, int n);
00069
00070 };
00071
00072
00073
00074
00075
00076
00077
00078
00079 template <class PointND>
00080 inline BSplineND<PointND>::BSplineND()
00081 {
00082 m_iGrad = 3;
00083 m_dLength = 0;
00084 }
00085
00086
00087 template <class PointND>
00088 BSplineND<PointND>::~BSplineND()
00089 {
00090 }
00091
00092
00093 template <class PointND>
00094 void BSplineND<PointND>::setCtrlPoints(const std::vector<PointND>& ctrlPointVec )
00095 {
00096 int iNumCtrlPoint;
00097 int i;
00098 double d;
00099
00100 m_CtrlPointVec = ctrlPointVec;
00101 iNumCtrlPoint = m_CtrlPointVec.size();
00102
00103 if (iNumCtrlPoint < m_iGrad)
00104 {
00105 return;
00106 }
00107
00108 m_KnotVec.resize( iNumCtrlPoint + m_iGrad );
00109
00110
00111 for(i = 0; i< m_iGrad; i++)
00112 {
00113 m_KnotVec[i] = 0;
00114 }
00115
00116 int iNumInternalKnots = iNumCtrlPoint - m_iGrad;
00117 for(i=0; i<iNumInternalKnots; i++)
00118 {
00119 double Distance1 = 0.0;
00120 for(unsigned int k = 0; k < m_CtrlPointVec[i+1].size(); k++)
00121 {
00122 Distance1 += (m_CtrlPointVec[i+1].at(k) - m_CtrlPointVec[i+2].at(k)) * (m_CtrlPointVec[i+1].at(k) - m_CtrlPointVec[i+2].at(k));
00123 }
00124 d= m_KnotVec[i+m_iGrad-1] + sqrt(Distance1);
00125
00126 m_KnotVec[i+m_iGrad] = d;
00127 }
00128 double Distance2 = 0.0;
00129 for(unsigned int k = 0; k < m_CtrlPointVec[iNumInternalKnots+1].size(); k++)
00130 {
00131 Distance2 += ( m_CtrlPointVec[iNumInternalKnots+1].at(k) - m_CtrlPointVec[iNumInternalKnots+2].at(k)) * ( m_CtrlPointVec[iNumInternalKnots+1].at(k) - m_CtrlPointVec[iNumInternalKnots+2].at(k));
00132 }
00133 d = m_KnotVec[iNumCtrlPoint-1] + sqrt(Distance2);
00134
00135
00136 for(i = 0; i< m_iGrad; i++)
00137 {
00138 m_KnotVec[i+iNumCtrlPoint] = d;
00139 }
00140
00141
00142
00143 m_dLength = d;
00144
00145 }
00146
00147
00148
00149 template <class PointND>
00150 void BSplineND<PointND>::eval(double dPos, PointND& point)
00151 {
00152 double dFak;
00153
00154 for(unsigned int i = 0; i<point.size(); i++)
00155 point.at(i) = 0.0;
00156 for(unsigned int i = 0; i < m_CtrlPointVec.size(); i++)
00157 {
00158 dFak = evalBasis(dPos, i, m_iGrad);
00159 for(unsigned int j = 0; j<point.size(); j++)
00160 point.at(j) += m_CtrlPointVec[i][j] * dFak;
00161 }
00162 }
00163
00164
00165
00166 template <class PointND>
00167 bool BSplineND<PointND>::ipoWithConstSampleDist(double dIpoDist, std::vector<PointND >& ipoVec)
00168 {
00169 PointND buf = m_CtrlPointVec.front();
00170 int iNumOfPoints;
00171 double dPos;
00172
00173
00174 if (m_CtrlPointVec.size() < m_iGrad)
00175 {
00176 ipoVec = m_CtrlPointVec;
00177 return false;
00178 }
00179
00180
00181
00182
00183 iNumOfPoints = m_KnotVec.back() / dIpoDist + 2;
00184 ipoVec.resize(iNumOfPoints);
00185
00186
00187 dPos = 0;
00188 for(int i=0; i < iNumOfPoints -1 ; i++)
00189 {
00190 eval(dPos, buf);
00191 ipoVec[i] = buf;
00192 dPos += dIpoDist;
00193 }
00194
00195 ipoVec.back() = m_CtrlPointVec.back();
00196
00197 return true;
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 template <class PointND>
00274 bool BSplineND<PointND>::ipoWithNumSamples(int iNumOfPoints, std::vector<PointND >& ipoVec)
00275 {
00276 PointND buf;
00277 double dPos, dInc;
00278
00279 if (m_CtrlPointVec.size() < m_iGrad)
00280 {
00281 ipoVec = m_CtrlPointVec;
00282 return false;
00283 }
00284
00285 dInc = m_KnotVec.back() / (double)(iNumOfPoints-1);
00286 ipoVec.resize(iNumOfPoints);
00287
00288
00289 dPos = 0;
00290 for(int i=0; i < iNumOfPoints -1 ; i++)
00291 {
00292 eval(dPos, buf);
00293
00294 ipoVec[i] = buf;
00295 dPos += dInc;
00296 }
00297
00298 ipoVec.back() = m_CtrlPointVec.back();
00299 return true;
00300 }
00301
00302
00303 template <class PointND>
00304 double BSplineND<PointND>::evalBasis(double u, unsigned int i, int n)
00305 {
00306 assert(i >= 0);
00307 assert(i < m_KnotVec.size() - 1 );
00308
00309 if (n==1)
00310 {
00311 if ( (m_KnotVec[i]<=u) && ( u<m_KnotVec[i+1]) )
00312 {
00313 return 1.0;
00314 }
00315 else
00316 {
00317 return 0.0;
00318 }
00319 }
00320 else
00321 {
00322 double N;
00323 double dNum1, dNum2;
00324 double dDen1, dDen2;
00325
00326 dDen1 = u - m_KnotVec[i];
00327 dNum1 = m_KnotVec[i+n-1] - m_KnotVec[i];
00328
00329 dDen2 = m_KnotVec[i+n] - u;
00330 dNum2 = m_KnotVec[i+n] - m_KnotVec[i+1];
00331
00332 if ( (fabs(dNum1) > BSPLINE_TINY)&&(fabs(dNum2) > BSPLINE_TINY) )
00333 {
00334 N = dDen1 / dNum1 * evalBasis(u, i , n-1);
00335 N += dDen2 / dNum2 * evalBasis(u, i+1 , n-1);
00336 }
00337 else if ( (fabs(dNum1) < BSPLINE_TINY)&&(fabs(dNum2) > BSPLINE_TINY) )
00338 {
00339 N = dDen2 / dNum2 * evalBasis(u, i+1 , n-1);
00340 }
00341 else if ((fabs(dNum1) > BSPLINE_TINY)&&(fabs(dNum2) < BSPLINE_TINY))
00342 {
00343 N = dDen1 / dNum1 * evalBasis(u, i , n-1);
00344 }
00345 else
00346 {
00347 N = 0;
00348 }
00349
00350 return N;
00351 }
00352 }
00353
00354
00355
00356 #endif