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