[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 ¶meters),
> 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