aimsalgo 6.0.0
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
41#include <cartodata/volume/volume.h>
42#include <aims/mesh/surface.h>
43#include <aims/bucket/bucket.h>
44#include <aims/math/eigen.h>
45
46
47template< class T > class Moment;
48
49
50template< class T >
51std::ostream& operator << ( std::ostream&, const Moment< T >& );
52
53
54template< class T >
55class Moment
56{
57 public:
58
60 {
61 mSub = -1,
62 mAdd = 1
63 };
64
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
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; }
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
163template< class T > inline
164Moment< 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
170template< 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
189template< 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"
223template< class T > inline
224void Moment< T >::update( Point3df& pt, int dir )
225{
226 update( (double)pt[ 0 ], (double)pt[ 1 ], (double)pt[ 2 ], dir );
227}
228
229
230template< class T > inline
232{
233 update( pt[ 0 ], pt[ 1 ], pt[ 2 ], dir );
234}
235
236
237template< class T > inline
238void Moment< T >::update( double, double, double, int )
239{
240 orientation();
241}
242#pragma GCC diagnostic pop
243
244
245template< class T > inline
247{
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
259 _eigenValue = eigen.doit( _eigenVector );
260 eigen.sort( _eigenVector, _eigenValue );
261}
262
263
264template< class T > inline
265std::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
295template< 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
399template< 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"
410template< 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
422template< 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
434template< 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.
double ct() const
Definition moment.h:101
double & m0()
Definition moment.h:112
double _cz
Definition moment.h:146
double _m2[6]
Definition moment.h:155
double * m3()
Definition moment.h:119
double _m3[10]
Definition moment.h:156
const double & sum() const
Definition moment.h:111
carto::VolumeRef< double > _eigenValue
Definition moment.h:158
virtual void update(AimsVector< double, 3 > &, int)
Definition moment.h:231
double _m1[3]
Definition moment.h:154
virtual void doit(const aims::BucketMap< Void > &)
Definition moment.h:435
double cx() const
Definition moment.h:98
const double * m3() const
Definition moment.h:120
Moment< T > & operator+=(const Moment< T > &)
Definition moment.h:296
double _sum
Definition moment.h:151
const carto::VolumeRef< double > & eigenValue() const
Definition moment.h:122
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
const double * m1() const
Definition moment.h:116
Moment(const Moment< T > &)
Definition moment.h:171
double _ct
Definition moment.h:147
const carto::VolumeRef< double > & eigenVector() const
Definition moment.h:124
void setcx(double x)
Definition moment.h:102
carto::VolumeRef< double > _eigenVector
Definition moment.h:159
virtual ~Moment()
Definition moment.h:95
const double * gravity() const
Definition moment.h:108
double * m2()
Definition moment.h:117
double _g[3]
Definition moment.h:149
virtual void orientation()
Definition moment.h:246
double _m0
Definition moment.h:152
const double * m2() const
Definition moment.h:118
Operation
Definition moment.h:60
@ mAdd
Definition moment.h:62
@ mSub
Definition moment.h:61
double cy() const
Definition moment.h:99
virtual void doit(AimsSurfaceTriangle &)
Definition moment.h:423
void setcz(double x)
Definition moment.h:104
const double & m0() const
Definition moment.h:113
double * gravity()
Definition moment.h:107
void setct(double x)
Definition moment.h:105
virtual void doit(carto::rc_ptr< carto::Volume< T > > &, T, int)
Definition moment.h:411
double _cx
Definition moment.h:144
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
double & sum()
Definition moment.h:110
double _cy
Definition moment.h:145
virtual void clear()
Definition moment.h:190
double * m1()
Definition moment.h:115
std::ostream & operator<<(std::ostream &, const Moment< T > &)
Definition moment.h:265
AIMSDATA_API AimsTimeSurface< 3, Void > AimsSurfaceTriangle
AimsVector< float, 3 > Point3df