[Insight-developers] iterator hierarchy

Damion Shelton dmsst59+@pitt.edu
Wed, 6 Jun 2001 13:14:54 -0400


Couple of thoughts about the below diagram:

> > >                         SpatialIterator
> > >            -------------------+-----------------------
> > >            |                                         |
> > >       FilledSpatialIterator            SurfaceSpatialIterator
> > >     |------+-----------------------|
> > > FunctionFilledSpatialIterator  MaskFilledSpatialIterator

I've been thinking about a new base class called ConditionalIterator (or
maybe ArbitraryRegionIterator), which defines very basic API stuff, probably
the following methods (all virtual):

ConditionalIterator::operator++
ConditionalIterator::IsAtEnd()
ConditionalIterator::IsPixelInRegion()

The idea of a ConditionalIterator is the membership in the region is
"conditional" on some event/property/function/etc. determined by the
IsPixelInRegion() member function.

There would be two (that I can think of) subclasses,
FilledConditionalIterator and LinearWalkConditionalIterator.
FilledConditionalIterator defines an additional function,
FilledConditionalIterator::DoFloodStep(), which contains the flood-fill
algorithm but doesn't define an implementation of IsPixelInRegion().

Derived from FilledConditionalIterator are
SpatialFunctionFilledConditionalIterator and MaskFilledConditionalIterator.
The former uses spatial functions to determine IsPixelInRegion(), while the
latter uses a mask.

The other main base class, LinearWalkConditionalIterator uses normal
iterators to traverse the entire image, and computes IsPixelInRegion() at
every pixel. The ++ API ensures that only pixels which pass the test are
returned. Derived from this would be
SpatialFunctionLinearWalkConditionalIterator. The advantage of this class
would be:

1) No need for a seed pixel
2) Greatly reduced memory requirements vs. filled iterators (no need to
create a temporary status image)

The disadvantage, obviously, is that it's a per-pixel operation. Which one
to use (filled vs. linear walk) would depend on whether your main concern is
computational efficiency or memory efficiency.

Whew. Also, a note on the SpatialFunction API, which I've been playing with
today...

SpatialFunctions are now templated over both function value type and
dimensionality. This allows return of an arbitrary type (vector valued,
scalar valued, etc.). Function coordinates are still specified by an
n-dimensional vector of doubles.

For use in the iterator and elsewhere, there is a subclass of
SpatialFunction called InteriorExteriorSpatialFunction which returns a bool
indicating whether the given position is "inside" or "outside" the function.
SphereSpatialFunction and ConeSpatialFunction are now derived from this
class.

SpatialFunctionImageEvaluatorFilter now evaluates the function value
directly; there is no longer interior/exterior behavior. The "drawing a
primitive" operation is now simple to do by creating a FilledIterator and
traversing it while setting pixel values.

I think that's about it for the moment. Splitting the iterator idea into
these classes should hopefully make integration into Vikram's and others'
work much easier, since the method for determining IsPixelInRegion() is now
arbitrary.

-Damion-