[ 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)