[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/pixelneighborhood.hxx

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*          Copyright 1998-2005 by Hans Meine, Ullrich Koethe           */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    ( Version 1.6.0, Aug 13 2008 )                                    */
00008 /*    The VIGRA Website is                                              */
00009 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00010 /*    Please direct questions, bug reports, and contributions to        */
00011 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00012 /*        vigra@informatik.uni-hamburg.de                               */
00013 /*                                                                      */
00014 /*    Permission is hereby granted, free of charge, to any person       */
00015 /*    obtaining a copy of this software and associated documentation    */
00016 /*    files (the "Software"), to deal in the Software without           */
00017 /*    restriction, including without limitation the rights to use,      */
00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00019 /*    sell copies of the Software, and to permit persons to whom the    */
00020 /*    Software is furnished to do so, subject to the following          */
00021 /*    conditions:                                                       */
00022 /*                                                                      */
00023 /*    The above copyright notice and this permission notice shall be    */
00024 /*    included in all copies or substantial portions of the             */
00025 /*    Software.                                                         */
00026 /*                                                                      */
00027 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00028 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00029 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00030 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00031 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00032 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00033 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00034 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00035 /*                                                                      */
00036 /************************************************************************/
00037 
00038 #ifndef VIGRA_PIXELNEIGHBORHOOD_HXX
00039 #define VIGRA_PIXELNEIGHBORHOOD_HXX
00040 
00041 #include "utilities.hxx"
00042 
00043 namespace vigra {
00044 
00045 /** \addtogroup PixelNeighborhood Utilities to manage pixel neighborhoods
00046 
00047     4- and 8-neighborhood definitions and circulators.
00048 
00049     <b>\#include</b> <<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>><br>
00050 
00051     <b>See also:</b> \ref vigra::NeighborhoodCirculator
00052  */
00053 //@{
00054 
00055 /********************************************************/
00056 /*                                                      */
00057 /*                      AtImageBorder                   */
00058 /*                                                      */
00059 /********************************************************/
00060 
00061 /** \brief Encode whether a point is near the image border.
00062 
00063     This enum is used with \ref isAtImageBorder() and
00064     \ref vigra::RestrictedNeighborhoodCirculator.
00065 
00066     <b>\#include</b> <<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>><br>
00067     Namespace: vigra
00068 */
00069 
00070 enum AtImageBorder
00071 {
00072         NotAtBorder       = 0,     ///< &nbsp;
00073         RightBorder       = 1,     ///< &nbsp;
00074         LeftBorder        = 2,     ///< &nbsp;
00075         TopBorder         = 4,     ///< &nbsp;
00076         BottomBorder      = 8,     ///< &nbsp;
00077         FrontBorder       = 16,    ///< &nbsp;
00078         RearBorder        = 32,
00079         TopRightBorder    = TopBorder    | RightBorder,   //5
00080         TopLeftBorder     = TopBorder    | LeftBorder,    //6
00081         TopFrontBorder    = TopBorder    | FrontBorder,   //20
00082         TopRearBorder     = TopBorder    | RearBorder,    //36
00083         BottomLeftBorder  = BottomBorder | LeftBorder,    //10
00084         BottomRightBorder = BottomBorder | RightBorder,   //9
00085         BottomFrontBorder = BottomBorder | FrontBorder,   //24
00086         BottomRearBorder  = BottomBorder | RearBorder,    //40
00087         FrontLeftBorder   = FrontBorder  | LeftBorder,    //18
00088         FrontRightBorder  = FrontBorder  | RightBorder,   //17
00089         RearLeftBorder    = RearBorder   | LeftBorder,    //34
00090         RearRightBorder   = RearBorder   | RightBorder,   //33
00091         
00092         TopRightFrontBorder    = TopBorder    | RightBorder | FrontBorder,    //21
00093         TopLeftFrontBorder     = TopBorder    | LeftBorder  | FrontBorder,    //22
00094         BottomLeftFrontBorder  = BottomBorder | LeftBorder  | FrontBorder,    //26
00095         BottomRightFrontBorder = BottomBorder | RightBorder | FrontBorder,    //25
00096         TopRightRearBorder     = TopBorder    | RightBorder | RearBorder,     //37
00097         TopLeftRearBorder      = TopBorder    | LeftBorder  | RearBorder,     //38
00098         BottomLeftRearBorder   = BottomBorder | LeftBorder  | RearBorder,     //42
00099         BottomRightRearBorder  = BottomBorder | RightBorder | RearBorder      //41
00100 };
00101 
00102 
00103 /** \brief Find out whether a point is at the image border.
00104 
00105     This function checks if \a x == 0 or \a x == \a width - 1 and
00106     \a y == 0 or \a y == \a height - 1 and returns the appropriate value
00107     of \ref vigra::AtImageBorder, or zero when the point is not at te image border.
00108     The behavior of the function is undefined if (x,y) is not inside the image.
00109 
00110     <b>\#include</b> <<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>><br>
00111     Namespace: vigra
00112 */
00113 inline AtImageBorder isAtImageBorder(int x, int y, int width, int height)
00114 {
00115     return static_cast<AtImageBorder>((x == 0
00116                                          ? LeftBorder
00117                                          : x == width-1
00118                                              ? RightBorder
00119                                              : NotAtBorder) |
00120                                        (y == 0
00121                                          ? TopBorder
00122                                          : y == height-1
00123                                              ? BottomBorder
00124                                              : NotAtBorder));
00125 }
00126 
00127 /********************************************************/
00128 /*                                                      */
00129 /*                    FourNeighborhood                  */
00130 /*                                                      */
00131 /********************************************************/
00132 
00133 /** Utilities for 4-neighborhood. */
00134 namespace FourNeighborhood
00135 {
00136 
00137 /** \brief Encapsulation of direction management for 4-neighborhood.
00138 
00139     This helper class allows the transformation between Freeman chain codes
00140     (East = 0, North = 1 etc.) and the corresponding Diff2D instances
00141     and back.
00142 
00143     You can either use the chain codes by explicit qualification:
00144 
00145     \code
00146     // the following three lines are equivalent
00147     FourNeighborhood::NeighborCode::Direction d = FourNeighborhood::NeighborCode::East;
00148     FourNeighborCode::Direction d = FourNeighborCode::East;
00149     FourNeighborhood::Direction d = FourNeighborhood::East;
00150     \endcode
00151 
00152     or you can fix 4-neighborhood by importing the entire namespace in
00153     your function:
00154 
00155     \code
00156     using namespace FourNeighborhood;
00157 
00158     Direction d = East;
00159     \endcode
00160 
00161     If you want to pass 4-neighborhood codes as a template parameter, use
00162     the class FourNeighborhood::NeighborCode.
00163 
00164     <b>\#include</b> <<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>><br>
00165     Namespace: vigra::FourNeighborhood
00166 */
00167 class NeighborCode
00168 {
00169   public:
00170 
00171     typedef Diff2D difference_type;
00172     
00173         /** Freeman direction codes for the 4-neighborhood.
00174             <tt>East = 0</tt>, <tt>North = 1</tt> etc.
00175             <tt>DirectionCount</tt> may be used for portable loop termination conditions.
00176             <tt>CausalFirst</tt> and <tt>CausalLast</tt> are the first and last (inclusive)
00177             neighbors in the causal neighborhood, i.e. in the set of neighbors that have
00178             already been visited when the image is traversed in scan order.
00179             <tt>AntiCausalFirst</tt> and <tt>AntiCausalLast</tt> are the opposite.
00180         */
00181     enum Direction {
00182         Error = -1,     ///< &nbsp;
00183         East = 0,       ///< &nbsp;
00184         North,          ///< &nbsp;
00185         West,           ///< &nbsp;
00186         South,          ///< &nbsp;
00187         DirectionCount, ///< &nbsp;
00188         CausalFirst = North,     ///< &nbsp;
00189         CausalLast  = West,      ///< &nbsp;
00190         AntiCausalFirst = South, ///< &nbsp;
00191         AntiCausalLast  = East,   ///< &nbsp;
00192    
00193         InitialDirection = East,
00194         OppositeDirPrefix = 1,
00195         OppositeOffset = West
00196  };
00197 
00198     static unsigned int directionBit(Direction d)
00199     {
00200         static unsigned int b[] = {1 << (East + 1),
00201                                    1 << (North + 1),
00202                                    1 << (West + 1),
00203                                    1 << (South + 1)};
00204         return b[d];
00205     };
00206 
00207         /** The number of valid neighbors if the current center is at the image border.
00208         */
00209     static unsigned int nearBorderDirectionCount(AtImageBorder b)
00210     {
00211         static unsigned int c[] = { 4, 3, 3, 0, 3, 2, 2, 0, 3, 2, 2};
00212         return c[b];
00213     }
00214 
00215         /** The valid direction codes when the center is at the image border.
00216             \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1</tt>.
00217         */
00218     static Direction nearBorderDirections(AtImageBorder b, int index)
00219     {
00220         static Direction c[11][4] = {
00221                 { East, North, West, South},
00222                 { North, West, South, Error},
00223                 { East, North, South, Error},
00224                 { Error, Error, Error, Error},
00225                 { East, West, South, Error},
00226                 { West, South, Error, Error},
00227                 { East, South, Error, Error},
00228                 { Error, Error, Error, Error},
00229                 { East, North, West, Error},
00230                 { North, West, Error, Error},
00231                 { East, North, Error, Error}
00232              };
00233         return c[b][index];
00234     }
00235 
00236         /** Transform direction code into corresponding Diff2D offset.
00237             (note: there is no bounds checking on the code you pass.)
00238         */
00239     static Diff2D const & diff(Direction code)
00240     {
00241         static Diff2D d[] = {
00242             Diff2D(1, 0), Diff2D(0, -1), Diff2D(-1, 0), Diff2D(0, 1)
00243         };
00244         return d[code];
00245     }
00246 
00247         /** Equivalent to <tt>diff(static_cast<Direction>(code))</tt>.
00248             (note: there is no bounds checking on the code you pass.)
00249         */
00250     static Diff2D const & diff(int code) { return diff(static_cast<Direction>(code)); }
00251 
00252         /** Get the relative offset from one neighbor to the other.
00253             For example, <tt>relativeDiff(East, West) == Diff2D(-2,0)</tt>.
00254             (note: there is no bounds checking on the code you pass.)
00255         */
00256     static Diff2D const & relativeDiff(Direction fromCode, Direction toCode)
00257     {
00258         static Diff2D d[][4] = {
00259             { Diff2D(0, 0), Diff2D(-1, -1), Diff2D(-2, 0), Diff2D(-1, 1) },
00260             { Diff2D(1, 1), Diff2D(0, 0), Diff2D(-1, 1), Diff2D(0, 2) },
00261             { Diff2D(2, 0), Diff2D(1, -1), Diff2D(0, 0), Diff2D(1, 1) },
00262             { Diff2D(1, -1), Diff2D(0, -2), Diff2D(-1, -1), Diff2D(0, 0) }
00263         };
00264 
00265         return d[fromCode][toCode];
00266     }
00267 
00268         /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode)).
00269             (note: there is no bounds checking on the code you pass.)
00270         */
00271     static Diff2D const & relativeDiff(int fromCode, int toCode)
00272     {
00273         return relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode));
00274     }
00275 
00276         /**  X-component of diff() */
00277     static int dX(Direction code) { return diff(code).x; }
00278         /**  Y-component of diff() */
00279     static int dY(Direction code) { return diff(code).y; }
00280         /**  X-component of diff() */
00281     static int dX(int code) { return diff(code).x; }
00282         /**  Y-component of diff() */
00283     static int dY(int code) { return diff(code).y; }
00284 
00285         /** Transform Diff2D offset into corresponding direction code.
00286             The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
00287             is not in the 4-neighborhood.
00288         */
00289     static Direction code(Diff2D const & diff)
00290     {
00291         switch(diff.x)
00292         {
00293             case  0:
00294             {
00295                 switch(diff.y)
00296                 {
00297                     case 1:
00298                         return South;
00299                     case -1:
00300                         return North;
00301                     default:
00302                         return Error;
00303                 }
00304             }
00305             case -1:
00306             {
00307                 return (diff.y == 0) ?
00308                             West :
00309                             Error;
00310             }
00311             case  1:
00312             {
00313                 return (diff.y == 0) ?
00314                             East :
00315                             Error;
00316             }
00317         }
00318         return Error;
00319     }
00320 
00321         /** Check whether a code refers to a diagonal direction.
00322             Useful if you want to abstract the differences between 4- and 8-neighborhood.
00323             Always <tt>false</tt> for 4-neighborhood.
00324         */
00325     static bool isDiagonal(Direction) { return false; }
00326 
00327     static Diff2D const & right()        { return diff(East); }    /**<  Offset to the right neighbor */
00328     static Diff2D const & top()          { return diff(North); }   /**<  Offset to the top neighbor */
00329     static Diff2D const & left()         { return diff(West); }    /**<  Offset to the left neighbor */
00330     static Diff2D const & bottom()       { return diff(South); }   /**<  Offset to the bottom neighbor */
00331 
00332     static Diff2D const & east()       { return diff(East); }    /**<  Offset to the east neighbor */
00333     static Diff2D const & north()      { return diff(North); }   /**<  Offset to the north neighbor */
00334     static Diff2D const & west()       { return diff(West); }    /**<  Offset to the west neighbor */
00335     static Diff2D const & south()      { return diff(South); }   /**<  Offset to the south neighbor */
00336 };
00337 
00338     /** Export NeighborCode::Direction into the scope of namespace FourNeighborhood.
00339     */
00340 typedef NeighborCode::Direction Direction;
00341 
00342 static const Direction East           = NeighborCode::East;           /**<  Export NeighborCode::East to namespace FourNeighborhood */
00343 static const Direction North          = NeighborCode::North;          /**<  Export NeighborCode::North to namespace FourNeighborhood */
00344 static const Direction West           = NeighborCode::West;           /**<  Export NeighborCode::West to namespace FourNeighborhood */
00345 static const Direction South          = NeighborCode::South;          /**<  Export NeighborCode::South to namespace FourNeighborhood */
00346 static const Direction DirectionCount = NeighborCode::DirectionCount; /**<  Export NeighborCode::DirectionCount to namespace FourNeighborhood */
00347 
00348 inline Diff2D const & east()       { return NeighborCode::diff(East); }    /**<  Offset to the east neighbor */
00349 inline Diff2D const & north()      { return NeighborCode::diff(North); }   /**<  Offset to the north neighbor */
00350 inline Diff2D const & west()       { return NeighborCode::diff(West); }    /**<  Offset to the west neighbor */
00351 inline Diff2D const & south()      { return NeighborCode::diff(South); }   /**<  Offset to the south neighbor */
00352 
00353 } // namespace FourNeighborhood
00354 
00355     /** Export \ref vigra::FourNeighborhood::NeighborCode into the scope of namespace vigra.
00356     */
00357 typedef FourNeighborhood::NeighborCode FourNeighborCode;
00358 
00359 /********************************************************/
00360 /*                                                      */
00361 /*                   EightNeighborhood                  */
00362 /*                                                      */
00363 /********************************************************/
00364 
00365 /** Utilities for 8-neighborhood. */
00366 namespace EightNeighborhood
00367 {
00368 /** \brief Encapsulation of direction management for the 8-neighborhood.
00369 
00370     This helper class allows the transformation between Freeman chain codes
00371     (East = 0, NorthEast = 1 etc.) and the corresponding Diff2D instances
00372     and back.
00373 
00374     You can either use the chain codes by explicit qualification:
00375 
00376     \code
00377     // the following three lines are equivalent
00378     EightNeighborhood::NeighborCode::Direction d = EightNeighborhood::NeighborCode::East;
00379     EightNeighborCode::Direction d               = EightNeighborCode::East;
00380     EightNeighborhood::Direction d               = EightNeighborhood::East;
00381     \endcode
00382 
00383     or you can fix 8-neighborhood by importing the entire namespace in
00384     your function:
00385 
00386     \code
00387     using namespace EightNeighborhood;
00388 
00389     Direction d = East;
00390     \endcode
00391 
00392     If you want to pass 8-neighborhood codes as a template parameter, use
00393     the class EightNeighborhood::NeighborCode.
00394 
00395     <b>\#include</b> <<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>><br>
00396     Namespace: vigra::EightNeighborhood
00397 */
00398 class NeighborCode
00399 {
00400   public:
00401 
00402     typedef Diff2D difference_type;
00403     
00404         /** Freeman direction codes for the 8-neighborhood.
00405             <tt>East = 0</tt>, <tt>North = 1</tt> etc.
00406             <tt>DirectionCount</tt> may be used for portable loop termination conditions.
00407             <tt>CausalFirst</tt> and <tt>CausalLast</tt> are the first and last (inclusive)
00408             neighbors in the causal neighborhood, i.e. in the set of neighbors that have
00409             already been visited when the image is traversed in scan order.
00410             <tt>AntiCausalFirst</tt> and <tt>AntiCausalLast</tt> are the opposite.
00411         */
00412     enum Direction {
00413         Error = -1,     ///< &nbsp;
00414         East = 0,       ///< &nbsp;
00415         NorthEast,      ///< &nbsp;
00416         North,          ///< &nbsp;
00417         NorthWest,      ///< &nbsp;
00418         West,           ///< &nbsp;
00419         SouthWest,      ///< &nbsp;
00420         South,          ///< &nbsp;
00421         SouthEast,      ///< &nbsp;
00422         DirectionCount, ///< &nbsp;
00423         CausalFirst = NorthEast,     ///< &nbsp;
00424         CausalLast  = West,          ///< &nbsp;
00425         AntiCausalFirst = SouthWest, ///< &nbsp;
00426         AntiCausalLast  = East,       ///< &nbsp;
00427    
00428         InitialDirection = East,
00429         OppositeDirPrefix = 1,
00430         OppositeOffset = West
00431     };
00432 
00433     static unsigned int directionBit(Direction d)
00434     {
00435         static unsigned int b[] = {1 << (East + 1),
00436                                    1 << (NorthEast + 1),
00437                                    1 << (North + 1),
00438                                    1 << (NorthWest + 1),
00439                                    1 << (West + 1),
00440                                    1 << (SouthWest + 1),
00441                                    1 << (South + 1),
00442                                    1 << (SouthEast + 1)};
00443         return b[d];
00444     };
00445 
00446         /** The number of valid neighbors if the current center is at the image border.
00447         */
00448     static unsigned int nearBorderDirectionCount(AtImageBorder b)
00449     {
00450         static unsigned int c[] = { 8, 5, 5, 0, 5, 3, 3, 0, 5, 3, 3};
00451         return c[b];
00452     }
00453 
00454         /** The valid direction codes when the center is at the image border.
00455             \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1</tt>.
00456         */
00457     static Direction nearBorderDirections(AtImageBorder b, int index)
00458     {
00459         static Direction c[11][8] = {
00460                 { East, NorthEast, North, NorthWest, West, SouthWest, South, SouthEast},
00461                 { North, NorthWest, West, SouthWest, South, Error, Error, Error},
00462                 { East, NorthEast, North, South, SouthEast, Error, Error, Error},
00463                 { Error, Error, Error, Error, Error, Error, Error, Error},
00464                 { East, West, SouthWest, South, SouthEast, Error, Error, Error},
00465                 { West, SouthWest, South, Error, Error, Error, Error, Error},
00466                 { East, South, SouthEast, Error, Error, Error, Error, Error},
00467                 { Error, Error, Error, Error, Error, Error, Error, Error},
00468                 { East, NorthEast, North, NorthWest, West, Error, Error, Error},
00469                 { North, NorthWest, West, Error, Error, Error, Error, Error},
00470                 { East, NorthEast, North, Error, Error, Error, Error, Error}
00471              };
00472         return c[b][index];
00473     }
00474 
00475         /** Transform direction code into corresponding Diff2D offset.
00476             (note: there is no bounds checking on the code you pass.)
00477         */
00478     static Diff2D const & diff(Direction code)
00479     {
00480         static Diff2D d[] = {
00481             Diff2D(1, 0), Diff2D(1, -1), Diff2D(0, -1), Diff2D(-1, -1),
00482             Diff2D(-1, 0), Diff2D(-1, 1), Diff2D(0, 1), Diff2D(1, 1)
00483         };
00484         return d[code];
00485     }
00486 
00487         /** Equivalent to diff(static_cast<Direction>(code)).
00488             (note: there is no bounds checking on the code you pass.)
00489         */
00490     static Diff2D const & diff(int code) { return diff(static_cast<Direction>(code)); }
00491 
00492         /** Get the relative offset from one neighbor to the other.
00493             For example, <tt>relativeDiff(East, West) == Diff2D(-2,0)</tt>.
00494             (note: there is no bounds checking on the code you pass.)
00495         */
00496     static Diff2D const & relativeDiff(Direction fromCode, Direction toCode)
00497     {
00498         static Diff2D d[][8] = {
00499             { Diff2D(0, 0), Diff2D(0, -1), Diff2D(-1, -1), Diff2D(-2, -1),
00500               Diff2D(-2, 0), Diff2D(-2, 1), Diff2D(-1, 1), Diff2D(0, 1) },
00501             { Diff2D(0, 1), Diff2D(0, 0), Diff2D(-1, 0), Diff2D(-2, 0),
00502               Diff2D(-2, 1), Diff2D(-2, 2), Diff2D(-1, 2), Diff2D(0, 2) },
00503             { Diff2D(1, 1), Diff2D(1, 0), Diff2D(0, 0), Diff2D(-1, 0),
00504               Diff2D(-1, 1), Diff2D(-1, 2), Diff2D(0, 2), Diff2D(1, 2) },
00505             { Diff2D(2, 1), Diff2D(2, 0), Diff2D(1, 0), Diff2D(0, 0),
00506               Diff2D(0, 1), Diff2D(0, 2), Diff2D(1, 2), Diff2D(2, 2) },
00507             { Diff2D(2, 0), Diff2D(2, -1), Diff2D(1, -1), Diff2D(0, -1),
00508               Diff2D(0, 0), Diff2D(0, 1), Diff2D(1, 1), Diff2D(2, 1) },
00509             { Diff2D(2, -1), Diff2D(2, -2), Diff2D(1, -2), Diff2D(0, -2),
00510               Diff2D(0, -1), Diff2D(0, 0), Diff2D(1, 0), Diff2D(2, 0) },
00511             { Diff2D(1, -1), Diff2D(1, -2), Diff2D(0, -2), Diff2D(-1, -2),
00512               Diff2D(-1, -1), Diff2D(-1, 0), Diff2D(0, 0), Diff2D(1, 0) },
00513             { Diff2D(0, -1), Diff2D(0, -2), Diff2D(-1, -2), Diff2D(-2, -2),
00514               Diff2D(-2, -1), Diff2D(-2, 0), Diff2D(-1, 0), Diff2D(0, 0) }
00515         };
00516 
00517         return d[fromCode][toCode];
00518     }
00519 
00520         /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode)).
00521             (note: there is no bounds checking on the code you pass.)
00522         */
00523     static Diff2D const & relativeDiff(int fromCode, int toCode)
00524     {
00525         return relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode));
00526     }
00527 
00528         /**  X-component of diff() */
00529     static int dX(Direction code) { return diff(code).x; }
00530         /**  Y-component of diff() */
00531     static int dY(Direction code) { return diff(code).y; }
00532         /**  X-component of diff() */
00533     static int dX(int code) { return diff(code).x; }
00534         /**  Y-component of diff() */
00535     static int dY(int code) { return diff(code).y; }
00536 
00537         /** Transform 4-neighborhood code into 8-neighborhood code.
00538         */
00539     static Direction code(FourNeighborhood::Direction d)
00540         { return static_cast<Direction>(2*d); }
00541 
00542         /** Transform Diff2D offset into corresponding direction code.
00543             The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
00544             is not in the 8-neighborhood.
00545         */
00546     static Direction code(Diff2D const & diff)
00547     {
00548         switch(diff.x)
00549         {
00550             case  0:
00551             {
00552                 switch(diff.y)
00553                 {
00554                     case 1:
00555                         return South;
00556                     case -1:
00557                         return North;
00558                     default:
00559                         return Error;
00560                 }
00561             }
00562             case -1:
00563             {
00564                 switch(diff.y)
00565                 {
00566                     case 0:
00567                         return West;
00568                     case 1:
00569                         return SouthWest;
00570                     case -1:
00571                         return NorthWest;
00572                     default:
00573                         return Error;
00574                 }
00575             }
00576             case  1:
00577             {
00578                 switch(diff.y)
00579                 {
00580                     case 0:
00581                         return East;
00582                     case 1:
00583                         return SouthEast;
00584                     case -1:
00585                         return NorthEast;
00586                     default:
00587                         return Error;
00588                 }
00589             }
00590         }
00591         return Error;
00592     }
00593 
00594         /** Check whether a code refers to a diagonal direction.
00595             Useful if you want to abstract the differences between 4- and 8-neighborhood.
00596         */
00597     static bool isDiagonal(Direction code) { return (code % 2) != 0; }
00598 
00599     static Diff2D const & right()        { return diff(East); }        /**<  Offset to the right neighbor */
00600     static Diff2D const & topRight()     { return diff(NorthEast); }   /**<  Offset to the topRight neighbor */
00601     static Diff2D const & top()          { return diff(North); }       /**<  Offset to the top neighbor */
00602     static Diff2D const & topLeft()      { return diff(NorthWest); }   /**<  Offset to the topLeft neighbor */
00603     static Diff2D const & left()         { return diff(West); }        /**<  Offset to the left neighbor */
00604     static Diff2D const & bottomLeft()   { return diff(SouthWest); }   /**<  Offset to the bottomLeft neighbor */
00605     static Diff2D const & bottom()       { return diff(South); }       /**<  Offset to the bottom neighbor */
00606     static Diff2D const & bottomRight()  { return diff(SouthEast); }   /**<  Offset to the bottomRight neighbor */
00607 
00608     static Diff2D const & east()       { return diff(East); }        /**<  Offset to the east neighbor */
00609     static Diff2D const & northEast()  { return diff(NorthEast); }   /**<  Offset to the northEast neighbor */
00610     static Diff2D const & north()      { return diff(North); }       /**<  Offset to the north neighbor */
00611     static Diff2D const & northWest()  { return diff(NorthWest); }   /**<  Offset to the northWest neighbor */
00612     static Diff2D const & west()       { return diff(West); }        /**<  Offset to the west neighbor */
00613     static Diff2D const & southWest()  { return diff(SouthWest); }   /**<  Offset to the southWest neighbor */
00614     static Diff2D const & south()      { return diff(South); }       /**<  Offset to the south neighbor */
00615     static Diff2D const & southEast()  { return diff(SouthEast); }   /**<  Offset to the southEast neighbor */
00616 };
00617 
00618     /** Export NeighborCode::Direction into the scope of namespace EightNeighborhood.
00619     */
00620 typedef NeighborCode::Direction Direction;
00621 
00622 static const Direction East           = NeighborCode::East;        /**<  Export NeighborCode::East to namespace EightNeighborhood */
00623 static const Direction NorthEast      = NeighborCode::NorthEast;   /**<  Export NeighborCode::NorthEast to namespace EightNeighborhood */
00624 static const Direction North          = NeighborCode::North;       /**<  Export NeighborCode::North to namespace EightNeighborhood */
00625 static const Direction NorthWest      = NeighborCode::NorthWest;   /**<  Export NeighborCode::NorthWest to namespace EightNeighborhood */
00626 static const Direction West           = NeighborCode::West;        /**<  Export NeighborCode::West to namespace EightNeighborhood */
00627 static const Direction SouthWest      = NeighborCode::SouthWest;   /**<  Export NeighborCode::SouthWest to namespace EightNeighborhood */
00628 static const Direction South          = NeighborCode::South;       /**<  Export NeighborCode::South to namespace EightNeighborhood */
00629 static const Direction SouthEast      = NeighborCode::SouthEast;   /**<  Export NeighborCode::SouthEast to namespace EightNeighborhood */
00630 static const Direction DirectionCount = NeighborCode::DirectionCount;   /**<  Export NeighborCode::DirectionCount to namespace EightNeighborhood */
00631 
00632 inline Diff2D const & east()       { return NeighborCode::diff(East); }        /**<  Offset to the east neighbor */
00633 inline Diff2D const & northEast()  { return NeighborCode::diff(NorthEast); }   /**<  Offset to the northEast neighbor */
00634 inline Diff2D const & north()      { return NeighborCode::diff(North); }       /**<  Offset to the north neighbor */
00635 inline Diff2D const & northWest()  { return NeighborCode::diff(NorthWest); }   /**<  Offset to the northWest neighbor */
00636 inline Diff2D const & west()       { return NeighborCode::diff(West); }        /**<  Offset to the west neighbor */
00637 inline Diff2D const & southWest()  { return NeighborCode::diff(SouthWest); }   /**<  Offset to the southWest neighbor */
00638 inline Diff2D const & south()      { return NeighborCode::diff(South); }       /**<  Offset to the south neighbor */
00639 inline Diff2D const & southEast()  { return NeighborCode::diff(SouthEast); }   /**<  Offset to the southEast neighbor */
00640 
00641 } // namespace EightNeighborhood
00642 
00643     /** Export \ref vigra::EightNeighborhood::NeighborCode into the scope of namespace vigra.
00644     */
00645 typedef EightNeighborhood::NeighborCode EightNeighborCode;
00646 
00647 /********************************************************/
00648 /*                                                      */
00649 /*              NeighborOffsetCirculator                */
00650 /*                                                      */
00651 /********************************************************/
00652 
00653 /** \brief Circulator that walks around a given location.
00654 
00655     The template parameter defines the kind of neighborhood used, e.g.
00656 
00657     \code
00658     NeighborOffsetCirculator<EightNeighborCode> eight_circulator;
00659     NeighborOffsetCirculator<FourNeighborCode>  four_circulator;
00660     \endcode
00661 
00662     Since this circulator doesn't now about the pixels in any particular image,
00663     you usually doesn't use it directly but rather as a base class or helper for
00664     neighborhood circulators refering to a particular image (e.g. NeighborhoodCirculator)
00665 
00666     <b>\#include</b> <<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>><br>
00667     Namespace: vigra
00668 */
00669 template<class NEIGHBORCODE>
00670 class NeighborOffsetCirculator
00671 : public NEIGHBORCODE
00672 {
00673 public:
00674     typedef NEIGHBORCODE NeighborCode;
00675 
00676         /** return type of direction()
00677         */
00678     typedef typename NEIGHBORCODE::Direction Direction;
00679 
00680         /** the circulator's value type
00681         */
00682     typedef typename NEIGHBORCODE::difference_type value_type;
00683 
00684         /** the circulator's reference type (return type of <TT>*circ</TT>)
00685         */
00686     typedef value_type const & reference;
00687 
00688         /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
00689         */
00690     typedef value_type const & index_reference;
00691 
00692         /** the circulator's pointer type (return type of <TT>operator-></TT>)
00693         */
00694     typedef value_type const * pointer;
00695 
00696         /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
00697         */
00698     typedef int difference_type;
00699 
00700         /** the circulator tag (random access iterator)
00701         */
00702     typedef random_access_circulator_tag iterator_category;
00703 
00704 protected:
00705     Direction direction_;
00706 
00707 public:
00708         /** Create circulator refering to the given direction.
00709         */
00710     NeighborOffsetCirculator(Direction dir = NEIGHBORCODE::InitialDirection)
00711         : direction_(dir)
00712     {
00713     }
00714 
00715         /** pre-increment */
00716     NeighborOffsetCirculator & operator++()
00717     {
00718         direction_ = static_cast<Direction>((direction_+1) % NEIGHBORCODE::DirectionCount);
00719         return *this;
00720     }
00721 
00722         /** pre-decrement */
00723     NeighborOffsetCirculator & operator--()
00724     {
00725         direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::DirectionCount-1) % NEIGHBORCODE::DirectionCount);
00726         return *this;
00727     }
00728 
00729         /** post-increment */
00730     NeighborOffsetCirculator operator++(int)
00731     {
00732         NeighborOffsetCirculator ret(*this);
00733         operator++();
00734         return ret;
00735     }
00736 
00737         /** post-decrement */
00738     NeighborOffsetCirculator operator--(int)
00739     {
00740         NeighborOffsetCirculator ret(*this);
00741         operator--();
00742         return ret;
00743     }
00744 
00745         /** add-assignment */
00746     NeighborOffsetCirculator & operator+=(difference_type d)
00747     {
00748         direction_ = static_cast<Direction>((direction_ + d) % NEIGHBORCODE::DirectionCount);
00749         if(direction_ < 0)
00750             direction_ = static_cast<Direction>(direction_ + NEIGHBORCODE::DirectionCount);
00751         return *this;
00752     }
00753 
00754         /** subtract-assignment */
00755     NeighborOffsetCirculator & operator-=(difference_type d)
00756     {
00757         direction_ = static_cast<Direction>((direction_ - d) % NEIGHBORCODE::DirectionCount);
00758         if(direction_ < 0)
00759             direction_ = static_cast<Direction>(direction_ + NEIGHBORCODE::DirectionCount);
00760         return *this;
00761     }
00762 
00763         /** addition */
00764     NeighborOffsetCirculator operator+(difference_type d) const
00765     {
00766         return NeighborOffsetCirculator(*this) += d;
00767     }
00768 
00769         /** subtraction */
00770     NeighborOffsetCirculator operator-(difference_type d) const
00771     {
00772         return NeighborOffsetCirculator(*this) -= d;
00773     }
00774 
00775         /** Move to the direction that is 'right' relative to the current direction.
00776             This is equivalent to <tt>four_circulator--</tt> and
00777             <tt>eight_circulator -= 2</tt> respectively.
00778         */
00779     NeighborOffsetCirculator & turnRight()
00780     {
00781         direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::South) % NEIGHBORCODE::DirectionCount);
00782         return *this;
00783     }
00784 
00785         /** Move to the direction that is 'left' relative to the current direction.
00786             This is equivalent to <tt>four_circulator++</tt> and
00787             <tt>eight_circulator += 2</tt> respectively.
00788         */
00789     NeighborOffsetCirculator & turnLeft()
00790     {
00791         direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::North) % NEIGHBORCODE::DirectionCount);
00792         return *this;
00793     }
00794 
00795         /** Move to the opposite direction of the current direction.
00796             This is equivalent to <tt>four_circulator += 2</tt> and
00797             <tt>eight_circulator += 4</tt> respectively.
00798         */
00799     NeighborOffsetCirculator & turnRound()
00800     {
00801         direction_ = opposite();
00802         return *this;
00803     }
00804 
00805         /** Move to the given direction.
00806         */
00807     NeighborOffsetCirculator & turnTo(Direction d)
00808     {
00809         direction_ = d;
00810         return *this;
00811     }
00812 
00813         /** equality */
00814     bool operator==(NeighborOffsetCirculator const & o) const
00815     {
00816         return direction_ == o.direction_;
00817     }
00818 
00819         /** unequality */
00820     bool operator!=(NeighborOffsetCirculator const & o) const
00821     {
00822         return direction_ != o.direction_;
00823     }
00824 
00825         /** subtraction */
00826     difference_type operator-(NeighborOffsetCirculator const & o) const
00827     {
00828         return direction_ - o.direction_;
00829     }
00830 
00831         /** dereference */
00832     reference operator*() const
00833     {
00834         return diff();
00835     }
00836 
00837         /** index */
00838     index_reference operator[](difference_type d) const
00839     {
00840         return NEIGHBORCODE::diff(direction(d));
00841     }
00842 
00843         /** member access */
00844     pointer operator->() const
00845     {
00846         return &diff();
00847     }
00848 
00849         /** Get offset from center to current neighbor.
00850         */
00851     reference diff() const
00852     {
00853         return NEIGHBORCODE::diff(direction_);
00854     }
00855 
00856         /** Get offset to given direction.
00857         */
00858     static reference diff(Direction dir)
00859     {
00860         return NEIGHBORCODE::diff(dir);
00861     }
00862 
00863         /** Get relative distance from current neighbor to neighbor
00864             at given offset.
00865         */
00866     value_type relativeDiff(difference_type offset) const
00867     {
00868         Direction toDir = static_cast<Direction>((direction_ + offset) % NEIGHBORCODE::DirectionCount);
00869         if(toDir < 0)
00870             toDir = static_cast<Direction>(toDir + NEIGHBORCODE::DirectionCount);
00871         return NEIGHBORCODE::relativeDiff(direction_, toDir);
00872     }
00873 
00874         /** X-component of diff()  */
00875     int dX() const
00876     {
00877         return NEIGHBORCODE::dX(direction_);
00878     }
00879 
00880         /** Y-component of diff() */
00881     int dY() const
00882     {
00883         return NEIGHBORCODE::dY(direction_);
00884     }
00885 
00886         /** Check whether current direction is a diagonal one.
00887         */
00888     bool isDiagonal() const
00889     {
00890         return NEIGHBORCODE::isDiagonal(direction_);
00891     }
00892 
00893         /** Get current direction.
00894         */
00895     Direction direction() const
00896     {
00897         return direction_;
00898     }
00899 
00900         /** Get current direction bit.
00901         */
00902     unsigned int directionBit() const
00903     {
00904         return NEIGHBORCODE::directionBit(direction_);
00905     }
00906 
00907         /** Get opposite of current direction.
00908         */
00909     Direction opposite() const
00910     {
00911         return static_cast<Direction>((NEIGHBORCODE::OppositeDirPrefix*direction_ + NEIGHBORCODE::OppositeOffset) % NEIGHBORCODE::DirectionCount);
00912     }
00913 
00914         /** Get opposite bit of current direction.
00915         */
00916     unsigned int oppositeDirectionBit() const
00917     {
00918         return NEIGHBORCODE::directionBit(opposite());
00919     }
00920 
00921         /** Get direction code at offset of current direction.
00922         */
00923     Direction direction(difference_type offset) const
00924     {
00925         int result = (direction_ + offset) % NEIGHBORCODE::DirectionCount;
00926         if(result < 0)
00927             result += NEIGHBORCODE::DirectionCount;
00928         return static_cast<Direction>(result);
00929     }
00930 };
00931 
00932 /** Specialization of NeighborOffsetCirculator for 8-neighborhood.
00933 */
00934 typedef NeighborOffsetCirculator<EightNeighborCode> EightNeighborOffsetCirculator;
00935 
00936 /** Specialization of NeighborOffsetCirculator for 4-neighborhood.
00937 */
00938 typedef NeighborOffsetCirculator<FourNeighborCode> FourNeighborOffsetCirculator;
00939 
00940 
00941 //@}
00942 
00943 /** \addtogroup ImageIteratorAdapters
00944  */
00945 //@{
00946 
00947 /********************************************************/
00948 /*                                                      */
00949 /*                NeighborhoodCirculator                */
00950 /*                                                      */
00951 /********************************************************/
00952 
00953 /** \brief Circulator that walks around a given location in a given image.
00954 
00955     The template parameters define the kind of neighborhood used and the underlying
00956     image. The access functions return the value of the current neighbor pixel.
00957     Use <tt>center()</tt> to access the center pixel of the neighborhood.
00958     The center can be changed by calling <tt>moveCenterToNeighbor()</tt>
00959     or <tt>swapCenterNeighbor()</tt>. Note that this circulator cannot
00960     when the center is at the image border. You must then use
00961     \ref vigra::RestrictedNeighborhoodCirculator
00962 
00963     <b>Usage:</b><br>
00964 
00965     <b>\#include</b> <<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>><br>
00966     Namespace: vigra
00967 
00968     \code
00969     BImage::traverser upperleft(...), lowerright(...);
00970 
00971     int width  = lowerright.x - upperleft.x;
00972     int height = lowerright.y - upperleft.y;
00973 
00974     ++upperleft.y; // avoid image border
00975     for(int y=1; y<height-1; ++y, ++upperleft.y)
00976     {
00977         BImage::traverser ix = upperleft + Diff2D(1,0);
00978         for(int x=1; x<width-1; ++x, ++ix.x)
00979         {
00980             // analyse all neighbors of a pixel (use FourNeighborCode
00981             // instead of EightNeighborCode for 4-neighborhood):
00982             NeighborhoodCirculator<BImage::traverser, EightNeighborCode>
00983                            circulator(ix),
00984                            end(circulator);
00985             do
00986             {
00987                 analysisFunc(*circulator, ...); // do sth. with current neighbor
00988             }
00989             while(++circulator != end); // compare with start/end circulator
00990         }
00991     }
00992     \endcode
00993 */
00994 template <class IMAGEITERATOR, class NEIGHBORCODE>
00995 class NeighborhoodCirculator : private IMAGEITERATOR
00996 {
00997     typedef NeighborOffsetCirculator<NEIGHBORCODE> NEIGHBOROFFSETCIRCULATOR;
00998 
00999 
01000 public:
01001         /** type of the underlying image iterator
01002         */
01003     typedef IMAGEITERATOR base_type;
01004 
01005         /** type of the used neighbor code
01006         */
01007     typedef NEIGHBORCODE NeighborCode;
01008 
01009         /** the circulator's value type
01010         */
01011     typedef typename IMAGEITERATOR::value_type value_type;
01012 
01013         /** type of the direction code
01014         */
01015     typedef typename NEIGHBORCODE::Direction Direction;
01016 
01017         /** the circulator's reference type (return type of <TT>*circ</TT>)
01018         */
01019     typedef typename IMAGEITERATOR::reference reference;
01020 
01021         /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
01022         */
01023 
01024     typedef reference index_reference;
01025 
01026         /** the circulator's pointer type (return type of <TT>operator-></TT>)
01027         */
01028     typedef typename IMAGEITERATOR::pointer pointer;
01029 
01030         /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
01031         */
01032     typedef typename NEIGHBOROFFSETCIRCULATOR::difference_type difference_type;
01033 
01034         /** the circulator tag (random_access_circulator_tag)
01035         */
01036     typedef typename NEIGHBOROFFSETCIRCULATOR::iterator_category iterator_category;
01037 
01038         /** Construct circulator with given <tt>center</tt> pixel, pointing to the neighbor
01039             at the given direction <tt>d</tt>.
01040         */
01041     NeighborhoodCirculator(IMAGEITERATOR const & center = IMAGEITERATOR(),
01042                            Direction d = NEIGHBOROFFSETCIRCULATOR::InitialDirection)
01043         : IMAGEITERATOR(center), neighborCode_(d)
01044     {
01045         IMAGEITERATOR::operator+=(neighborCode_.diff());
01046     }
01047 
01048         /** pre-increment */
01049     NeighborhoodCirculator & operator++()
01050     {
01051         return operator+=(1);
01052     }
01053 
01054         /** pre-decrement */
01055     NeighborhoodCirculator operator++(int)
01056     {
01057         NeighborhoodCirculator ret(*this);
01058         operator++();
01059         return ret;
01060     }
01061 
01062         /** post-increment */
01063     NeighborhoodCirculator & operator--()
01064     {
01065         return operator+=(-1);
01066     }
01067 
01068         /** post-decrement */
01069     NeighborhoodCirculator operator--(int)
01070     {
01071         NeighborhoodCirculator ret(*this);
01072         operator--();
01073         return ret;
01074     }
01075 
01076         /** add-assignment */
01077     NeighborhoodCirculator & operator+=(difference_type d)
01078     {
01079         IMAGEITERATOR::operator+=(neighborCode_.relativeDiff(d));
01080         neighborCode_+= d;
01081         return *this;
01082     }
01083 
01084         /** subtract-assignment */
01085     NeighborhoodCirculator & operator-=(difference_type d)
01086     {
01087         return operator+=(-d);
01088     }
01089 
01090         /** addition */
01091     NeighborhoodCirculator operator+(difference_type d) const
01092     {
01093         NeighborhoodCirculator result(*this);
01094         result+= d;
01095         return result;
01096     }
01097 
01098         /** subtraction */
01099     NeighborhoodCirculator operator-(difference_type d) const
01100     {
01101         NeighborhoodCirculator result(*this);
01102         result-= d;
01103         return result;
01104     }
01105 
01106         /** Move to the direction that is 'right' relative to the current direction.
01107             This is equivalent to <tt>four_circulator--</tt> and
01108             <tt>eight_circulator -= 2</tt> respectively.
01109         */
01110     NeighborhoodCirculator & turnRight()
01111     {
01112         Direction oldDirection = neighborCode_.direction();
01113         neighborCode_.turnRight();
01114         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
01115                                   (oldDirection, neighborCode_.direction()));
01116         return *this;
01117     }
01118 
01119         /** Move to the direction that is 'left' relative to the current direction.
01120             This is equivalent to <tt>four_circulator++</tt> and
01121             <tt>eight_circulator += 2</tt> respectively.
01122         */
01123     NeighborhoodCirculator & turnLeft()
01124     {
01125         Direction oldDirection = neighborCode_.direction();
01126         neighborCode_.turnLeft();
01127         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
01128                                   (oldDirection, neighborCode_.direction()));
01129         return *this;
01130     }
01131 
01132         /** Move to the opposite direction of the current direction.
01133             This is equivalent to <tt>four_circulator += 2</tt> and
01134             <tt>eight_circulator += 4</tt> respectively.
01135         */
01136     NeighborhoodCirculator & turnRound()
01137     {
01138         Direction oldDirection = neighborCode_.direction();
01139         neighborCode_.turnRound();
01140         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
01141                                   (oldDirection, neighborCode_.direction()));
01142         return *this;
01143     }
01144 
01145         /** Move to the given direction.
01146         */
01147     NeighborhoodCirculator & turnTo(Direction d)
01148     {
01149         Direction oldDirection = neighborCode_.direction();
01150         neighborCode_.turnTo(d);
01151         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
01152                                   (oldDirection, neighborCode_.direction()));
01153         return *this;
01154     }
01155 
01156         /** Move the center in the current direction.
01157             The current neighbor becomes the new center, the direction does not change.
01158         */
01159     NeighborhoodCirculator & moveCenterToNeighbor()
01160     {
01161         IMAGEITERATOR::operator+=(neighborCode_.diff());
01162         return *this;
01163     }
01164 
01165         /** Exchange the center with the current neighbor.
01166             Equivalent to <tt>circ.moveCenterToNeighbor().turnRound()</tt>
01167             (but shorter and more efficient).
01168         */
01169     NeighborhoodCirculator & swapCenterNeighbor()
01170     {
01171         neighborCode_.turnRound();
01172         IMAGEITERATOR::operator+=(neighborCode_.diff());
01173         return *this;
01174     }
01175 
01176         /** equality */
01177     bool operator==(NeighborhoodCirculator const & rhs) const
01178     {
01179         return neighborCode_ == rhs.neighborCode_ &&
01180                IMAGEITERATOR::operator==(rhs);
01181     }
01182 
01183         /** inequality */
01184     bool operator!=(NeighborhoodCirculator const & rhs) const
01185     {
01186         return neighborCode_ != rhs.neighborCode_ ||
01187                IMAGEITERATOR::operator!=(rhs);
01188     }
01189 
01190         /** subtraction */
01191     difference_type operator-(NeighborhoodCirculator const & rhs) const
01192     {
01193         return neighborCode_ - rhs.neighborCode_;
01194     }
01195 
01196         /** dereference */
01197     reference operator*() const
01198     {
01199         return IMAGEITERATOR::operator*();
01200     }
01201 
01202         /** index */
01203     index_reference operator[](difference_type d) const
01204     {
01205         return IMAGEITERATOR::operator[](neighborCode_.relativeDiff(d));
01206     }
01207 
01208         /** member access */
01209     pointer operator->() const
01210     {
01211         return IMAGEITERATOR::operator->();
01212     }
01213 
01214         /** Get the base iterator for the current neighbor. */
01215     base_type const & base() const
01216     {
01217         return *this;
01218     }
01219 
01220         /** Get the base iterator for the center of the circulator. */
01221     base_type center() const
01222     {
01223         return (base_type)*this - neighborCode_.diff();
01224     }
01225 
01226         /** Get the current direction. */
01227     Direction direction() const
01228     {
01229         return neighborCode_.direction();
01230     }
01231 
01232         /** Get the current direction bit. */
01233     unsigned int directionBit() const
01234     {
01235         return neighborCode_.directionBit();
01236     }
01237 
01238         /** Get the difference vector (Diff2D) from the center to the current neighbor. */
01239     Diff2D const & diff() const
01240     {
01241         return neighborCode_.diff();
01242     }
01243 
01244         /** Is the current neighbor a diagonal neighbor? */
01245     bool isDiagonal() const
01246     {
01247         return neighborCode_.isDiagonal();
01248     }
01249 
01250 private:
01251     NEIGHBOROFFSETCIRCULATOR neighborCode_;
01252 };
01253 
01254 /********************************************************/
01255 /*                                                      */
01256 /*            RestrictedNeighborhoodCirculator          */
01257 /*                                                      */
01258 /********************************************************/
01259 
01260 /** \brief Circulator that walks around a given location in a given image,
01261            unsing a restricted neighborhood.
01262 
01263     This circulator behaves essentially like \ref vigra::NeighborhoodCirculator,
01264     but can also be used near the image border, where some of the neighbor points
01265     would be outside the image und must not be accessed.
01266     The template parameters define the kind of neighborhood used (four or eight)
01267     and the underlying image, whereas the required neighbirhood restriction is
01268     given by the last constructur argument. This below for typical usage.
01269 
01270     The access functions return the value of the current neighbor pixel. Use <tt>center()</tt> to
01271     access the center pixel of the neighborhood.
01272 
01273     <b>Usage:</b><br>
01274 
01275     <b>\#include</b> <<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>><br>
01276     Namespace: vigra
01277 
01278     \code
01279     BImage::traverser upperleft(...), lowerright(...);
01280 
01281     int width  = lowerright.x - upperleft.x;
01282     int height = lowerright.y - upperleft.y;
01283 
01284     for(int y=0; y<height; ++y, ++upperleft.y)
01285     {
01286         BImage::traverser ix = upperleft;
01287         for(int x=0; x<width; ++x, ++ix.x)
01288         {
01289             // use FourNeighborCode instead of EightNeighborCode for 4-neighborhood
01290             RestrictedNeighborhoodCirculator<BImage::traverser, EightNeighborCode>
01291                            circulator(ix, isAtImageBorder(x, y, width, height)),
01292                            end(circulator);
01293             do
01294             {
01295                 ... // do something with the circulator
01296             }
01297             while(++circulator != end); // out-of-range pixels will be automatically skipped
01298         }
01299     }
01300     \endcode
01301 */
01302 template <class IMAGEITERATOR, class NEIGHBORCODE>
01303 class RestrictedNeighborhoodCirculator
01304 : private NeighborhoodCirculator<IMAGEITERATOR, NEIGHBORCODE>
01305 {
01306     typedef NeighborhoodCirculator<IMAGEITERATOR, NEIGHBORCODE> BaseType;
01307 
01308 public:
01309         /** type of the underlying image iterator
01310         */
01311     typedef IMAGEITERATOR base_type;
01312 
01313         /** type of the used neighbor code
01314         */
01315     typedef NEIGHBORCODE NeighborCode;
01316 
01317         /** the circulator's value type
01318         */
01319     typedef typename BaseType::value_type value_type;
01320 
01321         /** type of the direction code
01322         */
01323     typedef typename BaseType::Direction Direction;
01324 
01325         /** the circulator's reference type (return type of <TT>*circ</TT>)
01326         */
01327     typedef typename BaseType::reference reference;
01328 
01329         /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
01330         */
01331     typedef typename BaseType::index_reference index_reference;
01332 
01333         /** the circulator's pointer type (return type of <TT>operator-></TT>)
01334         */
01335     typedef typename BaseType::pointer pointer;
01336 
01337         /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
01338         */
01339     typedef typename BaseType::difference_type difference_type;
01340 
01341         /** the circulator tag (random_access_circulator_tag)
01342         */
01343     typedef typename BaseType::iterator_category iterator_category;
01344 
01345         /** Construct circulator with given <tt>center</tt> pixel, using the restricted
01346             neighborhood given by \a atBorder.
01347         */
01348     RestrictedNeighborhoodCirculator(IMAGEITERATOR const & center = IMAGEITERATOR(),
01349                                      AtImageBorder atBorder = NotAtBorder)
01350         : BaseType(center, NEIGHBORCODE::nearBorderDirections(atBorder, 0)),
01351           whichBorder_(atBorder),
01352           count_(NEIGHBORCODE::nearBorderDirectionCount(atBorder)),
01353           current_(0)
01354     {}
01355 
01356         /** pre-increment */
01357     RestrictedNeighborhoodCirculator & operator++()
01358     {
01359         return operator+=(1);
01360     }
01361 
01362         /** pre-decrement */
01363     RestrictedNeighborhoodCirculator operator++(int)
01364     {
01365         RestrictedNeighborhoodCirculator ret(*this);
01366         operator++();
01367         return ret;
01368     }
01369 
01370         /** post-increment */
01371     RestrictedNeighborhoodCirculator & operator--()
01372     {
01373         return operator+=(-1);
01374     }
01375 
01376         /** post-decrement */
01377     RestrictedNeighborhoodCirculator operator--(int)
01378     {
01379         RestrictedNeighborhoodCirculator ret(*this);
01380         operator--();
01381         return ret;
01382     }
01383 
01384         /** add-assignment */
01385     RestrictedNeighborhoodCirculator & operator+=(difference_type d)
01386     {
01387         current_ = static_cast<Direction>((current_ + count_ + d) % count_);
01388         BaseType::turnTo(NEIGHBORCODE::nearBorderDirections(whichBorder_, current_));
01389         return *this;
01390     }
01391 
01392         /** subtract-assignment */
01393     RestrictedNeighborhoodCirculator & operator-=(difference_type d)
01394     {
01395         return operator+=(-d);
01396     }
01397 
01398         /** addition */
01399     RestrictedNeighborhoodCirculator operator+(difference_type d) const
01400     {
01401         RestrictedNeighborhoodCirculator result(*this);
01402         result+= d;
01403         return result;
01404     }
01405 
01406         /** subtraction */
01407     RestrictedNeighborhoodCirculator operator-(difference_type d) const
01408     {
01409         RestrictedNeighborhoodCirculator result(*this);
01410         result-= d;
01411         return result;
01412     }
01413 
01414         /** equality */
01415     bool operator==(RestrictedNeighborhoodCirculator const & rhs) const
01416     {
01417         return current_ == rhs.current_;
01418     }
01419 
01420         /** inequality */
01421     bool operator!=(RestrictedNeighborhoodCirculator const & rhs) const
01422     {
01423         return current_ != rhs.current_;
01424     }
01425 
01426         /** subtraction */
01427     difference_type operator-(RestrictedNeighborhoodCirculator const & rhs) const
01428     {
01429         return (current_ - rhs.current_) % count_;
01430     }
01431 
01432         /** dereference */
01433     reference operator*() const
01434     {
01435         return BaseType::operator*();
01436     }
01437 
01438         /** member access */
01439     pointer operator->() const
01440     {
01441         return BaseType::operator->();
01442     }
01443 
01444         /** Get the base iterator for the current neighbor. */
01445     base_type const & base() const
01446     {
01447         return BaseType::base();
01448     }
01449 
01450         /** Get the base iterator for the center of the circulator. */
01451     base_type center() const
01452     {
01453         return BaseType::center();
01454     }
01455 
01456         /** Get the current direction. */
01457     Direction direction() const
01458     {
01459         return BaseType::direction();
01460     }
01461 
01462         /** Get the current direction bit. */
01463     unsigned int directionBit() const
01464     {
01465         return BaseType::directionBit();
01466     }
01467 
01468         /** Get the difference vector (Diff2D) from the center to the current neighbor. */
01469     Diff2D const & diff() const
01470     {
01471         return BaseType::diff();
01472     }
01473 
01474         /** Is the current neighbor a diagonal neighbor? */
01475     bool isDiagonal() const
01476     {
01477         return BaseType::isDiagonal();
01478     }
01479 
01480 private:
01481      AtImageBorder whichBorder_;
01482      signed char count_, current_;
01483 };
01484 
01485 //@}
01486 
01487 } // namespace vigra
01488 
01489 #endif /* VIGRA_PIXELNEIGHBORHOOD_HXX */

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
VIGRA 1.6.0 (13 Aug 2008)