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