/* Program: Insight Segmentation & Registration Toolkit Module: $RCSfile: itkHomogeneousTransform.h,v $ Language: C++ Date: $Date: 2007-03-14 12:37:08 $ Version: $Revision: 1.1 $ Copyright (c) Insight Software Consortium. All rights reserved. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. Contributed by Rupert Brooks =========================================================================*/ #ifndef __itkHomogeneousTransform_h #define __itkHomogeneousTransform_h #include #include "itkMatrix.h" #include "itkMatrixOffsetTransformBase.h" #include "itkTransform.h" #include "itkExceptionObject.h" #include "itkMacro.h" namespace itk { /** * Homogeneous transformation of a vector space (e.g. space coordinates) * * This class implements a homogenous transformation of point coordinates. * A homogeneous transformation operates on homogeneous coordinates. Such * coordinates extend the dimensionality of points in the space by 1, but * the last coordinate defines a equivalence class. Points * * This class does not implement the transformations of vectors or covariant * vectors. Vectors can be considered to be points at infinity, and since * the homogeneous transform can move points at infinity to non infinite * distances, it is unclear how they should be transformed when the last * coordinate is being dropped. * * There are two template parameters for this class: * * ScalarT The type to be used for scalar numeric values. Either * float or double. * * NDimensions The number of dimensions of the vector space. * * This class provides several methods for setting the matrix and vector * defining the transform. To support the registration framework, the * transform parameters can also be set as an Array of size * (NDimension + 1) * NDimension using method SetParameters(). * The first (NDimension x NDimension) parameters defines the matrix in * column-major order (where the column index) varies the fastest). * The last NDimension parameters defines the translation * in each dimensions. * * The parameter vector is in this order * | 0 1 4 | * | 2 3 5 | * | 6 7 x | * * This class also supports the specification of a center of rotation (center) * and a translation that is applied with respect to that centered rotation. * By default the center of rotation is set to the origin. * * \author Rupert Brooks, McGill Centre for Intelligent Machines, Montreal, Canada. * \ingroup Transforms * **/ template < class TScalarType=double, // Data type for scalars // (e.g. float or double) unsigned int NDimensions=2> // Number of dimensions in the input space class HomogeneousTransform : public Transform< TScalarType, NDimensions, NDimensions > { public: /** Standard typedefs */ typedef HomogeneousTransform Self; typedef Transform< TScalarType, NDimensions, NDimensions > Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; /** Run-time type information (and related methods). */ itkTypeMacro( HomogeneousTransform, Transform ); /** New macro for creation of through a Smart Pointer */ itkNewMacro( Self ); /** Dimension of the domain space. */ itkStaticConstMacro(SpaceDimension, unsigned int, NDimensions); itkStaticConstMacro(ParametersDimension, unsigned int, (NDimensions+1)*(NDimensions+1)-1); itkStaticConstMacro(MatrixDimension, unsigned int, (NDimensions+1)); /** Parameters Type */ typedef typename Superclass::ParametersType ParametersType; /** Jacobian Type */ typedef typename Superclass::JacobianType JacobianType; /** Standard scalar type for this class */ typedef typename Superclass::ScalarType ScalarType; /** Standard output vector type for this class */ typedef typename Superclass::OutputVectorType OutputVectorType; /** Standard coordinate point type for this class */ typedef Point InputPointType; typedef Point OutputPointType; typedef Point HomogeneousPointType; /** Standard matrix type for this class */ typedef Matrix MatrixType; /** MatrixOffsetTransform that can be composed with this transform */ typedef MatrixOffsetTransformBase MatrixTransformType; typedef typename MatrixTransformType::MatrixType AffineMatrixType; /** Get matrix of an HomogeneousTransform * * This method returns the value of the matrix of the * HomogeneousTransform. * To define a homogenous transform, you must set the matrix and center */ const MatrixType & GetMatrix() const { return m_Matrix; } /** Get center of rotation of the HomogeneousTransform * * This method returns the point used as the fixed * center of action for the HomogeneousTransform. * To define a homogenous transform, you must set the matrix and center */ const InputPointType & GetCenter() const { return m_Center; } /** Get translation component of the HomogeneousTransform * * This method returns the translation part of the matrix. * This translation will only actually happen at the center of the transform. * To define a homogenous transform, you must set the matrix and center */ OutputVectorType GetTranslation(void) const; /** Set the transformation to an Identity * * This sets the matrix to identity and the center to the origin. */ void SetIdentity( void ) { m_Matrix.SetIdentity(); m_Center.Fill( 0 ); m_Singular = false; m_InverseMatrix.SetIdentity(); } /** Create inverse of an affine transformation * * This populates the parameters an affine transform such that * the transform is the inverse of self. If self is not invertible, * false is returned. * Note that by default the inverse transform is centered at * the same center. */ bool GetInverse(Self* inverse) const; /** Set matrix of an HomogeneousTransform * * This method sets the matrix of an HomogeneousTransform to a * value specified by the user. * To define a homogenous transform, you must set the matrix and center */ void SetMatrix(const MatrixType &matrix) { m_Matrix = matrix; m_MatrixMTime.Modified(); this->Modified(); return; } /** Set center of rotation of an HomogeneousTransform * * This method sets the center of action of an HomogeneousTransform * to a fixed point - this point is not a "parameter" of the transform. * This updates translation wrt to current offset and matrix. * That is, changing the center does not change the transform. * To define an affine transform, you must set the matrix, * center, and translation OR the matrix and offset */ void SetCenter(const InputPointType & center); /** Set translation of an HomogeneousTransform * * This method sets the translation of an HomogeneousTransform. * This updates Offset to reflect current translation. * To define an affine transform, you must set the matrix, * center, and translation OR the matrix and offset */ void SetTranslation(const OutputVectorType & translation); /** Set the transformation from a container of parameters. * The first (NDimension x NDimension) parameters define the * matrix and the last NDimension parameters the translation. * Offset is updated based on current center. */ void SetParameters( const ParametersType & parameters ); /** Get the Transformation Parameters. */ const ParametersType& GetParameters(void) const; /** Utility methods for centering transform */ MatrixType DeCenter(MatrixType H, OutputPointType C) const; MatrixType DeCenter() const; MatrixType ReCenter(MatrixType H, OutputPointType C) const; void ReCenter(OutputPointType C) { SetMatrix(ReCenter(DeCenter(),C)); SetCenter(C); } /** Compose with another HomogeneousTransform * * This method composes self with another HomogeneousTransform of the * same dimension, modifying self to be the composition of self * and other. If the argument pre is true, then other is * precomposed with self; that is, the resulting transformation * consists of first applying other to the source, followed by * self. If pre is false or omitted, then other is post-composed * with self; that is the resulting transformation consists of * first applying self to the source, followed by other. */ void Compose(const Self * other, bool pre=0); /** Compose with a MatrixOffsetTransform * * This method composes self with a MatrixOffsetTransform of the * same dimension, modifying self to be the composition of self * and other. If the argument pre is true, then other is * precomposed with self; that is, the resulting transformation * consists of first applying other to the source, followed by * self. If pre is false or omitted, then other is post-composed * with self; that is the resulting transformation consists of * first applying self to the source, followed by other. */ void Compose(const MatrixTransformType* other, bool pre=0); /** Transform by a homogeneous transformation * * This method applies the homogeneous transform given by self to a * given point, returning the transformed point. */ OutputPointType TransformPoint (const InputPointType &point ) const; /** Back transform by a homogeneous transformation * * This method finds the point that maps to a given * point under the homogeneous transformation defined by * self. If no such point exists, an exception is thrown. **/ inline InputPointType BackTransform(const OutputPointType &point ) const; /** Back transform a point by an homogeneous transform * * This method finds the point that maps to a given point under * the homogeneous transformation defined by self. If no such point * exists, an exception is thrown. */ InputPointType BackTransformPoint(const OutputPointType &point) const; /** Compute distance between two homogeneous transformations * * This method computes a ``distance'' between two homogeneous * transformations. This distance is guaranteed to be a metric, * but not any particular metric. (At the moment, the algorithm * is to collect all the elements of the matrix and center into a * vector, and compute the euclidean (L2) norm of that vector.) * */ ScalarType Metric(const Self * other) const; /** This method computes the distance from self to the identity * transformation, using the same metric as the one-argument form * of the Metric() method. **/ ScalarType Metric(void) const; /** Compute the Jacobian of the transformation * * This method computes the Jacobian matrix of the transformation at * a point. The rank of the Jacobian will also indicate if the transform * is invertible at this point. */ const JacobianType & GetJacobian(const InputPointType &point ) const; /** Get the inverse matrix. * m_Singular is set to true if the inverse cannot be computed */ MatrixType GetInverseMatrix() const; /** Find inverse of an homogeneous transformation * * This method creates and returns a new HomogeneousTransform object * which is the inverse of self. If self is not invertible, * an exception is thrown. * Note that by default the inverese transform is centered at * the same position as the current one. */ typename HomogeneousTransform::Pointer Inverse(void) const; protected: /** Construct an HomogeneousTransform object * * This method constructs a new HomogeneousTransform object and * initializes the matrix and offset parts of the transformation * to values specified by the caller. If the arguments are * omitted, then the HomogeneousTransform is initialized to an identity * transformation in the appropriate number of dimensions. **/ HomogeneousTransform(const MatrixType &matrix, const OutputPointType ¢er); HomogeneousTransform(unsigned int outputSpaceDimension, unsigned int parametersDimension); HomogeneousTransform(); /** Destroy an HomogeneousTransform object **/ virtual ~HomogeneousTransform(); /** Print contents of an HomogeneousTransform */ void PrintSelf(std::ostream &s, Indent indent) const; /** To avoid recomputation of the inverse if not needed */ mutable TimeStamp m_InverseMatrixMTime; TimeStamp m_MatrixMTime; private: HomogeneousTransform(const Self & other); const Self & operator=( const Self & ); MatrixType m_Matrix; // Matrix of the transformation mutable MatrixType m_InverseMatrix; // Inverse of the matrix mutable bool m_Singular; // Is m_Inverse singular? InputPointType m_Center; OutputVectorType m_Translation; }; //class HomogeneousTransform } // namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkHomogeneousTransform.txx" #endif #endif /* __itkHomogeneousTransform_h */