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
00019
00020
00021
00022 #ifndef __itkNonUniformBSpline_txx
00023 #define __itkNonUniformBSpline_txx
00024
00025 #if defined(_MSC_VER)
00026 #pragma warning ( disable : 4786 )
00027 #endif
00028
00029 #include "itkNonUniformBSpline.h"
00030
00031 #include "vnl/vnl_vector.h"
00032 #include "vnl/vnl_matrix.h"
00033 #include "vnl/algo/vnl_lsqr.h"
00034 #include "vnl/vnl_linear_system.h"
00035
00036
00037
00038
00039 namespace itk
00040 {
00041
00043 template< unsigned int TDimension >
00044 NonUniformBSpline< TDimension >
00045 ::NonUniformBSpline()
00046 {
00047
00048 m_SplineOrder = 3;
00049 m_SpatialDimension = TDimension;
00050 }
00051
00053 template< unsigned int TDimension >
00054 NonUniformBSpline< TDimension >
00055 ::~NonUniformBSpline()
00056 {
00057 }
00058
00060 template< unsigned int TDimension >
00061 void
00062 NonUniformBSpline< TDimension >
00063 ::PrintSelf( std::ostream& os, Indent indent ) const
00064 {
00065 Superclass::PrintSelf( os, indent );
00066 os << indent << "NonUniformBSpline(" << this << ")" << std::endl;
00067
00068 os << indent << "Chord lengths : " << std::endl;
00069 for (ChordLengthListType::const_iterator iter = m_CumulativeChordLength.begin();
00070 iter != m_CumulativeChordLength.end();
00071 iter++)
00072 {
00073 os << indent << indent << *iter << std::endl;
00074 }
00075 os << indent << "Knots : " << std::endl;
00076 for (KnotListType::const_iterator kiter = m_Knots.begin();
00077 kiter != m_Knots.end();
00078 kiter++)
00079 {
00080 os << indent << indent << *kiter << std::endl;
00081 }
00082 os << indent << "Control Points : " << std::endl;
00083 for (typename ControlPointListType::const_iterator cpiter = m_ControlPoints.begin();
00084 cpiter != m_ControlPoints.end();
00085 cpiter++)
00086 {
00087 os << indent << indent << *cpiter << std::endl;
00088 }
00089 }
00090
00091
00093 template< unsigned int TDimension >
00094 void
00095 NonUniformBSpline< TDimension >
00096 ::SetPoints( PointListType & points )
00097 {
00098 m_Points.clear();
00099
00100 typename PointListType::iterator it,end;
00101 it = points.begin();
00102 end = points.end();
00103 while(it != end)
00104 {
00105 m_Points.push_back(*it);
00106 it++;
00107 }
00108
00109 this->Modified();
00110 }
00111
00113 template< unsigned int TDimension >
00114 void
00115 NonUniformBSpline< TDimension >
00116 ::SetKnots( KnotListType & knots )
00117 {
00118 m_Knots.clear();
00119
00120 int len = knots.size();
00121 double max_knot = knots[len - 1];
00122
00123 typename KnotListType::iterator it;
00124 typename KnotListType::iterator end;
00125
00126 it = knots.begin();
00127 end = knots.end();
00128
00129 while(it != end)
00130 {
00131 m_Knots.push_back(*it/max_knot);
00132 it++;
00133 }
00134
00135 this->Modified();
00136 }
00137
00138 template< unsigned int TDimension >
00139 double
00140 NonUniformBSpline< TDimension >
00141 ::NonUniformBSplineFunctionRecursive(unsigned int order, unsigned int i, double t) const
00142 {
00143 if (order == 1)
00144 {
00145 if (m_Knots[i] <= t && t < m_Knots[i+1])
00146 {
00147 return 1;
00148 }
00149 else
00150 {
00151 return 0;
00152 }
00153 }
00154
00155
00156
00157
00158
00159 double numer1 = (t - m_Knots[i]) * NonUniformBSplineFunctionRecursive(order-1, i, t);
00160 double denom1 = (m_Knots[i+order-1] - m_Knots[i]);
00161 double val1 = numer1 / denom1;
00162 if (denom1 == 0 && numer1 == 0)
00163 val1 = 0;
00164 else if (denom1 == 0)
00165 std::cout << "Error : " << denom1 << ", " << numer1 << std::endl;
00166
00167 double numer2 = (m_Knots[i+order] - t) * NonUniformBSplineFunctionRecursive(order-1, i+1, t);
00168 double denom2 = (m_Knots[i + order] - m_Knots[i+1]);
00169 double val2 = numer2 / denom2;
00170 if (denom2 == 0 && numer2 == 0)
00171 val2 = 0;
00172 else if (denom2 == 0)
00173 std::cout << "Error : " << denom2 << ", " << numer2 << std::endl;
00174
00175 return val1 + val2;
00176 }
00177
00178 template< unsigned int TDimension >
00179 void
00180 NonUniformBSpline< TDimension >
00181 ::ComputeChordLengths()
00182 {
00183 m_ChordLength.clear();
00184 m_CumulativeChordLength.clear();
00185
00186 m_ChordLength.push_back(0);
00187 m_CumulativeChordLength.push_back(0);
00188
00189 double total_chord_length = 0.0;
00190 ChordLengthListType temp;
00191
00192 for (::size_t i = 0; i < m_Points.size()-1; i++)
00193 {
00194 PointType pt = m_Points[i];
00195 PointType pt2 = m_Points[i+1];
00196
00197 double chord = pt.EuclideanDistanceTo(pt2);
00198 m_ChordLength.push_back(chord);
00199 total_chord_length = total_chord_length + chord;
00200 temp.push_back(total_chord_length);
00201 }
00202
00203 for (ChordLengthListType::iterator aiter = temp.begin();
00204 aiter != temp.end();
00205 aiter++)
00206 {
00207 m_CumulativeChordLength.push_back(*aiter/total_chord_length);
00208 }
00209
00210
00211
00212
00213 #ifdef DEBUG_SPLINE
00214 std::cout << "Total chord length : " << total_chord_length << std::endl;
00215
00216 std::cout << "Chord length : " << std::endl;
00217 for (ChordLengthListType::iterator aiter2 = m_ChordLength.begin();
00218 aiter2 != m_ChordLength.end();
00219 aiter2++)
00220 {
00221 std::cout << *aiter2 << std::endl;
00222 }
00223
00224 std::cout << "Cumulative chord length : " << std::endl;
00225 for (ChordLengthListType::iterator aiter3 = m_CumulativeChordLength.begin();
00226 aiter3 != m_CumulativeChordLength.end();
00227 aiter3++)
00228 {
00229 std::cout << *aiter3 << std::endl;
00230 }
00231 std::cout << std::endl;
00232 #endif
00233 }
00234
00235 template< unsigned int TDimension >
00236 void
00237 NonUniformBSpline< TDimension >
00238 ::SetControlPoints( ControlPointListType& ctrlpts )
00239 {
00240 m_ControlPoints.clear();
00241 for (typename ControlPointListType::iterator iter = ctrlpts.begin();
00242 iter != ctrlpts.end();
00243 iter++)
00244 {
00245 m_ControlPoints.push_back(*iter);
00246 }
00247 this->Modified();
00248 }
00249
00250
00251 template< unsigned int TDimension >
00252 const typename
00253 NonUniformBSpline< TDimension >::ControlPointListType &
00254 NonUniformBSpline< TDimension >::GetControlPoints() const
00255 {
00256 return this->m_ControlPoints;
00257 }
00258
00259
00260 template< unsigned int TDimension >
00261 const typename
00262 NonUniformBSpline< TDimension >::KnotListType &
00263 NonUniformBSpline< TDimension >::GetKnots() const
00264 {
00265 return this->m_Knots;
00266 }
00267
00268
00269 template< unsigned int TDimension >
00270 const typename
00271 NonUniformBSpline< TDimension >::PointListType &
00272 NonUniformBSpline< TDimension >::GetPoints() const
00273 {
00274 return this->m_Points;
00275 }
00276
00277
00278 template< unsigned int TDimension >
00279 void
00280 NonUniformBSpline< TDimension >::ComputeControlPoints()
00281 {
00282 unsigned int dim = m_Points[0].GetPointDimension();
00283
00284 #ifdef DEBUG_SPLINE
00285 std::cout << "Points have dimension : " << dim << std::endl;
00286 #endif
00287
00288
00289
00290
00291 vnl_matrix<double> data_matrix(m_Points.size(), dim);
00292
00293
00294
00295
00296 int rr = 0;
00297 for (typename PointListType::iterator iter = m_Points.begin();
00298 iter != m_Points.end();
00299 iter++)
00300 {
00301 PointType pt = (*iter);
00302 for (unsigned int i = 0; i < dim; i++)
00303 {
00304 data_matrix(rr, i) = pt.GetVnlVector()[i];
00305 }
00306 rr++;
00307 }
00308
00309 #ifdef DEBUG_SPLINE
00310 std::cout << std::endl << "Data matrix" << std::endl;
00311 std::cout << data_matrix << std::endl;
00312 #endif
00313
00314
00315
00316
00317
00318
00319 int num_rows = m_Points.size();
00320
00321
00322
00323
00324 int num_cols = m_Knots.size() - m_SplineOrder;
00325
00326 vnl_matrix<double> N_matrix(num_rows, num_cols);
00327
00328
00329
00330 for (int r = 0; r < num_rows; r++)
00331 {
00332 for (int c = 0; c < num_cols; c++)
00333 {
00334 double t = m_CumulativeChordLength[r];
00335 N_matrix(r, c) = NonUniformBSplineFunctionRecursive(m_SplineOrder, c, t);
00336 }
00337 }
00338
00339 N_matrix(num_rows-1, num_cols-1) = 1.0;
00340
00341 #ifdef DEBUG_SPLINE
00342 std::cout << "Basis function matrix : " << std::endl;
00343 std::cout << N_matrix << std::endl;
00344 #endif
00345
00346
00347 vnl_matrix<double> B;
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 std::cout << "Control point matrix : " << std::endl;
00358 std::cout << B << std::endl;
00359
00360
00361 m_ControlPoints.clear();
00362
00363 for ( unsigned int j = 0; j < B.rows(); j++ )
00364 {
00365 vnl_vector<double> v = B.get_row(j);
00366 itk::Vector<double> iv;
00367 iv.SetVnlVector(v);
00368 itk::Point<double, TDimension> pt;
00369 for ( unsigned int d = 0; d < dim; d++ )
00370 {
00371 pt[d] = v(d);
00372 }
00373 m_ControlPoints.push_back(pt);
00374 }
00375 return;
00376 }
00377
00378 template< unsigned int TDimension >
00379 typename NonUniformBSpline<TDimension>::PointType
00380 NonUniformBSpline< TDimension >
00381 ::EvaluateSpline(const itk::Array<double> & p) const
00382 {
00383 double t = p[0];
00384
00385 return EvaluateSpline(t);
00386 }
00387
00388 template< unsigned int TDimension >
00389 typename NonUniformBSpline<TDimension>::PointType
00390 NonUniformBSpline< TDimension >
00391 ::EvaluateSpline(double t) const
00392 {
00393 int i = 0;
00394
00395 vnl_vector<double> result(TDimension);
00396 result.fill(0);
00397
00398 for (typename ControlPointListType::const_iterator cpiter = m_ControlPoints.begin();
00399 cpiter != m_ControlPoints.end();
00400 cpiter++)
00401 {
00402 ControlPointType pt = *cpiter;
00403 vnl_vector<double> v = pt.GetVnlVector();
00404
00405 const double N = this->NonUniformBSplineFunctionRecursive(m_SplineOrder, i, t);
00406
00407 for( unsigned j = 0; j < TDimension; j++ )
00408 {
00409 result[j] += N * v[j];
00410 }
00411
00412 i++;
00413 }
00414
00415 double array[TDimension];
00416 for ( unsigned int d = 0; d < TDimension; d++ )
00417 {
00418 array[d] = result[d];
00419 }
00420
00421 ControlPointType sum(array);
00422 #ifdef DEBUG_SPLINE
00423 std::cout << "Result : " << result << std::endl;
00424 std::cout << "Sum : " << sum << std::endl;
00425 #endif
00426
00427 return sum;
00428 }
00429
00430 }
00431
00432 #endif