aimsalgo  5.1.2
Neuroimaging image processing
moment.h
Go to the documentation of this file.
1 /* This software and supporting documentation are distributed by
2  * Institut Federatif de Recherche 49
3  * CEA/NeuroSpin, Batiment 145,
4  * 91191 Gif-sur-Yvette cedex
5  * France
6  *
7  * This software is governed by the CeCILL-B license under
8  * French law and abiding by the rules of distribution of free software.
9  * You can use, modify and/or redistribute the software under the
10  * terms of the CeCILL-B license as circulated by CEA, CNRS
11  * and INRIA at the following URL "http://www.cecill.info".
12  *
13  * As a counterpart to the access to the source code and rights to copy,
14  * modify and redistribute granted by the license, users are provided only
15  * with a limited warranty and the software's author, the holder of the
16  * economic rights, and the successive licensors have only limited
17  * liability.
18  *
19  * In this respect, the user's attention is drawn to the risks associated
20  * with loading, using, modifying and/or developing or reproducing the
21  * software by the user in light of its specific status of free software,
22  * that may mean that it is complicated to manipulate, and that also
23  * therefore means that it is reserved for developers and experienced
24  * professionals having in-depth computer knowledge. Users are therefore
25  * encouraged to load and test the software's suitability as regards their
26  * requirements in conditions enabling the security of their systems and/or
27  * data to be ensured and, more generally, to use and operate it in the
28  * same conditions as regards security.
29  *
30  * The fact that you are presently reading this means that you have had
31  * knowledge of the CeCILL-B license and that you accept its terms.
32  */
33 
34 
35 #ifndef AIMS_MOMENT_MOMENT_H
36 #define AIMS_MOMENT_MOMENT_H
37 
38 #include <fstream>
39 #include <iostream>
40 
42 #include <aims/mesh/surface.h>
43 #include <aims/bucket/bucket.h>
44 #include <aims/math/eigen.h>
45 
46 
47 template< class T > class Moment;
48 
49 
50 template< class T >
51 std::ostream& operator << ( std::ostream&, const Moment< T >& );
52 
53 
54 template< class T >
55 class Moment
56 {
57  public:
58 
59  enum Operation
60  {
61  mSub = -1,
62  mAdd = 1
63  };
64 
65  enum MomentId
66  {
67  m000 = 0,
68 
69  m100 = 0,
70  m010 = 1,
71  m001 = 2,
72 
73  m200 = 0,
74  m020 = 1,
75  m002 = 2,
76  m110 = 3,
77  m101 = 4,
78  m011 = 5,
79 
80  m300 = 0,
81  m030 = 1,
82  m003 = 2,
83  m210 = 3,
84  m201 = 4,
85  m120 = 5,
86  m021 = 6,
87  m102 = 7,
88  m012 = 8,
89  m111 = 9
90  };
91 
93  Moment();
94  Moment( const Moment< T >& );
95  virtual ~Moment() { }
96 
97  virtual void clear();
98  double cx() const { return _cx; }
99  double cy() const { return _cy; }
100  double cz() const { return _cz; }
101  double ct() const { return _ct; }
102  void setcx( double x ) { _cx = x; }
103  void setcy( double x ) { _cy = x; }
104  void setcz( double x ) { _cz = x; }
105  void setct( double x ) { _ct = x; }
106 
107  double *gravity() { return &_g[ 0 ]; }
108  const double *gravity() const { return &_g[ 0 ]; }
109 
110  double& sum() { return _sum; }
111  const double& sum() const { return _sum; }
112  double& m0() { return _m0; }
113  const double& m0() const { return _m0; }
114 
115  double *m1() { return &_m1[ 0 ]; }
116  const double *m1() const { return &_m1[ 0 ]; }
117  double *m2() { return &_m2[ 0 ]; }
118  const double *m2() const { return &_m2[ 0 ]; }
119  double *m3() { return &_m3[ 0 ]; }
120  const double *m3() const { return &_m3[ 0 ]; }
121 
123  { return _eigenValue; }
125  { return _eigenVector; }
126 
127  virtual void update( Point3df&, int );
128  virtual void update( AimsVector<double,3>&, int );
129  virtual void update( double, double, double, int );
130 
131  // TODO: fix this API, having these methods left unimplemented is asking
132  // for trouble...
133  virtual void doit( carto::rc_ptr<carto::Volume< T > > &, T, int );
134  virtual void doit( AimsSurfaceTriangle& );
135  virtual void doit( const aims::BucketMap<Void> & );
136 
137  virtual void orientation();
138 
141 
142  protected:
143 
144  double _cx;
145  double _cy;
146  double _cz;
147  double _ct;
148 
149  double _g[ 3 ];
150 
151  double _sum;
152  double _m0;
153 
154  double _m1[ 3 ];
155  double _m2[ 6 ];
156  double _m3[ 10 ];
157 
160 };
161 
162 
163 template< class T > inline
164 Moment< T >::Moment() : _cx( 1.0 ), _cy( 1.0 ), _cz( 1.0 ), _ct( 1.0 ),
165  _sum( 0.0 ), _m0( 0.0 )
166 {
167 }
168 
169 
170 template< class T > inline
172  : _cx( other.cx() ), _cy( other.cy() ), _cz( other.cz() ),
173  _ct( other.ct() ), _sum( other.sum() ), _m0( other.m0() ),
174  _eigenValue( other.eigenValue() ),
175  _eigenVector( other.eigenVector() )
176 {
177  int i;
178 
179  for ( i=0; i<3; i++ )
180  {
181  _g[ i ] = other.gravity()[ i ];
182  _m1[ i ] = other.m1()[ i ];
183  }
184  for ( i=0; i<6; i++ ) _m2[ i ] = other.m2()[ i ];
185  for ( i=0; i<9; i++ ) _m3[ i ] = other.m3()[ i ];
186 }
187 
188 
189 template< class T > inline
191 {
192  _m0 = 0;
193  _m1[0] = 0;
194  _m1[1] = 0;
195  _m1[2] = 0;
196  _m2[0] = 0;
197  _m2[1] = 0;
198  _m2[2] = 0;
199  _m2[3] = 0;
200  _m2[4] = 0;
201  _m2[5] = 0;
202  _m3[0] = 0;
203  _m3[1] = 0;
204  _m3[2] = 0;
205  _m3[3] = 0;
206  _m3[4] = 0;
207  _m3[5] = 0;
208  _m3[6] = 0;
209  _m3[7] = 0;
210  _m3[8] = 0;
211  _m3[9] = 0;
212  _sum = 0;
213  _g[0] = 0;
214  _g[1] = 0;
215  _g[2] = 0;
216  // cx..ct ?
217 }
218 
219 
220 // make GCC warning non-fatal
221 #pragma GCC diagnostic push
222 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
223 template< class T > inline
224 void Moment< T >::update( Point3df& pt, int dir )
225 {
226  update( (double)pt[ 0 ], (double)pt[ 1 ], (double)pt[ 2 ], dir );
227 }
228 
229 
230 template< class T > inline
232 {
233  update( pt[ 0 ], pt[ 1 ], pt[ 2 ], dir );
234 }
235 
236 
237 template< class T > inline
238 void Moment< T >::update( double, double, double, int )
239 {
240  orientation();
241 }
242 #pragma GCC diagnostic pop
243 
244 
245 template< class T > inline
247 {
248  _eigenVector = carto::VolumeRef< double >( 3, 3, 1, 1,
249  carto::AllocatorContext::fast() );
250 
251  _eigenVector( 0, 0 ) = _m2[ 0 ];
252  _eigenVector( 1, 1 ) = _m2[ 1 ];
253  _eigenVector( 2, 2 ) = _m2[ 2 ];
254  _eigenVector( 0, 1 ) = _eigenVector( 1, 0 ) = _m2[ 3 ];
255  _eigenVector( 0, 2 ) = _eigenVector( 2, 0 ) = _m2[ 4 ];
256  _eigenVector( 1, 2 ) = _eigenVector( 2, 1 ) = _m2[ 5 ];
257 
258  AimsEigen< double > eigen;
259  _eigenValue = eigen.doit( _eigenVector );
260  eigen.sort( _eigenVector, _eigenValue );
261 }
262 
263 
264 template< class T > inline
265 std::ostream& operator << ( std::ostream& out , const Moment< T >& mom )
266 {
267  int i;
268 
269  out << "Image geometry: (" << mom.cx() << "x" << mom.cy() << "x" << mom.cz();
270  out << ")" << std::endl << "Volume : " << mom.m0() << "mm3" << std::endl;
271  out << "Number of points : " << mom.sum() << std::endl;
272  out << "Volume (mm3) : " << mom.m0() << std::endl;
273  out << "Order 1 moments : ";
274  for ( i=0; i<3; i++ ) out << mom.m1()[ i ] << " ";
275  out << std::endl << "Order 2 moments : ";
276  for ( i=0; i<6; i++ ) out << mom.m2()[ i ] << " ";
277  out << std::endl << "Order 3 moments : ";
278  for ( i=0; i<10; i++ ) out << mom.m3()[ i ] << " ";
279  out << std::endl << "Center of Mass : (" << mom.gravity()[ 0 ] << ",";
280  out << mom.gravity()[ 1 ] << "," << mom.gravity()[ 2 ] << ")" << std::endl;
281  out << "Orientation :" << std::endl << " Inerty : ";
282  out << mom.eigenValue()( 0, 0 ) << " ; " << mom.eigenValue()( 1, 1 );
283  out << " ; " << mom.eigenValue()( 2, 2 );
284  out << std::endl << " V1 : (" << mom.eigenVector()( 0, 0 ) << ",";
285  out << mom.eigenVector()( 1, 0 ) << "," << mom.eigenVector()( 2, 0 ) << ")";
286  out << std::endl << " V2 : (" << mom.eigenVector()( 0, 1 ) << ",";
287  out << mom.eigenVector()( 1, 1 ) << "," << mom.eigenVector()( 2, 1 ) << ")";
288  out << std::endl << " V3 : (" << mom.eigenVector()( 0, 2 ) << ",";
289  out << mom.eigenVector()( 1, 2 ) << "," << mom.eigenVector()( 2, 2 ) << ")";
290 
291  return out;
292 }
293 
294 
295 template< class T > inline
297 {
298  // un-center m2 and m3 which are centered, contrarily to m1
299  // don't ask me why (denis 22/07/2006)
300  if( _sum == 0 )
301  {
302  *this = m;
303  return *this;
304  }
305  else if( m._sum == 0 )
306  return *this;
307 
308  double g0 = _m1[0] / _m0;
309  double g1 = _m1[1] / _m0;
310  double g2 = _m1[2] / _m0;
311 
312  _m3[0] += _m0*g0*g0*g0 + g0*_m2[0]*3;
313  _m3[1] += _m0*g1*g1*g1 + g1*_m2[1]*3;
314  _m3[2] += _m0*g2*g2*g2 + g2*_m2[2]*3;
315  _m3[3] += _m0*g0*g0*g1 + g0*_m2[3]*2 + g1*_m2[0];
316  _m3[4] += _m0*g0*g0*g2 + g0*_m2[4]*2 + g2*_m2[0];
317  _m3[5] += _m0*g0*g1*g1 + g0*_m2[1] + g1*_m2[3]*2;
318  _m3[6] += _m0*g1*g1*g2 + g1*_m2[5]*2 + g2*_m2[1];
319  _m3[7] += _m0*g0*g2*g2 + g0*_m2[2] + g2*_m2[4]*2;
320  _m3[8] += _m0*g1*g2*g2 + g1*_m2[2] + g2*_m2[5]*2;
321  _m3[9] += _m0*g0*g1*g2 + g0*_m2[5] + g1*_m2[4] +g2*_m2[3];
322 
323  _m2[0] += _m0 * g0*g0;
324  _m2[1] += _m0 * g1*g1;
325  _m2[2] += _m0 * g2*g2;
326  _m2[3] += _m0 * g0*g1;
327  _m2[4] += _m0 * g0*g2;
328  _m2[5] += _m0 * g1*g2;
329 
330  double m20 = m._m2[0];
331  double m21 = m._m2[1];
332  double m22 = m._m2[2];
333  double m23 = m._m2[3];
334  double m24 = m._m2[4];
335  double m25 = m._m2[5];
336 
337  double h0 = m._m1[0] / m._m0;
338  double h1 = m._m1[1] / m._m0;
339  double h2 = m._m1[2] / m._m0;
340 
341  _sum += m._sum;
342  _m0 += m._m0;
343  _m1[0] += m._m1[0];
344  _m1[1] += m._m1[1];
345  _m1[2] += m._m1[2];
346 
347  _m3[0] += m._m3[0] + m._m0*h0*h0*h0 + h0*m20*3;
348  _m3[1] += m._m3[1] + m._m0*h1*h1*h1 + h1*m21*3;
349  _m3[2] += m._m3[2] + m._m0*h2*h2*h2 + h2*m22*3;
350  _m3[3] += m._m3[3] + m._m0*h0*h0*h1 + h0*m23*2 + h1*m20;
351  _m3[4] += m._m3[4] + m._m0*h0*h0*h2 + h0*m24*2 + h2*m20;
352  _m3[5] += m._m3[5] + m._m0*h0*h1*h1 + h0*m21 + h1*m23*2;
353  _m3[6] += m._m3[6] + m._m0*h1*h1*h2 + h1*m25*2 + h2*m21;
354  _m3[7] += m._m3[7] + m._m0*h0*h2*h2 + h0*m22 + h2*m24*2;
355  _m3[8] += m._m3[8] + m._m0*h1*h2*h2 + h1*m22 + h2*m25*2;
356  _m3[9] += m._m3[9] + m._m0*h0*h1*h2 + h0*m25 + h1*m24 +h2*m23;
357 
358  _m2[0] += m._m2[0] + m._m0 * h0*h0;
359  _m2[1] += m._m2[1] + m._m0 * h1*h1;
360  _m2[2] += m._m2[2] + m._m0 * h2*h2;
361  _m2[3] += m._m2[3] + m._m0 * h0*h1;
362  _m2[4] += m._m2[4] + m._m0 * h0*h2;
363  _m2[5] += m._m2[5] + m._m0 * h1*h2;
364 
365  // TODO: check that _cx..._ct match
366 
367  _g[0] = _m1[0] / _m0;
368  _g[1] = _m1[1] / _m0;
369  _g[2] = _m1[2] / _m0;
370 
371  g0 = _g[0];
372  g1 = _g[1];
373  g2 = _g[2];
374 
375  // center back m2 and m3
376  _m2[0] -= _m0 * g0*g0;
377  _m2[1] -= _m0 * g1*g1;
378  _m2[2] -= _m0 * g2*g2;
379  _m2[3] -= _m0 * g0*g1;
380  _m2[4] -= _m0 * g0*g2;
381  _m2[5] -= _m0 * g1*g2;
382 
383  _m3[0] -= _m0*g0*g0*g0 + g0*_m2[0]*3;
384  _m3[1] -= _m0*g1*g1*g1 + g1*_m2[1]*3;
385  _m3[2] -= _m0*g2*g2*g2 + g2*_m2[2]*3;
386  _m3[3] -= _m0*g0*g0*g1 + g0*_m2[3]*2 + g1*_m2[0];
387  _m3[4] -= _m0*g0*g0*g2 + g0*_m2[4]*2 + g2*_m2[0];
388  _m3[5] -= _m0*g0*g1*g1 + g0*_m2[1] + g1*_m2[3]*2;
389  _m3[6] -= _m0*g1*g1*g2 + g1*_m2[5]*2 + g2*_m2[1];
390  _m3[7] -= _m0*g0*g2*g2 + g0*_m2[2] + g2*_m2[4]*2;
391  _m3[8] -= _m0*g1*g2*g2 + g1*_m2[2] + g2*_m2[5]*2;
392  _m3[9] -= _m0*g0*g1*g2 + g0*_m2[5] + g1*_m2[4] +g2*_m2[3];
393 
394  orientation();
395  return *this;
396 }
397 
398 
399 template< class T > inline
401 {
402  Moment<T> mom( *this );
403  mom += m;
404  return mom;
405 }
406 
407 // make warning non-fatal (the API is broken, see comment in Moment<T>)
408 #pragma GCC diagnostic push
409 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
410 template< class T >
412 {
413  std::clog << "PROGRAMMING ERROR: called unimplemented base method"
414  " Moment<T>::doit( VolumeRef< T >&, T, int )"
415  << std::endl;
416 #ifndef NDEBUG
417  throw std::logic_error("called unimplemented base method"
418  " Moment<T>::doit( VolumeRef< T >&, T, int )");
419 #endif
420 }
421 
422 template< class T >
424 {
425  std::clog << "PROGRAMMING ERROR: called unimplemented base method"
426  " Moment<T>::doit( AimsSurfaceTriangle& )"
427  << std::endl;
428 #ifndef NDEBUG
429  throw std::logic_error("called unimplemented base method"
430  " Moment<T>::doit( AimsSurfaceTriangle& )");
431 #endif
432 }
433 
434 template< class T >
436 {
437  std::clog << "PROGRAMMING ERROR: called unimplemented base method"
438  " Moment<T>::doit( const aims::BucketMap<Void> & )"
439  << std::endl;
440 #ifndef NDEBUG
441  throw std::logic_error("called unimplemented base method"
442  " Moment<T>::doit( const aims::BucketMap<Void> & )");
443 #endif
444 }
445 #pragma GCC diagnostic pop
446 
447 #endif
void sort(carto::VolumeRef< T > eigenvectors, carto::VolumeRef< T > eigenvalues, carto::VolumeRef< T > *wi=NULL)
Sort the eigenvectors and eigenvalues in decreasing order.
carto::VolumeRef< T > doit(carto::VolumeRef< T >, carto::VolumeRef< T > *wi=NULL)
Eigen system resolution function.
Definition: moment.h:56
double ct() const
Definition: moment.h:101
double * m2()
Definition: moment.h:117
double _cz
Definition: moment.h:146
double _m2[6]
Definition: moment.h:155
double _m3[10]
Definition: moment.h:156
carto::VolumeRef< double > _eigenValue
Definition: moment.h:158
double * gravity()
Definition: moment.h:107
virtual void update(AimsVector< double, 3 > &, int)
Definition: moment.h:231
double _m1[3]
Definition: moment.h:154
double * m1()
Definition: moment.h:115
double & m0()
Definition: moment.h:112
virtual void doit(const aims::BucketMap< Void > &)
Definition: moment.h:435
double cx() const
Definition: moment.h:98
Moment< T > & operator+=(const Moment< T > &)
Definition: moment.h:296
const carto::VolumeRef< double > & eigenVector() const
Definition: moment.h:124
double _sum
Definition: moment.h:151
MomentId
Definition: moment.h:66
@ m300
Definition: moment.h:80
@ m003
Definition: moment.h:82
@ m102
Definition: moment.h:87
@ m200
Definition: moment.h:73
@ m210
Definition: moment.h:83
@ m020
Definition: moment.h:74
@ m030
Definition: moment.h:81
@ m021
Definition: moment.h:86
@ m001
Definition: moment.h:71
@ m100
Definition: moment.h:69
@ m120
Definition: moment.h:85
@ m010
Definition: moment.h:70
@ m201
Definition: moment.h:84
@ m111
Definition: moment.h:89
@ m002
Definition: moment.h:75
@ m110
Definition: moment.h:76
@ m011
Definition: moment.h:78
@ m101
Definition: moment.h:77
@ m012
Definition: moment.h:88
@ m000
Definition: moment.h:67
double cz() const
Definition: moment.h:100
void setcy(double x)
Definition: moment.h:103
double & sum()
Definition: moment.h:110
Moment(const Moment< T > &)
Definition: moment.h:171
const double * m1() const
Definition: moment.h:116
double _ct
Definition: moment.h:147
void setcx(double x)
Definition: moment.h:102
carto::VolumeRef< double > _eigenVector
Definition: moment.h:159
virtual ~Moment()
Definition: moment.h:95
double * m3()
Definition: moment.h:119
double _g[3]
Definition: moment.h:149
virtual void orientation()
Definition: moment.h:246
double _m0
Definition: moment.h:152
Operation
Definition: moment.h:60
@ mAdd
Definition: moment.h:62
@ mSub
Definition: moment.h:61
const double * m3() const
Definition: moment.h:120
double cy() const
Definition: moment.h:99
virtual void doit(AimsSurfaceTriangle &)
Definition: moment.h:423
const carto::VolumeRef< double > & eigenValue() const
Definition: moment.h:122
void setcz(double x)
Definition: moment.h:104
void setct(double x)
Definition: moment.h:105
const double & sum() const
Definition: moment.h:111
const double & m0() const
Definition: moment.h:113
virtual void doit(carto::rc_ptr< carto::Volume< T > > &, T, int)
Definition: moment.h:411
double _cx
Definition: moment.h:144
const double * m2() const
Definition: moment.h:118
Moment()
doesn't necessarily clear all moments to 0. Call clear() to be sure
Definition: moment.h:164
virtual void update(Point3df &, int)
Definition: moment.h:224
Moment< T > operator+(const Moment< T > &)
Definition: moment.h:400
virtual void update(double, double, double, int)
Definition: moment.h:238
const double * gravity() const
Definition: moment.h:108
double _cy
Definition: moment.h:145
virtual void clear()
Definition: moment.h:190
std::ostream & operator<<(std::ostream &, const Moment< T > &)
Definition: moment.h:265
DataTypeTraits< T >::LongType sum(const Volume< T > &vol)
AIMSDATA_API AimsTimeSurface< 3, Void > AimsSurfaceTriangle