[Insight-developers] ImageToImageFilter: dimension reductionp
roblem
Miller, James V (Research)
millerjv@crd.ge.com
Tue, 30 Apr 2002 10:50:43 -0400
I guess the "short putt" would be for the CallRegionCopier() method to
create its own local variable which is the RegionCopier function object
that it wants to use. The default implementation in ImageToImageFilter would use
ImageToImageFilterDetail::ImageRegionCopier. ExtractImageFilter would provide its
own CallRegionCopier() method that uses its own local variable which is the
ExtractImageFilterRegionCopier function object. Then remove the ivar m_RegionCopier
and remove the SetRegionCopier() and GetRegionCopier methods. Then remove the setting
of the RegionCopier in the constructor of ExtractImageFilter.
This is less of a hack than the "suboptimal" method I mentioned before and doesn't
require the RegionCopier function object be derived from LightObject. These
function objects have no data associated with them so having them be local variables
should not be a problem.
With this approach, the ExtractImageRegionCopier would not even have to be a
subclass of ImageRegionCopier (though the code might be clearer if it is a subclass).
-----Original Message-----
From: Wilson Chang [mailto:wmcst6+@pitt.edu]
Sent: Tuesday, April 30, 2002 9:34 AM
To: Miller, James V (Research)
Subject: Re: [Insight-developers] ImageToImageFilter: dimension
reductionproblem
I dont know what I was thinking yesterday when I wrote that email. of
course what you are saying makes sense, otherwise what would be the point of
virtual functions?
Yesterday, I tried making RegionCopier a smartpointer instead of an
instance of the object. Two issues I ran into were:
1.
I'm was sure what the minimal set of Typedefs and other things I needed to
add to the RegionCopier base class were in order to make to give it
"smartpointer" capability. I tried making it derive from LightObject, but I
didnt know if that was the right way to do it. Then I followed the standard
typedefs from other itk classes (typedef RegionCopier self...).
2.
When I seemed to get smartpointers to work with the ImageToImageFilterDetail
parent class, i was still getting the same problem as before . In the
ExtractImageFilter constructor:
m_ExtractImageRegionCopier = ExtractImageFilterRegionCopierType::New();
SetRegionCopier(m_ExtractImageRegionCopier);
where m_RegionCopier in ImageToImageFilter is a smartpointer to the
ImageToImageFilterDetailType base class.
somehow the calls were getting routed back up to the parent class instance,
and the m_ExtractImageRegionCopier instance was not getting called. it was
very mysterious and I couldnt figure out why. Currently in my build it is
implemented it in the "suboptimal" way (with a call to the virtual function
CallRegionCopier) and working, as it was really quick to implement that way.
thoughts?
wilson
----- Original Message -----
From: "Miller, James V (Research)" <millerjv@crd.ge.com>
To: "'Wilson Chang'" <wmcst6@pitt.edu>; "Insight-developers (E-mail)"
<Insight-developers@public.kitware.com>
Sent: Tuesday, April 30, 2002 8:41 AM
Subject: RE: [Insight-developers] ImageToImageFilter: dimension
reductionproblem
> Wilson,
>
> I do not expect to have a problem with keeping pointers to the
RegionCopier.
> This is why there are virtual functions. When an object is cast back to be
> a pointer to a base class, virtual function accesses are directed to the
> implementations in the derived class.
>
> For instance, ProcessObject keeps a vector of pointers to DataObjects.
> ProcessObject accesses these pointers calling virtual functions in the
> DataObject that are routed to implementations in the subclasses
(ImageBase,
> Image, ImageAdaptor, etc.)
>
> Jim
>
>
> -----Original Message-----
> From: Wilson Chang [mailto:wmcst6+@pitt.edu]
> Sent: Monday, April 29, 2002 4:56 PM
> To: Miller, James V (Research); Insight-developers (E-mail)
> Subject: Re: [Insight-developers] ImageToImageFilter: dimension
> reductionproblem
>
>
> I think that we will run into the same problem even if we use pointers or
> smart pointers to the RegionCopier because the pointers still have to have
> the ImageRegionCopier type associated with them. Therefore, the
> ExtractImageFilterRegionCopier pointer will get cast to a
ImageRegionCopier
> pointer, and we have the same problem all over again. we might have to
go
> with the less optimal solution you suggested.
>
> wilson
>
> ----- Original Message -----
> From: "Miller, James V (Research)" <millerjv@crd.ge.com>
> To: "'Wilson Chang'" <wmcst6@pitt.edu>; "Insight-developers (E-mail)"
> <Insight-developers@public.kitware.com>
> Sent: Monday, April 29, 2002 10:10 AM
> Subject: RE: [Insight-developers] ImageToImageFilter: dimension
> reductionproblem
>
>
> > Wilson,
> >
> > I am guessing the problem here is that the function object ivar
> m_RegionCopier
> > is held as an instance of an ImageRegionCopier as opposed to a
"reference
> > to" or a "pointer to" an ImageRegionCopier. So the SetRegionCopier()
> method
> > is casting your subclass back to the baseclass and copying it into the
> baseclass
> > type. It must be loosing the virtual function table.
> >
> > I tried to model the RegionCopier after STL. Specifically, the
> priority_queue
> > class (snippet below) has an ivar of type std::less<> but allows the
value
> of
> > this function object to be overridden at constructor time. Truthfully, I
> am surprised that this works
> > in STL. I would have thought that passing in a subclass to
> > std::less<> would still end up calling std::less<>::operator() and not
the
> > subclass's version. Perhaps the only reason STL allows you to override
> this
> > function object at constructor time is to allow you to use a function
> object
> > which is a subclass of less that carries around additional information
but
> > still uses std::less<>::operator() for the call operator. If STL does
> allow
> > you to reroute the function object's call operator by passing in a
> subclass
> > of std::less at constructor time, then the difference between STL and
the
> RegionCopier
> > is that STL calls the function object's copy constructor where we are
> calling
> > the RegionCopier's operator=().
> >
> > Unless someone has another idea, I would suggest making the RegionCopier
> ivar
> > a pointer (smart pointer?) to a RegionCopier.
> >
> > A less optimal solution be to change line 137 of ImageToImageFilter.txx
> from
> >
> > m_RegionCopier(inputRegion, this->GetOutput()->GetRequestedRegion());
> >
> > to
> >
> > this->CallRegionCopier(inputRegion,
> this->GetOutput()->GetRequestedRegion());
> >
> > where CallRegionCopier() is a virual method in ImageToImageFilter which
> has the
> > original line 137 of ImageToImageFilter.txx as its implementation.
> ExtractImageFilter
> > would override the CallRegionCopier() method and use an
> ExtractImageFilterDetail
> > instead of the standard region copier. This is the "less optimal"
solution
> because
> > the ExtractImageFilter ends up with two ivars for the RegionCopier. It
> could
> > get confusing as to which ivar is used when...
> >
> > (By the by, I think your class should be called
> ExtractImageFilterRegionCopier
> > and not ExtractImageFilterDetail (as shown in your code snippets)).
> >
> >
> >
> > // TEMPLATE CLASS priority_queue
> > template<class _Ty, class _C = vector<_Ty>,
> > class _Pr = less<_C::value_type> >
> > class priority_queue {
> > public:
> > typedef _C::allocator_type allocator_type;
> > typedef _C::value_type value_type;
> > typedef _C::size_type size_type;
> > explicit priority_queue(const _Pr& _X = _Pr(),
> > const allocator_type& _Al = allocator_type())
> > : c(_Al), comp(_X) {}
> > typedef const value_type *_It;
> > priority_queue(_It _F, _It _L, const _Pr& _X = _Pr(),
> > const allocator_type& _Al = allocator_type())
> > : c(_Al), comp(_X)
> > {for (; _F != _L; ++_F)
> > push(*_F); }
> > allocator_type get_allocator() const
> > {return (c.get_allocator()); }
> > bool empty() const
> > {return (c.empty()); }
> > size_type size() const
> > {return (c.size()); }
> > value_type& top()
> > {return (c.front()); }
> > const value_type& top() const
> > {return (c.front()); }
> > void push(const value_type& _X)
> > {c.push_back(_X);
> > push_heap(c.begin(), c.end(), comp); }
> > void pop()
> > {pop_heap(c.begin(), c.end(), comp);
> > c.pop_back(); }
> > protected:
> > _C c;
> > _Pr comp;
> > };
> >
> >
> > -----Original Message-----
> > From: Wilson Chang [mailto:wmcst6+@pitt.edu]
> > Sent: Friday, April 26, 2002 4:18 PM
> > To: Insight-developers (E-mail)
> > Subject: Re: [Insight-developers] ImageToImageFilter: dimension
> > reductionproblem
> >
> >
> > Within the ImageToImageFilterDetail namespace, I have been trying to
make
> a
> > class called ExtractImageRegionCopier that derives from
ImageRegionCopier:
> >
> > template <unsigned int D1, unsigned int D2>
> > class ITK_EXPORT ExtractImageFilterDetail: public
ImageRegionCopier<D1,
> > D2>
> > {
> >
> > public:
> > void operator() (ImageRegion<D1> &destRegion,
> > const ImageRegion<D2> &srcRegion) const
> > {
> > std::cout<<"ExtractImageFilterDetail call"<<std::endl;
> > ExtractImageCopyRegion<D1, D2>(BinaryUnsignedIntDispatch<D1,
> > D2>::ComparisonType(),
> > destRegion, srcRegion);
> > }
> > };
> >
> > In the ExtractImageFilter class:
> >
> > typedef
> >
> ImageToImageFilterDetail::ExtractImageFilterDetail<InputImageDimension,
> > OutputImageDimension> ExtractImageFilterDetailType;
> >
> > and in ExtractImageFilter's constructor:
> >
> > this->SetRegionCopier(m_ExtractImageRegionCopier);
> >
> > But for some reason, all of the to "CopyRegion()" are getting routed to
> the
> > parent class ImageRegionCopier and not the child class
> > ExtractImageRegionCopier.
> > Ideas?
> > Does this have somethign to do with the fact that the "SetRegionCopier"
> call
> > expects a type of ImageRegionCopier, and not a child class?
> >
> > wilson
> >
> >
> >
> > _______________________________________________
> > Insight-developers mailing list
> > Insight-developers@public.kitware.com
> > http://public.kitware.com/mailman/listinfo/insight-developers
> >
>