1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkIdentityTransform_h
19 #define itkIdentityTransform_h
20 
21 #include "itkObject.h"
22 #include "itkPoint.h"
23 #include "itkCovariantVector.h"
24 #include "vnl/vnl_vector_fixed.h"
25 #include "itkArray2D.h"
26 #include "itkTransform.h"
27 
28 namespace itk
29 {
30 /** \class IdentityTransform
31  * \brief Implementation of an Identity Transform.
32  *
33  * This class defines the generic interface for an Identity Transform.
34  *
35  * It will map every point to itself, every vector to itself and
36  * every covariant vector to itself.
37  *
38  * This class is intended to be used primarily as a default Transform
39  * for initializing those classes supporting a generic Transform.
40  *
41  * This class is templated over the Representation type for coordinates
42  * (that is the type used for representing the components of points and
43  * vectors) and over the dimension of the space. In this case the Input
44  * and Output spaces are the same so only one dimension is required.
45  *
46  *
47  * \ingroup ITKTransform
48  */
49 template<typename TParametersValueType,
50           unsigned int NDimensions=3>
51 class ITK_TEMPLATE_EXPORT IdentityTransform : public Transform<TParametersValueType, NDimensions, NDimensions>
52 {
53 public:
54   ITK_DISALLOW_COPY_AND_ASSIGN(IdentityTransform);
55 
56   /** Standard class type aliases. */
57   using Self = IdentityTransform;
58   using Superclass = Transform<TParametersValueType, NDimensions, NDimensions>;
59   using Pointer = SmartPointer<Self>;
60   using ConstPointer = SmartPointer<const Self>;
61 
62   /** New method for creating an object using a factory. */
63   itkNewMacro(Self);
64 
65   /** Run-time type information (and related methods). */
66   itkTypeMacro(IdentityTransform, Transform);
67 
68   /** Dimension of the domain space. */
69   static constexpr unsigned int InputSpaceDimension = NDimensions;
70   static constexpr unsigned int OutputSpaceDimension = NDimensions;
71 
72   /** Type of the input parameters. */
73   using ParametersType = typename Superclass::ParametersType;
74   using ParametersValueType = typename Superclass::ParametersValueType;
75   using FixedParametersType = typename Superclass::FixedParametersType;
76   using FixedParametersValueType = typename Superclass::FixedParametersValueType;
77   using ScalarType = ParametersValueType;
78 
79 
80   /** Type of the Jacobian matrix. */
81   using JacobianType = typename Superclass::JacobianType;
82   using JacobianPositionType = typename Superclass::JacobianPositionType;
83   using InverseJacobianPositionType = typename Superclass::InverseJacobianPositionType;
84 
85   /** Transform category type. */
86   using TransformCategoryType = typename Superclass::TransformCategoryType;
87 
88   /** Standard vector type for this class. */
89   using InputVectorType = Vector<TParametersValueType,
90                  Self::InputSpaceDimension>;
91   using OutputVectorType = Vector<TParametersValueType,
92                  Self::OutputSpaceDimension>;
93 
94   /** Standard covariant vector type for this class */
95   using InputCovariantVectorType = CovariantVector<TParametersValueType,
96                           Self::InputSpaceDimension>;
97   using OutputCovariantVectorType = CovariantVector<TParametersValueType,
98                           Self::OutputSpaceDimension>;
99 
100   /** Standard vnl_vector type for this class. */
101   using InputVnlVectorType = vnl_vector_fixed<TParametersValueType,
102                            Self::InputSpaceDimension>;
103   using OutputVnlVectorType = vnl_vector_fixed<TParametersValueType,
104                            Self::OutputSpaceDimension>;
105 
106   /** Standard coordinate point type for this class */
107   using InputPointType = Point<TParametersValueType,
108                 Self::InputSpaceDimension>;
109   using OutputPointType = Point<TParametersValueType,
110                 Self::OutputSpaceDimension>;
111 
112   /** Base inverse transform type. This type should not be changed to the
113    * concrete inverse transform type or inheritance would be lost.*/
114   using InverseTransformBaseType = typename Superclass::InverseTransformBaseType;
115   using InverseTransformBasePointer = typename InverseTransformBaseType::Pointer;
116 
117   /**  Method to transform a point. */
TransformPoint(const InputPointType & point)118   OutputPointType TransformPoint(const InputPointType  & point) const override
119   {
120     return point;
121   }
122 
123   /**  Method to transform a vector. */
124   using Superclass::TransformVector;
TransformVector(const InputVectorType & vector)125   OutputVectorType TransformVector(const InputVectorType & vector) const override
126   {
127     return vector;
128   }
129 
130   /**  Method to transform a vnl_vector. */
TransformVector(const InputVnlVectorType & vector)131   OutputVnlVectorType TransformVector(const InputVnlVectorType & vector) const override
132   {
133     return vector;
134   }
135 
136   /**  Method to transform a CovariantVector. */
137   using Superclass::TransformCovariantVector;
TransformCovariantVector(const InputCovariantVectorType & vector)138   OutputCovariantVectorType TransformCovariantVector(
139     const InputCovariantVectorType & vector) const override
140   {
141     return vector;
142   }
143 
144   /** Set the transformation to an Identity
145    *
146    * This is a nullptr operation in the case of this particular transform.
147      The method is provided only to comply with the interface of other transforms. */
SetIdentity()148   void SetIdentity()
149   {
150   }
151 
152   /** Compute the Jacobian of the transformation
153    *
154    * This method computes the Jacobian matrix of the transformation.
155    * given point or vector, returning the transformed point or
156    * vector. The rank of the Jacobian will also indicate if the transform
157    * is invertible at this point.
158    *
159    * The Jacobian can be expressed as a set of partial derivatives of the
160    * output point components with respect to the parameters that defined
161    * the transform:
162    *
163    * \f[
164    *
165       J=\left[ \begin{array}{cccc}
166       \frac{\partial x_{1}}{\partial p_{1}} &
167       \frac{\partial x_{2}}{\partial p_{1}} &
168       \cdots  & \frac{\partial x_{n}}{\partial p_{1}}\\
169       \frac{\partial x_{1}}{\partial p_{2}} &
170       \frac{\partial x_{2}}{\partial p_{2}} &
171       \cdots  & \frac{\partial x_{n}}{\partial p_{2}}\\
172       \vdots  & \vdots  & \ddots  & \vdots \\
173       \frac{\partial x_{1}}{\partial p_{m}} &
174       \frac{\partial x_{2}}{\partial p_{m}} &
175       \cdots  & \frac{\partial x_{n}}{\partial p_{m}}
176       \end{array}\right]
177    *
178    * \f]
179    */
ComputeJacobianWithRespectToParameters(const InputPointType &,JacobianType & jacobian)180   void ComputeJacobianWithRespectToParameters( const InputPointType &,
181                                                        JacobianType & jacobian) const override
182   {
183     jacobian = this->m_ZeroJacobian;
184   }
185 
186 
187   /** Get the jacobian with respect to position, which simply is an identity
188    *  jacobian because the transform is position-invariant.
189    *  jac will be resized as needed, but it will be more efficient if
190    *  it is already properly sized. */
ComputeJacobianWithRespectToPosition(const InputPointType &,JacobianPositionType & jac)191   void ComputeJacobianWithRespectToPosition(const InputPointType &,
192                                             JacobianPositionType & jac) const override
193   {
194     jac.set_identity();
195   }
196   using Superclass::ComputeJacobianWithRespectToPosition;
197 
198   /* Always returns true if not null, as an identity is it's own inverse */
GetInverse(Self * inverseTransform)199   bool GetInverse( Self *inverseTransform ) const
200   {
201     return (inverseTransform != nullptr);
202   }
203 
204   /** Return an inverse of the identity transform - another identity transform.
205     */
GetInverseTransform()206   InverseTransformBasePointer GetInverseTransform() const override
207   {
208     return this->New().GetPointer();
209   }
210 
211   /** Indicates that this transform is linear. That is, given two
212    * points P and Q, and scalar coefficients a and b, then
213    *
214    * \f[ T( a*P + b*Q ) = a * T(P) + b * T(Q) \f]
215    */
GetTransformCategory()216   TransformCategoryType GetTransformCategory() const override
217   {
218     return Self::Linear;
219   }
220 
221   /** Get the Fixed Parameters. */
GetFixedParameters()222   const FixedParametersType & GetFixedParameters() const override
223   {
224     return this->m_FixedParameters;
225   }
226 
227   /** Set the fixed parameters and update internal transformation. */
SetFixedParameters(const FixedParametersType &)228   void SetFixedParameters(const FixedParametersType &) override
229   {
230   }
231 
232   /** Get the Parameters. */
GetParameters()233   const ParametersType & GetParameters() const override
234   {
235     return this->m_Parameters;
236   }
237 
238   /** Set the fixed parameters and update internal transformation. */
SetParameters(const ParametersType &)239   void SetParameters(const ParametersType &) override
240   {
241   }
242 
243 protected:
IdentityTransform()244   IdentityTransform() : Transform<TParametersValueType, NDimensions, NDimensions>(0),
245     m_ZeroJacobian(NDimensions, 0)
246   {
247     // The Jacobian is constant, therefore it can be initialized in the
248     // constructor.
249     this->m_ZeroJacobian.Fill(0.0);
250   }
251 
252   ~IdentityTransform() override = default;
253 
254 private:
255   JacobianType m_ZeroJacobian;
256 };
257 } // end namespace itk
258 
259 #endif
260