Orfeo Toolbox  3.16
itkSimilarity3DTransform.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkSimilarity3DTransform.txx,v $
5  Language: C++
6  Date: $Date: 2009-03-03 15:09:21 $
7  Version: $Revision: 1.10 $
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 __itkSimilarity3DTransform_txx
18 #define __itkSimilarity3DTransform_txx
19 
21 #include "vnl/vnl_math.h"
22 #include "vnl/vnl_det.h"
23 
24 
25 namespace itk
26 {
27 
28 // Constructor with default arguments
29 template <class TScalarType>
32  Superclass(OutputSpaceDimension, ParametersDimension)
33 {
34  m_Scale = 1.0;
35 }
36 
37 
38 // Constructor with arguments
39 template<class TScalarType>
41 Similarity3DTransform( unsigned int outputSpaceDim,
42  unsigned int paramDim) :
43  Superclass(outputSpaceDim,paramDim)
44 {
45 }
46 
47 
48 // Constructor with arguments
49 template<class TScalarType>
52  const OutputVectorType & offset) :
53  Superclass(matrix,offset)
54 {
55 }
56 
57 
58 // Set the scale factor
59 template <class TScalarType>
60 void
63 {
64  m_Scale = scale;
65  this->ComputeMatrix();
66 }
67 
68 
69 // Directly set the matrix
70 template<class TScalarType>
71 void
73 ::SetMatrix( const MatrixType & matrix )
74 {
75  //
76  // Since the matrix should be an orthogonal matrix
77  // multiplied by the scale factor, then its determinant
78  // must be equal to the cube of the scale factor.
79  //
80  double det = vnl_det( matrix.GetVnlMatrix() );
81 
82  if( det == 0.0 )
83  {
84  itkExceptionMacro( << "Attempting to set a matrix with a zero determinant" );
85  }
86 
87  //
88  // A negative scale is not acceptable
89  // It will imply a reflection of the coordinate system.
90  //
91 
92  double s = vnl_math_cuberoot( det );
93 
94  //
95  // A negative scale is not acceptable
96  // It will imply a reflection of the coordinate system.
97  //
98  if( s <= 0.0 )
99  {
100  itkExceptionMacro( << "Attempting to set a matrix with a negative trace" );
101  }
102 
103  MatrixType testForOrthogonal = matrix;
104  testForOrthogonal /= s;
105 
106  const double tolerance = 1e-10;
107  if( !this->MatrixIsOrthogonal( testForOrthogonal, tolerance ) )
108  {
109  itkExceptionMacro( << "Attempting to set a non-orthogonal matrix (after removing scaling)" );
110  }
111 
113  this->Baseclass::SetMatrix( matrix );
114 }
115 
116 
117 // Set Parameters
118 template <class TScalarType>
119 void
121 ::SetParameters( const ParametersType & parameters )
122 {
123 
124  itkDebugMacro( << "Setting parameters " << parameters );
125 
126  // Transfer the versor part
127 
128  AxisType axis;
129 
130  double norm = parameters[0]*parameters[0];
131  axis[0] = parameters[0];
132  norm += parameters[1]*parameters[1];
133  axis[1] = parameters[1];
134  norm += parameters[2]*parameters[2];
135  axis[2] = parameters[2];
136  if( norm > 0)
137  {
138  norm = vcl_sqrt(norm);
139  }
140 
141  double epsilon = 1e-10;
142  if(norm >= 1.0-epsilon)
143  {
144  axis = axis / (norm+epsilon*norm);
145  }
146  VersorType newVersor;
147  newVersor.Set(axis);
148  this->SetVarVersor( newVersor );
149  m_Scale = parameters[6]; // must be set before calling ComputeMatrix();
150  this->ComputeMatrix();
151 
152  itkDebugMacro( <<"Versor is now " << this->GetVersor() );
153 
154 
155  // Transfer the translation part
156  TranslationType newTranslation;
157  newTranslation[0] = parameters[3];
158  newTranslation[1] = parameters[4];
159  newTranslation[2] = parameters[5];
160  this->SetVarTranslation(newTranslation);
161  this->ComputeOffset();
162 
163  // Modified is always called since we just have a pointer to the
164  // parameters and cannot know if the parameters have changed.
165  this->Modified();
166 
167  itkDebugMacro(<<"After setting parameters ");
168 }
169 
170 
171 //
172 // Get Parameters
173 //
174 // Parameters are ordered as:
175 //
176 // p[0:2] = right part of the versor (axis times vcl_sin(t/2))
177 // p[3:5} = translation components
178 // p[6:6} = scaling factor (isotropic)
179 //
180 
181 template <class TScalarType>
184 ::GetParameters( void ) const
185 {
186  itkDebugMacro( << "Getting parameters ");
187 
188  this->m_Parameters[0] = this->GetVersor().GetX();
189  this->m_Parameters[1] = this->GetVersor().GetY();
190  this->m_Parameters[2] = this->GetVersor().GetZ();
191 
192  // Transfer the translation
193  this->m_Parameters[3] = this->GetTranslation()[0];
194  this->m_Parameters[4] = this->GetTranslation()[1];
195  this->m_Parameters[5] = this->GetTranslation()[2];
196 
197  this->m_Parameters[6] = this->GetScale();
198 
199  itkDebugMacro(<<"After getting parameters " << this->m_Parameters );
200 
201  return this->m_Parameters;
202 }
203 
204 // Set parameters
205 template<class TScalarType>
208 GetJacobian( const InputPointType & p ) const
209 {
210  typedef typename VersorType::ValueType ValueType;
211 
212  // compute derivatives with respect to rotation
213  const ValueType vx = this->GetVersor().GetX();
214  const ValueType vy = this->GetVersor().GetY();
215  const ValueType vz = this->GetVersor().GetZ();
216  const ValueType vw = this->GetVersor().GetW();
217 
218  this->m_Jacobian.Fill(0.0);
219 
220  const InputVectorType pp = p - this->GetCenter();
221 
222  const double px = pp[0];
223  const double py = pp[1];
224  const double pz = pp[2];
225 
226  const double vxx = vx * vx;
227  const double vyy = vy * vy;
228  const double vzz = vz * vz;
229  const double vww = vw * vw;
230 
231  const double vxy = vx * vy;
232  const double vxz = vx * vz;
233  const double vxw = vx * vw;
234 
235  const double vyz = vy * vz;
236  const double vyw = vy * vw;
237 
238  const double vzw = vz * vw;
239 
240 
241  // compute Jacobian with respect to quaternion parameters
242  this->m_Jacobian[0][0] = 2.0 * ( (vyw+vxz)*py + (vzw-vxy)*pz)
243  / vw;
244  this->m_Jacobian[1][0] = 2.0 * ((vyw-vxz)*px -2*vxw *py + (vxx-vww)*pz)
245  / vw;
246  this->m_Jacobian[2][0] = 2.0 * ((vzw+vxy)*px + (vww-vxx)*py -2*vxw *pz)
247  / vw;
248 
249  this->m_Jacobian[0][1] = 2.0 * ( -2*vyw *px + (vxw+vyz)*py + (vww-vyy)*pz)
250  / vw;
251  this->m_Jacobian[1][1] = 2.0 * ((vxw-vyz)*px + (vzw+vxy)*pz)
252  / vw;
253  this->m_Jacobian[2][1] = 2.0 * ((vyy-vww)*px + (vzw-vxy)*py -2*vyw *pz)
254  / vw;
255 
256  this->m_Jacobian[0][2] = 2.0 * ( -2*vzw *px + (vzz-vww)*py + (vxw-vyz)*pz)
257  / vw;
258  this->m_Jacobian[1][2] = 2.0 * ((vww-vzz)*px -2*vzw *py + (vyw+vxz)*pz)
259  / vw;
260  this->m_Jacobian[2][2] = 2.0 * ((vxw+vyz)*px + (vyw-vxz)*py )
261  / vw;
262 
263  // compute Jacobian with respect to the translation parameters
264  this->m_Jacobian[0][3] = 1.0;
265  this->m_Jacobian[1][4] = 1.0;
266  this->m_Jacobian[2][5] = 1.0;
267 
268  // compute Jacobian with respect to the scale parameter
269  const MatrixType & matrix = this->GetMatrix();
270 
271  const InputVectorType mpp = matrix * pp;
272 
273  this->m_Jacobian[0][6] = mpp[0] / m_Scale;
274  this->m_Jacobian[1][6] = mpp[1] / m_Scale;
275  this->m_Jacobian[2][6] = mpp[2] / m_Scale;
276 
277  return this->m_Jacobian;
278 
279 }
280 
281 
282 // Set the scale factor
283 template <class TScalarType>
284 void
287 {
288  this->Superclass::ComputeMatrix();
289  MatrixType newMatrix = this->GetMatrix();
290  newMatrix *= m_Scale;
291  this->SetVarMatrix(newMatrix);
292 }
293 
294 
296 template <class TScalarType>
297 void
300 {
301  MatrixType matrix = this->GetMatrix();
302 
303  m_Scale = vnl_math_cuberoot( vnl_det( matrix.GetVnlMatrix() ) );
304 
305  matrix /= m_Scale;
306 
307  VersorType v;
308  v.Set( matrix );
309  this->SetVarVersor( v );
310 
311 }
312 
313 // Print self
314 template<class TScalarType>
315 void
317 PrintSelf(std::ostream &os, Indent indent) const
318 {
319  Superclass::PrintSelf(os,indent);
320  os << indent << "Scale = " << m_Scale << std::endl;
321 }
322 
323 } // namespace
324 
325 #endif

Generated at Sun Feb 3 2013 00:07:09 for Orfeo Toolbox with doxygen 1.8.1.1