Overte C++ Documentation
FloodFill.h
1 //
2 // FloodFill.h
3 // libraries/shared/src
4 //
5 // Copyright 2013 High Fidelity, Inc.
6 //
7 // Distributed under the Apache License, Version 2.0.
8 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
9 //
10 
11 #ifndef hifi_FloodFill_h
12 #define hifi_FloodFill_h
13 
14 //
15 // Line scanning, iterative flood fill algorithm.
16 //
17 // The strategy must obey the following contract:
18 //
19 // There is an associated cursor that represents a position on the image.
20 // The member functions 'left(C&)', 'right(C&)', 'up(C&)', and 'down(C&)'
21 // move it.
22 // The state of a cursor can be deferred to temporary storage (typically a
23 // stack or a queue) using the 'defer(C const&)' member function.
24 // Calling 'deferred(C&)' restores a cursor's state from temporary storage
25 // and removes it there.
26 // The 'select(C const&)' and 'process(C const&)' functions control the
27 // algorithm. The former is called to determine where to go. It may be
28 // called multiple times but does not have to (and should not) return
29 // 'true' more than once for a pixel to be selected (will cause memory
30 // overuse, otherwise). The latter will never be called for a given pixel
31 // unless previously selected. It may be called multiple times, in which
32 // case it should return 'true' upon successful processing and 'false'
33 // when an already processed pixel has been visited.
34 //
35 // Note: The terms "image" and "pixel" are used for illustratory purposes
36 // and mean "undirected graph with 4-connected 2D grid topology" and "node",
37 // respectively.
38 //
39 template< class Strategy, typename Cursor >
40 void floodFill(Cursor const& position,
41  Strategy const& strategy = Strategy());
42 
43 
44 template< class Strategy, typename Cursor >
45 struct floodFill_impl : Strategy {
46 
47  floodFill_impl(Strategy const& s) : Strategy(s) { }
48 
49  using Strategy::select;
50  using Strategy::process;
51 
52  using Strategy::left;
53  using Strategy::right;
54  using Strategy::up;
55  using Strategy::down;
56 
57  using Strategy::defer;
58  using Strategy::deferred;
59 
60  void go(Cursor position) {
61 
62  if (! select(position)) {
63  return;
64  }
65 
66  Cursor higher, lower, h,l, i;
67  do {
68 
69  if (! process(position)) {
70  continue;
71  }
72 
73  higher = position;
74  up(higher);
75  if (select(higher)) { defer(higher); }
76 
77  lower = position;
78  down(lower);
79  if (select(lower)) { defer(lower); }
80 
81  i = position, h = higher, l = lower;
82  do {
83 
84  right(i), right(h), right(l);
85  if (select(h)) { defer(h); }
86  if (select(l)) { defer(l); }
87 
88  } while (select(i) && process(i));
89 
90  i = position, h = higher, l = lower;
91  do {
92  left(i); left(h); left(l);
93  if (select(h)) { defer(h); }
94  if (select(l)) { defer(l); }
95 
96  } while (select(i) && process(i));
97 
98  } while (deferred(position));
99  }
100 };
101 
102 template< class Strategy, typename Cursor >
103 void floodFill(Cursor const& p, Strategy const& s) {
104 
105  floodFill_impl<Strategy,Cursor>(s).go(p);
106 }
107 
108 
109 #endif // hifi_FloodFill_h