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