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