[ 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, ///< 00072 RightBorder = 1, ///< 00073 LeftBorder = 2, ///< 00074 TopBorder = 4, ///< 00075 BottomBorder = 8, ///< 00076 TopRightBorder = TopBorder | RightBorder, ///< 00077 TopLeftBorder = TopBorder | LeftBorder, ///< 00078 BottomLeftBorder = BottomBorder | LeftBorder, ///< 00079 BottomRightBorder = BottomBorder | RightBorder ///< 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, ///< 00159 East = 0, ///< 00160 North, ///< 00161 West, ///< 00162 South, ///< 00163 DirectionCount, ///< 00164 CausalFirst = North, ///< 00165 CausalLast = West, ///< 00166 AntiCausalFirst = South, ///< 00167 AntiCausalLast = East ///< 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, ///< 00383 East = 0, ///< 00384 NorthEast, ///< 00385 North, ///< 00386 NorthWest, ///< 00387 West, ///< 00388 SouthWest, ///< 00389 South, ///< 00390 SouthEast, ///< 00391 DirectionCount, ///< 00392 CausalFirst = NorthEast, ///< 00393 CausalLast = West, ///< 00394 AntiCausalFirst = SouthWest, ///< 00395 AntiCausalLast = East ///< 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) |
html generated using doxygen and Python
|