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

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

    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.5.0, Dec 07 2006 )                                    */
    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 "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; // avoid 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.5.0 (7 Dec 2006)