Orfeo Toolbox  3.16
itkMatrixOffsetTransformBase.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkMatrixOffsetTransformBase.txx,v $
5  Language: C++
6  Date: $Date: 2010-03-30 15:20:02 $
7  Version: $Revision: 1.23 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifndef __itkMatrixOffsetTransformBase_txx
18 #define __itkMatrixOffsetTransformBase_txx
19 
20 #include "itkNumericTraits.h"
22 #include "vnl/algo/vnl_matrix_inverse.h"
23 #include "itkMath.h"
24 
25 
26 namespace itk
27 {
28 
29 // Constructor with default arguments
30 template<class TScalarType, unsigned int NInputDimensions,
31  unsigned int NOutputDimensions>
34  : Superclass(OutputSpaceDimension, ParametersDimension)
35 {
36  m_Matrix.SetIdentity();
37  m_MatrixMTime.Modified();
38  m_Offset.Fill( 0 );
39  m_Center.Fill( 0 );
40  m_Translation.Fill( 0 );
41  m_Singular = false;
42  m_InverseMatrix.SetIdentity();
43  m_InverseMatrixMTime = m_MatrixMTime;
44  this->m_FixedParameters.SetSize ( NInputDimensions );
45  this->m_FixedParameters.Fill ( 0.0 );
46 }
47 
48 
49 // Constructor with default arguments
50 template<class TScalarType, unsigned int NInputDimensions,
51  unsigned int NOutputDimensions>
53 ::MatrixOffsetTransformBase( unsigned int outputDims,
54  unsigned int paramDims )
55  : Superclass(outputDims, paramDims)
56 {
57  m_Matrix.SetIdentity();
58  m_MatrixMTime.Modified();
59  m_Offset.Fill( 0 );
60  m_Center.Fill( 0 );
61  m_Translation.Fill( 0 );
62  m_Singular = false;
63  m_InverseMatrix.SetIdentity();
64  m_InverseMatrixMTime = m_MatrixMTime;
65 }
66 
67 // Constructor with explicit arguments
68 template<class TScalarType, unsigned int NInputDimensions,
69  unsigned int NOutputDimensions>
72  const OutputVectorType &offset)
73 {
74  m_Matrix = matrix;
75  m_MatrixMTime.Modified();
76  m_Offset = offset;
77  m_Center.Fill( 0 );
78  m_Translation.Fill(0);
79  for(unsigned int i=0; i<NOutputDimensions; i++)
80  {
81  m_Translation[i] = offset[i];
82  }
83  this->ComputeMatrixParameters();
84 }
85 
86 // Destructor
87 template<class TScalarType, unsigned int NInputDimensions,
88  unsigned int NOutputDimensions>
91 {
92  return;
93 }
94 
95 // Print self
96 template<class TScalarType, unsigned int NInputDimensions,
97  unsigned int NOutputDimensions>
98 void
100 ::PrintSelf(std::ostream &os, Indent indent) const
101 {
102  Superclass::PrintSelf(os,indent);
103 
104  unsigned int i, j;
105 
106  os << indent << "Matrix: " << std::endl;
107  for (i = 0; i < NInputDimensions; i++)
108  {
109  os << indent.GetNextIndent();
110  for (j = 0; j < NOutputDimensions; j++)
111  {
112  os << m_Matrix[i][j] << " ";
113  }
114  os << std::endl;
115  }
116 
117  os << indent << "Offset: " << m_Offset << std::endl;
118  os << indent << "Center: " << m_Center << std::endl;
119  os << indent << "Translation: " << m_Translation << std::endl;
120 
121  os << indent << "Inverse: " << std::endl;
122  for (i = 0; i < NInputDimensions; i++)
123  {
124  os << indent.GetNextIndent();
125  for (j = 0; j < NOutputDimensions; j++)
126  {
127  os << this->GetInverseMatrix()[i][j] << " ";
128  }
129  os << std::endl;
130  }
131  os << indent << "Singular: " << m_Singular << std::endl;
132 }
133 
134 // Constructor with explicit arguments
135 template<class TScalarType, unsigned int NInputDimensions,
136  unsigned int NOutputDimensions>
137 void
140 {
141  m_Matrix.SetIdentity();
142  m_MatrixMTime.Modified();
143  m_Offset.Fill( NumericTraits< OutputVectorValueType >::Zero );
144  m_Translation.Fill( NumericTraits< OutputVectorValueType >::Zero );
145  m_Center.Fill( NumericTraits< InputPointValueType >::Zero );
146  m_Singular = false;
147  m_InverseMatrix.SetIdentity();
148  m_InverseMatrixMTime = m_MatrixMTime;
149  this->Modified();
150 }
151 
152 
153 // Compose with another affine transformation
154 template<class TScalarType, unsigned int NInputDimensions,
155  unsigned int NOutputDimensions>
156 void
158 ::Compose(const Self * other, bool pre)
159 {
160  if (pre)
161  {
162  m_Offset = m_Matrix * other->m_Offset + m_Offset;
163  m_Matrix = m_Matrix * other->m_Matrix;
164  }
165  else
166  {
167  m_Offset = other->m_Matrix * m_Offset + other->m_Offset;
168  m_Matrix = other->m_Matrix * m_Matrix;
169  }
170 
171  this->ComputeTranslation();
172  this->ComputeMatrixParameters();
173 
174  m_MatrixMTime.Modified();
175  this->Modified();
176 
177  return;
178 }
179 
180 // Transform a point
181 template<class TScalarType, unsigned int NInputDimensions,
182  unsigned int NOutputDimensions>
183 typename MatrixOffsetTransformBase<TScalarType,
184  NInputDimensions,
185  NOutputDimensions>::OutputPointType
187 ::TransformPoint(const InputPointType &point) const
188 {
189  return m_Matrix * point + m_Offset;
190 }
191 
192 
193 // Transform a vector
194 template<class TScalarType, unsigned int NInputDimensions,
195  unsigned int NOutputDimensions>
196 typename MatrixOffsetTransformBase<TScalarType,
197  NInputDimensions,
198  NOutputDimensions>::OutputVectorType
201 {
202  return m_Matrix * vect;
203 }
204 
205 
206 // Transform a vnl_vector_fixed
207 template<class TScalarType, unsigned int NInputDimensions,
208  unsigned int NOutputDimensions>
209 typename MatrixOffsetTransformBase<TScalarType,
210  NInputDimensions,
211  NOutputDimensions>::OutputVnlVectorType
214 {
215  return m_Matrix * vect;
216 }
217 
218 
219 // Transform a CovariantVector
220 template<class TScalarType, unsigned int NInputDimensions,
221  unsigned int NOutputDimensions>
222 typename MatrixOffsetTransformBase<TScalarType,
223  NInputDimensions,
224  NOutputDimensions>::OutputCovariantVectorType
227 {
228  OutputCovariantVectorType result; // Converted vector
229 
230  for (unsigned int i = 0; i < NOutputDimensions; i++)
231  {
232  result[i] = NumericTraits<ScalarType>::Zero;
233  for (unsigned int j = 0; j < NInputDimensions; j++)
234  {
235  result[i] += this->GetInverseMatrix()[j][i]*vec[j]; // Inverse transposed
236  }
237  }
238  return result;
239 }
240 
241 // Recompute the inverse matrix (internal)
242 template<class TScalarType, unsigned int NInputDimensions,
243  unsigned int NOutputDimensions>
244 const typename MatrixOffsetTransformBase<TScalarType,
245  NInputDimensions,
246  NOutputDimensions>::InverseMatrixType &
248 ::GetInverseMatrix( void ) const
249 {
250  // If the transform has been modified we recompute the inverse
251  if(m_InverseMatrixMTime != m_MatrixMTime)
252  {
253  m_Singular = false;
254  try
255  {
256  m_InverseMatrix = m_Matrix.GetInverse();
257  }
258  catch(...)
259  {
260  m_Singular = true;
261  }
262  m_InverseMatrixMTime = m_MatrixMTime;
263  }
264 
265  return m_InverseMatrix;
266 }
267 
268 // return an inverse transformation
269 template<class TScalarType, unsigned int NInputDimensions,
270  unsigned int NOutputDimensions>
271 bool
273 ::GetInverse( Self * inverse) const
274 {
275  if(!inverse)
276  {
277  return false;
278  }
279 
280  this->GetInverseMatrix();
281  if(m_Singular)
282  {
283  return false;
284  }
285 
286  inverse->m_Matrix = this->GetInverseMatrix();
287  inverse->m_InverseMatrix = m_Matrix;
288  inverse->m_Offset = -(this->GetInverseMatrix() * m_Offset);
289  inverse->ComputeTranslation();
290  inverse->ComputeMatrixParameters();
291 
292  return true;
293 }
294 
295 // Return an inverse of this transform
296 template<class TScalarType, unsigned int NInputDimensions,
297  unsigned int NOutputDimensions>
298 typename MatrixOffsetTransformBase<TScalarType, NInputDimensions,
299  NOutputDimensions>::InverseTransformBasePointer
302 {
303  Pointer inv = New();
304  return GetInverse(inv) ? inv.GetPointer() : NULL;
305 }
306 
307 
308 // Get fixed parameters
309 template<class TScalarType, unsigned int NInputDimensions,
310  unsigned int NOutputDimensions>
311 void
314 {
315  this->m_FixedParameters = fp;
316  InputPointType c;
317  typedef typename ParametersType::ValueType ParameterValueType;
318  for ( unsigned int i = 0; i < NInputDimensions; i++ )
319  {
320  c[i] = this->m_FixedParameters[i];
321  }
322  this->SetCenter ( c );
323 }
324 
326 template<class TScalarType, unsigned int NInputDimensions,
327  unsigned int NOutputDimensions>
328 const typename MatrixOffsetTransformBase<TScalarType,
329  NInputDimensions,
330  NOutputDimensions>::ParametersType &
333 {
334  this->m_FixedParameters.SetSize ( NInputDimensions );
335  for ( unsigned int i = 0; i < NInputDimensions; i++ )
336  {
337  this->m_FixedParameters[i] = this->m_Center[i];
338  }
339  return this->m_FixedParameters;
340 }
341 
342 // Get parameters
343 template<class TScalarType, unsigned int NInputDimensions,
344  unsigned int NOutputDimensions>
345 const typename MatrixOffsetTransformBase<TScalarType,
346  NInputDimensions,
347  NOutputDimensions>::ParametersType &
349 ::GetParameters( void ) const
350 {
351  // Transfer the linear part
352  unsigned int par = 0;
353 
354  for(unsigned int row=0; row<NOutputDimensions; row++)
355  {
356  for(unsigned int col=0; col<NInputDimensions; col++)
357  {
358  this->m_Parameters[par] = m_Matrix[row][col];
359  ++par;
360  }
361  }
362 
363  // Transfer the constant part
364  for(unsigned int i=0; i<NOutputDimensions; i++)
365  {
366  this->m_Parameters[par] = m_Translation[i];
367  ++par;
368  }
369 
370  return this->m_Parameters;
371 }
372 
373 
374 // Set parameters
375 template<class TScalarType, unsigned int NInputDimensions,
376  unsigned int NOutputDimensions>
377 void
379 ::SetParameters( const ParametersType & parameters )
380 {
381  if (parameters.Size() <
382  (NOutputDimensions * NInputDimensions + NOutputDimensions))
383  {
384  itkExceptionMacro
385  (<< "Error setting parameters: parameters array size ("
386  << parameters.Size() << ") is less than expected "
387  << " (NInputDimensions * NOutputDimensions + NOutputDimensions) "
388  << " (" << NInputDimensions << " * " << NOutputDimensions
389  << " + " << NOutputDimensions
390  << " = " << NInputDimensions*NOutputDimensions+NOutputDimensions << ")"
391  );
392  }
393 
394  unsigned int par = 0;
395 
396  this->m_Parameters = parameters;
397 
398  for(unsigned int row=0; row<NOutputDimensions; row++)
399  {
400  for(unsigned int col=0; col<NInputDimensions; col++)
401  {
402  m_Matrix[row][col] = this->m_Parameters[par];
403  ++par;
404  }
405  }
406 
407  // Transfer the constant part
408  for(unsigned int i=0; i<NOutputDimensions; i++)
409  {
410  m_Translation[i] = this->m_Parameters[par];
411  ++par;
412  }
413 
414  m_MatrixMTime.Modified();
415 
416  this->ComputeMatrix(); // Not necessary since parameters explicitly define
417  // the matrix
418  this->ComputeOffset();
419 
420  // Modified is always called since we just have a pointer to the
421  // parameters and cannot know if the parameters have changed.
422  this->Modified();
423 
424 }
425 
426 
427 // Compute the Jacobian in one position
428 template<class TScalarType, unsigned int NInputDimensions,
429  unsigned int NOutputDimensions>
432 ::GetJacobian( const InputPointType & p ) const
433 {
434  // The Jacobian of the affine transform is composed of
435  // subblocks of diagonal matrices, each one of them having
436  // a constant value in the diagonal.
437 
438  this->m_Jacobian.Fill( 0.0 );
439 
440  const InputVectorType v = p - this->GetCenter();
441 
442  unsigned int blockOffset = 0;
443 
444  for(unsigned int block=0; block < NInputDimensions; block++)
445  {
446  for(unsigned int dim=0; dim < NOutputDimensions; dim++ )
447  {
448  this->m_Jacobian( block , blockOffset + dim ) = v[dim];
449  }
450 
451  blockOffset += NInputDimensions;
452 
453  }
454 
455  for(unsigned int dim=0; dim < NOutputDimensions; dim++ )
456  {
457  this->m_Jacobian( dim , blockOffset + dim ) = 1.0;
458  }
459 
460  return this->m_Jacobian;
461 
462 }
463 
464 // Computes offset based on center, matrix, and translation variables
465 template<class TScalarType, unsigned int NInputDimensions,
466  unsigned int NOutputDimensions>
467 void
470 {
471  const MatrixType & matrix = this->GetMatrix();
472 
473  OffsetType offset;
474  for(unsigned int i=0; i<NOutputDimensions; i++)
475  {
476  offset[i] = m_Translation[i] + m_Center[i];
477  for(unsigned int j=0; j<NInputDimensions; j++)
478  {
479  offset[i] -= matrix[i][j] * m_Center[j];
480  }
481  }
482 
483  m_Offset = offset;
484 }
485 
486 // Computes translation based on offset, matrix, and center
487 template<class TScalarType, unsigned int NInputDimensions,
488  unsigned int NOutputDimensions>
489 void
492 {
493  const MatrixType & matrix = this->GetMatrix();
494 
495  OffsetType translation;
496  for(unsigned int i=0; i<NOutputDimensions; i++)
497  {
498  translation[i] = m_Offset[i] - m_Center[i];
499  for(unsigned int j=0; j<NInputDimensions; j++)
500  {
501  translation[i] += matrix[i][j] * m_Center[j];
502  }
503  }
504 
505  m_Translation = translation;
506 }
507 
508 
509 // Computes matrix - base class does nothing. In derived classes is
510 // used to convert, for example, versor into a matrix
511 template<class TScalarType, unsigned int NInputDimensions,
512  unsigned int NOutputDimensions>
513 void
516 {
517  // Since parameters explicitly define the matrix in this base class, this
518  // function does nothing. Normally used to compute a matrix when
519  // its parameterization (e.g., the class' versor) is modified.
520 }
521 
522 
523 // Computes parameters - base class does nothing. In derived classes is
524 // used to convert, for example, matrix into a versor
525 template<class TScalarType, unsigned int NInputDimensions,
526  unsigned int NOutputDimensions>
527 void
530 {
531  // Since parameters explicitly define the matrix in this base class, this
532  // function does nothing. Normally used to update the parameterization
533  // of the matrix (e.g., the class' versor) when the matrix is explicitly
534  // set.
535 }
536 
537 } // namespace
538 
539 #endif

Generated at Sat Feb 2 2013 23:51:49 for Orfeo Toolbox with doxygen 1.8.1.1