1 /************************************************************************/
2 /*                                                                      */
3 /*          Copyright 1998-2005 by Hans Meine, Ullrich Koethe           */
4 /*       Cognitive Systems Group, University of Hamburg, Germany        */
5 /*                                                                      */
6 /*    This file is part of the VIGRA computer vision library.           */
7 /*    ( Version 1.5.0, Dec 07 2006 )                                    */
8 /*    The VIGRA Website is                                              */
9 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
10 /*    Please direct questions, bug reports, and contributions to        */
11 /*        koethe@informatik.uni-hamburg.de          or                  */
12 /*        vigra@kogs1.informatik.uni-hamburg.de                         */
13 /*                                                                      */
14 /*    Permission is hereby granted, free of charge, to any person       */
15 /*    obtaining a copy of this software and associated documentation    */
16 /*    files (the "Software"), to deal in the Software without           */
17 /*    restriction, including without limitation the rights to use,      */
18 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
19 /*    sell copies of the Software, and to permit persons to whom the    */
20 /*    Software is furnished to do so, subject to the following          */
21 /*    conditions:                                                       */
22 /*                                                                      */
23 /*    The above copyright notice and this permission notice shall be    */
24 /*    included in all copies or substantial portions of the             */
25 /*    Software.                                                         */
26 /*                                                                      */
27 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
28 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
29 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
30 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
31 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
32 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
33 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
34 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
35 /*                                                                      */
36 /************************************************************************/
37 
38 #ifndef VIGRA_PIXELNEIGHBORHOOD_HXX
39 #define VIGRA_PIXELNEIGHBORHOOD_HXX
40 
41 #include "utilities.hxx"
42 
43 namespace vigra {
44 
45 /** \addtogroup PixelNeighborhood Utilities to manage pixel neighborhoods
46 
47     4- and 8-neighborhood definitions and circulators.
48 
49     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
50 
51     <b>See also:</b> \ref vigra::NeighborhoodCirculator
52  */
53 //@{
54 
55 /********************************************************/
56 /*                                                      */
57 /*                      AtImageBorder                   */
58 /*                                                      */
59 /********************************************************/
60 
61 /** \brief Encode whether a point is near the image border.
62 
63     This enum is used with \ref isAtImageBorder() and
64     \ref vigra::RestrictedNeighborhoodCirculator.
65 
66     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
67     Namespace: vigra
68 */
69 enum AtImageBorder
70 {
71     NotAtBorder       = 0,     ///< &nbsp;
72     RightBorder       = 1,     ///< &nbsp;
73     LeftBorder        = 2,     ///< &nbsp;
74     TopBorder         = 4,     ///< &nbsp;
75     BottomBorder      = 8,     ///< &nbsp;
76     TopRightBorder    = TopBorder    | RightBorder,    ///< &nbsp;
77     TopLeftBorder     = TopBorder    | LeftBorder,     ///< &nbsp;
78     BottomLeftBorder  = BottomBorder | LeftBorder,     ///< &nbsp;
79     BottomRightBorder = BottomBorder | RightBorder     ///< &nbsp;
80 };
81 
82 /** \brief Find out whether a point is at the image border.
83 
84     This function checks if \a x == 0 or \a x == \a width - 1 and
85     \a y == 0 or \a y == \a height - 1 and returns the appropriate value
86     of \ref vigra::AtImageBorder, or zero when the point is not at te image border.
87     The behavior of the function is undefined if (x,y) is not inside the image.
88 
89     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
90     Namespace: vigra
91 */
isAtImageBorder(int x,int y,int width,int height)92 inline AtImageBorder isAtImageBorder(int x, int y, int width, int height)
93 {
94     return static_cast<AtImageBorder>((x == 0
95                                          ? LeftBorder
96                                          : x == width-1
97                                              ? RightBorder
98                                              : NotAtBorder) |
99                                        (y == 0
100                                          ? TopBorder
101                                          : y == height-1
102                                              ? BottomBorder
103                                              : NotAtBorder));
104 }
105 
106 /********************************************************/
107 /*                                                      */
108 /*                    FourNeighborhood                  */
109 /*                                                      */
110 /********************************************************/
111 
112 /** Utilities for 4-neighborhood. */
113 namespace FourNeighborhood
114 {
115 
116 /** \brief Encapsulation of direction management for 4-neighborhood.
117 
118     This helper class allows the transformation between Freeman chain codes
119     (East = 0, North = 1 etc.) and the corresponding Diff2D instances
120     and back.
121 
122     You can either use the chain codes by explicit qualification:
123 
124     \code
125     // the following three lines are equivalent
126     FourNeighborhood::NeighborCode::Direction d = FourNeighborhood::NeighborCode::East;
127     FourNeighborCode::Direction d = FourNeighborCode::East;
128     FourNeighborhood::Direction d = FourNeighborhood::East;
129     \endcode
130 
131     or you can fix 4-neighborhood by importing the entire namespace in
132     your function:
133 
134     \code
135     using namespace FourNeighborhood;
136 
137     Direction d = East;
138     \endcode
139 
140     If you want to pass 4-neighborhood codes as a template parameter, use
141     the class FourNeighborhood::NeighborCode.
142 
143     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
144     Namespace: vigra::FourNeighborhood
145 */
146 class NeighborCode
147 {
148   public:
149         /** Freeman direction codes for the 4-neighborhood.
150             <tt>East = 0</tt>, <tt>North = 1</tt> etc.
151             <tt>DirectionCount</tt> may be used for portable loop termination conditions.
152             <tt>CausalFirst</tt> and <tt>CausalLast</tt> are the first and last (inclusive)
153             neighbors in the causal neighborhood, i.e. in the set of neighbors that have
154             already been visited when the image is traversed in scan order.
155             <tt>AntiCausalFirst</tt> and <tt>AntiCausalLast</tt> are the opposite.
156         */
157     enum Direction {
158         Error = -1,     ///< &nbsp;
159         East = 0,       ///< &nbsp;
160         North,          ///< &nbsp;
161         West,           ///< &nbsp;
162         South,          ///< &nbsp;
163         DirectionCount, ///< &nbsp;
164         CausalFirst = North,     ///< &nbsp;
165         CausalLast  = West,      ///< &nbsp;
166         AntiCausalFirst = South, ///< &nbsp;
167         AntiCausalLast  = East   ///< &nbsp;
168     };
169 
directionBit(Direction d)170     static unsigned int directionBit(Direction d)
171     {
172         static unsigned int b[] = {1 << (East + 1),
173                                    1 << (North + 1),
174                                    1 << (West + 1),
175                                    1 << (South + 1)};
176         return b[d];
177     };
178 
179         /** The number of valid neighbors if the current center is at the image border.
180         */
nearBorderDirectionCount(AtImageBorder b)181     static unsigned int nearBorderDirectionCount(AtImageBorder b)
182     {
183         static unsigned int c[] = { 4, 3, 3, 0, 3, 2, 2, 0, 3, 2, 2};
184         return c[b];
185     }
186 
187         /** The valid direction codes when the center is at the image border.
188             \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1</tt>.
189         */
nearBorderDirections(AtImageBorder b,int index)190     static Direction nearBorderDirections(AtImageBorder b, int index)
191     {
192         static Direction c[11][4] = {
193                 { East, North, West, South},
194                 { North, West, South, Error},
195                 { East, North, South, Error},
196                 { Error, Error, Error, Error},
197                 { East, West, South, Error},
198                 { West, South, Error, Error},
199                 { East, South, Error, Error},
200                 { Error, Error, Error, Error},
201                 { East, North, West, Error},
202                 { North, West, Error, Error},
203                 { East, North, Error, Error}
204              };
205         return c[b][index];
206     }
207 
208         /** Transform direction code into corresponding Diff2D offset.
209             (note: there is no bounds checking on the code you pass.)
210         */
diff(Direction code)211     static Diff2D const & diff(Direction code)
212     {
213         static Diff2D d[] = {
214             Diff2D(1, 0), Diff2D(0, -1), Diff2D(-1, 0), Diff2D(0, 1)
215         };
216         return d[code];
217     }
218 
219         /** Equivalent to <tt>diff(static_cast<Direction>(code))</tt>.
220             (note: there is no bounds checking on the code you pass.)
221         */
diff(int code)222     static Diff2D const & diff(int code) { return diff(static_cast<Direction>(code)); }
223 
224         /** Get the relative offset from one neighbor to the other.
225             For example, <tt>relativeDiff(East, West) == Diff2D(-2,0)</tt>.
226             (note: there is no bounds checking on the code you pass.)
227         */
relativeDiff(Direction fromCode,Direction toCode)228     static Diff2D const & relativeDiff(Direction fromCode, Direction toCode)
229     {
230         static Diff2D d[][4] = {
231             { Diff2D(0, 0), Diff2D(-1, -1), Diff2D(-2, 0), Diff2D(-1, 1) },
232             { Diff2D(1, 1), Diff2D(0, 0), Diff2D(-1, 1), Diff2D(0, 2) },
233             { Diff2D(2, 0), Diff2D(1, -1), Diff2D(0, 0), Diff2D(1, 1) },
234             { Diff2D(1, -1), Diff2D(0, -2), Diff2D(-1, -1), Diff2D(0, 0) }
235         };
236 
237         return d[fromCode][toCode];
238     }
239 
240         /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode)).
241             (note: there is no bounds checking on the code you pass.)
242         */
relativeDiff(int fromCode,int toCode)243     static Diff2D const & relativeDiff(int fromCode, int toCode)
244     {
245         return relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode));
246     }
247 
248         /**  X-component of diff() */
dX(Direction code)249     static int dX(Direction code) { return diff(code).x; }
250         /**  Y-component of diff() */
dY(Direction code)251     static int dY(Direction code) { return diff(code).y; }
252         /**  X-component of diff() */
dX(int code)253     static int dX(int code) { return diff(code).x; }
254         /**  Y-component of diff() */
dY(int code)255     static int dY(int code) { return diff(code).y; }
256 
257         /** Transform Diff2D offset into corresponding direction code.
258             The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
259             is not in the 4-neighborhood.
260         */
code(Diff2D const & diff)261     static Direction code(Diff2D const & diff)
262     {
263         switch(diff.x)
264         {
265             case  0:
266             {
267                 switch(diff.y)
268                 {
269                     case 1:
270                         return South;
271                     case -1:
272                         return North;
273                     default:
274                         return Error;
275                 }
276             }
277             case -1:
278             {
279                 return (diff.y == 0) ?
280                             West :
281                             Error;
282             }
283             case  1:
284             {
285                 return (diff.y == 0) ?
286                             East :
287                             Error;
288             }
289         }
290         return Error;
291     }
292 
293         /** Check whether a code refers to a diagonal direction.
294             Useful if you want to abstract the differences between 4- and 8-neighborhood.
295             Always <tt>false</tt> for 4-neighborhood.
296         */
isDiagonal(Direction)297     static bool isDiagonal(Direction) { return false; }
298 
right()299     static Diff2D const & right()        { return diff(East); }    /**<  Offset to the right neighbor */
top()300     static Diff2D const & top()          { return diff(North); }   /**<  Offset to the top neighbor */
left()301     static Diff2D const & left()         { return diff(West); }    /**<  Offset to the left neighbor */
bottom()302     static Diff2D const & bottom()       { return diff(South); }   /**<  Offset to the bottom neighbor */
303 
east()304     static Diff2D const & east()       { return diff(East); }    /**<  Offset to the east neighbor */
north()305     static Diff2D const & north()      { return diff(North); }   /**<  Offset to the north neighbor */
west()306     static Diff2D const & west()       { return diff(West); }    /**<  Offset to the west neighbor */
south()307     static Diff2D const & south()      { return diff(South); }   /**<  Offset to the south neighbor */
308 };
309 
310     /** Export NeighborCode::Direction into the scope of namespace FourNeighborhood.
311     */
312 typedef NeighborCode::Direction Direction;
313 
314 static const Direction East           = NeighborCode::East;           /**<  Export NeighborCode::East to namespace FourNeighborhood */
315 static const Direction North          = NeighborCode::North;          /**<  Export NeighborCode::North to namespace FourNeighborhood */
316 static const Direction West           = NeighborCode::West;           /**<  Export NeighborCode::West to namespace FourNeighborhood */
317 static const Direction South          = NeighborCode::South;          /**<  Export NeighborCode::South to namespace FourNeighborhood */
318 static const Direction DirectionCount = NeighborCode::DirectionCount; /**<  Export NeighborCode::DirectionCount to namespace FourNeighborhood */
319 
east()320 inline Diff2D const & east()       { return NeighborCode::diff(East); }    /**<  Offset to the east neighbor */
north()321 inline Diff2D const & north()      { return NeighborCode::diff(North); }   /**<  Offset to the north neighbor */
west()322 inline Diff2D const & west()       { return NeighborCode::diff(West); }    /**<  Offset to the west neighbor */
south()323 inline Diff2D const & south()      { return NeighborCode::diff(South); }   /**<  Offset to the south neighbor */
324 
325 } // namespace FourNeighborhood
326 
327     /** Export \ref vigra::FourNeighborhood::NeighborCode into the scope of namespace vigra.
328     */
329 typedef FourNeighborhood::NeighborCode FourNeighborCode;
330 
331 /********************************************************/
332 /*                                                      */
333 /*                   EightNeighborhood                  */
334 /*                                                      */
335 /********************************************************/
336 
337 /** Utilities for 8-neighborhood. */
338 namespace EightNeighborhood
339 {
340 /** \brief Encapsulation of direction management for the 8-neighborhood.
341 
342     This helper class allows the transformation between Freeman chain codes
343     (East = 0, NorthEast = 1 etc.) and the corresponding Diff2D instances
344     and back.
345 
346     You can either use the chain codes by explicit qualification:
347 
348     \code
349     // the following three lines are equivalent
350     EightNeighborhood::NeighborCode::Direction d = EightNeighborhood::NeighborCode::East;
351     EightNeighborCode::Direction d               = EightNeighborCode::East;
352     EightNeighborhood::Direction d               = EightNeighborhood::East;
353     \endcode
354 
355     or you can fix 8-neighborhood by importing the entire namespace in
356     your function:
357 
358     \code
359     using namespace EightNeighborhood;
360 
361     Direction d = East;
362     \endcode
363 
364     If you want to pass 8-neighborhood codes as a template parameter, use
365     the class EightNeighborhood::NeighborCode.
366 
367     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
368     Namespace: vigra::EightNeighborhood
369 */
370 class NeighborCode
371 {
372   public:
373         /** Freeman direction codes for the 8-neighborhood.
374             <tt>East = 0</tt>, <tt>North = 1</tt> etc.
375             <tt>DirectionCount</tt> may be used for portable loop termination conditions.
376             <tt>CausalFirst</tt> and <tt>CausalLast</tt> are the first and last (inclusive)
377             neighbors in the causal neighborhood, i.e. in the set of neighbors that have
378             already been visited when the image is traversed in scan order.
379             <tt>AntiCausalFirst</tt> and <tt>AntiCausalLast</tt> are the opposite.
380         */
381     enum Direction {
382         Error = -1,     ///< &nbsp;
383         East = 0,       ///< &nbsp;
384         NorthEast,      ///< &nbsp;
385         North,          ///< &nbsp;
386         NorthWest,      ///< &nbsp;
387         West,           ///< &nbsp;
388         SouthWest,      ///< &nbsp;
389         South,          ///< &nbsp;
390         SouthEast,      ///< &nbsp;
391         DirectionCount, ///< &nbsp;
392         CausalFirst = NorthEast,     ///< &nbsp;
393         CausalLast  = West,          ///< &nbsp;
394         AntiCausalFirst = SouthWest, ///< &nbsp;
395         AntiCausalLast  = East       ///< &nbsp;
396     };
397 
directionBit(Direction d)398     static unsigned int directionBit(Direction d)
399     {
400         static unsigned int b[] = {1 << (East + 1),
401                                    1 << (NorthEast + 1),
402                                    1 << (North + 1),
403                                    1 << (NorthWest + 1),
404                                    1 << (West + 1),
405                                    1 << (SouthWest + 1),
406                                    1 << (South + 1),
407                                    1 << (SouthEast + 1)};
408         return b[d];
409     };
410 
411         /** The number of valid neighbors if the current center is at the image border.
412         */
nearBorderDirectionCount(AtImageBorder b)413     static unsigned int nearBorderDirectionCount(AtImageBorder b)
414     {
415         static unsigned int c[] = { 8, 5, 5, 0, 5, 3, 3, 0, 5, 3, 3};
416         return c[b];
417     }
418 
419         /** The valid direction codes when the center is at the image border.
420             \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1</tt>.
421         */
nearBorderDirections(AtImageBorder b,int index)422     static Direction nearBorderDirections(AtImageBorder b, int index)
423     {
424         static Direction c[11][8] = {
425                 { East, NorthEast, North, NorthWest, West, SouthWest, South, SouthEast},
426                 { North, NorthWest, West, SouthWest, South, Error, Error, Error},
427                 { East, NorthEast, North, South, SouthEast, Error, Error, Error},
428                 { Error, Error, Error, Error, Error, Error, Error, Error},
429                 { East, West, SouthWest, South, SouthEast, Error, Error, Error},
430                 { West, SouthWest, South, Error, Error, Error, Error, Error},
431                 { East, South, SouthEast, Error, Error, Error, Error, Error},
432                 { Error, Error, Error, Error, Error, Error, Error, Error},
433                 { East, NorthEast, North, NorthWest, West, Error, Error, Error},
434                 { North, NorthWest, West, Error, Error, Error, Error, Error},
435                 { East, NorthEast, North, Error, Error, Error, Error, Error}
436              };
437         return c[b][index];
438     }
439 
440         /** Transform direction code into corresponding Diff2D offset.
441             (note: there is no bounds checking on the code you pass.)
442         */
diff(Direction code)443     static Diff2D const & diff(Direction code)
444     {
445         static Diff2D d[] = {
446             Diff2D(1, 0), Diff2D(1, -1), Diff2D(0, -1), Diff2D(-1, -1),
447             Diff2D(-1, 0), Diff2D(-1, 1), Diff2D(0, 1), Diff2D(1, 1)
448         };
449         return d[code];
450     }
451 
452         /** Equivalent to diff(static_cast<Direction>(code)).
453             (note: there is no bounds checking on the code you pass.)
454         */
diff(int code)455     static Diff2D const & diff(int code) { return diff(static_cast<Direction>(code)); }
456 
457         /** Get the relative offset from one neighbor to the other.
458             For example, <tt>relativeDiff(East, West) == Diff2D(-2,0)</tt>.
459             (note: there is no bounds checking on the code you pass.)
460         */
relativeDiff(Direction fromCode,Direction toCode)461     static Diff2D const & relativeDiff(Direction fromCode, Direction toCode)
462     {
463         static Diff2D d[][8] = {
464             { Diff2D(0, 0), Diff2D(0, -1), Diff2D(-1, -1), Diff2D(-2, -1),
465               Diff2D(-2, 0), Diff2D(-2, 1), Diff2D(-1, 1), Diff2D(0, 1) },
466             { Diff2D(0, 1), Diff2D(0, 0), Diff2D(-1, 0), Diff2D(-2, 0),
467               Diff2D(-2, 1), Diff2D(-2, 2), Diff2D(-1, 2), Diff2D(0, 2) },
468             { Diff2D(1, 1), Diff2D(1, 0), Diff2D(0, 0), Diff2D(-1, 0),
469               Diff2D(-1, 1), Diff2D(-1, 2), Diff2D(0, 2), Diff2D(1, 2) },
470             { Diff2D(2, 1), Diff2D(2, 0), Diff2D(1, 0), Diff2D(0, 0),
471               Diff2D(0, 1), Diff2D(0, 2), Diff2D(1, 2), Diff2D(2, 2) },
472             { Diff2D(2, 0), Diff2D(2, -1), Diff2D(1, -1), Diff2D(0, -1),
473               Diff2D(0, 0), Diff2D(0, 1), Diff2D(1, 1), Diff2D(2, 1) },
474             { Diff2D(2, -1), Diff2D(2, -2), Diff2D(1, -2), Diff2D(0, -2),
475               Diff2D(0, -1), Diff2D(0, 0), Diff2D(1, 0), Diff2D(2, 0) },
476             { Diff2D(1, -1), Diff2D(1, -2), Diff2D(0, -2), Diff2D(-1, -2),
477               Diff2D(-1, -1), Diff2D(-1, 0), Diff2D(0, 0), Diff2D(1, 0) },
478             { Diff2D(0, -1), Diff2D(0, -2), Diff2D(-1, -2), Diff2D(-2, -2),
479               Diff2D(-2, -1), Diff2D(-2, 0), Diff2D(-1, 0), Diff2D(0, 0) }
480         };
481 
482         return d[fromCode][toCode];
483     }
484 
485         /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode)).
486             (note: there is no bounds checking on the code you pass.)
487         */
relativeDiff(int fromCode,int toCode)488     static Diff2D const & relativeDiff(int fromCode, int toCode)
489     {
490         return relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode));
491     }
492 
493         /**  X-component of diff() */
dX(Direction code)494     static int dX(Direction code) { return diff(code).x; }
495         /**  Y-component of diff() */
dY(Direction code)496     static int dY(Direction code) { return diff(code).y; }
497         /**  X-component of diff() */
dX(int code)498     static int dX(int code) { return diff(code).x; }
499         /**  Y-component of diff() */
dY(int code)500     static int dY(int code) { return diff(code).y; }
501 
502         /** Transform 4-neighborhood code into 8-neighborhood code.
503         */
code(FourNeighborhood::Direction d)504     static Direction code(FourNeighborhood::Direction d)
505         { return static_cast<Direction>(2*d); }
506 
507         /** Transform Diff2D offset into corresponding direction code.
508             The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
509             is not in the 8-neighborhood.
510         */
code(Diff2D const & diff)511     static Direction code(Diff2D const & diff)
512     {
513         switch(diff.x)
514         {
515             case  0:
516             {
517                 switch(diff.y)
518                 {
519                     case 1:
520                         return South;
521                     case -1:
522                         return North;
523                     default:
524                         return Error;
525                 }
526             }
527             case -1:
528             {
529                 switch(diff.y)
530                 {
531                     case 0:
532                         return West;
533                     case 1:
534                         return SouthWest;
535                     case -1:
536                         return NorthWest;
537                     default:
538                         return Error;
539                 }
540             }
541             case  1:
542             {
543                 switch(diff.y)
544                 {
545                     case 0:
546                         return East;
547                     case 1:
548                         return SouthEast;
549                     case -1:
550                         return NorthEast;
551                     default:
552                         return Error;
553                 }
554             }
555         }
556         return Error;
557     }
558 
559         /** Check whether a code refers to a diagonal direction.
560             Useful if you want to abstract the differences between 4- and 8-neighborhood.
561         */
isDiagonal(Direction code)562     static bool isDiagonal(Direction code) { return (code % 2) != 0; }
563 
right()564     static Diff2D const & right()        { return diff(East); }        /**<  Offset to the right neighbor */
topRight()565     static Diff2D const & topRight()     { return diff(NorthEast); }   /**<  Offset to the topRight neighbor */
top()566     static Diff2D const & top()          { return diff(North); }       /**<  Offset to the top neighbor */
topLeft()567     static Diff2D const & topLeft()      { return diff(NorthWest); }   /**<  Offset to the topLeft neighbor */
left()568     static Diff2D const & left()         { return diff(West); }        /**<  Offset to the left neighbor */
bottomLeft()569     static Diff2D const & bottomLeft()   { return diff(SouthWest); }   /**<  Offset to the bottomLeft neighbor */
bottom()570     static Diff2D const & bottom()       { return diff(South); }       /**<  Offset to the bottom neighbor */
bottomRight()571     static Diff2D const & bottomRight()  { return diff(SouthEast); }   /**<  Offset to the bottomRight neighbor */
572 
east()573     static Diff2D const & east()       { return diff(East); }        /**<  Offset to the east neighbor */
northEast()574     static Diff2D const & northEast()  { return diff(NorthEast); }   /**<  Offset to the northEast neighbor */
north()575     static Diff2D const & north()      { return diff(North); }       /**<  Offset to the north neighbor */
northWest()576     static Diff2D const & northWest()  { return diff(NorthWest); }   /**<  Offset to the northWest neighbor */
west()577     static Diff2D const & west()       { return diff(West); }        /**<  Offset to the west neighbor */
southWest()578     static Diff2D const & southWest()  { return diff(SouthWest); }   /**<  Offset to the southWest neighbor */
south()579     static Diff2D const & south()      { return diff(South); }       /**<  Offset to the south neighbor */
southEast()580     static Diff2D const & southEast()  { return diff(SouthEast); }   /**<  Offset to the southEast neighbor */
581 };
582 
583     /** Export NeighborCode::Direction into the scope of namespace EightNeighborhood.
584     */
585 typedef NeighborCode::Direction Direction;
586 
587 static const Direction East           = NeighborCode::East;        /**<  Export NeighborCode::East to namespace EightNeighborhood */
588 static const Direction NorthEast      = NeighborCode::NorthEast;   /**<  Export NeighborCode::NorthEast to namespace EightNeighborhood */
589 static const Direction North          = NeighborCode::North;       /**<  Export NeighborCode::North to namespace EightNeighborhood */
590 static const Direction NorthWest      = NeighborCode::NorthWest;   /**<  Export NeighborCode::NorthWest to namespace EightNeighborhood */
591 static const Direction West           = NeighborCode::West;        /**<  Export NeighborCode::West to namespace EightNeighborhood */
592 static const Direction SouthWest      = NeighborCode::SouthWest;   /**<  Export NeighborCode::SouthWest to namespace EightNeighborhood */
593 static const Direction South          = NeighborCode::South;       /**<  Export NeighborCode::South to namespace EightNeighborhood */
594 static const Direction SouthEast      = NeighborCode::SouthEast;   /**<  Export NeighborCode::SouthEast to namespace EightNeighborhood */
595 static const Direction DirectionCount = NeighborCode::DirectionCount;   /**<  Export NeighborCode::DirectionCount to namespace EightNeighborhood */
596 
east()597 inline Diff2D const & east()       { return NeighborCode::diff(East); }        /**<  Offset to the east neighbor */
northEast()598 inline Diff2D const & northEast()  { return NeighborCode::diff(NorthEast); }   /**<  Offset to the northEast neighbor */
north()599 inline Diff2D const & north()      { return NeighborCode::diff(North); }       /**<  Offset to the north neighbor */
northWest()600 inline Diff2D const & northWest()  { return NeighborCode::diff(NorthWest); }   /**<  Offset to the northWest neighbor */
west()601 inline Diff2D const & west()       { return NeighborCode::diff(West); }        /**<  Offset to the west neighbor */
southWest()602 inline Diff2D const & southWest()  { return NeighborCode::diff(SouthWest); }   /**<  Offset to the southWest neighbor */
south()603 inline Diff2D const & south()      { return NeighborCode::diff(South); }       /**<  Offset to the south neighbor */
southEast()604 inline Diff2D const & southEast()  { return NeighborCode::diff(SouthEast); }   /**<  Offset to the southEast neighbor */
605 
606 } // namespace EightNeighborhood
607 
608     /** Export \ref vigra::EightNeighborhood::NeighborCode into the scope of namespace vigra.
609     */
610 typedef EightNeighborhood::NeighborCode EightNeighborCode;
611 
612 /********************************************************/
613 /*                                                      */
614 /*              NeighborOffsetCirculator                */
615 /*                                                      */
616 /********************************************************/
617 
618 /** \brief Circulator that walks around a given location.
619 
620     The template parameter defines the kind of neighborhood used, e.g.
621 
622     \code
623     NeighborOffsetCirculator<EightNeighborCode> eight_circulator;
624     NeighborOffsetCirculator<FourNeighborCode>  four_circulator;
625     \endcode
626 
627     Since this circulator doesn't now about the pixels in any particular image,
628     you usually doesn't use it directly but rather as a base class or helper for
629     neighborhood circulators refering to a particular image (e.g. NeighborhoodCirculator)
630 
631     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
632     Namespace: vigra
633 */
634 template<class NEIGHBORCODE>
635 class NeighborOffsetCirculator
636 : public NEIGHBORCODE
637 {
638 public:
639     typedef NEIGHBORCODE NeighborCode;
640 
641         /** return type of direction()
642         */
643     typedef typename NEIGHBORCODE::Direction Direction;
644 
645         /** the circulator's value type
646         */
647     typedef Diff2D value_type;
648 
649         /** the circulator's reference type (return type of <TT>*circ</TT>)
650         */
651     typedef Diff2D const & reference;
652 
653         /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
654         */
655     typedef Diff2D const & index_reference;
656 
657         /** the circulator's pointer type (return type of <TT>operator-></TT>)
658         */
659     typedef Diff2D const * pointer;
660 
661         /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
662         */
663     typedef int difference_type;
664 
665         /** the circulator tag (random access iterator)
666         */
667     typedef random_access_circulator_tag iterator_category;
668 
669 protected:
670     Direction direction_;
671 
672 public:
673         /** Create circulator refering to the given direction.
674         */
NeighborOffsetCirculator(Direction dir=NEIGHBORCODE::East)675     NeighborOffsetCirculator(Direction dir = NEIGHBORCODE::East)
676         : direction_(dir)
677     {
678     }
679 
680         /** pre-increment */
operator ++()681     NeighborOffsetCirculator & operator++()
682     {
683         direction_ = static_cast<Direction>((direction_+1) % NEIGHBORCODE::DirectionCount);
684         return *this;
685     }
686 
687         /** pre-decrement */
operator --()688     NeighborOffsetCirculator & operator--()
689     {
690         direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::DirectionCount-1) % NEIGHBORCODE::DirectionCount);
691         return *this;
692     }
693 
694         /** post-increment */
operator ++(int)695     NeighborOffsetCirculator operator++(int)
696     {
697         NeighborOffsetCirculator ret(*this);
698         operator++();
699         return ret;
700     }
701 
702         /** post-decrement */
operator --(int)703     NeighborOffsetCirculator operator--(int)
704     {
705         NeighborOffsetCirculator ret(*this);
706         operator--();
707         return ret;
708     }
709 
710         /** add-assignment */
operator +=(difference_type d)711     NeighborOffsetCirculator & operator+=(difference_type d)
712     {
713         direction_ = static_cast<Direction>((direction_ + d) % NEIGHBORCODE::DirectionCount);
714         if(direction_ < 0)
715             direction_ = static_cast<Direction>(direction_ + NEIGHBORCODE::DirectionCount);
716         return *this;
717     }
718 
719         /** subtract-assignment */
operator -=(difference_type d)720     NeighborOffsetCirculator & operator-=(difference_type d)
721     {
722         direction_ = static_cast<Direction>((direction_ - d) % NEIGHBORCODE::DirectionCount);
723         if(direction_ < 0)
724             direction_ = static_cast<Direction>(direction_ + NEIGHBORCODE::DirectionCount);
725         return *this;
726     }
727 
728         /** addition */
operator +(difference_type d) const729     NeighborOffsetCirculator operator+(difference_type d) const
730     {
731         return NeighborOffsetCirculator(*this) += d;
732     }
733 
734         /** subtraction */
operator -(difference_type d) const735     NeighborOffsetCirculator operator-(difference_type d) const
736     {
737         return NeighborOffsetCirculator(*this) -= d;
738     }
739 
740         /** Move to the direction that is 'right' relative to the current direction.
741             This is equivalent to <tt>four_circulator--</tt> and
742             <tt>eight_circulator -= 2</tt> respectively.
743         */
turnRight()744     NeighborOffsetCirculator & turnRight()
745     {
746         direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::South) % NEIGHBORCODE::DirectionCount);
747         return *this;
748     }
749 
750         /** Move to the direction that is 'left' relative to the current direction.
751             This is equivalent to <tt>four_circulator++</tt> and
752             <tt>eight_circulator += 2</tt> respectively.
753         */
turnLeft()754     NeighborOffsetCirculator & turnLeft()
755     {
756         direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::North) % NEIGHBORCODE::DirectionCount);
757         return *this;
758     }
759 
760         /** Move to the opposite direction of the current direction.
761             This is equivalent to <tt>four_circulator += 2</tt> and
762             <tt>eight_circulator += 4</tt> respectively.
763         */
turnRound()764     NeighborOffsetCirculator & turnRound()
765     {
766         direction_ = opposite();
767         return *this;
768     }
769 
770         /** Move to the given direction.
771         */
turnTo(Direction d)772     NeighborOffsetCirculator & turnTo(Direction d)
773     {
774         direction_ = d;
775         return *this;
776     }
777 
778         /** equality */
operator ==(NeighborOffsetCirculator const & o) const779     bool operator==(NeighborOffsetCirculator const & o) const
780     {
781         return direction_ == o.direction_;
782     }
783 
784         /** unequality */
operator !=(NeighborOffsetCirculator const & o) const785     bool operator!=(NeighborOffsetCirculator const & o) const
786     {
787         return direction_ != o.direction_;
788     }
789 
790         /** subtraction */
operator -(NeighborOffsetCirculator const & o) const791     difference_type operator-(NeighborOffsetCirculator const & o) const
792     {
793         return direction_ - o.direction_;
794     }
795 
796         /** dereference */
operator *() const797     reference operator*() const
798     {
799         return diff();
800     }
801 
802         /** index */
operator [](difference_type d) const803     index_reference operator[](difference_type d) const
804     {
805         return NEIGHBORCODE::diff(direction(d));
806     }
807 
808         /** member access */
operator ->() const809     pointer operator->() const
810     {
811         return &diff();
812     }
813 
814         /** Get Diff2D offset from center to current neighbor.
815         */
diff() const816     Diff2D const & diff() const
817     {
818         return NEIGHBORCODE::diff(direction_);
819     }
820 
821         /** Get Diff2D offset to given direction.
822         */
diff(Direction dir)823     static Diff2D const & diff(Direction dir)
824     {
825         return NEIGHBORCODE::diff(dir);
826     }
827 
828         /** Get relative distance (Diff2D) from current neighbor to neighbor
829             at given offset.
830         */
relativeDiff(difference_type offset) const831     Diff2D const &relativeDiff(difference_type offset) const
832     {
833         Direction toDir = static_cast<Direction>((direction_ + offset) % NEIGHBORCODE::DirectionCount);
834         if(toDir < 0)
835             toDir = static_cast<Direction>(toDir + NEIGHBORCODE::DirectionCount);
836         return NEIGHBORCODE::relativeDiff(direction_, toDir);
837     }
838 
839         /** X-component of diff()  */
dX() const840     int dX() const
841     {
842         return NEIGHBORCODE::dX(direction_);
843     }
844 
845         /** Y-component of diff() */
dY() const846     int dY() const
847     {
848         return NEIGHBORCODE::dY(direction_);
849     }
850 
851         /** Check whether current direction is a diagonal one.
852         */
isDiagonal() const853     bool isDiagonal() const
854     {
855         return NEIGHBORCODE::isDiagonal(direction_);
856     }
857 
858         /** Get current direction.
859         */
direction() const860     Direction direction() const
861     {
862         return direction_;
863     }
864 
865         /** Get current direction bit.
866         */
directionBit() const867     unsigned int directionBit() const
868     {
869         return NEIGHBORCODE::directionBit(direction_);
870     }
871 
872         /** Get opposite of current direction.
873         */
opposite() const874     Direction opposite() const
875     {
876         return static_cast<Direction>((direction_ + NEIGHBORCODE::West) % NEIGHBORCODE::DirectionCount);
877     }
878 
879         /** Get opposite bit of current direction.
880         */
oppositeDirectionBit() const881     unsigned int oppositeDirectionBit() const
882     {
883         return NEIGHBORCODE::directionBit(opposite());
884     }
885 
886         /** Get direction code at offset of current direction.
887         */
direction(difference_type offset) const888     Direction direction(difference_type offset) const
889     {
890         int result = (direction_ + offset) % NEIGHBORCODE::DirectionCount;
891         if(result < 0)
892             result += NEIGHBORCODE::DirectionCount;
893         return static_cast<Direction>(result);
894     }
895 };
896 
897 /** Specialization of NeighborOffsetCirculator for 8-neighborhood.
898 */
899 typedef NeighborOffsetCirculator<EightNeighborCode> EightNeighborOffsetCirculator;
900 
901 /** Specialization of NeighborOffsetCirculator for 4-neighborhood.
902 */
903 typedef NeighborOffsetCirculator<FourNeighborCode> FourNeighborOffsetCirculator;
904 
905 
906 //@}
907 
908 /** \addtogroup ImageIteratorAdapters
909  */
910 //@{
911 
912 /********************************************************/
913 /*                                                      */
914 /*                NeighborhoodCirculator                */
915 /*                                                      */
916 /********************************************************/
917 
918 /** \brief Circulator that walks around a given location in a given image.
919 
920     The template parameters define the kind of neighborhood used and the underlying
921     image. The access functions return the value of the current neighbor pixel.
922     Use <tt>center()</tt> to access the center pixel of the neighborhood.
923     The center can be changed by calling <tt>moveCenterToNeighbor()</tt>
924     or <tt>swapCenterNeighbor()</tt>. Note that this circulator cannot
925     when the center is at the image border. You must then use
926     \ref vigra::RestrictedNeighborhoodCirculator
927 
928     <b>Usage:</b><br>
929 
930     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
931     Namespace: vigra
932 
933     \code
934     BImage::traverser upperleft(...), lowerright(...);
935 
936     int width  = lowerright.x - upperleft.x;
937     int height = lowerright.y - upperleft.y;
938 
939     ++upperleft.y; // avoid image border
940     for(int y=1; y<height-1; ++y, ++upperleft.y)
941     {
942         BImage::traverser ix = upperleft + Diff2D(1,0);
943         for(int x=1; x<width-1; ++x, ++ix.x)
944         {
945             // analyse all neighbors of a pixel (use FourNeighborCode
946             // instead of EightNeighborCode for 4-neighborhood):
947             NeighborhoodCirculator<BImage::traverser, EightNeighborCode>
948                            circulator(ix),
949                            end(circulator);
950             do
951             {
952                 analysisFunc(*circulator, ...); // do sth. with current neighbor
953             }
954             while(++circulator != end); // compare with start/end circulator
955         }
956     }
957     \endcode
958 */
959 template <class IMAGEITERATOR, class NEIGHBORCODE>
960 class NeighborhoodCirculator : private IMAGEITERATOR
961 {
962     typedef NeighborOffsetCirculator<NEIGHBORCODE> NEIGHBOROFFSETCIRCULATOR;
963 
964 public:
965         /** type of the underlying image iterator
966         */
967     typedef IMAGEITERATOR base_type;
968 
969         /** type of the used neighbor code
970         */
971     typedef NEIGHBORCODE NeighborCode;
972 
973         /** the circulator's value type
974         */
975     typedef typename IMAGEITERATOR::value_type value_type;
976 
977         /** type of the direction code
978         */
979     typedef typename NEIGHBORCODE::Direction Direction;
980 
981         /** the circulator's reference type (return type of <TT>*circ</TT>)
982         */
983     typedef typename IMAGEITERATOR::reference reference;
984 
985         /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
986         */
987     typedef typename IMAGEITERATOR::index_reference index_reference;
988 
989         /** the circulator's pointer type (return type of <TT>operator-></TT>)
990         */
991     typedef typename IMAGEITERATOR::pointer pointer;
992 
993         /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
994         */
995     typedef typename NEIGHBOROFFSETCIRCULATOR::difference_type difference_type;
996 
997         /** the circulator tag (random_access_circulator_tag)
998         */
999     typedef typename NEIGHBOROFFSETCIRCULATOR::iterator_category iterator_category;
1000 
1001         /** Construct circulator with given <tt>center</tt> pixel, pointing to the neighbor
1002             at the given direction <tt>d</tt>.
1003         */
NeighborhoodCirculator(IMAGEITERATOR const & center=IMAGEITERATOR (),Direction d=NEIGHBOROFFSETCIRCULATOR::East)1004     NeighborhoodCirculator(IMAGEITERATOR const & center = IMAGEITERATOR(),
1005                            Direction d = NEIGHBOROFFSETCIRCULATOR::East)
1006         : IMAGEITERATOR(center), neighborCode_(d)
1007     {
1008         IMAGEITERATOR::operator+=(neighborCode_.diff());
1009     }
1010 
1011         /** pre-increment */
operator ++()1012     NeighborhoodCirculator & operator++()
1013     {
1014         return operator+=(1);
1015     }
1016 
1017         /** pre-decrement */
operator ++(int)1018     NeighborhoodCirculator operator++(int)
1019     {
1020         NeighborhoodCirculator ret(*this);
1021         operator++();
1022         return ret;
1023     }
1024 
1025         /** post-increment */
operator --()1026     NeighborhoodCirculator & operator--()
1027     {
1028         return operator+=(-1);
1029     }
1030 
1031         /** post-decrement */
operator --(int)1032     NeighborhoodCirculator operator--(int)
1033     {
1034         NeighborhoodCirculator ret(*this);
1035         operator--();
1036         return ret;
1037     }
1038 
1039         /** add-assignment */
operator +=(difference_type d)1040     NeighborhoodCirculator & operator+=(difference_type d)
1041     {
1042         IMAGEITERATOR::operator+=(neighborCode_.relativeDiff(d));
1043         neighborCode_+= d;
1044         return *this;
1045     }
1046 
1047         /** subtract-assignment */
operator -=(difference_type d)1048     NeighborhoodCirculator & operator-=(difference_type d)
1049     {
1050         return operator+=(-d);
1051     }
1052 
1053         /** addition */
operator +(difference_type d) const1054     NeighborhoodCirculator operator+(difference_type d) const
1055     {
1056         NeighborhoodCirculator result(*this);
1057         result+= d;
1058         return result;
1059     }
1060 
1061         /** subtraction */
operator -(difference_type d) const1062     NeighborhoodCirculator operator-(difference_type d) const
1063     {
1064         NeighborhoodCirculator result(*this);
1065         result-= d;
1066         return result;
1067     }
1068 
1069         /** Move to the direction that is 'right' relative to the current direction.
1070             This is equivalent to <tt>four_circulator--</tt> and
1071             <tt>eight_circulator -= 2</tt> respectively.
1072         */
turnRight()1073     NeighborhoodCirculator & turnRight()
1074     {
1075         Direction oldDirection = neighborCode_.direction();
1076         neighborCode_.turnRight();
1077         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1078                                   (oldDirection, neighborCode_.direction()));
1079         return *this;
1080     }
1081 
1082         /** Move to the direction that is 'left' relative to the current direction.
1083             This is equivalent to <tt>four_circulator++</tt> and
1084             <tt>eight_circulator += 2</tt> respectively.
1085         */
turnLeft()1086     NeighborhoodCirculator & turnLeft()
1087     {
1088         Direction oldDirection = neighborCode_.direction();
1089         neighborCode_.turnLeft();
1090         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1091                                   (oldDirection, neighborCode_.direction()));
1092         return *this;
1093     }
1094 
1095         /** Move to the opposite direction of the current direction.
1096             This is equivalent to <tt>four_circulator += 2</tt> and
1097             <tt>eight_circulator += 4</tt> respectively.
1098         */
turnRound()1099     NeighborhoodCirculator & turnRound()
1100     {
1101         Direction oldDirection = neighborCode_.direction();
1102         neighborCode_.turnRound();
1103         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1104                                   (oldDirection, neighborCode_.direction()));
1105         return *this;
1106     }
1107 
1108         /** Move to the given direction.
1109         */
turnTo(Direction d)1110     NeighborhoodCirculator & turnTo(Direction d)
1111     {
1112         Direction oldDirection = neighborCode_.direction();
1113         neighborCode_.turnTo(d);
1114         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1115                                   (oldDirection, neighborCode_.direction()));
1116         return *this;
1117     }
1118 
1119         /** Move the center in the current direction.
1120             The current neighbor becomes the new center, the direction does not change.
1121         */
moveCenterToNeighbor()1122     NeighborhoodCirculator & moveCenterToNeighbor()
1123     {
1124         IMAGEITERATOR::operator+=(neighborCode_.diff());
1125         return *this;
1126     }
1127 
1128         /** Exchange the center with the current neighbor.
1129             Equivalent to <tt>circ.moveCenterToNeighbor().turnRound()</tt>
1130             (but shorter and more efficient).
1131         */
swapCenterNeighbor()1132     NeighborhoodCirculator & swapCenterNeighbor()
1133     {
1134         neighborCode_.turnRound();
1135         IMAGEITERATOR::operator+=(neighborCode_.diff());
1136         return *this;
1137     }
1138 
1139         /** equality */
operator ==(NeighborhoodCirculator const & rhs) const1140     bool operator==(NeighborhoodCirculator const & rhs) const
1141     {
1142         return neighborCode_ == rhs.neighborCode_ &&
1143                IMAGEITERATOR::operator==(rhs);
1144     }
1145 
1146         /** inequality */
operator !=(NeighborhoodCirculator const & rhs) const1147     bool operator!=(NeighborhoodCirculator const & rhs) const
1148     {
1149         return neighborCode_ != rhs.neighborCode_ ||
1150                IMAGEITERATOR::operator!=(rhs);
1151     }
1152 
1153         /** subtraction */
operator -(NeighborhoodCirculator const & rhs) const1154     difference_type operator-(NeighborhoodCirculator const & rhs) const
1155     {
1156         return neighborCode_ - rhs.neighborCode_;
1157     }
1158 
1159         /** dereference */
operator *() const1160     reference operator*() const
1161     {
1162         return IMAGEITERATOR::operator*();
1163     }
1164 
1165         /** index */
operator [](difference_type d) const1166     index_reference operator[](difference_type d) const
1167     {
1168         return IMAGEITERATOR::operator[](neighborCode_.relativeDiff(d));
1169     }
1170 
1171         /** member access */
operator ->() const1172     pointer operator->() const
1173     {
1174         return IMAGEITERATOR::operator->();
1175     }
1176 
1177         /** Get the base iterator for the current neighbor. */
base() const1178     base_type const & base() const
1179     {
1180         return *this;
1181     }
1182 
1183         /** Get the base iterator for the center of the circulator. */
center() const1184     base_type center() const
1185     {
1186         return (base_type)*this - neighborCode_.diff();
1187     }
1188 
1189         /** Get the current direction. */
direction() const1190     Direction direction() const
1191     {
1192         return neighborCode_.direction();
1193     }
1194 
1195         /** Get the current direction bit. */
directionBit() const1196     unsigned int directionBit() const
1197     {
1198         return neighborCode_.directionBit();
1199     }
1200 
1201         /** Get the difference vector (Diff2D) from the center to the current neighbor. */
diff() const1202     Diff2D const & diff() const
1203     {
1204         return neighborCode_.diff();
1205     }
1206 
1207         /** Is the current neighbor a diagonal neighbor? */
isDiagonal() const1208     bool isDiagonal() const
1209     {
1210         return neighborCode_.isDiagonal();
1211     }
1212 
1213 private:
1214     NEIGHBOROFFSETCIRCULATOR neighborCode_;
1215 };
1216 
1217 /********************************************************/
1218 /*                                                      */
1219 /*            RestrictedNeighborhoodCirculator          */
1220 /*                                                      */
1221 /********************************************************/
1222 
1223 /** \brief Circulator that walks around a given location in a given image,
1224            unsing a restricted neighborhood.
1225 
1226     This circulator behaves essentially like \ref vigra::NeighborhoodCirculator,
1227     but can also be used near the image border, where some of the neighbor points
1228     would be outside the image und must not be accessed.
1229     The template parameters define the kind of neighborhood used (four or eight)
1230     and the underlying image, whereas the required neighbirhood restriction is
1231     given by the last constructur argument. This below for typical usage.
1232 
1233     The access functions return the value of the current neighbor pixel. Use <tt>center()</tt> to
1234     access the center pixel of the neighborhood.
1235 
1236     <b>Usage:</b><br>
1237 
1238     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
1239     Namespace: vigra
1240 
1241     \code
1242     BImage::traverser upperleft(...), lowerright(...);
1243 
1244     int width  = lowerright.x - upperleft.x;
1245     int height = lowerright.y - upperleft.y;
1246 
1247     for(int y=0; y<height; ++y, ++upperleft.y)
1248     {
1249         BImage::traverser ix = upperleft;
1250         for(int x=0; x<width; ++x, ++ix.x)
1251         {
1252             // use FourNeighborCode instead of EightNeighborCode for 4-neighborhood
1253             RestrictedNeighborhoodCirculator<BImage::traverser, EightNeighborCode>
1254                            circulator(ix, isAtImageBorder(x, y, width, height)),
1255                            end(circulator);
1256             do
1257             {
1258                 ... // do something with the circulator
1259             }
1260             while(++circulator != end); // out-of-range pixels will be automatically skipped
1261         }
1262     }
1263     \endcode
1264 */
1265 template <class IMAGEITERATOR, class NEIGHBORCODE>
1266 class RestrictedNeighborhoodCirculator
1267 : private NeighborhoodCirculator<IMAGEITERATOR, NEIGHBORCODE>
1268 {
1269     typedef NeighborhoodCirculator<IMAGEITERATOR, NEIGHBORCODE> BaseType;
1270 
1271 public:
1272         /** type of the underlying image iterator
1273         */
1274     typedef IMAGEITERATOR base_type;
1275 
1276         /** type of the used neighbor code
1277         */
1278     typedef NEIGHBORCODE NeighborCode;
1279 
1280         /** the circulator's value type
1281         */
1282     typedef typename BaseType::value_type value_type;
1283 
1284         /** type of the direction code
1285         */
1286     typedef typename BaseType::Direction Direction;
1287 
1288         /** the circulator's reference type (return type of <TT>*circ</TT>)
1289         */
1290     typedef typename BaseType::reference reference;
1291 
1292         /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
1293         */
1294     typedef typename BaseType::index_reference index_reference;
1295 
1296         /** the circulator's pointer type (return type of <TT>operator-></TT>)
1297         */
1298     typedef typename BaseType::pointer pointer;
1299 
1300         /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
1301         */
1302     typedef typename BaseType::difference_type difference_type;
1303 
1304         /** the circulator tag (random_access_circulator_tag)
1305         */
1306     typedef typename BaseType::iterator_category iterator_category;
1307 
1308         /** Construct circulator with given <tt>center</tt> pixel, using the restricted
1309             neighborhood given by \a atBorder.
1310         */
RestrictedNeighborhoodCirculator(IMAGEITERATOR const & center=IMAGEITERATOR (),AtImageBorder atBorder=NotAtBorder)1311     RestrictedNeighborhoodCirculator(IMAGEITERATOR const & center = IMAGEITERATOR(),
1312                                      AtImageBorder atBorder = NotAtBorder)
1313         : BaseType(center, NEIGHBORCODE::nearBorderDirections(atBorder, 0)),
1314           whichBorder_(atBorder),
1315           count_(NEIGHBORCODE::nearBorderDirectionCount(atBorder)),
1316           current_(0)
1317     {}
1318 
1319         /** pre-increment */
operator ++()1320     RestrictedNeighborhoodCirculator & operator++()
1321     {
1322         return operator+=(1);
1323     }
1324 
1325         /** pre-decrement */
operator ++(int)1326     RestrictedNeighborhoodCirculator operator++(int)
1327     {
1328         RestrictedNeighborhoodCirculator ret(*this);
1329         operator++();
1330         return ret;
1331     }
1332 
1333         /** post-increment */
operator --()1334     RestrictedNeighborhoodCirculator & operator--()
1335     {
1336         return operator+=(-1);
1337     }
1338 
1339         /** post-decrement */
operator --(int)1340     RestrictedNeighborhoodCirculator operator--(int)
1341     {
1342         RestrictedNeighborhoodCirculator ret(*this);
1343         operator--();
1344         return ret;
1345     }
1346 
1347         /** add-assignment */
operator +=(difference_type d)1348     RestrictedNeighborhoodCirculator & operator+=(difference_type d)
1349     {
1350         current_ = static_cast<Direction>((current_ + count_ + d) % count_);
1351         BaseType::turnTo(NEIGHBORCODE::nearBorderDirections(whichBorder_, current_));
1352         return *this;
1353     }
1354 
1355         /** subtract-assignment */
operator -=(difference_type d)1356     RestrictedNeighborhoodCirculator & operator-=(difference_type d)
1357     {
1358         return operator+=(-d);
1359     }
1360 
1361         /** addition */
operator +(difference_type d) const1362     RestrictedNeighborhoodCirculator operator+(difference_type d) const
1363     {
1364         RestrictedNeighborhoodCirculator result(*this);
1365         result+= d;
1366         return result;
1367     }
1368 
1369         /** subtraction */
operator -(difference_type d) const1370     RestrictedNeighborhoodCirculator operator-(difference_type d) const
1371     {
1372         RestrictedNeighborhoodCirculator result(*this);
1373         result-= d;
1374         return result;
1375     }
1376 
1377         /** equality */
operator ==(RestrictedNeighborhoodCirculator const & rhs) const1378     bool operator==(RestrictedNeighborhoodCirculator const & rhs) const
1379     {
1380         return current_ == rhs.current_;
1381     }
1382 
1383         /** inequality */
operator !=(RestrictedNeighborhoodCirculator const & rhs) const1384     bool operator!=(RestrictedNeighborhoodCirculator const & rhs) const
1385     {
1386         return current_ != rhs.current_;
1387     }
1388 
1389         /** subtraction */
operator -(RestrictedNeighborhoodCirculator const & rhs) const1390     difference_type operator-(RestrictedNeighborhoodCirculator const & rhs) const
1391     {
1392         return (current_ - rhs.current_) % count_;
1393     }
1394 
1395         /** dereference */
operator *() const1396     reference operator*() const
1397     {
1398         return BaseType::operator*();
1399     }
1400 
1401         /** member access */
operator ->() const1402     pointer operator->() const
1403     {
1404         return BaseType::operator->();
1405     }
1406 
1407         /** Get the base iterator for the current neighbor. */
base() const1408     base_type const & base() const
1409     {
1410         return BaseType::base();
1411     }
1412 
1413         /** Get the base iterator for the center of the circulator. */
center() const1414     base_type center() const
1415     {
1416         return BaseType::center();
1417     }
1418 
1419         /** Get the current direction. */
direction() const1420     Direction direction() const
1421     {
1422         return BaseType::direction();
1423     }
1424 
1425         /** Get the current direction bit. */
directionBit() const1426     unsigned int directionBit() const
1427     {
1428         return BaseType::directionBit();
1429     }
1430 
1431         /** Get the difference vector (Diff2D) from the center to the current neighbor. */
diff() const1432     Diff2D const & diff() const
1433     {
1434         return BaseType::diff();
1435     }
1436 
1437         /** Is the current neighbor a diagonal neighbor? */
isDiagonal() const1438     bool isDiagonal() const
1439     {
1440         return BaseType::isDiagonal();
1441     }
1442 
1443 private:
1444      AtImageBorder whichBorder_;
1445      signed char count_, current_;
1446 };
1447 
1448 //@}
1449 
1450 } // namespace vigra
1451 
1452 #endif /* VIGRA_PIXELNEIGHBORHOOD_HXX */
1453