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

details vigra/pixelneighborhood.hxx VIGRA

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