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

vigra/pixelneighborhood.hxx VIGRA

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.8.0 (20 Sep 2011)