vigra - vigra/pixelneighborhood.hxx Source File

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