[Insight-users] Bresenham Line Iterator

Miller, James V (Research) millerjv at crd.ge.com
Tue Jun 7 08:44:15 EDT 2005


Benjamin, 

This is sounding good.

The IsAtEnd() is the best name we found to describe what an ITK iterator 
is doing.  We liked the STL convention that container.end() returned an iterator
one past the end of the container.  As you have seen, ITK can provide a much
richer set of iterators than an STL container, so we couldn't incorporate all
the iterators into the ITK containers.  Furthermore, the ITK iterators are
fairly heavyweight, so we wouldn't want to create them frequently, like in an
STL loop below (in the it != vec.end() clause)

	for (std::vector<int>:iterator it = vec.begin(); it != vec.end(); ++it)
	   {}

I would change the IsAtLastElement() to just IsAtLast(). STL also has a notion
of front() and back() that could be used.  I always forget the name of the back()
method in STL and end up trying to call last().  I may have polluted some of the
ITK iterators with the notion of "last" when it probably should be "back".  In 
my defense, "back" doesn't sound quite right to me in the context of ND iterators.
(I also wonder if the early versions of STL, circa 1992, called back() last()).

Your LineInterpolator2D might be called an Linear2DIndexInterpolator. I'd want
to keep the name sufficiently different for the ImageFunction Interpolators we have.

Your function object CurrentXSmallerCurrentYSmaller could be called 
Linear2DIndexComparator

Does your scan converter only work on the XY plane?  Or could I scan convert
a polygon on the YZ plane?

Jim


-----Original Message-----
From: Benjamin King [mailto:king.benjamin at mh-hannover.de]
Sent: Tuesday, June 07, 2005 4:43 AM
To: Miller, James V (Research); ITK
Subject: Re: [Insight-users] Bresenham Line Iterator


Hi Jim,

> FYI, I checked in a few changes to the LineIterator this morning.
I just took a look at them and I think you found a nice way to check for "one 
past the end" condition.

> IsAtEnd() is supposed to report true if the 
> iterator is one pixel past the end of the section it is iterating.  
Oh dear, I think I got this wrong. Matches the STL way, though. I probably was 
confused by the method's name.

I changed the polygon scan conversion code in this regard and removed some 
documentation debris from an earlier version. 

Summary:

Two (+0.5) new classes interact (with some STL-code):


1) LineInterpolator2D

A class similar but not equal to itk::LineIterator. The constructor takes two 
coordinates, x1, y1 and x2, y2. Let n := x2 - x1.

After initialization or a call to GoToBegin(), GetX()/GetY() return x1/y1.

After i calls of operator++ (0 <= i <= n), 
	GetX() returns x1+i/n(x2-x1) = x1+i and
	GetY() returns floor(y1+i/n(y2-y1))

With a call to IsYExact() the user of the class can test if rounding was 
necessary.

I just changed IsAtEnd() to return true after *more* than n calls of 
operator++ to match ITK convention.

IsAtLastElement() returns true after exactly n calls of operator++. This is a 
non-standard iterator feature, but I really need that functionality in the 
PolygonScanConverter class. Could be moved to the private section if 
PolygonScanConverter is made a friend class of LineInterpolator2D.


1.5) CurrentXSmallerCurrentYSmaller

That's a function class that sorts LineInterpolator2D's first by current x, 
then by current y, then by error offset.


2) PolygonScanConverter

The constructor takes a list of 2D coordinates that are the vertices of a 
closed 2D polygon in cyclic order. The polygon may be self-intersecting.
It can be used to iterate over all pixels inside the polygon.
A pixel is inside, iff there is a line from this pixel to infinity that 
intersects an odd number of polygon edges.
Please note that the set of inside pixels may be not connected even for simple 
polygons like this triangle: (0,0) (0,1) (3,2).

During iteration with operator++, scan rows are traversed from small x to 
large x and within a scan row from small y to large y.

GetX()/GetY() return the current iterator position

IsAtEnd() now matches the ITK convention and returns true iff the iterator 
travelled past the end.


Both classes still lack the ability to take an itk::Image and the 
corresponding Get()/Set(), GetIndex()/SetIndex() methods, but that is easily 
added.

I also provided a test program for PolygonScanConverter that can also measure 
iteration performance. For random polygons with n vertices, the run time is 
more than O(n), because there is some sorting necessary, <handwaiving>but 
that's not too bad in practice</handwaiving>.


Okay, please ignore the code I sent before and take the one in the attachment 
instead.


Cheers,
	Benjamin

-- 
Benjamin King
Experimentelle Radiologie
Medizinische Hochschule Hannover
Tel.: +49  511  532-2663


More information about the Insight-users mailing list