aimstil  5.0.5
Neighborhood.h
Go to the documentation of this file.
1 #ifndef TIL_NEIGHBORHOOD_H
2 #define TIL_NEIGHBORHOOD_H
3 
4 // include from STL library
5 #include <cassert>
6 #include <vector>
7 
8 // includes from TIL library
9 #include "til/labels.h"
10 #include "til/numeric_array.h"
11 #include "til/Range.h"
12 
13 // Ignore specific warnings
14 #ifdef _MSC_VER
15 #pragma warning( push )
16 // X needs to have dll-interface to be used by clients of class Z
17 #pragma warning( disable : 4251 )
18 #endif
19 
22 #define COFFSET(i,j,k) ((i)+3*(j)+9*(k)+13)
23 
24 // To be undefined at the end of this file
25 #define FOR_ALL_NEIGHBORS \
26 for (i=-1; i<=1; ++i) \
27  for (j=-1; j<=1; ++j) \
28  for (k=-1; k<=1; ++k) \
29 
30 #define APPY_ALL_NEIGHBORS(macro) \
31  macro(-1,-1,-1) \
32  macro( 0,-1,-1) \
33  macro(+1,-1,-1) \
34  macro(-1, 0,-1) \
35  macro( 0, 0,-1) \
36  macro(+1, 0,-1) \
37  macro(-1,+1,-1) \
38  macro( 0,+1,-1) \
39  macro(+1,+1,-1) \
40  macro(-1,-1, 0) \
41  macro( 0,-1, 0) \
42  macro(+1,-1, 0) \
43  macro(-1, 0, 0) \
44  macro( 0, 0, 0) \
45  macro(+1, 0, 0) \
46  macro(-1,+1, 0) \
47  macro( 0,+1, 0) \
48  macro(+1,+1, 0) \
49  macro(-1,-1,+1) \
50  macro( 0,-1,+1) \
51  macro(+1,-1,+1) \
52  macro(-1, 0,+1) \
53  macro( 0, 0,+1) \
54  macro(+1, 0,+1) \
55  macro(-1,+1,+1) \
56  macro( 0,+1,+1) \
57  macro(+1,+1,+1) \
58 
59 
60 // Namespace
61 namespace til {
62 
63 
64 // The type encoding neighborhood internally
65 // Could be int, bool, char...
66 //typedef bool t_nh;
67 
68 
69 
70 // The neighborhood class represents a discrete, 3x3 neighborhood
71 // used e.g. for 3d image topology operations
72 
73 // The neighborhood is center on (0,0,0), i.e. its range is [-1,1]^3
74 
75 
77 // NB: I have chosen to use a std::vector container rather than a std::list. This might
78 // seem awkward as all the operations used in this class are rather costly when using a vector.
79 // But the bottleneck here is when we iterate, not when we actually manipulate the neighborhood.
81 {
82 public: // typedefs
83 
85  typedef std::vector<numeric_array<int,3> > NeighborList;
86  typedef NeighborList::iterator iterator;
87  typedef NeighborList::const_iterator const_iterator;
88 
89 public: // constructors & destructor
90 
92  Neighborhood_list() : m_neighbors() { }
93 
95  template < class TNeighborhood >
96  Neighborhood_list(const TNeighborhood &nh) : m_neighbors() { this->init(nh); }
97 
99  Neighborhood_list(const bool array[3*3*3]) : m_neighbors() { this->init(array); }
100 
101 public: // initialization
102 
103  template < class TNeighborhood >
105  init(const TNeighborhood &nh)
106  {
107  // We first clear the neighborhood, in case their were something else before
108  this->reset();
109  //nh.for_all_neighbors(this->set(_1));
110  // We add a neighbor whenever there is one in the old neighborhood
111  typename TNeighborhood::const_iterator iNeighbor = nh.begin();
112  for (; iNeighbor < nh.end(); ++iNeighbor)
113  {
114  if (nh.isNeighbor(*iNeighbor))
115  {
116  this->set(*iNeighbor);
117  }
118  }
119  }
120 
122  void init(const bool array[3*3*3])
123  {
124  this->reset();
125  int i, j, k;
127  {
128  if (array[COFFSET(i,j,k)]) this->set(numeric_array<int,3>(i,j,k));
129  }
130  }
131 
133  template < typename TFunctor >
134  void for_all_neighbors(const TFunctor &functor)
135  {
136  for (
137  std::vector<numeric_array<int,3> >::const_iterator iNeighbor = m_neighbors.begin();
138  iNeighbor != m_neighbors.end();
139  ++iNeighbor)
140  {
141  functor(*iNeighbor);
142  }
143  }
144 
145 public: // iterators
146 
147  Self::iterator begin() { return m_neighbors.begin(); }
148  Self::iterator end() { return m_neighbors.end(); }
149  Self::const_iterator begin() const { return m_neighbors.begin(); }
150  Self::const_iterator end() const { return m_neighbors.end(); }
151 
152 public: // set & get
153 
154  void set(const numeric_array<int,3> &v)
155  {
156  (void)(v);
157  // Check that input vector verifies basic assumptions
158  assert(all_less_equal(v, numeric_array<int,3>(1,1,1)));
159  assert(all_greater_equal(v, numeric_array<int,3>(-1,-1,-1)));
160  // Check that the input neighbor is not already inside the list
161  // If not, add the neighbor
162  }
164  {
165  (void)(v);
166  // Check that input vector verifies basic assumptions
167  assert(all_less_equal(v, numeric_array<int,3>(1,1,1)));
168  assert(all_greater_equal(v, numeric_array<int,3>(-1,-1,-1)));
169  // Remove input vector
170  }
171 
172  /*
173  bool get()(const numeric_array<int,3> &v)
174  {
175  }
176  */
177 
178 public: // functions
179 
180  void reset() { m_neighbors.clear(); }
181 
182  /*
183  template < class TFunctor >
184  INLINE void forAllNeighbors(const TFunctor &functor) const
185  {
186  for (
187  NeighborList::const_iterator iNeighbor = m_neighbors.begin();
188  iNeighbor < m_neighbors.end();
189  ++iNeighbor)
190  {
191  functor(*iNeighbor);
192  }
193  }
194  */
195 
196 private: // typedefs
197 
198 private: // classes
199 
200  struct Assign
201  {
202  void operator()(const numeric_array<int,3> &)
203  {
204  }
205  };
206 
207 private: // data
208  NeighborList m_neighbors;
209 };
210 
211 
213 {
214 public: // typedefs
215 
217 
218 public: // constructors &destructor
219 
221  Neighborhood() { this->reset(); }
222 
224  Neighborhood(const Neighborhood & nh) { this->init(nh); }
225 
227  Neighborhood(const bool array[3*3*3]) { this->init(array); }
228 
231  bool n000, bool n001, bool n002,
232  bool n010, bool n011, bool n012,
233  bool n020, bool n021, bool n022,
234  bool n100, bool n101, bool n102,
235  bool n110, bool n111, bool n112,
236  bool n120, bool n121, bool n122,
237  bool n200, bool n201, bool n202,
238  bool n210, bool n211, bool n212,
239  bool n220, bool n221, bool n222)
240  {
241  m_cube[0]= n000; m_cube[1]= n001; m_cube[2]= n002;
242  m_cube[3]= n010; m_cube[4]= n011; m_cube[5]= n012;
243  m_cube[6]= n020; m_cube[7]= n021; m_cube[8]= n022;
244  m_cube[9]= n100; m_cube[10]= n101; m_cube[11]= n102;
245  m_cube[12]= n110; m_cube[13]= n111; m_cube[14]= n112;
246  m_cube[15]= n120; m_cube[16]= n121; m_cube[17]= n122;
247  m_cube[18]= n200; m_cube[19]= n201; m_cube[20]= n202;
248  m_cube[21]= n210; m_cube[22]= n211; m_cube[23]= n212;
249  m_cube[24]= n220; m_cube[25]= n221; m_cube[26]= n222;
250  }
251 
252 public: // initialization
253 
254  // from another neighborhood
255  void init(const Neighborhood &nh) { this->init(nh.m_cube); }
256 
257  // from C array
258  void init(const bool array[3*3*3])
259  {
260  for (int i = 0; i < 3*3*3; ++i) m_cube[i] = array[i];
261  }
262 
263 public: // functions
264 
266  void reset() { for (int i = 0; i <= 3*3*3; ++i) m_cube[i] = false; }
267 
269  void set(int i, int j, int k)
270  {
271  this->setValue(i,j,k,true);
272  }
273 
275  void set(const numeric_array<int,3> &v)
276  {
277  this->set(EXPAND_VECTOR(v));
278  }
279 
280 
282  void remove(int i, int j, int k)
283  {
284  this->setValue(i,j,k,false);
285  }
286 
288  void remove(const numeric_array<int,3> &v)
289  {
290  this->remove(EXPAND_VECTOR(v));
291  }
292 
293  // The returned value evalutes to true iff there is a neighbor
294  // at point (i,j,k)
295  bool isNeighbor(int i, int j, int k) const
296  {
298  return m_cube[Self::offset(i,j,k)];
299  }
301  {
302  return this->isNeighbor(EXPAND_VECTOR(v));
303  }
304 
305  template < typename TFunctor >
306  void for_all_neighbors(const TFunctor &functor)
307  {
308  int i, j, k;
310  {
311  if (m_cube[COFFSET(i,j,k)])
312  {
313  functor(i,j,k);
314  }
315  }
316  }
317 
318 public: // interface to use Neigbors as template
319 
320  template <int i, int j, int k>
321  INLINE bool isNeighbor() const
322  {
323  // Check that we are not out of range
324  // NB: this could/should be compile-time checking
325  assert(i >=-1 && i <= 1);
326  assert(j >=-1 && j <= 1);
327  assert(k >=-1 && k <= 1);
328  return m_cube[Self::offset(i,j,k)];
329  }
330 
331 
332 private: // functions
333 
334  void setValue(int i, int j, int k, bool value)
335  {
337  m_cube[Self::offset(i,j,k)] = value;
338  }
339 
340  INLINE static int offset(int i, int j, int k) { return i+3*j+9*k+13; }
341 
342 private: // data
343 
344  bool m_cube[3*3*3];
345 };
346 
347 
348 
349 
350 const Neighborhood N26(
351 1,1,1,
352 1,1,1,
353 1,1,1,
354 
355 1,1,1,
356 1,0,1,
357 1,1,1,
358 
359 1,1,1,
360 1,1,1,
361 1,1,1);
362 
363 const Neighborhood N6(
364 0,0,0,
365 0,1,0,
366 0,0,0,
367 
368 0,1,0,
369 1,0,1,
370 0,1,0,
371 
372 0,0,0,
373 0,1,0,
374 0,0,0);
375 
376 const Neighborhood N18(
377 0,1,0,
378 1,1,1,
379 0,1,0,
380 
381 1,1,1,
382 1,0,1,
383 1,1,1,
384 
385 0,1,0,
386 1,1,1,
387 0,1,0);
388 
389 #define TNDECARG \
390 bool n000, bool n001, bool n002,\
391 bool n010, bool n011, bool n012,\
392 bool n020, bool n021, bool n022,\
393 bool n100, bool n101, bool n102,\
394 bool n110, bool n111, bool n112,\
395 bool n120, bool n121, bool n122,\
396 bool n200, bool n201, bool n202,\
397 bool n210, bool n211, bool n212,\
398 bool n220, bool n221, bool n222
399 #define TNARG \
400 n000, n001, n002,\
401 n010, n011, n012,\
402 n020, n021, n022,\
403 n100, n101, n102,\
404 n110, n111, n112,\
405 n120, n121, n122,\
406 n200, n201, n202,\
407 n210, n211, n212,\
408 n220, n221, n222
409 
410 
413 template <
414 bool n000, bool n001, bool n002,
415 bool n010, bool n011, bool n012,
416 bool n020, bool n021, bool n022,
417 bool n100, bool n101, bool n102,
418 bool n110, bool n111, bool n112,
419 bool n120, bool n121, bool n122,
420 bool n200, bool n201, bool n202,
421 bool n210, bool n211, bool n212,
422 bool n220, bool n221, bool n222 >
424 {
425 public:
426  /*
427  template <int i, int j, int k>
428  struct isNeighbor;
429 
430  template <>
431  struct isNeighbor<-1,-1,-1>
432  {
433  static INLINE bool operator()() { return n000; }
434  };
435  */
436 
437  INLINE bool isNeighbor(int i, int j, int k) const
438  {
439  if (i==-1 && j==-1 && k==-1) return n000;
440  if (i==-1 && j==-1 && k== 0) return n001;
441  if (i==-1 && j==-1 && k==+1) return n002;
442 
443  if (i==-1 && j== 0 && k==-1) return n010;
444  if (i==-1 && j== 0 && k== 0) return n011;
445  if (i==-1 && j== 0 && k==+1) return n012;
446 
447  if (i==-1 && j==+1 && k==-1) return n020;
448  if (i==-1 && j==+1 && k== 0) return n021;
449  if (i==-1 && j==+1 && k==+1) return n022;
450 
451  if (i== 0 && j==-1 && k==-1) return n100;
452  if (i== 0 && j==-1 && k== 0) return n101;
453  if (i== 0 && j==-1 && k==+1) return n102;
454 
455  if (i== 0 && j== 0 && k==-1) return n110;
456  if (i== 0 && j== 0 && k== 0) return n111;
457  if (i== 0 && j== 0 && k==+1) return n112;
458 
459  if (i== 0 && j==+1 && k==-1) return n120;
460  if (i== 0 && j==+1 && k== 0) return n121;
461  if (i== 0 && j==+1 && k==+1) return n122;
462 
463  if (i==+1 && j==-1 && k==-1) return n200;
464  if (i==+1 && j==-1 && k== 0) return n201;
465  if (i==+1 && j==-1 && k==+1) return n202;
466 
467  if (i==+1 && j== 0 && k==-1) return n210;
468  if (i==+1 && j== 0 && k== 0) return n211;
469  if (i==+1 && j== 0 && k==+1) return n212;
470 
471  if (i==+1 && j==+1 && k==-1) return n220;
472  if (i==+1 && j==+1 && k== 0) return n221;
473  if (i==+1 && j==+1 && k==+1) return n222;
474  return false;
475  }
476 
477  template <int i, int j, int k>
478  INLINE bool isNeighbor() const { return this->isNeighbor(i,j,k); }
479 
480  /*
481  template <> INLINE bool isNeighbor<-1,-1,-1>() const { return n000; }
482  template <> INLINE bool isNeighbor<-1,-1, 0>() const { return n001; }
483  template <> INLINE bool isNeighbor<-1,-1,+1>() const { return n002; }
484 
485  template <> INLINE bool isNeighbor<-1, 0,-1>() const { return n010; }
486  template <> INLINE bool isNeighbor<-1, 0, 0>() const { return n011; }
487  template <> INLINE bool isNeighbor<-1, 0,+1>() const { return n012; }
488 
489  template <> INLINE bool isNeighbor<-1,+1,-1>() const { return n020; }
490  template <> INLINE bool isNeighbor<-1,+1, 0>() const { return n021; }
491  template <> INLINE bool isNeighbor<-1,+1,+1>() const { return n022; }
492 
493  template <> INLINE bool isNeighbor< 0,-1,-1>() const { return n100; }
494  template <> INLINE bool isNeighbor< 0,-1, 0>() const { return n101; }
495  template <> INLINE bool isNeighbor< 0,-1,+1>() const { return n102; }
496 
497  template <> INLINE bool isNeighbor< 0, 0,-1>() const { return n110; }
498  template <> INLINE bool isNeighbor< 0, 0, 0>() const { return n111; }
499  template <> INLINE bool isNeighbor< 0, 0,+1>() const { return n112; }
500 
501  template <> INLINE bool isNeighbor< 0,+1,-1>() const { return n120; }
502  template <> INLINE bool isNeighbor< 0,+1, 0>() const { return n121; }
503  template <> INLINE bool isNeighbor< 0,+1,+1>() const { return n122; }
504 
505  template <> INLINE bool isNeighbor<+1,-1,-1>() const { return n200; }
506  template <> INLINE bool isNeighbor<+1,-1, 0>() const { return n201; }
507  template <> INLINE bool isNeighbor<+1,-1,+1>() const { return n202; }
508 
509  template <> INLINE bool isNeighbor<+1, 0,-1>() const { return n210; }
510  template <> INLINE bool isNeighbor<+1, 0, 0>() const { return n211; }
511  template <> INLINE bool isNeighbor<+1, 0,+1>() const { return n212; }
512 
513  template <> INLINE bool isNeighbor<+1,+1,-1>() const { return n220; }
514  template <> INLINE bool isNeighbor<+1,+1, 0>() const { return n221; }
515  template <> INLINE bool isNeighbor<+1,+1,+1>() const { return n222; }
516 */
517 };
518 
519 /*
520 template <int i, int j, int k, class TNeighborhood>
521 struct IsNeighbor;
522 
523 template <class TNeighborhood>
524 struct IsNeighbor<-1,-1,-1,TNeighborhood>
525 {
526  static const bool value = TNeighborhood::n000;
527 };
528 
529 template <int i, int j, int k, class TNeighborhood>
530 bool isNeighbor(const TNeighborhood&);
531 
532 template <int i, int j, int k, TNDECARG>
533 bool isNeighbor(const TArgNeighborhood<TNARG> &)
534 {
535  return n000;
536 }
537 
538 template <int i, int j, int k>
539 struct RPos {};
540 
541 template <TNDECARG>
542 bool isNeighbor<TNARG>(const TArgNeighborhood<TNARG> &)
543 {
544  return n000;
545 }
546 */
547 
548 // Below are some predefined template neighborhoods corresponding to standard 3D
549 // connectivities
550 
553 typedef TArgNeighborhood<
554 0,0,0,
555 0,1,0,
556 0,0,0,
557 0,1,0,
558 1,0,1,
559 0,1,0,
560 0,0,0,
561 0,1,0,
562 0,0,0> TN6;
563 
566 typedef TArgNeighborhood<
567 0,1,0,
568 1,1,1,
569 0,1,0,
570 1,1,1,
571 1,0,1,
572 1,1,1,
573 0,1,0,
574 1,1,1,
575 0,1,0> TN18;
576 
579 typedef TArgNeighborhood<
580 1,1,1,
581 1,1,1,
582 1,1,1,
583 1,1,1,
584 1,0,1,
585 1,1,1,
586 1,1,1,
587 1,1,1,
588 1,1,1> TN26;
589 
590 } // namespace
591 
592 #undef FOR_ALL_NEIGHBORS
593 
594 #ifdef _MSC_VER
595 #pragma warning ( pop )
596 #endif
597 
598 #endif
599 
const Neighborhood N6(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0)
TArgNeighborhood< 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0 > TN18
Template neighborhood for standard 3D 18-connectivity Note that the center is not included...
Definition: Neighborhood.h:575
void reset(const numeric_array< int, 3 > &v)
Definition: Neighborhood.h:163
void for_all_neighbors(const TFunctor &functor)
Definition: Neighborhood.h:306
Neighborhood(bool n000, bool n001, bool n002, bool n010, bool n011, bool n012, bool n020, bool n021, bool n022, bool n100, bool n101, bool n102, bool n110, bool n111, bool n112, bool n120, bool n121, bool n122, bool n200, bool n201, bool n202, bool n210, bool n211, bool n212, bool n220, bool n221, bool n222)
manual
Definition: Neighborhood.h:230
NeighborList::iterator iterator
Definition: Neighborhood.h:86
#define EXPAND_VECTOR(v)
Definition: til_common.h:54
Neighborhood_list(const bool array[3 *3 *3])
From C array.
Definition: Neighborhood.h:99
DetemplateAssignOperator1< til::functor::Assign > Assign
TArgNeighborhood< 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 > TN6
Template neighborhood for standard 3D 6-connectivity.
Definition: Neighborhood.h:562
#define COFFSET(i, j, k)
A macro to quickly index into a 3^3 cube.
Definition: Neighborhood.h:22
TArgNeighborhood< 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 > TN26
Template neighborhood for standard 3D 26-connectivity Note that the center is not included...
Definition: Neighborhood.h:588
NeighborList::const_iterator const_iterator
Definition: Neighborhood.h:87
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
Self::const_iterator begin() const
Definition: Neighborhood.h:149
INLINE bool isNeighbor() const
Definition: Neighborhood.h:321
Defines empty classes that serves as labels.
#define TIL_API
Definition: til_common.h:42
Neighborhood()
No neighbors.
Definition: Neighborhood.h:221
#define INLINE
Definition: til_common.h:26
void reset()
Remove all neighbors from neighborhood.
Definition: Neighborhood.h:266
INLINE bool isNeighbor() const
Definition: Neighborhood.h:478
Neighborhood(const bool array[3 *3 *3])
from C array
Definition: Neighborhood.h:227
Neighborhood_list()
Default constructor, empty neighborhood.
Definition: Neighborhood.h:92
Neighborhood as a list of vectors.
Definition: Neighborhood.h:80
Neighborhood_list(const TNeighborhood &nh)
Copy constructor from any type of neighborhood.
Definition: Neighborhood.h:96
boost::enable_if< is_numeric_container< TStorage >, bool >::type contains(const Box< T, D > &box, const TStorage &v)
Check whether a point lies within box.
Definition: boxTools.h:15
bool isNeighbor(const numeric_array< int, 3 > &v)
Definition: Neighborhood.h:300
INLINE bool isNeighbor(int i, int j, int k) const
Definition: Neighborhood.h:437
void init(const bool array[3 *3 *3])
From C array.
Definition: Neighborhood.h:122
Neighborhood Self
Definition: Neighborhood.h:216
Neighborhood_list Self
Definition: Neighborhood.h:84
Self::iterator end()
Definition: Neighborhood.h:148
std::vector< numeric_array< int, 3 > > NeighborList
Definition: Neighborhood.h:85
const Neighborhood N18(0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0)
void for_all_neighbors(const TFunctor &functor)
A loop to execute something per neighbor.
Definition: Neighborhood.h:134
Neighborhood(const Neighborhood &nh)
Copy constructor.
Definition: Neighborhood.h:224
Self::iterator begin()
Definition: Neighborhood.h:147
Template neighborhoods.
Definition: Neighborhood.h:423
enable_if< is_Neighborhood< TNeighborhood > >::type init(const TNeighborhood &nh)
Definition: Neighborhood.h:105
void init(const Neighborhood &nh)
Definition: Neighborhood.h:255
#define FOR_ALL_NEIGHBORS
Definition: Neighborhood.h:25
Self::const_iterator end() const
Definition: Neighborhood.h:150
bool isNeighbor(int i, int j, int k) const
Definition: Neighborhood.h:295
const Neighborhood N26(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
void init(const bool array[3 *3 *3])
Definition: Neighborhood.h:258