[Insight-users] Re: Question about itkBSplineDeformableTransform

Luis Ibanez luis.ibanez@kitware.com
Sat May 15 05:01:48 EDT 2004


Hi Stefan,

1) This is normal in C++.

    When you have class B deriving from class A,
    you only need to declare "virtual" the methods
    at the level of class A.  The overloded methods
    in class B are forced to be virtual due to the
    declaration in the parent class.

    You could repeat the "virtual" keyword in the
    declarations in class B... it will not hurt,
    but it is not needed.


2) The 'virtual' keyword was added to the TransformPoint
    method that is specific to the BSplineTransform.  This
    will allow you to overload the method in a derived class.


3) A TransformGroup sounds like a good Idea.
    We will look closer at this class and make
    sure that matches the ITK style before
    addit it to the repository.



  Thanks for contributing your code,



    Regards,



      Luis



--------------------
Stefan Klein wrote:

> Hi Luis,
> 
> 
> I have a question about ITK and hope you have some time to answer it.
> 
> 
> My question is about the itkBSplineDeformableTransform. In this 
> transform the methods
> 
> void  SetParameters (const ParametersType &parameters),
> and
> OutputPointType  TransformPoint (const InputPointType &point) const,
> 
> are not declared virtual, whereas in the Transform class they are. Is 
> there any good reason for this? It actually surprises me that it 
> compiles without errors.
> 
> When I inherit from this transform and override these methods (but then 
> declaring them virtual again) it works anyway, so it's not really a 
> problem. I'm just wondering why.
> 
> 
> Furthermore, i wondered if it's possible to make the following method 
> virtual, in future releases of ITK. I would like to override it.
> void TransformPoint (const InputPointType &inputPoint, OutputPointType 
> &outputPoint, WeightsType &weights, ParameterIndexArrayType &indices, 
> bool &inside) const
> 
> 
> A third question/remark: I have written a generic "TransformGrouper", 
> which allows the setting of a BulkTransform (like in the 
> BSplineDeformableTransform) in every transform. Moreover, it allows the 
> user to set the way of combining the BulkTransform and the actual 
> transform: 'Add' them together ( deformationfield u(x) = u_bulk(x) + 
> u_actual(x) ) or 'Concatenate' them ( u(x) = u_actual( x + u_bulk(x) ) ).
> Would you be interested to include it in the ITK? I included the source 
> code as an attachment.
> 
> Thanks in advance.
> 
> Regards,
> Stefan
> 
> 
> 
> ------------------------------------------------------------------------
> 
> #ifndef __itkTransformGrouperInterface_h
> #define __itkTransformGrouperInterface_h
> 
> #include "itkObject.h"
> #include <string>
> 
> namespace itk
> {
> 	
> 	class TransformGrouperInterface
> 		{
> 		
> 		public:
> 			
> 			typedef TransformGrouperInterface Self;
> 
> 			typedef itk::Object ObjectType;
> 			typedef std::string GrouperDescriptionType;
> 			
> 			/** declare here already to allow elastix to use it;
> 			* in the TransformGrouper an implementation is defined */
> 
> 			virtual ObjectType * GetInitialTransform(void) = 0;
> 			virtual void SetInitialTransform(ObjectType * _arg) = 0;
> 
> 			virtual int SetGrouper(const GrouperDescriptionType & name)	= 0;
> 			virtual const GrouperDescriptionType & GetNameOfDesiredGrouper(void) const = 0;
> 			virtual const GrouperDescriptionType & GetNameOfCurrentGrouper(void) const = 0;
> 
> 				
> 		protected:
> 			
> 			/** Constructor */
> 			TransformGrouperInterface() {}
> 			/** Destructor */
> 			virtual ~TransformGrouperInterface() {}
> 			
> 						
> 		private:
> 			
> 			TransformGrouperInterface(const Self&); //purposely not implemented
> 			void operator=(const Self&); //purposely not implemented
> 	
> 			
> 		}; //end class
> 
> 	
> } //end namespace itk
> 
> 
> #endif //#ifndef __itkTransformGrouperInterface_h
> 
> 
> ------------------------------------------------------------------------
> 
> #ifndef __itkTransformGrouper_h
> #define __itkTransformGrouper_h
> 
> #include "itkTransformGrouperInterface.h"
> #include "itkTransform.h"
> 
> #include <map>
> 
> 
> namespace itk
> {
>   
>   template <class TAnyITKTransform>
>     class TransformGrouper :
>       public TAnyITKTransform,
>       public TransformGrouperInterface
>     {
>     public:
>       
>       typedef TransformGrouper Self;
>       
>       typedef TAnyITKTransform  Superclass1;
>       
>       typedef TransformGrouper  Superclass2;
>       
>       typedef SmartPointer< Self >   Pointer;
>       typedef SmartPointer< const Self >  ConstPointer;
>       
>       /** New method for creating an object using a factory. */
>       itkNewMacro(Self);
>       
>       /** Itk Type info */
>       itkTypeMacro(TransformGrouper, TransformGrouperInterface);
>       
>       /** Input and Output space dimension */
>       itkStaticConstMacro(InputSpaceDimension, unsigned int, Superclass1::InputSpaceDimension);
>       itkStaticConstMacro(OutputSpaceDimension, unsigned int, Superclass1::OutputSpaceDimension);
>       
>       /** typedefs inherited from Superclass1 */
>       
>       typedef typename Superclass1::ScalarType                ScalarType;
>       typedef typename Superclass1::ParametersType            ParametersType;
>       typedef typename Superclass1::JacobianType              JacobianType;
>       typedef typename Superclass1::InputVectorType           InputVectorType;
>       typedef typename Superclass1::OutputVectorType          OutputVectorType;
>       typedef typename Superclass1::InputCovariantVectorType  InputCovariantVectorType;
>       typedef typename Superclass1::OutputCovariantVectorType OutputCovariantVectorType;
>       typedef typename Superclass1::InputVnlVectorType        InputVnlVectorType;
>       typedef typename Superclass1::OutputVnlVectorType       OutputVnlVectorType;
>       typedef typename Superclass1::InputPointType            InputPointType;
>       typedef typename Superclass1::OutputPointType           OutputPointType;
>       
>       /** typedefs inherited from Superclass2 */
> 
>       typedef Superclass2::ObjectType               ObjectType;
>       typedef Superclass2::GrouperDescriptionType   GrouperDescriptionType;
>       
> 
> 
>       /** A pointer to a function that 'eats' a const InputPointType  & 
>       * and spits out an OutputPointType  */
>       typedef OutputPointType (Self::*PtrToGrouper)(const InputPointType  & ) const;
>       
>       /** A map of pointers to groupers and their description */
>       typedef std::map< GrouperDescriptionType, PtrToGrouper>   GrouperMapType; 
>       typedef typename GrouperMapType::value_type               MapEntryType;
>       
>       typedef itk::Transform<
>         ScalarType,
>         itkGetStaticConstMacro(InputSpaceDimension),
>         itkGetStaticConstMacro(OutputSpaceDimension) > InitialTransformType;
>       typedef typename InitialTransformType::Pointer            InitialTransformPointer;
>       typedef typename InitialTransformType::InputPointType     InitialInputPointType;
>       typedef typename InitialTransformType::OutputPointType    InitialOutputPointType;
> 
> 
> 
> 
>       /**  Method to transform a point. Calls the appropriate Grouper */
>       virtual OutputPointType TransformPoint(const InputPointType  & point ) const;
>       
> 
>       /** Get a pointer to the InitialTransform */
>       itkGetObjectMacro(InitialTransform, ObjectType);
>       
>       /** Set the InitialTransform */
>       virtual void SetInitialTransform(ObjectType * _arg);      
> 
> 
>       /** Set the desired grouper (Add, Concatenate and NoInitialTransform 
>       * are supported by default) */
>       virtual int SetGrouper(const GrouperDescriptionType & name);
> 
> 
>       /** Get the name of the desired grouper  */
>       virtual const GrouperDescriptionType & GetNameOfDesiredGrouper(void) const;
>       
>       /** Get the name of the actual (currently used) grouper */
>       virtual const GrouperDescriptionType & GetNameOfCurrentGrouper(void) const;
>       
>       
> 
>       /** Adds a Grouper that could be used; returns 0 if successful */
>       virtual int AddGrouperToMap(const GrouperDescriptionType & name, PtrToGrouper funcptr);
> 
> 
>       
>     protected:
>       
>       /** Constructor */
>       TransformGrouper();
>       
>       /** Destructor */
>       virtual ~TransformGrouper();
>   
>       virtual void SetCurrentGrouper(const GrouperDescriptionType & name);
> 
>       
>       inline OutputPointType TransformPoint0(const InputPointType  & point ) const;
>       
>       InitialTransformPointer m_InitialTransform;
> 
>       /** the map of grouper functions */
>       GrouperMapType m_GrouperMap;
> 
>       /** The name of the grouper desired by the user. */
>       GrouperDescriptionType m_NameOfDesiredGrouper;
>       GrouperDescriptionType m_NameOfCurrentGrouper;
>       
> 
>       
>     private:
>       
>       TransformGrouper(const Self&); //purposely not implemented
>       void operator=(const Self&); //purposely not implemented
>       
>       /** Methods to combine the TransformPoint functions of the 
>       * initial and the current transform
>       *
>       * warning: these only work when the inputpointtype and the 
>       * outputpointtype of both transforms are the same!
>       */
>       
>       
>       /** ADD: u(x) = u0(x) + u1(x) */
>       inline OutputPointType Add(const InputPointType  & point) const;
>       
>       
>       
>       /** CONCATENATE: u(x) = u1( x + u0(x) ) */
>       inline OutputPointType Concatenate(const InputPointType  & point) const;
>       
>       
>       /** CURRENT ONLY: u(x) = u1(x) */
>       inline OutputPointType NoInitialTransform(const InputPointType & point) const;
>       
> 
>       /**  A pointer to one of the functions Add, Concatenate and NoInitialTransform */
>       
>       PtrToGrouper m_Grouper;
> 
> 
> 
>       
>     }; //end class
>     
>     
> } //end namespace itk
> 
> 
> #ifndef ITK_MANUAL_INSTANTIATION
> #include "itkTransformGrouper.hxx"
> #endif
> 
> 
> #endif //#ifndef __itkTransformGrouper_h
> 
> 
> 
> ------------------------------------------------------------------------
> 
> #ifndef __itkTransformGrouper_hxx
> #define __itkTransformGrouper_hxx
> 
> #include "itkTransformGrouper.h"
> 
> 
> namespace itk
> {
> 	
> 	/**
> 	*********************** Constructor	***********************
> 	*/
> 	template <class TAnyITKTransform>
> 		TransformGrouper<TAnyITKTransform>::TransformGrouper()
> 	{
> 
> 		m_InitialTransform = 0;
> 		
> 				
> 		/** Add the default groupers to the map */
> 		this->AddGrouperToMap("NoInitialTransform",&Self::NoInitialTransform);
> 		this->AddGrouperToMap("Add",&Self::Add);
> 		this->AddGrouperToMap("Concatenate",&Self::Concatenate);
> 				
> 		/** Set the default grouper */
> 		this->SetGrouper("Add"); 
> 				
> 	}
> 	
> 	/**
> 	************************ Destructor ************************
> 	*/
> 	template <class TAnyITKTransform>
> 		TransformGrouper<TAnyITKTransform>::~TransformGrouper()
> 	{
> 		//nothing
> 	}
> 
> 
> 	/**
> 	************************ SetCurrentGrouper ******************
> 	*/
> 	template <class TAnyITKTransform>
> 		void TransformGrouper<TAnyITKTransform>::
> 		SetCurrentGrouper(const GrouperDescriptionType & name)
> 	{
> 		m_NameOfCurrentGrouper = name;
> 		m_Grouper = m_GrouperMap[name];
> 	}
> 
> 
> 	/**
> 	************************ TransformPoint0 ********************
> 	*/
> 	template <class TAnyITKTransform>
> 		typename TransformGrouper<TAnyITKTransform>::OutputPointType
> 		TransformGrouper<TAnyITKTransform>::
> 		TransformPoint0(const InputPointType  & point ) const
> 	{	
> 		return m_InitialTransform->TransformPoint(point);
> 	}
> 
> 
> 	/**
> 	************ ADD: u(x) = u0(x) + u1(x) **********************
> 	*/
> 	template <class TAnyITKTransform>
> 		typename TransformGrouper<TAnyITKTransform>::OutputPointType
> 		TransformGrouper<TAnyITKTransform>::
> 	  Add(const InputPointType  & point) const
> 	{
> 				
> 		/** The initial transform
> 		*
> 		* It is assumed that the InitialTransform has been set. */
> 		InitialOutputPointType out0 = this->TransformPoint0(point);
> 		
> 		/** The Current transform */
> 		OutputPointType out = this->Superclass1::TransformPoint(point);
> 		
> 		/** Both added together */
> 		for (unsigned int i=0; i < InputSpaceDimension; i++)
> 		{
> 			out[i] += (out0[i] - point[i] );
> 		}
> 		
> 		return out;
> 				
> 	}
> 
> 
> 	/**
> 	***************** CONCATENATE: u(x) = u1( x + u0(x) ) *************
> 	*/
> 	template <class TAnyITKTransform>
> 		typename TransformGrouper<TAnyITKTransform>::OutputPointType
> 		TransformGrouper<TAnyITKTransform>::
> 		Concatenate(const InputPointType  & point) const
> 		{
> 			InitialOutputPointType out0 = this->TransformPoint0(point);
> 			return  this->Superclass1::TransformPoint(out0);
> 		}
> 			
> 			
> 	/**
> 	***************** CURRENT ONLY: u(x) = u1(x) ****************
> 	*/
> 	template <class TAnyITKTransform>
> 		typename TransformGrouper<TAnyITKTransform>::OutputPointType
> 		TransformGrouper<TAnyITKTransform>::	
> 		NoInitialTransform(const InputPointType & point) const
> 	{
> 		return  this->Superclass1::TransformPoint(point);
> 	}
> 
> 
> 	/**
>   ****************** TransformPoint ****************************
> 	*
> 	* Method to transform a point. Calls the appropriate Grouper 
> 	*/
> 	template <class TAnyITKTransform>
> 		typename TransformGrouper<TAnyITKTransform>::OutputPointType
> 		TransformGrouper<TAnyITKTransform>::	
> 		TransformPoint(const InputPointType  & point ) const
> 	{ 
> 		/** Call the selected Grouper */
> 		return ((*this).*m_Grouper)(point);
> 	} 
> 
> 
> 	/**
> 	****************** Set the InitialTransform ******************
> 	*/
> 	template <class TAnyITKTransform>
> 		void TransformGrouper<TAnyITKTransform>::	
> 		SetInitialTransform(ObjectType * _arg)
> 	{
> 
> 		if (m_InitialTransform != _arg)
> 		{
> 			m_InitialTransform = dynamic_cast<InitialTransformType *>(_arg);
> 			this->Modified();
> 			if (_arg)
> 			{
> 				/** if not zero, try to set the DesiredGrouper  */
> 				this->SetGrouper(m_NameOfDesiredGrouper);
> 			}
> 			else
> 			{
> 				/** if set to zero, set the Grouper temporarily back to "NoInitialTransform" */
> 				this->SetCurrentGrouper("NoInitialTransform");
> 				/** but don't set the name of the desired grouper!
> 				* because it is not desired by the user! */
> 			}
> 		}
> 
> 	} //end SetInitialTransform
> 
> 
> 
> 	/**
> 	******************* Set the desired grouper *******************
> 	*/
> 	template <class TAnyITKTransform>
> 		int TransformGrouper<TAnyITKTransform>::	
> 		SetGrouper(const GrouperDescriptionType & name)
> 	{
> 	
> 		if ( m_GrouperMap.count(name)==0 ) 
> 		{
> 			std::cerr << "Error: " << std::endl;
> 			std::cerr << name << " - This grouper is not installed!" << std::endl;
> 			return 1;
> 		}
> 		else
> 		{
> 			m_NameOfDesiredGrouper = name;
> 
> 			/** Set the Grouper to the desired grouper, but only if the Transform
> 			* is non-zero, or if the desired grouper is "NoInitialTransform" */
> 			if (m_InitialTransform) 
> 			{
> 				this->SetCurrentGrouper(name);
> 			}
> 			else 
> 			{
> 				this->SetCurrentGrouper("NoInitialTransform");
> 			}
> 	
> 			return 0;
> 		}
> 													
> 	} //end SetGrouper
> 
> 
> 	/**
> 	**************** Get the name of the desired grouper **************
> 	*/
> 	template <class TAnyITKTransform>
> 		const typename TransformGrouper<TAnyITKTransform>::GrouperDescriptionType &
> 		TransformGrouper<TAnyITKTransform>::	
> 		GetNameOfDesiredGrouper(void) const
> 	{
> 		return m_NameOfDesiredGrouper;
> 	}
> 
> 
> 	/**
> 	*********** Get the name of the actual (currently used) grouper ***
> 	*/
> 	template <class TAnyITKTransform>
> 		const typename TransformGrouper<TAnyITKTransform>::GrouperDescriptionType &
> 		TransformGrouper<TAnyITKTransform>::	
> 		GetNameOfCurrentGrouper(void) const
> 	{
> 		return m_NameOfCurrentGrouper;
> 	}
> 
> 
> 
> 	/**
> 	**** Adds a Grouper that could be used; returns 0 if successful ***
> 	*/
> 	template <class TAnyITKTransform>
> 		int TransformGrouper<TAnyITKTransform>::	
> 		AddGrouperToMap(const GrouperDescriptionType & name, PtrToGrouper funcptr)
> 	{
> 				
> 		if ( m_GrouperMap.count(name) ) //==1
> 		{
> 			std::cerr << "Error: " << std::endl;
> 			std::cerr << name << " - This grouper has already been installed!" << std::endl;
> 			return 1;
> 		}
> 		else
> 		{
> 			m_GrouperMap.insert(	MapEntryType( name,	funcptr	)	);
> 			return 0;
> 		}
> 		
> 	} //end AddGrouperToMap
> 
> 
> 
> 
> 
> } //end namespace itk
> 
> 
> 
> 
> #endif //#ifndef __itkTransformGrouper_hxx
> 
> 
> ------------------------------------------------------------------------
> 






More information about the Insight-users mailing list