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