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