1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2005 by Hans Meine, Ullrich Koethe */
4 /* Cognitive Systems Group, University of Hamburg, Germany */
5 /* */
6 /* This file is part of the VIGRA computer vision library. */
7 /* ( Version 1.5.0, Dec 07 2006 ) */
8 /* The VIGRA Website is */
9 /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */
10 /* Please direct questions, bug reports, and contributions to */
11 /* koethe@informatik.uni-hamburg.de or */
12 /* vigra@kogs1.informatik.uni-hamburg.de */
13 /* */
14 /* Permission is hereby granted, free of charge, to any person */
15 /* obtaining a copy of this software and associated documentation */
16 /* files (the "Software"), to deal in the Software without */
17 /* restriction, including without limitation the rights to use, */
18 /* copy, modify, merge, publish, distribute, sublicense, and/or */
19 /* sell copies of the Software, and to permit persons to whom the */
20 /* Software is furnished to do so, subject to the following */
21 /* conditions: */
22 /* */
23 /* The above copyright notice and this permission notice shall be */
24 /* included in all copies or substantial portions of the */
25 /* Software. */
26 /* */
27 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
28 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
29 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
30 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
31 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
32 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
33 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
34 /* OTHER DEALINGS IN THE SOFTWARE. */
35 /* */
36 /************************************************************************/
37
38 #ifndef VIGRA_PIXELNEIGHBORHOOD_HXX
39 #define VIGRA_PIXELNEIGHBORHOOD_HXX
40
41 #include "utilities.hxx"
42
43 namespace vigra {
44
45 /** \addtogroup PixelNeighborhood Utilities to manage pixel neighborhoods
46
47 4- and 8-neighborhood definitions and circulators.
48
49 <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
50
51 <b>See also:</b> \ref vigra::NeighborhoodCirculator
52 */
53 //@{
54
55 /********************************************************/
56 /* */
57 /* AtImageBorder */
58 /* */
59 /********************************************************/
60
61 /** \brief Encode whether a point is near the image border.
62
63 This enum is used with \ref isAtImageBorder() and
64 \ref vigra::RestrictedNeighborhoodCirculator.
65
66 <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
67 Namespace: vigra
68 */
69 enum AtImageBorder
70 {
71 NotAtBorder = 0, ///<
72 RightBorder = 1, ///<
73 LeftBorder = 2, ///<
74 TopBorder = 4, ///<
75 BottomBorder = 8, ///<
76 TopRightBorder = TopBorder | RightBorder, ///<
77 TopLeftBorder = TopBorder | LeftBorder, ///<
78 BottomLeftBorder = BottomBorder | LeftBorder, ///<
79 BottomRightBorder = BottomBorder | RightBorder ///<
80 };
81
82 /** \brief Find out whether a point is at the image border.
83
84 This function checks if \a x == 0 or \a x == \a width - 1 and
85 \a y == 0 or \a y == \a height - 1 and returns the appropriate value
86 of \ref vigra::AtImageBorder, or zero when the point is not at te image border.
87 The behavior of the function is undefined if (x,y) is not inside the image.
88
89 <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
90 Namespace: vigra
91 */
isAtImageBorder(int x,int y,int width,int height)92 inline AtImageBorder isAtImageBorder(int x, int y, int width, int height)
93 {
94 return static_cast<AtImageBorder>((x == 0
95 ? LeftBorder
96 : x == width-1
97 ? RightBorder
98 : NotAtBorder) |
99 (y == 0
100 ? TopBorder
101 : y == height-1
102 ? BottomBorder
103 : NotAtBorder));
104 }
105
106 /********************************************************/
107 /* */
108 /* FourNeighborhood */
109 /* */
110 /********************************************************/
111
112 /** Utilities for 4-neighborhood. */
113 namespace FourNeighborhood
114 {
115
116 /** \brief Encapsulation of direction management for 4-neighborhood.
117
118 This helper class allows the transformation between Freeman chain codes
119 (East = 0, North = 1 etc.) and the corresponding Diff2D instances
120 and back.
121
122 You can either use the chain codes by explicit qualification:
123
124 \code
125 // the following three lines are equivalent
126 FourNeighborhood::NeighborCode::Direction d = FourNeighborhood::NeighborCode::East;
127 FourNeighborCode::Direction d = FourNeighborCode::East;
128 FourNeighborhood::Direction d = FourNeighborhood::East;
129 \endcode
130
131 or you can fix 4-neighborhood by importing the entire namespace in
132 your function:
133
134 \code
135 using namespace FourNeighborhood;
136
137 Direction d = East;
138 \endcode
139
140 If you want to pass 4-neighborhood codes as a template parameter, use
141 the class FourNeighborhood::NeighborCode.
142
143 <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
144 Namespace: vigra::FourNeighborhood
145 */
146 class NeighborCode
147 {
148 public:
149 /** Freeman direction codes for the 4-neighborhood.
150 <tt>East = 0</tt>, <tt>North = 1</tt> etc.
151 <tt>DirectionCount</tt> may be used for portable loop termination conditions.
152 <tt>CausalFirst</tt> and <tt>CausalLast</tt> are the first and last (inclusive)
153 neighbors in the causal neighborhood, i.e. in the set of neighbors that have
154 already been visited when the image is traversed in scan order.
155 <tt>AntiCausalFirst</tt> and <tt>AntiCausalLast</tt> are the opposite.
156 */
157 enum Direction {
158 Error = -1, ///<
159 East = 0, ///<
160 North, ///<
161 West, ///<
162 South, ///<
163 DirectionCount, ///<
164 CausalFirst = North, ///<
165 CausalLast = West, ///<
166 AntiCausalFirst = South, ///<
167 AntiCausalLast = East ///<
168 };
169
directionBit(Direction d)170 static unsigned int directionBit(Direction d)
171 {
172 static unsigned int b[] = {1 << (East + 1),
173 1 << (North + 1),
174 1 << (West + 1),
175 1 << (South + 1)};
176 return b[d];
177 };
178
179 /** The number of valid neighbors if the current center is at the image border.
180 */
nearBorderDirectionCount(AtImageBorder b)181 static unsigned int nearBorderDirectionCount(AtImageBorder b)
182 {
183 static unsigned int c[] = { 4, 3, 3, 0, 3, 2, 2, 0, 3, 2, 2};
184 return c[b];
185 }
186
187 /** The valid direction codes when the center is at the image border.
188 \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1</tt>.
189 */
nearBorderDirections(AtImageBorder b,int index)190 static Direction nearBorderDirections(AtImageBorder b, int index)
191 {
192 static Direction c[11][4] = {
193 { East, North, West, South},
194 { North, West, South, Error},
195 { East, North, South, Error},
196 { Error, Error, Error, Error},
197 { East, West, South, Error},
198 { West, South, Error, Error},
199 { East, South, Error, Error},
200 { Error, Error, Error, Error},
201 { East, North, West, Error},
202 { North, West, Error, Error},
203 { East, North, Error, Error}
204 };
205 return c[b][index];
206 }
207
208 /** Transform direction code into corresponding Diff2D offset.
209 (note: there is no bounds checking on the code you pass.)
210 */
diff(Direction code)211 static Diff2D const & diff(Direction code)
212 {
213 static Diff2D d[] = {
214 Diff2D(1, 0), Diff2D(0, -1), Diff2D(-1, 0), Diff2D(0, 1)
215 };
216 return d[code];
217 }
218
219 /** Equivalent to <tt>diff(static_cast<Direction>(code))</tt>.
220 (note: there is no bounds checking on the code you pass.)
221 */
diff(int code)222 static Diff2D const & diff(int code) { return diff(static_cast<Direction>(code)); }
223
224 /** Get the relative offset from one neighbor to the other.
225 For example, <tt>relativeDiff(East, West) == Diff2D(-2,0)</tt>.
226 (note: there is no bounds checking on the code you pass.)
227 */
relativeDiff(Direction fromCode,Direction toCode)228 static Diff2D const & relativeDiff(Direction fromCode, Direction toCode)
229 {
230 static Diff2D d[][4] = {
231 { Diff2D(0, 0), Diff2D(-1, -1), Diff2D(-2, 0), Diff2D(-1, 1) },
232 { Diff2D(1, 1), Diff2D(0, 0), Diff2D(-1, 1), Diff2D(0, 2) },
233 { Diff2D(2, 0), Diff2D(1, -1), Diff2D(0, 0), Diff2D(1, 1) },
234 { Diff2D(1, -1), Diff2D(0, -2), Diff2D(-1, -1), Diff2D(0, 0) }
235 };
236
237 return d[fromCode][toCode];
238 }
239
240 /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode)).
241 (note: there is no bounds checking on the code you pass.)
242 */
relativeDiff(int fromCode,int toCode)243 static Diff2D const & relativeDiff(int fromCode, int toCode)
244 {
245 return relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode));
246 }
247
248 /** X-component of diff() */
dX(Direction code)249 static int dX(Direction code) { return diff(code).x; }
250 /** Y-component of diff() */
dY(Direction code)251 static int dY(Direction code) { return diff(code).y; }
252 /** X-component of diff() */
dX(int code)253 static int dX(int code) { return diff(code).x; }
254 /** Y-component of diff() */
dY(int code)255 static int dY(int code) { return diff(code).y; }
256
257 /** Transform Diff2D offset into corresponding direction code.
258 The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
259 is not in the 4-neighborhood.
260 */
code(Diff2D const & diff)261 static Direction code(Diff2D const & diff)
262 {
263 switch(diff.x)
264 {
265 case 0:
266 {
267 switch(diff.y)
268 {
269 case 1:
270 return South;
271 case -1:
272 return North;
273 default:
274 return Error;
275 }
276 }
277 case -1:
278 {
279 return (diff.y == 0) ?
280 West :
281 Error;
282 }
283 case 1:
284 {
285 return (diff.y == 0) ?
286 East :
287 Error;
288 }
289 }
290 return Error;
291 }
292
293 /** Check whether a code refers to a diagonal direction.
294 Useful if you want to abstract the differences between 4- and 8-neighborhood.
295 Always <tt>false</tt> for 4-neighborhood.
296 */
isDiagonal(Direction)297 static bool isDiagonal(Direction) { return false; }
298
right()299 static Diff2D const & right() { return diff(East); } /**< Offset to the right neighbor */
top()300 static Diff2D const & top() { return diff(North); } /**< Offset to the top neighbor */
left()301 static Diff2D const & left() { return diff(West); } /**< Offset to the left neighbor */
bottom()302 static Diff2D const & bottom() { return diff(South); } /**< Offset to the bottom neighbor */
303
east()304 static Diff2D const & east() { return diff(East); } /**< Offset to the east neighbor */
north()305 static Diff2D const & north() { return diff(North); } /**< Offset to the north neighbor */
west()306 static Diff2D const & west() { return diff(West); } /**< Offset to the west neighbor */
south()307 static Diff2D const & south() { return diff(South); } /**< Offset to the south neighbor */
308 };
309
310 /** Export NeighborCode::Direction into the scope of namespace FourNeighborhood.
311 */
312 typedef NeighborCode::Direction Direction;
313
314 static const Direction East = NeighborCode::East; /**< Export NeighborCode::East to namespace FourNeighborhood */
315 static const Direction North = NeighborCode::North; /**< Export NeighborCode::North to namespace FourNeighborhood */
316 static const Direction West = NeighborCode::West; /**< Export NeighborCode::West to namespace FourNeighborhood */
317 static const Direction South = NeighborCode::South; /**< Export NeighborCode::South to namespace FourNeighborhood */
318 static const Direction DirectionCount = NeighborCode::DirectionCount; /**< Export NeighborCode::DirectionCount to namespace FourNeighborhood */
319
east()320 inline Diff2D const & east() { return NeighborCode::diff(East); } /**< Offset to the east neighbor */
north()321 inline Diff2D const & north() { return NeighborCode::diff(North); } /**< Offset to the north neighbor */
west()322 inline Diff2D const & west() { return NeighborCode::diff(West); } /**< Offset to the west neighbor */
south()323 inline Diff2D const & south() { return NeighborCode::diff(South); } /**< Offset to the south neighbor */
324
325 } // namespace FourNeighborhood
326
327 /** Export \ref vigra::FourNeighborhood::NeighborCode into the scope of namespace vigra.
328 */
329 typedef FourNeighborhood::NeighborCode FourNeighborCode;
330
331 /********************************************************/
332 /* */
333 /* EightNeighborhood */
334 /* */
335 /********************************************************/
336
337 /** Utilities for 8-neighborhood. */
338 namespace EightNeighborhood
339 {
340 /** \brief Encapsulation of direction management for the 8-neighborhood.
341
342 This helper class allows the transformation between Freeman chain codes
343 (East = 0, NorthEast = 1 etc.) and the corresponding Diff2D instances
344 and back.
345
346 You can either use the chain codes by explicit qualification:
347
348 \code
349 // the following three lines are equivalent
350 EightNeighborhood::NeighborCode::Direction d = EightNeighborhood::NeighborCode::East;
351 EightNeighborCode::Direction d = EightNeighborCode::East;
352 EightNeighborhood::Direction d = EightNeighborhood::East;
353 \endcode
354
355 or you can fix 8-neighborhood by importing the entire namespace in
356 your function:
357
358 \code
359 using namespace EightNeighborhood;
360
361 Direction d = East;
362 \endcode
363
364 If you want to pass 8-neighborhood codes as a template parameter, use
365 the class EightNeighborhood::NeighborCode.
366
367 <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
368 Namespace: vigra::EightNeighborhood
369 */
370 class NeighborCode
371 {
372 public:
373 /** Freeman direction codes for the 8-neighborhood.
374 <tt>East = 0</tt>, <tt>North = 1</tt> etc.
375 <tt>DirectionCount</tt> may be used for portable loop termination conditions.
376 <tt>CausalFirst</tt> and <tt>CausalLast</tt> are the first and last (inclusive)
377 neighbors in the causal neighborhood, i.e. in the set of neighbors that have
378 already been visited when the image is traversed in scan order.
379 <tt>AntiCausalFirst</tt> and <tt>AntiCausalLast</tt> are the opposite.
380 */
381 enum Direction {
382 Error = -1, ///<
383 East = 0, ///<
384 NorthEast, ///<
385 North, ///<
386 NorthWest, ///<
387 West, ///<
388 SouthWest, ///<
389 South, ///<
390 SouthEast, ///<
391 DirectionCount, ///<
392 CausalFirst = NorthEast, ///<
393 CausalLast = West, ///<
394 AntiCausalFirst = SouthWest, ///<
395 AntiCausalLast = East ///<
396 };
397
directionBit(Direction d)398 static unsigned int directionBit(Direction d)
399 {
400 static unsigned int b[] = {1 << (East + 1),
401 1 << (NorthEast + 1),
402 1 << (North + 1),
403 1 << (NorthWest + 1),
404 1 << (West + 1),
405 1 << (SouthWest + 1),
406 1 << (South + 1),
407 1 << (SouthEast + 1)};
408 return b[d];
409 };
410
411 /** The number of valid neighbors if the current center is at the image border.
412 */
nearBorderDirectionCount(AtImageBorder b)413 static unsigned int nearBorderDirectionCount(AtImageBorder b)
414 {
415 static unsigned int c[] = { 8, 5, 5, 0, 5, 3, 3, 0, 5, 3, 3};
416 return c[b];
417 }
418
419 /** The valid direction codes when the center is at the image border.
420 \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1</tt>.
421 */
nearBorderDirections(AtImageBorder b,int index)422 static Direction nearBorderDirections(AtImageBorder b, int index)
423 {
424 static Direction c[11][8] = {
425 { East, NorthEast, North, NorthWest, West, SouthWest, South, SouthEast},
426 { North, NorthWest, West, SouthWest, South, Error, Error, Error},
427 { East, NorthEast, North, South, SouthEast, Error, Error, Error},
428 { Error, Error, Error, Error, Error, Error, Error, Error},
429 { East, West, SouthWest, South, SouthEast, Error, Error, Error},
430 { West, SouthWest, South, Error, Error, Error, Error, Error},
431 { East, South, SouthEast, Error, Error, Error, Error, Error},
432 { Error, Error, Error, Error, Error, Error, Error, Error},
433 { East, NorthEast, North, NorthWest, West, Error, Error, Error},
434 { North, NorthWest, West, Error, Error, Error, Error, Error},
435 { East, NorthEast, North, Error, Error, Error, Error, Error}
436 };
437 return c[b][index];
438 }
439
440 /** Transform direction code into corresponding Diff2D offset.
441 (note: there is no bounds checking on the code you pass.)
442 */
diff(Direction code)443 static Diff2D const & diff(Direction code)
444 {
445 static Diff2D d[] = {
446 Diff2D(1, 0), Diff2D(1, -1), Diff2D(0, -1), Diff2D(-1, -1),
447 Diff2D(-1, 0), Diff2D(-1, 1), Diff2D(0, 1), Diff2D(1, 1)
448 };
449 return d[code];
450 }
451
452 /** Equivalent to diff(static_cast<Direction>(code)).
453 (note: there is no bounds checking on the code you pass.)
454 */
diff(int code)455 static Diff2D const & diff(int code) { return diff(static_cast<Direction>(code)); }
456
457 /** Get the relative offset from one neighbor to the other.
458 For example, <tt>relativeDiff(East, West) == Diff2D(-2,0)</tt>.
459 (note: there is no bounds checking on the code you pass.)
460 */
relativeDiff(Direction fromCode,Direction toCode)461 static Diff2D const & relativeDiff(Direction fromCode, Direction toCode)
462 {
463 static Diff2D d[][8] = {
464 { Diff2D(0, 0), Diff2D(0, -1), Diff2D(-1, -1), Diff2D(-2, -1),
465 Diff2D(-2, 0), Diff2D(-2, 1), Diff2D(-1, 1), Diff2D(0, 1) },
466 { Diff2D(0, 1), Diff2D(0, 0), Diff2D(-1, 0), Diff2D(-2, 0),
467 Diff2D(-2, 1), Diff2D(-2, 2), Diff2D(-1, 2), Diff2D(0, 2) },
468 { Diff2D(1, 1), Diff2D(1, 0), Diff2D(0, 0), Diff2D(-1, 0),
469 Diff2D(-1, 1), Diff2D(-1, 2), Diff2D(0, 2), Diff2D(1, 2) },
470 { Diff2D(2, 1), Diff2D(2, 0), Diff2D(1, 0), Diff2D(0, 0),
471 Diff2D(0, 1), Diff2D(0, 2), Diff2D(1, 2), Diff2D(2, 2) },
472 { Diff2D(2, 0), Diff2D(2, -1), Diff2D(1, -1), Diff2D(0, -1),
473 Diff2D(0, 0), Diff2D(0, 1), Diff2D(1, 1), Diff2D(2, 1) },
474 { Diff2D(2, -1), Diff2D(2, -2), Diff2D(1, -2), Diff2D(0, -2),
475 Diff2D(0, -1), Diff2D(0, 0), Diff2D(1, 0), Diff2D(2, 0) },
476 { Diff2D(1, -1), Diff2D(1, -2), Diff2D(0, -2), Diff2D(-1, -2),
477 Diff2D(-1, -1), Diff2D(-1, 0), Diff2D(0, 0), Diff2D(1, 0) },
478 { Diff2D(0, -1), Diff2D(0, -2), Diff2D(-1, -2), Diff2D(-2, -2),
479 Diff2D(-2, -1), Diff2D(-2, 0), Diff2D(-1, 0), Diff2D(0, 0) }
480 };
481
482 return d[fromCode][toCode];
483 }
484
485 /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode)).
486 (note: there is no bounds checking on the code you pass.)
487 */
relativeDiff(int fromCode,int toCode)488 static Diff2D const & relativeDiff(int fromCode, int toCode)
489 {
490 return relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode));
491 }
492
493 /** X-component of diff() */
dX(Direction code)494 static int dX(Direction code) { return diff(code).x; }
495 /** Y-component of diff() */
dY(Direction code)496 static int dY(Direction code) { return diff(code).y; }
497 /** X-component of diff() */
dX(int code)498 static int dX(int code) { return diff(code).x; }
499 /** Y-component of diff() */
dY(int code)500 static int dY(int code) { return diff(code).y; }
501
502 /** Transform 4-neighborhood code into 8-neighborhood code.
503 */
code(FourNeighborhood::Direction d)504 static Direction code(FourNeighborhood::Direction d)
505 { return static_cast<Direction>(2*d); }
506
507 /** Transform Diff2D offset into corresponding direction code.
508 The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
509 is not in the 8-neighborhood.
510 */
code(Diff2D const & diff)511 static Direction code(Diff2D const & diff)
512 {
513 switch(diff.x)
514 {
515 case 0:
516 {
517 switch(diff.y)
518 {
519 case 1:
520 return South;
521 case -1:
522 return North;
523 default:
524 return Error;
525 }
526 }
527 case -1:
528 {
529 switch(diff.y)
530 {
531 case 0:
532 return West;
533 case 1:
534 return SouthWest;
535 case -1:
536 return NorthWest;
537 default:
538 return Error;
539 }
540 }
541 case 1:
542 {
543 switch(diff.y)
544 {
545 case 0:
546 return East;
547 case 1:
548 return SouthEast;
549 case -1:
550 return NorthEast;
551 default:
552 return Error;
553 }
554 }
555 }
556 return Error;
557 }
558
559 /** Check whether a code refers to a diagonal direction.
560 Useful if you want to abstract the differences between 4- and 8-neighborhood.
561 */
isDiagonal(Direction code)562 static bool isDiagonal(Direction code) { return (code % 2) != 0; }
563
right()564 static Diff2D const & right() { return diff(East); } /**< Offset to the right neighbor */
topRight()565 static Diff2D const & topRight() { return diff(NorthEast); } /**< Offset to the topRight neighbor */
top()566 static Diff2D const & top() { return diff(North); } /**< Offset to the top neighbor */
topLeft()567 static Diff2D const & topLeft() { return diff(NorthWest); } /**< Offset to the topLeft neighbor */
left()568 static Diff2D const & left() { return diff(West); } /**< Offset to the left neighbor */
bottomLeft()569 static Diff2D const & bottomLeft() { return diff(SouthWest); } /**< Offset to the bottomLeft neighbor */
bottom()570 static Diff2D const & bottom() { return diff(South); } /**< Offset to the bottom neighbor */
bottomRight()571 static Diff2D const & bottomRight() { return diff(SouthEast); } /**< Offset to the bottomRight neighbor */
572
east()573 static Diff2D const & east() { return diff(East); } /**< Offset to the east neighbor */
northEast()574 static Diff2D const & northEast() { return diff(NorthEast); } /**< Offset to the northEast neighbor */
north()575 static Diff2D const & north() { return diff(North); } /**< Offset to the north neighbor */
northWest()576 static Diff2D const & northWest() { return diff(NorthWest); } /**< Offset to the northWest neighbor */
west()577 static Diff2D const & west() { return diff(West); } /**< Offset to the west neighbor */
southWest()578 static Diff2D const & southWest() { return diff(SouthWest); } /**< Offset to the southWest neighbor */
south()579 static Diff2D const & south() { return diff(South); } /**< Offset to the south neighbor */
southEast()580 static Diff2D const & southEast() { return diff(SouthEast); } /**< Offset to the southEast neighbor */
581 };
582
583 /** Export NeighborCode::Direction into the scope of namespace EightNeighborhood.
584 */
585 typedef NeighborCode::Direction Direction;
586
587 static const Direction East = NeighborCode::East; /**< Export NeighborCode::East to namespace EightNeighborhood */
588 static const Direction NorthEast = NeighborCode::NorthEast; /**< Export NeighborCode::NorthEast to namespace EightNeighborhood */
589 static const Direction North = NeighborCode::North; /**< Export NeighborCode::North to namespace EightNeighborhood */
590 static const Direction NorthWest = NeighborCode::NorthWest; /**< Export NeighborCode::NorthWest to namespace EightNeighborhood */
591 static const Direction West = NeighborCode::West; /**< Export NeighborCode::West to namespace EightNeighborhood */
592 static const Direction SouthWest = NeighborCode::SouthWest; /**< Export NeighborCode::SouthWest to namespace EightNeighborhood */
593 static const Direction South = NeighborCode::South; /**< Export NeighborCode::South to namespace EightNeighborhood */
594 static const Direction SouthEast = NeighborCode::SouthEast; /**< Export NeighborCode::SouthEast to namespace EightNeighborhood */
595 static const Direction DirectionCount = NeighborCode::DirectionCount; /**< Export NeighborCode::DirectionCount to namespace EightNeighborhood */
596
east()597 inline Diff2D const & east() { return NeighborCode::diff(East); } /**< Offset to the east neighbor */
northEast()598 inline Diff2D const & northEast() { return NeighborCode::diff(NorthEast); } /**< Offset to the northEast neighbor */
north()599 inline Diff2D const & north() { return NeighborCode::diff(North); } /**< Offset to the north neighbor */
northWest()600 inline Diff2D const & northWest() { return NeighborCode::diff(NorthWest); } /**< Offset to the northWest neighbor */
west()601 inline Diff2D const & west() { return NeighborCode::diff(West); } /**< Offset to the west neighbor */
southWest()602 inline Diff2D const & southWest() { return NeighborCode::diff(SouthWest); } /**< Offset to the southWest neighbor */
south()603 inline Diff2D const & south() { return NeighborCode::diff(South); } /**< Offset to the south neighbor */
southEast()604 inline Diff2D const & southEast() { return NeighborCode::diff(SouthEast); } /**< Offset to the southEast neighbor */
605
606 } // namespace EightNeighborhood
607
608 /** Export \ref vigra::EightNeighborhood::NeighborCode into the scope of namespace vigra.
609 */
610 typedef EightNeighborhood::NeighborCode EightNeighborCode;
611
612 /********************************************************/
613 /* */
614 /* NeighborOffsetCirculator */
615 /* */
616 /********************************************************/
617
618 /** \brief Circulator that walks around a given location.
619
620 The template parameter defines the kind of neighborhood used, e.g.
621
622 \code
623 NeighborOffsetCirculator<EightNeighborCode> eight_circulator;
624 NeighborOffsetCirculator<FourNeighborCode> four_circulator;
625 \endcode
626
627 Since this circulator doesn't now about the pixels in any particular image,
628 you usually doesn't use it directly but rather as a base class or helper for
629 neighborhood circulators refering to a particular image (e.g. NeighborhoodCirculator)
630
631 <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
632 Namespace: vigra
633 */
634 template<class NEIGHBORCODE>
635 class NeighborOffsetCirculator
636 : public NEIGHBORCODE
637 {
638 public:
639 typedef NEIGHBORCODE NeighborCode;
640
641 /** return type of direction()
642 */
643 typedef typename NEIGHBORCODE::Direction Direction;
644
645 /** the circulator's value type
646 */
647 typedef Diff2D value_type;
648
649 /** the circulator's reference type (return type of <TT>*circ</TT>)
650 */
651 typedef Diff2D const & reference;
652
653 /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
654 */
655 typedef Diff2D const & index_reference;
656
657 /** the circulator's pointer type (return type of <TT>operator-></TT>)
658 */
659 typedef Diff2D const * pointer;
660
661 /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
662 */
663 typedef int difference_type;
664
665 /** the circulator tag (random access iterator)
666 */
667 typedef random_access_circulator_tag iterator_category;
668
669 protected:
670 Direction direction_;
671
672 public:
673 /** Create circulator refering to the given direction.
674 */
NeighborOffsetCirculator(Direction dir=NEIGHBORCODE::East)675 NeighborOffsetCirculator(Direction dir = NEIGHBORCODE::East)
676 : direction_(dir)
677 {
678 }
679
680 /** pre-increment */
operator ++()681 NeighborOffsetCirculator & operator++()
682 {
683 direction_ = static_cast<Direction>((direction_+1) % NEIGHBORCODE::DirectionCount);
684 return *this;
685 }
686
687 /** pre-decrement */
operator --()688 NeighborOffsetCirculator & operator--()
689 {
690 direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::DirectionCount-1) % NEIGHBORCODE::DirectionCount);
691 return *this;
692 }
693
694 /** post-increment */
operator ++(int)695 NeighborOffsetCirculator operator++(int)
696 {
697 NeighborOffsetCirculator ret(*this);
698 operator++();
699 return ret;
700 }
701
702 /** post-decrement */
operator --(int)703 NeighborOffsetCirculator operator--(int)
704 {
705 NeighborOffsetCirculator ret(*this);
706 operator--();
707 return ret;
708 }
709
710 /** add-assignment */
operator +=(difference_type d)711 NeighborOffsetCirculator & operator+=(difference_type d)
712 {
713 direction_ = static_cast<Direction>((direction_ + d) % NEIGHBORCODE::DirectionCount);
714 if(direction_ < 0)
715 direction_ = static_cast<Direction>(direction_ + NEIGHBORCODE::DirectionCount);
716 return *this;
717 }
718
719 /** subtract-assignment */
operator -=(difference_type d)720 NeighborOffsetCirculator & operator-=(difference_type d)
721 {
722 direction_ = static_cast<Direction>((direction_ - d) % NEIGHBORCODE::DirectionCount);
723 if(direction_ < 0)
724 direction_ = static_cast<Direction>(direction_ + NEIGHBORCODE::DirectionCount);
725 return *this;
726 }
727
728 /** addition */
operator +(difference_type d) const729 NeighborOffsetCirculator operator+(difference_type d) const
730 {
731 return NeighborOffsetCirculator(*this) += d;
732 }
733
734 /** subtraction */
operator -(difference_type d) const735 NeighborOffsetCirculator operator-(difference_type d) const
736 {
737 return NeighborOffsetCirculator(*this) -= d;
738 }
739
740 /** Move to the direction that is 'right' relative to the current direction.
741 This is equivalent to <tt>four_circulator--</tt> and
742 <tt>eight_circulator -= 2</tt> respectively.
743 */
turnRight()744 NeighborOffsetCirculator & turnRight()
745 {
746 direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::South) % NEIGHBORCODE::DirectionCount);
747 return *this;
748 }
749
750 /** Move to the direction that is 'left' relative to the current direction.
751 This is equivalent to <tt>four_circulator++</tt> and
752 <tt>eight_circulator += 2</tt> respectively.
753 */
turnLeft()754 NeighborOffsetCirculator & turnLeft()
755 {
756 direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::North) % NEIGHBORCODE::DirectionCount);
757 return *this;
758 }
759
760 /** Move to the opposite direction of the current direction.
761 This is equivalent to <tt>four_circulator += 2</tt> and
762 <tt>eight_circulator += 4</tt> respectively.
763 */
turnRound()764 NeighborOffsetCirculator & turnRound()
765 {
766 direction_ = opposite();
767 return *this;
768 }
769
770 /** Move to the given direction.
771 */
turnTo(Direction d)772 NeighborOffsetCirculator & turnTo(Direction d)
773 {
774 direction_ = d;
775 return *this;
776 }
777
778 /** equality */
operator ==(NeighborOffsetCirculator const & o) const779 bool operator==(NeighborOffsetCirculator const & o) const
780 {
781 return direction_ == o.direction_;
782 }
783
784 /** unequality */
operator !=(NeighborOffsetCirculator const & o) const785 bool operator!=(NeighborOffsetCirculator const & o) const
786 {
787 return direction_ != o.direction_;
788 }
789
790 /** subtraction */
operator -(NeighborOffsetCirculator const & o) const791 difference_type operator-(NeighborOffsetCirculator const & o) const
792 {
793 return direction_ - o.direction_;
794 }
795
796 /** dereference */
operator *() const797 reference operator*() const
798 {
799 return diff();
800 }
801
802 /** index */
operator [](difference_type d) const803 index_reference operator[](difference_type d) const
804 {
805 return NEIGHBORCODE::diff(direction(d));
806 }
807
808 /** member access */
operator ->() const809 pointer operator->() const
810 {
811 return &diff();
812 }
813
814 /** Get Diff2D offset from center to current neighbor.
815 */
diff() const816 Diff2D const & diff() const
817 {
818 return NEIGHBORCODE::diff(direction_);
819 }
820
821 /** Get Diff2D offset to given direction.
822 */
diff(Direction dir)823 static Diff2D const & diff(Direction dir)
824 {
825 return NEIGHBORCODE::diff(dir);
826 }
827
828 /** Get relative distance (Diff2D) from current neighbor to neighbor
829 at given offset.
830 */
relativeDiff(difference_type offset) const831 Diff2D const &relativeDiff(difference_type offset) const
832 {
833 Direction toDir = static_cast<Direction>((direction_ + offset) % NEIGHBORCODE::DirectionCount);
834 if(toDir < 0)
835 toDir = static_cast<Direction>(toDir + NEIGHBORCODE::DirectionCount);
836 return NEIGHBORCODE::relativeDiff(direction_, toDir);
837 }
838
839 /** X-component of diff() */
dX() const840 int dX() const
841 {
842 return NEIGHBORCODE::dX(direction_);
843 }
844
845 /** Y-component of diff() */
dY() const846 int dY() const
847 {
848 return NEIGHBORCODE::dY(direction_);
849 }
850
851 /** Check whether current direction is a diagonal one.
852 */
isDiagonal() const853 bool isDiagonal() const
854 {
855 return NEIGHBORCODE::isDiagonal(direction_);
856 }
857
858 /** Get current direction.
859 */
direction() const860 Direction direction() const
861 {
862 return direction_;
863 }
864
865 /** Get current direction bit.
866 */
directionBit() const867 unsigned int directionBit() const
868 {
869 return NEIGHBORCODE::directionBit(direction_);
870 }
871
872 /** Get opposite of current direction.
873 */
opposite() const874 Direction opposite() const
875 {
876 return static_cast<Direction>((direction_ + NEIGHBORCODE::West) % NEIGHBORCODE::DirectionCount);
877 }
878
879 /** Get opposite bit of current direction.
880 */
oppositeDirectionBit() const881 unsigned int oppositeDirectionBit() const
882 {
883 return NEIGHBORCODE::directionBit(opposite());
884 }
885
886 /** Get direction code at offset of current direction.
887 */
direction(difference_type offset) const888 Direction direction(difference_type offset) const
889 {
890 int result = (direction_ + offset) % NEIGHBORCODE::DirectionCount;
891 if(result < 0)
892 result += NEIGHBORCODE::DirectionCount;
893 return static_cast<Direction>(result);
894 }
895 };
896
897 /** Specialization of NeighborOffsetCirculator for 8-neighborhood.
898 */
899 typedef NeighborOffsetCirculator<EightNeighborCode> EightNeighborOffsetCirculator;
900
901 /** Specialization of NeighborOffsetCirculator for 4-neighborhood.
902 */
903 typedef NeighborOffsetCirculator<FourNeighborCode> FourNeighborOffsetCirculator;
904
905
906 //@}
907
908 /** \addtogroup ImageIteratorAdapters
909 */
910 //@{
911
912 /********************************************************/
913 /* */
914 /* NeighborhoodCirculator */
915 /* */
916 /********************************************************/
917
918 /** \brief Circulator that walks around a given location in a given image.
919
920 The template parameters define the kind of neighborhood used and the underlying
921 image. The access functions return the value of the current neighbor pixel.
922 Use <tt>center()</tt> to access the center pixel of the neighborhood.
923 The center can be changed by calling <tt>moveCenterToNeighbor()</tt>
924 or <tt>swapCenterNeighbor()</tt>. Note that this circulator cannot
925 when the center is at the image border. You must then use
926 \ref vigra::RestrictedNeighborhoodCirculator
927
928 <b>Usage:</b><br>
929
930 <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
931 Namespace: vigra
932
933 \code
934 BImage::traverser upperleft(...), lowerright(...);
935
936 int width = lowerright.x - upperleft.x;
937 int height = lowerright.y - upperleft.y;
938
939 ++upperleft.y; // avoid image border
940 for(int y=1; y<height-1; ++y, ++upperleft.y)
941 {
942 BImage::traverser ix = upperleft + Diff2D(1,0);
943 for(int x=1; x<width-1; ++x, ++ix.x)
944 {
945 // analyse all neighbors of a pixel (use FourNeighborCode
946 // instead of EightNeighborCode for 4-neighborhood):
947 NeighborhoodCirculator<BImage::traverser, EightNeighborCode>
948 circulator(ix),
949 end(circulator);
950 do
951 {
952 analysisFunc(*circulator, ...); // do sth. with current neighbor
953 }
954 while(++circulator != end); // compare with start/end circulator
955 }
956 }
957 \endcode
958 */
959 template <class IMAGEITERATOR, class NEIGHBORCODE>
960 class NeighborhoodCirculator : private IMAGEITERATOR
961 {
962 typedef NeighborOffsetCirculator<NEIGHBORCODE> NEIGHBOROFFSETCIRCULATOR;
963
964 public:
965 /** type of the underlying image iterator
966 */
967 typedef IMAGEITERATOR base_type;
968
969 /** type of the used neighbor code
970 */
971 typedef NEIGHBORCODE NeighborCode;
972
973 /** the circulator's value type
974 */
975 typedef typename IMAGEITERATOR::value_type value_type;
976
977 /** type of the direction code
978 */
979 typedef typename NEIGHBORCODE::Direction Direction;
980
981 /** the circulator's reference type (return type of <TT>*circ</TT>)
982 */
983 typedef typename IMAGEITERATOR::reference reference;
984
985 /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
986 */
987 typedef typename IMAGEITERATOR::index_reference index_reference;
988
989 /** the circulator's pointer type (return type of <TT>operator-></TT>)
990 */
991 typedef typename IMAGEITERATOR::pointer pointer;
992
993 /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
994 */
995 typedef typename NEIGHBOROFFSETCIRCULATOR::difference_type difference_type;
996
997 /** the circulator tag (random_access_circulator_tag)
998 */
999 typedef typename NEIGHBOROFFSETCIRCULATOR::iterator_category iterator_category;
1000
1001 /** Construct circulator with given <tt>center</tt> pixel, pointing to the neighbor
1002 at the given direction <tt>d</tt>.
1003 */
NeighborhoodCirculator(IMAGEITERATOR const & center=IMAGEITERATOR (),Direction d=NEIGHBOROFFSETCIRCULATOR::East)1004 NeighborhoodCirculator(IMAGEITERATOR const & center = IMAGEITERATOR(),
1005 Direction d = NEIGHBOROFFSETCIRCULATOR::East)
1006 : IMAGEITERATOR(center), neighborCode_(d)
1007 {
1008 IMAGEITERATOR::operator+=(neighborCode_.diff());
1009 }
1010
1011 /** pre-increment */
operator ++()1012 NeighborhoodCirculator & operator++()
1013 {
1014 return operator+=(1);
1015 }
1016
1017 /** pre-decrement */
operator ++(int)1018 NeighborhoodCirculator operator++(int)
1019 {
1020 NeighborhoodCirculator ret(*this);
1021 operator++();
1022 return ret;
1023 }
1024
1025 /** post-increment */
operator --()1026 NeighborhoodCirculator & operator--()
1027 {
1028 return operator+=(-1);
1029 }
1030
1031 /** post-decrement */
operator --(int)1032 NeighborhoodCirculator operator--(int)
1033 {
1034 NeighborhoodCirculator ret(*this);
1035 operator--();
1036 return ret;
1037 }
1038
1039 /** add-assignment */
operator +=(difference_type d)1040 NeighborhoodCirculator & operator+=(difference_type d)
1041 {
1042 IMAGEITERATOR::operator+=(neighborCode_.relativeDiff(d));
1043 neighborCode_+= d;
1044 return *this;
1045 }
1046
1047 /** subtract-assignment */
operator -=(difference_type d)1048 NeighborhoodCirculator & operator-=(difference_type d)
1049 {
1050 return operator+=(-d);
1051 }
1052
1053 /** addition */
operator +(difference_type d) const1054 NeighborhoodCirculator operator+(difference_type d) const
1055 {
1056 NeighborhoodCirculator result(*this);
1057 result+= d;
1058 return result;
1059 }
1060
1061 /** subtraction */
operator -(difference_type d) const1062 NeighborhoodCirculator operator-(difference_type d) const
1063 {
1064 NeighborhoodCirculator result(*this);
1065 result-= d;
1066 return result;
1067 }
1068
1069 /** Move to the direction that is 'right' relative to the current direction.
1070 This is equivalent to <tt>four_circulator--</tt> and
1071 <tt>eight_circulator -= 2</tt> respectively.
1072 */
turnRight()1073 NeighborhoodCirculator & turnRight()
1074 {
1075 Direction oldDirection = neighborCode_.direction();
1076 neighborCode_.turnRight();
1077 IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1078 (oldDirection, neighborCode_.direction()));
1079 return *this;
1080 }
1081
1082 /** Move to the direction that is 'left' relative to the current direction.
1083 This is equivalent to <tt>four_circulator++</tt> and
1084 <tt>eight_circulator += 2</tt> respectively.
1085 */
turnLeft()1086 NeighborhoodCirculator & turnLeft()
1087 {
1088 Direction oldDirection = neighborCode_.direction();
1089 neighborCode_.turnLeft();
1090 IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1091 (oldDirection, neighborCode_.direction()));
1092 return *this;
1093 }
1094
1095 /** Move to the opposite direction of the current direction.
1096 This is equivalent to <tt>four_circulator += 2</tt> and
1097 <tt>eight_circulator += 4</tt> respectively.
1098 */
turnRound()1099 NeighborhoodCirculator & turnRound()
1100 {
1101 Direction oldDirection = neighborCode_.direction();
1102 neighborCode_.turnRound();
1103 IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1104 (oldDirection, neighborCode_.direction()));
1105 return *this;
1106 }
1107
1108 /** Move to the given direction.
1109 */
turnTo(Direction d)1110 NeighborhoodCirculator & turnTo(Direction d)
1111 {
1112 Direction oldDirection = neighborCode_.direction();
1113 neighborCode_.turnTo(d);
1114 IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1115 (oldDirection, neighborCode_.direction()));
1116 return *this;
1117 }
1118
1119 /** Move the center in the current direction.
1120 The current neighbor becomes the new center, the direction does not change.
1121 */
moveCenterToNeighbor()1122 NeighborhoodCirculator & moveCenterToNeighbor()
1123 {
1124 IMAGEITERATOR::operator+=(neighborCode_.diff());
1125 return *this;
1126 }
1127
1128 /** Exchange the center with the current neighbor.
1129 Equivalent to <tt>circ.moveCenterToNeighbor().turnRound()</tt>
1130 (but shorter and more efficient).
1131 */
swapCenterNeighbor()1132 NeighborhoodCirculator & swapCenterNeighbor()
1133 {
1134 neighborCode_.turnRound();
1135 IMAGEITERATOR::operator+=(neighborCode_.diff());
1136 return *this;
1137 }
1138
1139 /** equality */
operator ==(NeighborhoodCirculator const & rhs) const1140 bool operator==(NeighborhoodCirculator const & rhs) const
1141 {
1142 return neighborCode_ == rhs.neighborCode_ &&
1143 IMAGEITERATOR::operator==(rhs);
1144 }
1145
1146 /** inequality */
operator !=(NeighborhoodCirculator const & rhs) const1147 bool operator!=(NeighborhoodCirculator const & rhs) const
1148 {
1149 return neighborCode_ != rhs.neighborCode_ ||
1150 IMAGEITERATOR::operator!=(rhs);
1151 }
1152
1153 /** subtraction */
operator -(NeighborhoodCirculator const & rhs) const1154 difference_type operator-(NeighborhoodCirculator const & rhs) const
1155 {
1156 return neighborCode_ - rhs.neighborCode_;
1157 }
1158
1159 /** dereference */
operator *() const1160 reference operator*() const
1161 {
1162 return IMAGEITERATOR::operator*();
1163 }
1164
1165 /** index */
operator [](difference_type d) const1166 index_reference operator[](difference_type d) const
1167 {
1168 return IMAGEITERATOR::operator[](neighborCode_.relativeDiff(d));
1169 }
1170
1171 /** member access */
operator ->() const1172 pointer operator->() const
1173 {
1174 return IMAGEITERATOR::operator->();
1175 }
1176
1177 /** Get the base iterator for the current neighbor. */
base() const1178 base_type const & base() const
1179 {
1180 return *this;
1181 }
1182
1183 /** Get the base iterator for the center of the circulator. */
center() const1184 base_type center() const
1185 {
1186 return (base_type)*this - neighborCode_.diff();
1187 }
1188
1189 /** Get the current direction. */
direction() const1190 Direction direction() const
1191 {
1192 return neighborCode_.direction();
1193 }
1194
1195 /** Get the current direction bit. */
directionBit() const1196 unsigned int directionBit() const
1197 {
1198 return neighborCode_.directionBit();
1199 }
1200
1201 /** Get the difference vector (Diff2D) from the center to the current neighbor. */
diff() const1202 Diff2D const & diff() const
1203 {
1204 return neighborCode_.diff();
1205 }
1206
1207 /** Is the current neighbor a diagonal neighbor? */
isDiagonal() const1208 bool isDiagonal() const
1209 {
1210 return neighborCode_.isDiagonal();
1211 }
1212
1213 private:
1214 NEIGHBOROFFSETCIRCULATOR neighborCode_;
1215 };
1216
1217 /********************************************************/
1218 /* */
1219 /* RestrictedNeighborhoodCirculator */
1220 /* */
1221 /********************************************************/
1222
1223 /** \brief Circulator that walks around a given location in a given image,
1224 unsing a restricted neighborhood.
1225
1226 This circulator behaves essentially like \ref vigra::NeighborhoodCirculator,
1227 but can also be used near the image border, where some of the neighbor points
1228 would be outside the image und must not be accessed.
1229 The template parameters define the kind of neighborhood used (four or eight)
1230 and the underlying image, whereas the required neighbirhood restriction is
1231 given by the last constructur argument. This below for typical usage.
1232
1233 The access functions return the value of the current neighbor pixel. Use <tt>center()</tt> to
1234 access the center pixel of the neighborhood.
1235
1236 <b>Usage:</b><br>
1237
1238 <b>\#include</b> "<a href="pixelneighborhood_8hxx-source.html">vigra/pixelneighborhood.hxx</a>"<br>
1239 Namespace: vigra
1240
1241 \code
1242 BImage::traverser upperleft(...), lowerright(...);
1243
1244 int width = lowerright.x - upperleft.x;
1245 int height = lowerright.y - upperleft.y;
1246
1247 for(int y=0; y<height; ++y, ++upperleft.y)
1248 {
1249 BImage::traverser ix = upperleft;
1250 for(int x=0; x<width; ++x, ++ix.x)
1251 {
1252 // use FourNeighborCode instead of EightNeighborCode for 4-neighborhood
1253 RestrictedNeighborhoodCirculator<BImage::traverser, EightNeighborCode>
1254 circulator(ix, isAtImageBorder(x, y, width, height)),
1255 end(circulator);
1256 do
1257 {
1258 ... // do something with the circulator
1259 }
1260 while(++circulator != end); // out-of-range pixels will be automatically skipped
1261 }
1262 }
1263 \endcode
1264 */
1265 template <class IMAGEITERATOR, class NEIGHBORCODE>
1266 class RestrictedNeighborhoodCirculator
1267 : private NeighborhoodCirculator<IMAGEITERATOR, NEIGHBORCODE>
1268 {
1269 typedef NeighborhoodCirculator<IMAGEITERATOR, NEIGHBORCODE> BaseType;
1270
1271 public:
1272 /** type of the underlying image iterator
1273 */
1274 typedef IMAGEITERATOR base_type;
1275
1276 /** type of the used neighbor code
1277 */
1278 typedef NEIGHBORCODE NeighborCode;
1279
1280 /** the circulator's value type
1281 */
1282 typedef typename BaseType::value_type value_type;
1283
1284 /** type of the direction code
1285 */
1286 typedef typename BaseType::Direction Direction;
1287
1288 /** the circulator's reference type (return type of <TT>*circ</TT>)
1289 */
1290 typedef typename BaseType::reference reference;
1291
1292 /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
1293 */
1294 typedef typename BaseType::index_reference index_reference;
1295
1296 /** the circulator's pointer type (return type of <TT>operator-></TT>)
1297 */
1298 typedef typename BaseType::pointer pointer;
1299
1300 /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
1301 */
1302 typedef typename BaseType::difference_type difference_type;
1303
1304 /** the circulator tag (random_access_circulator_tag)
1305 */
1306 typedef typename BaseType::iterator_category iterator_category;
1307
1308 /** Construct circulator with given <tt>center</tt> pixel, using the restricted
1309 neighborhood given by \a atBorder.
1310 */
RestrictedNeighborhoodCirculator(IMAGEITERATOR const & center=IMAGEITERATOR (),AtImageBorder atBorder=NotAtBorder)1311 RestrictedNeighborhoodCirculator(IMAGEITERATOR const & center = IMAGEITERATOR(),
1312 AtImageBorder atBorder = NotAtBorder)
1313 : BaseType(center, NEIGHBORCODE::nearBorderDirections(atBorder, 0)),
1314 whichBorder_(atBorder),
1315 count_(NEIGHBORCODE::nearBorderDirectionCount(atBorder)),
1316 current_(0)
1317 {}
1318
1319 /** pre-increment */
operator ++()1320 RestrictedNeighborhoodCirculator & operator++()
1321 {
1322 return operator+=(1);
1323 }
1324
1325 /** pre-decrement */
operator ++(int)1326 RestrictedNeighborhoodCirculator operator++(int)
1327 {
1328 RestrictedNeighborhoodCirculator ret(*this);
1329 operator++();
1330 return ret;
1331 }
1332
1333 /** post-increment */
operator --()1334 RestrictedNeighborhoodCirculator & operator--()
1335 {
1336 return operator+=(-1);
1337 }
1338
1339 /** post-decrement */
operator --(int)1340 RestrictedNeighborhoodCirculator operator--(int)
1341 {
1342 RestrictedNeighborhoodCirculator ret(*this);
1343 operator--();
1344 return ret;
1345 }
1346
1347 /** add-assignment */
operator +=(difference_type d)1348 RestrictedNeighborhoodCirculator & operator+=(difference_type d)
1349 {
1350 current_ = static_cast<Direction>((current_ + count_ + d) % count_);
1351 BaseType::turnTo(NEIGHBORCODE::nearBorderDirections(whichBorder_, current_));
1352 return *this;
1353 }
1354
1355 /** subtract-assignment */
operator -=(difference_type d)1356 RestrictedNeighborhoodCirculator & operator-=(difference_type d)
1357 {
1358 return operator+=(-d);
1359 }
1360
1361 /** addition */
operator +(difference_type d) const1362 RestrictedNeighborhoodCirculator operator+(difference_type d) const
1363 {
1364 RestrictedNeighborhoodCirculator result(*this);
1365 result+= d;
1366 return result;
1367 }
1368
1369 /** subtraction */
operator -(difference_type d) const1370 RestrictedNeighborhoodCirculator operator-(difference_type d) const
1371 {
1372 RestrictedNeighborhoodCirculator result(*this);
1373 result-= d;
1374 return result;
1375 }
1376
1377 /** equality */
operator ==(RestrictedNeighborhoodCirculator const & rhs) const1378 bool operator==(RestrictedNeighborhoodCirculator const & rhs) const
1379 {
1380 return current_ == rhs.current_;
1381 }
1382
1383 /** inequality */
operator !=(RestrictedNeighborhoodCirculator const & rhs) const1384 bool operator!=(RestrictedNeighborhoodCirculator const & rhs) const
1385 {
1386 return current_ != rhs.current_;
1387 }
1388
1389 /** subtraction */
operator -(RestrictedNeighborhoodCirculator const & rhs) const1390 difference_type operator-(RestrictedNeighborhoodCirculator const & rhs) const
1391 {
1392 return (current_ - rhs.current_) % count_;
1393 }
1394
1395 /** dereference */
operator *() const1396 reference operator*() const
1397 {
1398 return BaseType::operator*();
1399 }
1400
1401 /** member access */
operator ->() const1402 pointer operator->() const
1403 {
1404 return BaseType::operator->();
1405 }
1406
1407 /** Get the base iterator for the current neighbor. */
base() const1408 base_type const & base() const
1409 {
1410 return BaseType::base();
1411 }
1412
1413 /** Get the base iterator for the center of the circulator. */
center() const1414 base_type center() const
1415 {
1416 return BaseType::center();
1417 }
1418
1419 /** Get the current direction. */
direction() const1420 Direction direction() const
1421 {
1422 return BaseType::direction();
1423 }
1424
1425 /** Get the current direction bit. */
directionBit() const1426 unsigned int directionBit() const
1427 {
1428 return BaseType::directionBit();
1429 }
1430
1431 /** Get the difference vector (Diff2D) from the center to the current neighbor. */
diff() const1432 Diff2D const & diff() const
1433 {
1434 return BaseType::diff();
1435 }
1436
1437 /** Is the current neighbor a diagonal neighbor? */
isDiagonal() const1438 bool isDiagonal() const
1439 {
1440 return BaseType::isDiagonal();
1441 }
1442
1443 private:
1444 AtImageBorder whichBorder_;
1445 signed char count_, current_;
1446 };
1447
1448 //@}
1449
1450 } // namespace vigra
1451
1452 #endif /* VIGRA_PIXELNEIGHBORHOOD_HXX */
1453