$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
tests/topo/complex.cc
1 // Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
28 
29 #include <algorithm>
30 #include <iterator>
31 #include <iostream>
32 
33 #include <mln/topo/complex.hh>
34 
35 using namespace mln;
36 
37 /* FIXME: Split this test (and maybe factor common parts, like the
38  construction of the complex), since it exercises too many features
39  in a single file. */
40 
41 // Forward declarations.
42 template <unsigned N, unsigned D>
43 void test_static_n_face_iter(topo::complex<D>& c);
44 // FIXME: Disabled (moved to the attic).
45 #if 0
46 template <unsigned N, unsigned D>
47 void test_faces_iter(topo::complex<D>& c);
48 #endif
49 
50 
51 int main()
52 {
53  /* A 2-d (simplicial) complex and its adjacency graph.
54 
55  v0 e3 v3
56  o-----------o v0----e3----v3
57  / \ ,-----. / / \ | /
58  / . \ \ t1/ / / \ t1 /
59  e0 / / \ e1\ / / e4 e0. ,e1' `e4
60  / /t0 \ \ ' / / t0 \ /
61  / `-----' \ / / | \ /
62  o-----------o v1----e2----v2
63  v1 e2 v2
64 
65  v = vertex (0-face)
66  e = edge (1-face)
67  t = triangle (2-face)
68  */
69 
70 
71  const unsigned D = 2;
72 
73  /*-----------------------.
74  | Complex construction. |
75  `-----------------------*/
76 
78 
79  // 0-faces (points).
84 
85  // 1-faces (segments).
86  topo::n_face<1, D> e0 = c.add_face(-v1 + v0);
87  topo::n_face<1, D> e1 = c.add_face(-v0 + v2);
88  topo::n_face<1, D> e2 = c.add_face(-v2 + v1);
89  topo::n_face<1, D> e3 = c.add_face(-v0 + v3);
90  topo::n_face<1, D> e4 = c.add_face(-v3 + v2);
91 
92  // 2-faces (triangles).
93  topo::n_face<2, D> t0 = c.add_face( e0 + e1 + e2);
94  topo::n_face<2, D> t1 = c.add_face(-e1 + e3 + e4);
95 
96  std::cout << c << std::endl;
97 
98  std::cout
99  << "Using ``static'' manipulators." << std::endl
100  << " number of 0-faces: c.nfaces_of_static_dim<0>() = "
101  << c.nfaces_of_static_dim<0>() << std::endl
102  << " number of 1-faces: c.nfaces_of_static_dim<1>() = "
103  << c.nfaces_of_static_dim<1>() << std::endl
104  << " number of 2-faces: c.nfaces_of_static_dim<2>() = "
105  << c.nfaces_of_static_dim<2>() << std::endl
106  << " total number of faces: c.nfaces() = " << c.nfaces() << std::endl
107  << std::endl;
108 
109  std::cout
110  << "Using ``dynamic'' manipulators." << std::endl
111  << " number of 0-faces: c.nfaces_of_dim(0) = "
112  << c.nfaces_of_dim(0) << std::endl
113  << " number of 1-faces: c.nfaces_of_dim(1) = "
114  << c.nfaces_of_dim(1) << std::endl
115  << " number of 2-faces: c.nfaces_of_dim(2) = "
116  << c.nfaces_of_dim(2) << std::endl
117  << std::endl;
118 
119  /*-------------------.
120  | Handles and data. |
121  `-------------------*/
122 
123  // Get the face data from (``static'') face handle E0.
124  const topo::face_data<1, D>& face1 = e0.data();
125 
126  /* FIXME: Rename AF (everywhere) as `any-face handles' have been
127  renamed to `face'. */
128  // Any-face handle.
129  topo::face<D> af(e0);
130  // Get the face data from (``dynamic'') face handle AF.
131  const topo::face_data<1, D>& face2 = af.data<1>();
132 
133  mln_assertion(&face1 == &face2);
134 
135  /*-----------------.
136  | Adjacent faces. |
137  `-----------------*/
138 
139  // Adjacent lower-dimension faces of AF.
140  std::vector< topo::algebraic_face<D> > af_lower_dim_adj_faces =
141  af.lower_dim_adj_faces();
142  std::cout << "lower-dimension faces adjacent to " << af << ":" << std::endl;
143  std::copy (af_lower_dim_adj_faces.begin(), af_lower_dim_adj_faces.end(),
144  std::ostream_iterator< topo::face<D> > (std::cout, "\n"));
145  std::cout << std::endl;
146 
147  // Adjacent higher-dimension faces of AF.
148  std::vector< topo::algebraic_face<D> > af_higher_dim_adj_faces =
149  af.higher_dim_adj_faces();
150  std::cout << "higher-dimension faces adjacent to " << af << ":" << std::endl;
151  std::copy (af_higher_dim_adj_faces.begin(), af_higher_dim_adj_faces.end(),
152  std::ostream_iterator< topo::face<D> > (std::cout, "\n"));
153  std::cout << std::endl;
154 
155 
156  /*------------.
157  | Iteration. |
158  `------------*/
159 
160  // FIXME: Possibly split this test (create a test for iterators).
161 
162  // --------------- //
163  // Iterator on C. //
164  // --------------- //
165 
166  // Iterators on a complex (not complex_image), or more precisely on
167  // (all) the faces of complex C.
168  topo::face_fwd_iter<D> fwd_f(c);
169  topo::face_bkd_iter<D> bkd_f(c);
170  for_all_2(fwd_f, bkd_f)
171  std::cout << fwd_f << ' ' << bkd_f << std::endl;
172  std::cout << std::endl;
173 
174  // -------------------------- //
175  // Iterator on n-faces of C. //
176  // -------------------------- //
177 
178  /* FIXME: There's probably useless code here; I (Roland) think that
179  faces_{fwd,bkd}_iter<N, D> won't be really useful to work with
180  actual complex processing since they are not really flexible ---
181  but I'm not sure. */
182 
183  // Dynamic version.
184  for (unsigned n = 0; n <= D; ++n)
185  {
186  topo::n_face_fwd_iter<D> fwd_nf(c, n);
187  topo::n_face_fwd_iter<D> bkd_nf(c, n);
188  std::cout << "test (dynamic) n_face_iters (n = " << n << "):"
189  << std::endl;
190  for_all_2(fwd_nf, bkd_nf)
191  std::cout << fwd_nf << ' ' << bkd_nf << std::endl;
192  std::cout << std::endl;
193  }
194 
195  // Static version.
196  test_static_n_face_iter<0>(c);
197  test_static_n_face_iter<1>(c);
198  test_static_n_face_iter<2>(c);
199 
200 // FIXME: Disabled (moved to the attic).
201 # if 0
202  /* Using faces_{fwd,bkd}_iter_<N, D>, which are proxies to
203  n_faces<N, D>. */
204  test_faces_iter<0>(c);
205  test_faces_iter<1>(c);
206  test_faces_iter<2>(c);
207 #endif
208 
209  /*------------------------------.
210  | Iterators on adjacent faces. |
211  `------------------------------*/
212 
213  /* FIXME: Write and exercise more iterators (see
214  milena/tests/core/complex_image.cc) and ticket #162
215  (https://trac.lrde.org/olena/ticket/162) */
216 
217  // ------------------------------------------------------------ //
218  // Iterate on the the set of (n-1)- and/or (n+1)-faces adjacent //
219  // to the faces of C. //
220  // ------------------------------------------------------------ //
221 
222  /* Note: this can be solved with iterators where the dimension can
223  be either static or dynamic. For the moment, our iterators are
224  dynamic w.r.t. the dimensions of the faces (both the reference
225  face and the iterated ones).
226 
227  Static versions might be useful, and more efficient too, when
228  flexibility is not needed. */
229 
230  // Iterate on the the set of (n-1)-faces adjacent to the faces of C.
231  topo::adj_lower_face_fwd_iter<D> fwd_alf(fwd_f);
232  topo::adj_lower_face_bkd_iter<D> bkd_alf(fwd_f);
233  for_all(fwd_f)
234  {
235  std::cout << "Lower-dimension faces adjacent to " << fwd_f << ": "
236  << std::endl;
237  for_all_2(fwd_alf, bkd_alf)
238  std::cout << " " << fwd_alf << '\t' << bkd_alf << std::endl;
239  }
240  std::cout << std::endl;
241 
242  // Iterate on the the set of (n+1)-faces adjacent to the faces of C.
243  topo::adj_higher_face_fwd_iter<D> fwd_ahf(fwd_f);
244  topo::adj_higher_face_bkd_iter<D> bkd_ahf(fwd_f);
245  for_all(fwd_f)
246  {
247  std::cout << "Higher-dimension faces adjacent to " << fwd_f << ": "
248  << std::endl;
249  for_all_2(fwd_ahf, bkd_ahf)
250  std::cout << " " << fwd_ahf << '\t' << bkd_ahf << std::endl;
251  }
252  std::cout << std::endl;
253 
254  // Iterate on the the set of (n+1)-faces *and* (n+1)-faces adjacent
255  // to the faces of C.
256  topo::adj_lower_higher_face_fwd_iter<D> fwd_alhf(fwd_f);
257  topo::adj_lower_higher_face_bkd_iter<D> bkd_alhf(fwd_f);
258  for_all(fwd_f)
259  {
260  std::cout << "Lower- and higher-dimension faces adjacent to " << fwd_f
261  << ": " << std::endl;
262  for_all_2(fwd_alhf, bkd_alhf)
263  std::cout << " " << fwd_alhf << '\t' << bkd_alhf << std::endl;
264  }
265  std::cout << std::endl;
266 
267 
268  // ------------------------------------------------------- //
269  // Iterators on the the set of n-faces sharing an adjacent //
270  // (n-1)-face or (n+1)-face with f, n being dynamic. //
271  // ------------------------------------------------------- //
272 
273  // For each face F of C, iterate on the the set of n-faces sharing
274  // adjacent (n-1)-faces with F.
275  topo::adj_lower_dim_connected_n_face_fwd_iter<D> fwd_aldcf(fwd_f);
276  topo::adj_lower_dim_connected_n_face_bkd_iter<D> bkd_aldcf(fwd_f);
277  for_all(fwd_f)
278  {
279  std::cout << "Lower-dim-connected faces adjacent to " << fwd_f
280  << ": " << std::endl;
281  for_all_2(fwd_aldcf, bkd_aldcf)
282  std::cout << " " << fwd_aldcf << '\t' << bkd_aldcf << std::endl;
283  }
284  std::cout << std::endl;
285 
286  // For each face F of C, iterate on the the set of n-faces sharing
287  // adjacent (n+1)-faces with F.
288  topo::adj_higher_dim_connected_n_face_fwd_iter<D> fwd_ahdcf(fwd_f);
289  topo::adj_higher_dim_connected_n_face_bkd_iter<D> bkd_ahdcf(fwd_f);
290  for_all(fwd_f)
291  {
292  std::cout << "Higher-dim-connected faces adjacent to " << fwd_f
293  << ": " << std::endl;
294  for_all_2(fwd_ahdcf, bkd_ahdcf)
295  std::cout << " " << fwd_ahdcf << '\t' << bkd_ahdcf << std::endl;
296  }
297  std::cout << std::endl;
298 
299  // For each face F of C, and for M in [0, D], iterate on the the set
300  // of M-faces transitively adjacent to F.
301  topo::adj_m_face_fwd_iter<D> fwd_amf(fwd_f, 0);
302  topo::adj_m_face_bkd_iter<D> bkd_amf(fwd_f, 0);
303  for_all(fwd_f)
304  {
305  for (unsigned m = 0; m <= D; ++m)
306  {
307  fwd_amf.set_m(m);
308  bkd_amf.set_m(m);
309  std::cout << m << "-faces (transitively) adjacent to " << fwd_f
310  << ": " << std::endl;
311  for_all_2(fwd_amf, bkd_amf)
312  std::cout << " " << fwd_amf << '\t' << bkd_amf << std::endl;
313  }
314  std::cout << std::endl;
315  }
316 
317 
318  /* Next, write these:
319 
320  -----------------------------------------------------------------
321  Name Definition
322  -----------------------------------------------------------------
323  cell_fwd_iter<D>(c, f) | Iterators on the set of the
324  cell_bkd_iter<D>(c, f) | faces in the ``cell''
325  | including p, i.e. the set of
326  | all m-faces adjacent to p,
327  | where m is in [0, n-1];
328  | this set is name ``f-hat''
329 
330  cell_boundary_fwd_iter<D>(c, f) | Likewise, but excluding p;
331  cell_boundary_bkd_iter<D>(c, f) | this set is named ``p-hat*''
332  -----------------------------------------------------------------
333 
334  We could also have generic iterators based on predicated, and
335  even use them to provide first (non efficient) implementations of
336  the iterators from the previous list.
337 
338  -----------------------------------------------------------------
339  Name Definition
340  -----------------------------------------------------------------
341  generic_face_fwd_iter<D>(c, pred) | Generic face iterators on c
342  generic_face_bkd_iter<D>(c, pred) | using predicate pred to
343  | define the iterated subset.
344  -----------------------------------------------------------------
345 
346 
347  I'm unsure about the old iterators on n-faces (with a static n)
348  moved to the attic; should we keep them? What are they good for,
349  except testing our code? At least, we should find better names
350  for them, as we might confuse them with new iterators.
351 
352  -----------------------------------------------------------------
353  Current name Definition
354  -----------------------------------------------------------------
355  complex_faces_fwd_iter_<N, D> Iterators on N-faces, N being
356  complex_faces_fwd_iter_<N, D> static, acting as proxies of
357  n_face<N, D>'s.
358 
359  faces_fwd_iter_<N, D> Iterators on N-faces, N being
360  faces_fwd_iter_<N, D> static, acting as proxies of
361  face<D>'s.
362  -----------------------------------------------------------------
363 
364  See also https://trac.lrde.org/olena/wiki/Olena/ComplexBasedImages */
365 
366 
367  /*------------------.
368  | Other iterators. |
369  `------------------*/
370 
371  // For each face, iterate on itself. (This iterator is not
372  // interesting as-is, but is useful when combined with others,
373  // e.g. in topo::centered_iter_adapter).
374  std::cout << "Center-only iterator:" << std::endl;
375  topo::center_only_iter<D> center(fwd_f);
376  for_all(fwd_f)
377  for_all(center)
378  std::cout << " " << center << std::endl;
379  std::cout << std::endl;
380 }
381 
382 
383 template <unsigned N, unsigned D>
384 void
385 test_static_n_face_iter(topo::complex<D>& c)
386 {
387  std::cout << "test_static_n_face_iter<" << N << ", " << D << ">:"
388  << std::endl;
389  /* FIXME: Provide sugar. Maybe redefined mln_fwd_fiter and
390  mln_bkd_fiter so that they expand as complex_faces_iters (instead
391  of faces_iters). */
394  for_all_2(fwd_nf, bkd_nf)
395  std::cout << fwd_nf << ' ' << bkd_nf << std::endl;
396  std::cout << std::endl;
397 }
398 
399 // FIXME: Disabled (moved to the attic).
400 # if 0
401 template <unsigned N, unsigned D>
402 void
403 test_faces_iter(topo::complex<D>& c)
404 {
405  std::cout << "test_faces_iter<" << N << ", " << D << ">:"
406  << std::endl;
407  mln_fwd_fiter(N, topo::complex<D>) fwd_nf(c);
408  mln_bkd_fiter(N, topo::complex<D>) bkd_nf(c);
409  for_all_2(fwd_nf, bkd_nf)
410  std::cout << fwd_nf << ' ' << bkd_nf << std::endl;
411  std::cout << std::endl;
412 }
413 #endif