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

details vigra/pixelneighborhood.hxx VIGRA

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)