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

| vigra/pixelneighborhood.hxx |
--- | --- | ---

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*          Copyright 1998-2002 by Hans Meine, Ullrich Koethe           */
    00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
    00005 /*                                                                      */
    00006 /*    This file is part of the VIGRA computer vision library.           */
    00007 /*    ( Version 1.3.2, Jan 27 2005 )                                    */
    00008 /*    You may use, modify, and distribute this software according       */
    00009 /*    to the terms stated in the LICENSE file included in               */
    00010 /*    the VIGRA distribution.                                           */
    00011 /*                                                                      */
    00012 /*    The VIGRA Website is                                              */
    00013 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
    00014 /*    Please direct questions, bug reports, and contributions to        */
    00015 /*        koethe@informatik.uni-hamburg.de                              */
    00016 /*                                                                      */
    00017 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
    00018 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
    00019 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
    00020 /*                                                                      */
    00021 /************************************************************************/
    00022
    00023 #ifndef VIGRA_PIXELNEIGHBORHOOD_HXX
    00024 #define VIGRA_PIXELNEIGHBORHOOD_HXX
    00025
    00026 #include <vigra/utilities.hxx>
    00027
    00028 namespace vigra {
    00029
    00030 /** \addtogroup PixelNeighborhood Utilities to manage pixel neighborhoods
    00031
    00032     4- and 8-neighborhood definitions and circulators.
    00033
    00034     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
    00035
    00036     <b>See also:</b> \ref vigra::NeighborhoodCirculator
    00037  */
    00038 //@{
    00039
    00040 /********************************************************/
    00041 /*                                                      */
    00042 /*                    FourNeighborhood                  */
    00043 /*                                                      */
    00044 /********************************************************/
    00045
    00046 /** Utilities for 4-neighborhood. */
    00047 namespace FourNeighborhood
    00048 {
    00049
    00050 /** \brief Encapsulation of direction management for 4-neighborhood.
    00051
    00052     This helper class allows the transformation between Freeman chain codes
    00053     (East = 0, North = 1 etc.) and the corresponding Diff2D instances
    00054     and back.
    00055
    00056     You can either use the chain codes by explicit qualification:
    00057
    00058     \code
    00059     // the following three lines are equivalent
    00060     FourNeighborhood::NeighborCode::Direction d = FourNeighborhood::NeighborCode::East;
    00061     FourNeighborCode::Direction d = FourNeighborCode::East;
    00062     FourNeighborhood::Direction d = FourNeighborhood::East;
    00063     \endcode
    00064
    00065     or you can fix 4-neighborhood by importing the entire namespace in
    00066     your function:
    00067
    00068     \code
    00069     using namespace FourNeighborhood;
    00070
    00071     Direction d = East;
    00072     \endcode
    00073
    00074     If you want to pass 4-neighborhood codes as a template parameter, use
    00075     the class FourNeighborhood::NeighborCode.
    00076
    00077     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
    00078     Namespace: vigra::FourNeighborhood
    00079 */
    00080 class NeighborCode
    00081 {
    00082   public:
    00083         /** Freeman direction codes for 4-neighborhood.
    00084             East = 0, North = 1 etc.
    00085             DirectionCount may be used for portable loop termination conditions.
    00086         */
    00087     enum Direction {
    00088         Error = -1,    ///< &nbsp;
    00089         East = 0,      ///< &nbsp;
    00090         North,         ///< &nbsp;
    00091         West,          ///< &nbsp;
    00092         South,         ///< &nbsp;
    00093         DirectionCount ///< &nbsp;
    00094     };
    00095
    00096         /** Transform direction code into corresponding Diff2D offset.
    00097             (note: there is no bounds checking on the code you pass.)
    00098         */
    00099     static Diff2D const & diff(Direction code)
    00100     {
    00101         static Diff2D d[] = {
    00102             Diff2D(1, 0), Diff2D(0, -1), Diff2D(-1, 0), Diff2D(0, 1)
    00103         };
    00104         return d[code];
    00105     }
    00106
    00107         /** Equivalent to <tt>diff(static_cast<Direction>(code))</tt>.
    00108             (note: there is no bounds checking on the code you pass.)
    00109         */
    00110     static Diff2D const & diff(int code) { return diff(static_cast<Direction>(code)); }
    00111
    00112         /** Get the relative offset from one neighbor to the other.
    00113             For example, <tt>relativeDiff(East, West) == Diff2D(-2,0)</tt>.
    00114             (note: there is no bounds checking on the code you pass.)
    00115         */
    00116     static Diff2D const & relativeDiff(Direction fromCode, Direction toCode)
    00117     {
    00118         static Diff2D d[][4] = {
    00119             { Diff2D(0, 0), Diff2D(-1, -1), Diff2D(-2, 0), Diff2D(-1, 1) },
    00120             { Diff2D(1, 1), Diff2D(0, 0), Diff2D(-1, 1), Diff2D(0, 2) },
    00121             { Diff2D(2, 0), Diff2D(1, -1), Diff2D(0, 0), Diff2D(1, 1) },
    00122             { Diff2D(1, -1), Diff2D(0, -2), Diff2D(-1, -1), Diff2D(0, 0) }
    00123         };
    00124
    00125         return d[fromCode][toCode];
    00126     }
    00127
    00128         /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode)).
    00129             (note: there is no bounds checking on the code you pass.)
    00130         */
    00131     static Diff2D const & relativeDiff(int fromCode, int toCode)
    00132     {
    00133         return relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode));
    00134     }
    00135
    00136         /**  X-component of diff() */
    00137     static int dX(Direction code) { return diff(code).x; }
    00138         /**  Y-component of diff() */
    00139     static int dY(Direction code) { return diff(code).y; }
    00140         /**  X-component of diff() */
    00141     static int dX(int code) { return diff(code).x; }
    00142         /**  Y-component of diff() */
    00143     static int dY(int code) { return diff(code).y; }
    00144
    00145         /** Transform Diff2D offset into corresponding direction code.
    00146             The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
    00147             is not in the 4-neighborhood.
    00148         */
    00149     static Direction code(Diff2D const & diff)
    00150     {
    00151         switch(diff.x)
    00152         {
    00153             case  0:
    00154             {
    00155                 switch(diff.y)
    00156                 {
    00157                     case 1:
    00158                         return South;
    00159                     case -1:
    00160                         return North;
    00161                     default:
    00162                         return Error;
    00163                 }
    00164             }
    00165             case -1:
    00166             {
    00167                 return (diff.y == 0) ?
    00168                             West :
    00169                             Error;
    00170             }
    00171             case  1:
    00172             {
    00173                 return (diff.y == 0) ?
    00174                             East :
    00175                             Error;
    00176             }
    00177         }
    00178         return Error;
    00179     }
    00180
    00181         /** Check whether a code refers to a diagonal direction.
    00182             Useful if you want to abstract the differences between 4- and 8-neighborhood.
    00183             Always <tt>false</tt> for 4-neighborhood.
    00184         */
    00185     static bool isDiagonal(Direction) { return false; }
    00186
    00187     static Diff2D const & right()        { return diff(East); }    /**<  Offset to the right neighbor */
    00188     static Diff2D const & top()          { return diff(North); }   /**<  Offset to the top neighbor */
    00189     static Diff2D const & left()         { return diff(West); }    /**<  Offset to the left neighbor */
    00190     static Diff2D const & bottom()       { return diff(South); }   /**<  Offset to the bottom neighbor */
    00191
    00192     static Diff2D const & east()       { return diff(East); }    /**<  Offset to the east neighbor */
    00193     static Diff2D const & north()      { return diff(North); }   /**<  Offset to the north neighbor */
    00194     static Diff2D const & west()       { return diff(West); }    /**<  Offset to the west neighbor */
    00195     static Diff2D const & south()      { return diff(South); }   /**<  Offset to the south neighbor */
    00196 };
    00197
    00198     /** Export NeighborCode::Direction into the scope of namespace FourNeighborhood.
    00199     */
    00200 typedef NeighborCode::Direction Direction;
    00201
    00202 static const Direction East           = NeighborCode::East;           /**<  Export NeighborCode::East to namespace FourNeighborhood */
    00203 static const Direction North          = NeighborCode::North;          /**<  Export NeighborCode::North to namespace FourNeighborhood */
    00204 static const Direction West           = NeighborCode::West;           /**<  Export NeighborCode::West to namespace FourNeighborhood */
    00205 static const Direction South          = NeighborCode::South;          /**<  Export NeighborCode::South to namespace FourNeighborhood */
    00206 static const Direction DirectionCount = NeighborCode::DirectionCount; /**<  Export NeighborCode::DirectionCount to namespace FourNeighborhood */
    00207
    00208 } // namespace FourNeighborhood
    00209
    00210     /** Export \ref vigra::FourNeighborhood::NeighborCode into the scope of namespace vigra.
    00211     */
    00212 typedef FourNeighborhood::NeighborCode FourNeighborCode;
    00213
    00214 /********************************************************/
    00215 /*                                                      */
    00216 /*                   EightNeighborhood                  */
    00217 /*                                                      */
    00218 /********************************************************/
    00219
    00220 /** Utilities for 8-neighborhood. */
    00221 namespace EightNeighborhood
    00222 {
    00223 /** \brief Encapsulation of direction management for the 8-neighborhood.
    00224
    00225     This helper class allows the transformation between Freeman chain codes
    00226     (East = 0, NorthEast = 1 etc.) and the corresponding Diff2D instances
    00227     and back.
    00228
    00229     You can either use the chain codes by explicit qualification:
    00230
    00231     \code
    00232     // the following three lines are equivalent
    00233     EightNeighborhood::NeighborCode::Direction d = EightNeighborhood::NeighborCode::East;
    00234     EightNeighborCode::Direction d               = EightNeighborCode::East;
    00235     EightNeighborhood::Direction d               = EightNeighborhood::East;
    00236     \endcode
    00237
    00238     or you can fix 8-neighborhood by importing the entire namespace in
    00239     your function:
    00240
    00241     \code
    00242     using namespace EightNeighborhood;
    00243
    00244     Direction d = East;
    00245     \endcode
    00246
    00247     If you want to pass 8-neighborhood codes as a template parameter, use
    00248     the class EightNeighborhood::NeighborCode.
    00249
    00250     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
    00251     Namespace: vigra::EightNeighborhood
    00252 */
    00253 class NeighborCode
    00254 {
    00255   public:
    00256         /** Freeman direction codes for the 8-neighborhood.
    00257             East = 0, NorthEast = 1 etc.
    00258             DirectionCount may be used for portable loop termination conditions.
    00259         */
    00260     enum Direction {
    00261         Error = -1,     ///< &nbsp;
    00262         East = 0,       ///< &nbsp;
    00263         NorthEast,      ///< &nbsp;
    00264         North,          ///< &nbsp;
    00265         NorthWest,      ///< &nbsp;
    00266         West,           ///< &nbsp;
    00267         SouthWest,      ///< &nbsp;
    00268         South,          ///< &nbsp;
    00269         SouthEast,      ///< &nbsp;
    00270         DirectionCount  ///< &nbsp;
    00271     };
    00272
    00273         /** Transform direction code into corresponding Diff2D offset.
    00274             (note: there is no bounds checking on the code you pass.)
    00275         */
    00276     static Diff2D const & diff(Direction code)
    00277     {
    00278         static Diff2D d[] = {
    00279             Diff2D(1, 0), Diff2D(1, -1), Diff2D(0, -1), Diff2D(-1, -1),
    00280             Diff2D(-1, 0), Diff2D(-1, 1), Diff2D(0, 1), Diff2D(1, 1)
    00281         };
    00282         return d[code];
    00283     }
    00284
    00285         /** Equivalent to diff(static_cast<Direction>(code)).
    00286             (note: there is no bounds checking on the code you pass.)
    00287         */
    00288     static Diff2D const & diff(int code) { return diff(static_cast<Direction>(code)); }
    00289
    00290         /** Get the relative offset from one neighbor to the other.
    00291             For example, <tt>relativeDiff(East, West) == Diff2D(-2,0)</tt>.
    00292             (note: there is no bounds checking on the code you pass.)
    00293         */
    00294     static Diff2D const & relativeDiff(Direction fromCode, Direction toCode)
    00295     {
    00296         static Diff2D d[][8] = {
    00297             { Diff2D(0, 0), Diff2D(0, -1), Diff2D(-1, -1), Diff2D(-2, -1),
    00298               Diff2D(-2, 0), Diff2D(-2, 1), Diff2D(-1, 1), Diff2D(0, 1) },
    00299             { Diff2D(0, 1), Diff2D(0, 0), Diff2D(-1, 0), Diff2D(-2, 0),
    00300               Diff2D(-2, 1), Diff2D(-2, 2), Diff2D(-1, 2), Diff2D(0, 2) },
    00301             { Diff2D(1, 1), Diff2D(1, 0), Diff2D(0, 0), Diff2D(-1, 0),
    00302               Diff2D(-1, 1), Diff2D(-1, 2), Diff2D(0, 2), Diff2D(1, 2) },
    00303             { Diff2D(2, 1), Diff2D(2, 0), Diff2D(1, 0), Diff2D(0, 0),
    00304               Diff2D(0, 1), Diff2D(0, 2), Diff2D(1, 2), Diff2D(2, 2) },
    00305             { Diff2D(2, 0), Diff2D(2, -1), Diff2D(1, -1), Diff2D(0, -1),
    00306               Diff2D(0, 0), Diff2D(0, 1), Diff2D(1, 1), Diff2D(2, 1) },
    00307             { Diff2D(2, -1), Diff2D(2, -2), Diff2D(1, -2), Diff2D(0, -2),
    00308               Diff2D(0, -1), Diff2D(0, 0), Diff2D(1, 0), Diff2D(2, 0) },
    00309             { Diff2D(1, -1), Diff2D(1, -2), Diff2D(0, -2), Diff2D(-1, -2),
    00310               Diff2D(-1, -1), Diff2D(-1, 0), Diff2D(0, 0), Diff2D(1, 0) },
    00311             { Diff2D(0, -1), Diff2D(0, -2), Diff2D(-1, -2), Diff2D(-2, -2),
    00312               Diff2D(-2, -1), Diff2D(-2, 0), Diff2D(-1, 0), Diff2D(0, 0) }
    00313         };
    00314
    00315         return d[fromCode][toCode];
    00316     }
    00317
    00318         /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode)).
    00319             (note: there is no bounds checking on the code you pass.)
    00320         */
    00321     static Diff2D const & relativeDiff(int fromCode, int toCode)
    00322     {
    00323         return relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode));
    00324     }
    00325
    00326         /**  X-component of diff() */
    00327     static int dX(Direction code) { return diff(code).x; }
    00328         /**  Y-component of diff() */
    00329     static int dY(Direction code) { return diff(code).y; }
    00330         /**  X-component of diff() */
    00331     static int dX(int code) { return diff(code).x; }
    00332         /**  Y-component of diff() */
    00333     static int dY(int code) { return diff(code).y; }
    00334
    00335         /** Transform 4-neighborhood code into 8-neighborhood code.
    00336         */
    00337     static Direction code(FourNeighborhood::Direction d)
    00338         { return static_cast<Direction>(2*d); }
    00339
    00340         /** Transform Diff2D offset into corresponding direction code.
    00341             The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
    00342             is not in the 8-neighborhood.
    00343         */
    00344     static Direction code(Diff2D const & diff)
    00345     {
    00346         switch(diff.x)
    00347         {
    00348             case  0:
    00349             {
    00350                 switch(diff.y)
    00351                 {
    00352                     case 1:
    00353                         return South;
    00354                     case -1:
    00355                         return North;
    00356                     default:
    00357                         return Error;
    00358                 }
    00359             }
    00360             case -1:
    00361             {
    00362                 switch(diff.y)
    00363                 {
    00364                     case 0:
    00365                         return West;
    00366                     case 1:
    00367                         return SouthWest;
    00368                     case -1:
    00369                         return NorthWest;
    00370                     default:
    00371                         return Error;
    00372                 }
    00373             }
    00374             case  1:
    00375             {
    00376                 switch(diff.y)
    00377                 {
    00378                     case 0:
    00379                         return East;
    00380                     case 1:
    00381                         return SouthEast;
    00382                     case -1:
    00383                         return NorthEast;
    00384                     default:
    00385                         return Error;
    00386                 }
    00387             }
    00388         }
    00389         return Error;
    00390     }
    00391
    00392         /** Check whether a code refers to a diagonal direction.
    00393             Useful if you want to abstract the differences between 4- and 8-neighborhood.
    00394         */
    00395     static bool isDiagonal(Direction code) { return (code % 2) != 0; }
    00396
    00397     static Diff2D const & right()        { return diff(East); }        /**<  Offset to the right neighbor */
    00398     static Diff2D const & topRight()     { return diff(NorthEast); }   /**<  Offset to the topRight neighbor */
    00399     static Diff2D const & top()          { return diff(North); }       /**<  Offset to the top neighbor */
    00400     static Diff2D const & topLeft()      { return diff(NorthWest); }   /**<  Offset to the topLeft neighbor */
    00401     static Diff2D const & left()         { return diff(West); }        /**<  Offset to the left neighbor */
    00402     static Diff2D const & bottomLeft()   { return diff(SouthWest); }   /**<  Offset to the bottomLeft neighbor */
    00403     static Diff2D const & bottom()       { return diff(South); }       /**<  Offset to the bottom neighbor */
    00404     static Diff2D const & bottomRight()  { return diff(SouthEast); }   /**<  Offset to the bottomRight neighbor */
    00405
    00406     static Diff2D const & east()       { return diff(East); }        /**<  Offset to the east neighbor */
    00407     static Diff2D const & northEast()  { return diff(NorthEast); }   /**<  Offset to the northEast neighbor */
    00408     static Diff2D const & north()      { return diff(North); }       /**<  Offset to the north neighbor */
    00409     static Diff2D const & northWest()  { return diff(NorthWest); }   /**<  Offset to the northWest neighbor */
    00410     static Diff2D const & west()       { return diff(West); }        /**<  Offset to the west neighbor */
    00411     static Diff2D const & southWest()  { return diff(SouthWest); }   /**<  Offset to the southWest neighbor */
    00412     static Diff2D const & south()      { return diff(South); }       /**<  Offset to the south neighbor */
    00413     static Diff2D const & southEast()  { return diff(SouthEast); }   /**<  Offset to the southEast neighbor */
    00414 };
    00415
    00416     /** Export NeighborCode::Direction into the scope of namespace EightNeighborhood.
    00417     */
    00418 typedef NeighborCode::Direction Direction;
    00419
    00420 static const Direction East           = NeighborCode::East;        /**<  Export NeighborCode::East to namespace EightNeighborhood */
    00421 static const Direction NorthEast      = NeighborCode::NorthEast;   /**<  Export NeighborCode::NorthEast to namespace EightNeighborhood */
    00422 static const Direction North          = NeighborCode::North;       /**<  Export NeighborCode::North to namespace EightNeighborhood */
    00423 static const Direction NorthWest      = NeighborCode::NorthWest;   /**<  Export NeighborCode::NorthWest to namespace EightNeighborhood */
    00424 static const Direction West           = NeighborCode::West;        /**<  Export NeighborCode::West to namespace EightNeighborhood */
    00425 static const Direction SouthWest      = NeighborCode::SouthWest;   /**<  Export NeighborCode::SouthWest to namespace EightNeighborhood */
    00426 static const Direction South          = NeighborCode::South;       /**<  Export NeighborCode::South to namespace EightNeighborhood */
    00427 static const Direction SouthEast      = NeighborCode::SouthEast;   /**<  Export NeighborCode::SouthEast to namespace EightNeighborhood */
    00428 static const Direction DirectionCount = NeighborCode::DirectionCount;   /**<  Export NeighborCode::DirectionCount to namespace EightNeighborhood */
    00429
    00430 } // namespace EightNeighborhood
    00431
    00432     /** Export \ref vigra::EightNeighborhood::NeighborCode into the scope of namespace vigra.
    00433     */
    00434 typedef EightNeighborhood::NeighborCode EightNeighborCode;
    00435
    00436 /********************************************************/
    00437 /*                                                      */
    00438 /*              NeighborOffsetCirculator                */
    00439 /*                                                      */
    00440 /********************************************************/
    00441
    00442 /** \brief Circulator that walks around a given location.
    00443
    00444     The template parameter defines the kind of neighborhood used, e.g.
    00445
    00446     \code
    00447     NeighborOffsetCirculator<EightNeighborCode> eight_circulator;
    00448     NeighborOffsetCirculator<FourNeighborCode>  four_circulator;
    00449     \endcode
    00450
    00451     Since this circulator doesn't now about the pixels in any particular image,
    00452     you usually doesn't use it directly but rather as a base class or helper for
    00453     neighborhood circulators refering to a particular image (e.g. NeighborhoodCirculator)
    00454
    00455     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
    00456     Namespace: vigra
    00457 */
    00458 template<class NEIGHBORCODE>
    00459 class NeighborOffsetCirculator
    00460 : public NEIGHBORCODE
    00461 {
    00462 public:
    00463     typedef NEIGHBORCODE NeighborCode;
    00464
    00465         /** return type of direction()
    00466         */
    00467     typedef typename NEIGHBORCODE::Direction Direction;
    00468
    00469         /** the circulator's value type
    00470         */
    00471     typedef Diff2D value_type;
    00472
    00473         /** the circulator's reference type (return type of <TT>*circ</TT>)
    00474         */
    00475     typedef Diff2D const & reference;
    00476
    00477         /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
    00478         */
    00479     typedef Diff2D const & index_reference;
    00480
    00481         /** the circulator's pointer type (return type of <TT>operator-></TT>)
    00482         */
    00483     typedef Diff2D const * pointer;
    00484
    00485         /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
    00486         */
    00487     typedef int difference_type;
    00488
    00489         /** the circulator tag (random access iterator)
    00490         */
    00491     typedef random_access_circulator_tag iterator_category;
    00492
    00493 protected:
    00494     Direction direction_;
    00495
    00496 public:
    00497         /** Create circulator refering to the given direction.
    00498         */
    00499     NeighborOffsetCirculator(Direction dir = NEIGHBORCODE::East)
    00500         : direction_(dir)
    00501     {
    00502     }
    00503
    00504         /** pre-increment */
    00505     NeighborOffsetCirculator & operator++()
    00506     {
    00507         direction_ = static_cast<Direction>((direction_+1) % NEIGHBORCODE::DirectionCount);
    00508         return *this;
    00509     }
    00510
    00511         /** pre-decrement */
    00512     NeighborOffsetCirculator & operator--()
    00513     {
    00514         direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::DirectionCount-1) % NEIGHBORCODE::DirectionCount);
    00515         return *this;
    00516     }
    00517
    00518         /** post-increment */
    00519     NeighborOffsetCirculator operator++(int)
    00520     {
    00521         NeighborOffsetCirculator ret(*this);
    00522         operator++();
    00523         return ret;
    00524     }
    00525
    00526         /** post-decrement */
    00527     NeighborOffsetCirculator operator--(int)
    00528     {
    00529         NeighborOffsetCirculator ret(*this);
    00530         operator--();
    00531         return ret;
    00532     }
    00533
    00534         /** add-assignment */
    00535     NeighborOffsetCirculator & operator+=(difference_type d)
    00536     {
    00537         direction_ = static_cast<Direction>((direction_ + d) % NEIGHBORCODE::DirectionCount);
    00538         if(direction_ < 0)
    00539             direction_ = static_cast<Direction>(direction_ + NEIGHBORCODE::DirectionCount);
    00540         return *this;
    00541     }
    00542
    00543         /** subtract-assignment */
    00544     NeighborOffsetCirculator & operator-=(difference_type d)
    00545     {
    00546         direction_ = static_cast<Direction>((direction_ - d) % NEIGHBORCODE::DirectionCount);
    00547         if(direction_ < 0)
    00548             direction_ = static_cast<Direction>(direction_ + NEIGHBORCODE::DirectionCount);
    00549         return *this;
    00550     }
    00551
    00552         /** addition */
    00553     NeighborOffsetCirculator operator+(difference_type d) const
    00554     {
    00555         return NeighborOffsetCirculator(*this) += d;
    00556     }
    00557
    00558         /** subtraction */
    00559     NeighborOffsetCirculator operator-(difference_type d) const
    00560     {
    00561         return NeighborOffsetCirculator(*this) -= d;
    00562     }
    00563
    00564         /** Move to the direction that is 'right' relative to the current direction.
    00565             This is equivalent to <tt>four_circulator--</tt> and
    00566             <tt>eight_circulator -= 2</tt> respectively.
    00567         */
    00568     NeighborOffsetCirculator & turnRight()
    00569     {
    00570         direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::South) % NEIGHBORCODE::DirectionCount);
    00571         return *this;
    00572     }
    00573
    00574         /** Move to the direction that is 'left' relative to the current direction.
    00575             This is equivalent to <tt>four_circulator++</tt> and
    00576             <tt>eight_circulator += 2</tt> respectively.
    00577         */
    00578     NeighborOffsetCirculator & turnLeft()
    00579     {
    00580         direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::North) % NEIGHBORCODE::DirectionCount);
    00581         return *this;
    00582     }
    00583
    00584         /** Move to the opposite direction of the current direction.
    00585             This is equivalent to <tt>four_circulator += 2</tt> and
    00586             <tt>eight_circulator += 4</tt> respectively.
    00587         */
    00588     NeighborOffsetCirculator & turnRound()
    00589     {
    00590         direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::West) % NEIGHBORCODE::DirectionCount);
    00591         return *this;
    00592     }
    00593
    00594         /** Move to the given direction.
    00595         */
    00596     NeighborOffsetCirculator & turnTo(Direction d)
    00597     {
    00598         direction_ = d;
    00599         return *this;
    00600     }
    00601
    00602         /** equality */
    00603     bool operator==(NeighborOffsetCirculator const & o) const
    00604     {
    00605         return direction_ == o.direction_;
    00606     }
    00607
    00608         /** unequality */
    00609     bool operator!=(NeighborOffsetCirculator const & o) const
    00610     {
    00611         return direction_ != o.direction_;
    00612     }
    00613
    00614         /** subtraction */
    00615     difference_type operator-(NeighborOffsetCirculator const & o) const
    00616     {
    00617         return direction_ - o.direction_;
    00618     }
    00619
    00620         /** dereference */
    00621     reference operator*() const
    00622     {
    00623         return diff();
    00624     }
    00625
    00626         /** index */
    00627     index_reference operator[](difference_type d) const
    00628     {
    00629         return NEIGHBORCODE::diff(direction(d));
    00630     }
    00631
    00632         /** member access */
    00633     pointer operator->() const
    00634     {
    00635         return &diff();
    00636     }
    00637
    00638         /** Get Diff2D offset from center to current neighbor.
    00639         */
    00640     Diff2D const & diff() const
    00641     {
    00642         return NEIGHBORCODE::diff(direction_);
    00643     }
    00644
    00645         /** Get Diff2D offset to given direction.
    00646         */
    00647     static Diff2D const & diff(Direction dir)
    00648     {
    00649         return NEIGHBORCODE::diff(dir);
    00650     }
    00651
    00652         /** Get relative distance (Diff2D) from current neighbor to neighbor
    00653             at given offset.
    00654         */
    00655     Diff2D const &relativeDiff(difference_type offset) const
    00656     {
    00657         Direction toDir = static_cast<Direction>((direction_ + offset) % NEIGHBORCODE::DirectionCount);
    00658         if(toDir < 0)
    00659             toDir = static_cast<Direction>(toDir + NEIGHBORCODE::DirectionCount);
    00660         return NEIGHBORCODE::relativeDiff(direction_, toDir);
    00661     }
    00662
    00663         /** X-component of diff()  */
    00664     int dX() const
    00665     {
    00666         return NEIGHBORCODE::dX(direction_);
    00667     }
    00668
    00669         /** Y-component of diff() */
    00670     int dY() const
    00671     {
    00672         return NEIGHBORCODE::dY(direction_);
    00673     }
    00674
    00675         /** Check whether current direction is a diagonal one.
    00676         */
    00677     bool isDiagonal() const
    00678     {
    00679         return NEIGHBORCODE::isDiagonal(direction_);
    00680     }
    00681
    00682         /** Get current direction.
    00683         */
    00684     Direction direction() const
    00685     {
    00686         return direction_;
    00687     }
    00688
    00689         /** Get direction code at offset of current direction.
    00690         */
    00691     Direction direction(difference_type offset) const
    00692     {
    00693         int result = (direction_ + offset) % NEIGHBORCODE::DirectionCount;
    00694         if(result < 0)
    00695             result += NEIGHBORCODE::DirectionCount;
    00696         return static_cast<Direction>(result);
    00697     }
    00698 };
    00699
    00700 /** Specialization of NeighborOffsetCirculator for 8-neighborhood.
    00701 */
    00702 typedef NeighborOffsetCirculator<EightNeighborCode> EightNeighborOffsetCirculator;
    00703
    00704 /** Specialization of NeighborOffsetCirculator for 4-neighborhood.
    00705 */
    00706 typedef NeighborOffsetCirculator<FourNeighborCode> FourNeighborOffsetCirculator;
    00707
    00708
    00709 //@}
    00710
    00711 /** \addtogroup ImageIteratorAdapters
    00712  */
    00713 //@{
    00714
    00715 /********************************************************/
    00716 /*                                                      */
    00717 /*                NeighborhoodCirculator                */
    00718 /*                                                      */
    00719 /********************************************************/
    00720
    00721 /** \brief Circulator that walks around a given location in a given image.
    00722
    00723     The template parameters define the kind of neighborhood used and the underlying
    00724     image, e.g.
    00725
    00726     \code
    00727     NeighborhoodCirculator<BImage::traverser, EightNeighborCode> eight_circulator(image.upperLeft()+Diff2D(2,2));
    00728     NeighborhoodCirculator<BImage::traverser, FourNeighborCode>  four_circulator(image.upperLeft()+Diff2D(2,2));
    00729     \endcode
    00730
    00731     The access functions return the value of the current neighbor pixel. Use <tt>center()</tt> to
    00732     access the center pixel of the neighborhood. The center can be changed by calling
    00733     <tt>moveCenterToNeighbor()</tt> or <tt>swapCenterNeighbor()</tt>.
    00734
    00735     <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
    00736     Namespace: vigra
    00737 */
    00738 template <class IMAGEITERATOR, class NEIGHBORCODE>
    00739 class NeighborhoodCirculator : private IMAGEITERATOR
    00740 {
    00741     typedef NeighborOffsetCirculator<NEIGHBORCODE> NEIGHBOROFFSETCIRCULATOR;
    00742
    00743 public:
    00744         /** type of the underlying image iterator
    00745         */
    00746     typedef IMAGEITERATOR base_type;
    00747
    00748         /** type of the used neighbor code
    00749         */
    00750     typedef NEIGHBORCODE NeighborCode;
    00751
    00752         /** the circulator's value type
    00753         */
    00754     typedef typename IMAGEITERATOR::value_type value_type;
    00755
    00756         /** type of the direction code
    00757         */
    00758     typedef typename NEIGHBORCODE::Direction Direction;
    00759
    00760         /** the circulator's reference type (return type of <TT>*circ</TT>)
    00761         */
    00762     typedef typename IMAGEITERATOR::reference reference;
    00763
    00764         /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
    00765         */
    00766     typedef typename IMAGEITERATOR::index_reference index_reference;
    00767
    00768         /** the circulator's pointer type (return type of <TT>operator-></TT>)
    00769         */
    00770     typedef typename IMAGEITERATOR::pointer pointer;
    00771
    00772         /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
    00773         */
    00774     typedef typename NEIGHBOROFFSETCIRCULATOR::difference_type difference_type;
    00775
    00776         /** the circulator tag (random_access_circulator_tag)
    00777         */
    00778     typedef typename NEIGHBOROFFSETCIRCULATOR::iterator_category iterator_category;
    00779
    00780         /** Construct circulator with given <tt>center</tt> pixel, pointing to the neighbor
    00781             at the given direction <tt>d</tt>.
    00782         */
    00783     NeighborhoodCirculator(IMAGEITERATOR const & center = IMAGEITERATOR(),
    00784                            Direction d = NEIGHBOROFFSETCIRCULATOR::East)
    00785         : IMAGEITERATOR(center), neighborCode_(d)
    00786     {
    00787         IMAGEITERATOR::operator+=(neighborCode_.diff());
    00788     }
    00789
    00790         /** pre-increment */
    00791     NeighborhoodCirculator & operator++()
    00792     {
    00793         return operator+=(1);
    00794     }
    00795
    00796         /** pre-decrement */
    00797     NeighborhoodCirculator operator++(int)
    00798     {
    00799         NeighborhoodCirculator ret(*this);
    00800         operator++();
    00801         return ret;
    00802     }
    00803
    00804         /** post-increment */
    00805     NeighborhoodCirculator & operator--()
    00806     {
    00807         return operator+=(-1);
    00808     }
    00809
    00810         /** post-decrement */
    00811     NeighborhoodCirculator operator--(int)
    00812     {
    00813         NeighborhoodCirculator ret(*this);
    00814         operator--();
    00815         return ret;
    00816     }
    00817
    00818         /** add-assignment */
    00819     NeighborhoodCirculator & operator+=(difference_type d)
    00820     {
    00821         IMAGEITERATOR::operator+=(neighborCode_.relativeDiff(d));
    00822         neighborCode_+= d;
    00823         return *this;
    00824     }
    00825
    00826         /** subtract-assignment */
    00827     NeighborhoodCirculator & operator-=(difference_type d)
    00828     {
    00829         return operator+=(-d);
    00830     }
    00831
    00832         /** addition */
    00833     NeighborhoodCirculator operator+(difference_type d) const
    00834     {
    00835         NeighborhoodCirculator result(*this);
    00836         result+= d;
    00837         return result;
    00838     }
    00839
    00840         /** subtraction */
    00841     NeighborhoodCirculator operator-(difference_type d) const
    00842     {
    00843         NeighborhoodCirculator result(*this);
    00844         result-= d;
    00845         return result;
    00846     }
    00847
    00848         /** Move to the direction that is 'right' relative to the current direction.
    00849             This is equivalent to <tt>four_circulator--</tt> and
    00850             <tt>eight_circulator -= 2</tt> respectively.
    00851         */
    00852     NeighborhoodCirculator & turnRight()
    00853     {
    00854         Direction oldDirection = neighborCode_.direction();
    00855         neighborCode_.turnRight();
    00856         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
    00857                                   (oldDirection, neighborCode_.direction()));
    00858         return *this;
    00859     }
    00860
    00861         /** Move to the direction that is 'left' relative to the current direction.
    00862             This is equivalent to <tt>four_circulator++</tt> and
    00863             <tt>eight_circulator += 2</tt> respectively.
    00864         */
    00865     NeighborhoodCirculator & turnLeft()
    00866     {
    00867         Direction oldDirection = neighborCode_.direction();
    00868         neighborCode_.turnLeft();
    00869         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
    00870                                   (oldDirection, neighborCode_.direction()));
    00871         return *this;
    00872     }
    00873
    00874         /** Move to the opposite direction of the current direction.
    00875             This is equivalent to <tt>four_circulator += 2</tt> and
    00876             <tt>eight_circulator += 4</tt> respectively.
    00877         */
    00878     NeighborhoodCirculator & turnRound()
    00879     {
    00880         Direction oldDirection = neighborCode_.direction();
    00881         neighborCode_.turnRound();
    00882         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
    00883                                   (oldDirection, neighborCode_.direction()));
    00884         return *this;
    00885     }
    00886
    00887         /** Move to the given direction.
    00888         */
    00889     NeighborhoodCirculator & turnTo(Direction d)
    00890     {
    00891         Direction oldDirection = neighborCode_.direction();
    00892         neighborCode_.turnTo(d);
    00893         IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
    00894                                   (oldDirection, neighborCode_.direction()));
    00895         return *this;
    00896     }
    00897
    00898         /** Move the center in the current direction.
    00899             The current neighbor becomes the new center, the direction does not change.
    00900         */
    00901     NeighborhoodCirculator & moveCenterToNeighbor()
    00902     {
    00903         IMAGEITERATOR::operator+=(neighborCode_.diff());
    00904         return *this;
    00905     }
    00906
    00907         /** Exchange the center with the current neighbor.
    00908             Equivalent to <tt>circ.moveCenterToNeighbor().turnRound()</tt>
    00909             (but shorter and more efficient).
    00910         */
    00911     NeighborhoodCirculator & swapCenterNeighbor()
    00912     {
    00913         neighborCode_.turnRound();
    00914         IMAGEITERATOR::operator+=(neighborCode_.diff());
    00915         return *this;
    00916     }
    00917
    00918         /** equality */
    00919     bool operator==(NeighborhoodCirculator const & rhs) const
    00920     {
    00921         return neighborCode_ == rhs.neighborCode_ &&
    00922                IMAGEITERATOR::operator==(rhs);
    00923     }
    00924
    00925         /** inequality */
    00926     bool operator!=(NeighborhoodCirculator const & rhs) const
    00927     {
    00928         return neighborCode_ != rhs.neighborCode_ ||
    00929                IMAGEITERATOR::operator!=(rhs);
    00930     }
    00931
    00932         /** subtraction */
    00933     difference_type operator-(NeighborhoodCirculator const & rhs) const
    00934     {
    00935         return neighborCode_ - rhs.neighborCode_;
    00936     }
    00937
    00938         /** dereference */
    00939     reference operator*() const
    00940     {
    00941         return IMAGEITERATOR::operator*();
    00942     }
    00943
    00944         /** index */
    00945     index_reference operator[](difference_type d) const
    00946     {
    00947         return IMAGEITERATOR::operator[](neighborCode_.relativeDiff(d));
    00948     }
    00949
    00950         /** member access */
    00951     pointer operator->() const
    00952     {
    00953         return IMAGEITERATOR::operator->();
    00954     }
    00955
    00956         /** Get the base iterator for the current neighbor. */
    00957     base_type const & base() const
    00958     {
    00959         return *this;
    00960     }
    00961
    00962         /** Get the base iterator for the center of the circulator. */
    00963     base_type center() const
    00964     {
    00965         return (base_type)*this - neighborCode_.diff();
    00966     }
    00967
    00968         /** Get the current direction. */
    00969     Direction direction() const
    00970     {
    00971         return neighborCode_.direction();
    00972     }
    00973
    00974         /** Get the difference vector (Diff2D) from the center to the current neighbor. */
    00975     Diff2D const & diff() const
    00976     {
    00977         return neighborCode_.diff();
    00978     }
    00979
    00980         /** Is the current neighbor a diagonal neighbor? */
    00981     bool isDiagonal() const
    00982     {
    00983         return neighborCode_.isDiagonal();
    00984     }
    00985
    00986 private:
    00987     NEIGHBOROFFSETCIRCULATOR neighborCode_;
    00988 };
    00989
    00990 //@}
    00991
    00992 } // namespace vigra
    00993
    00994 #endif /* VIGRA_PIXELNEIGHBORHOOD_HXX */

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.3.2 (27 Jan 2005)