Milena (Olena)
User documentation 2.0a Id
|
00001 // Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) 00002 // 00003 // This file is part of Olena. 00004 // 00005 // Olena is free software: you can redistribute it and/or modify it under 00006 // the terms of the GNU General Public License as published by the Free 00007 // Software Foundation, version 2 of the License. 00008 // 00009 // Olena is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Olena. If not, see <http://www.gnu.org/licenses/>. 00016 // 00017 // As a special exception, you may use this file as part of a free 00018 // software project without restriction. Specifically, if other files 00019 // instantiate templates or use macros or inline functions from this 00020 // file, or you compile this file and link it with other files to produce 00021 // an executable, this file does not by itself cause the resulting 00022 // executable to be covered by the GNU General Public License. This 00023 // exception does not however invalidate any other reasons why the 00024 // executable file might be covered by the GNU General Public License. 00025 00026 #include <algorithm> 00027 #include <iterator> 00028 #include <iostream> 00029 00030 #include <mln/topo/complex.hh> 00031 00032 using namespace mln; 00033 00034 /* FIXME: Split this test (and maybe factor common parts, like the 00035 construction of the complex), since it exercises too many features 00036 in a single file. */ 00037 00038 // Forward declarations. 00039 template <unsigned N, unsigned D> 00040 void test_static_n_face_iter(topo::complex<D>& c); 00041 // FIXME: Disabled (moved to the attic). 00042 #if 0 00043 template <unsigned N, unsigned D> 00044 void test_faces_iter(topo::complex<D>& c); 00045 #endif 00046 00047 00048 int main() 00049 { 00050 /* A 2-d (simplicial) complex and its adjacency graph. 00051 00052 v0 e3 v3 00053 o-----------o v0----e3----v3 00054 / \ ,-----. / / \ | / 00055 / . \ \ t1/ / / \ t1 / 00056 e0 / / \ e1\ / / e4 e0. ,e1´ `e4 00057 / /t0 \ \ ' / / t0 \ / 00058 / `-----' \ / / | \ / 00059 o-----------o v1----e2----v2 00060 v1 e2 v2 00061 00062 v = vertex (0-face) 00063 e = edge (1-face) 00064 t = triangle (2-face) 00065 */ 00066 00067 00068 const unsigned D = 2; 00069 00070 /*-----------------------. 00071 | Complex construction. | 00072 `-----------------------*/ 00073 00074 topo::complex<D> c; 00075 00076 // 0-faces (points). 00077 topo::n_face<0, D> v0 = c.add_face(); 00078 topo::n_face<0, D> v1 = c.add_face(); 00079 topo::n_face<0, D> v2 = c.add_face(); 00080 topo::n_face<0, D> v3 = c.add_face(); 00081 00082 // 1-faces (segments). 00083 topo::n_face<1, D> e0 = c.add_face(-v1 + v0); 00084 topo::n_face<1, D> e1 = c.add_face(-v0 + v2); 00085 topo::n_face<1, D> e2 = c.add_face(-v2 + v1); 00086 topo::n_face<1, D> e3 = c.add_face(-v0 + v3); 00087 topo::n_face<1, D> e4 = c.add_face(-v3 + v2); 00088 00089 // 2-faces (triangles). 00090 topo::n_face<2, D> t0 = c.add_face( e0 + e1 + e2); 00091 topo::n_face<2, D> t1 = c.add_face(-e1 + e3 + e4); 00092 00093 std::cout << c << std::endl; 00094 00095 std::cout 00096 << "Using ``static'' manipulators." << std::endl 00097 << " number of 0-faces: c.nfaces_of_static_dim<0>() = " 00098 << c.nfaces_of_static_dim<0>() << std::endl 00099 << " number of 1-faces: c.nfaces_of_static_dim<1>() = " 00100 << c.nfaces_of_static_dim<1>() << std::endl 00101 << " number of 2-faces: c.nfaces_of_static_dim<2>() = " 00102 << c.nfaces_of_static_dim<2>() << std::endl 00103 << " total number of faces: c.nfaces() = " << c.nfaces() << std::endl 00104 << std::endl; 00105 00106 std::cout 00107 << "Using ``dynamic'' manipulators." << std::endl 00108 << " number of 0-faces: c.nfaces_of_dim(0) = " 00109 << c.nfaces_of_dim(0) << std::endl 00110 << " number of 1-faces: c.nfaces_of_dim(1) = " 00111 << c.nfaces_of_dim(1) << std::endl 00112 << " number of 2-faces: c.nfaces_of_dim(2) = " 00113 << c.nfaces_of_dim(2) << std::endl 00114 << std::endl; 00115 00116 /*-------------------. 00117 | Handles and data. | 00118 `-------------------*/ 00119 00120 // Get the face data from (``static'') face handle E0. 00121 const topo::face_data<1, D>& face1 = e0.data(); 00122 00123 /* FIXME: Rename AF (everywhere) as `any-face handles' have been 00124 renamed to `face'. */ 00125 // Any-face handle. 00126 topo::face<D> af(e0); 00127 // Get the face data from (``dynamic'') face handle AF. 00128 const topo::face_data<1, D>& face2 = af.data<1>(); 00129 00130 mln_assertion(&face1 == &face2); 00131 00132 /*-----------------. 00133 | Adjacent faces. | 00134 `-----------------*/ 00135 00136 // Adjacent lower-dimension faces of AF. 00137 std::vector< topo::algebraic_face<D> > af_lower_dim_adj_faces = 00138 af.lower_dim_adj_faces(); 00139 std::cout << "lower-dimension faces adjacent to " << af << ":" << std::endl; 00140 std::copy (af_lower_dim_adj_faces.begin(), af_lower_dim_adj_faces.end(), 00141 std::ostream_iterator< topo::face<D> > (std::cout, "\n")); 00142 std::cout << std::endl; 00143 00144 // Adjacent higher-dimension faces of AF. 00145 std::vector< topo::algebraic_face<D> > af_higher_dim_adj_faces = 00146 af.higher_dim_adj_faces(); 00147 std::cout << "higher-dimension faces adjacent to " << af << ":" << std::endl; 00148 std::copy (af_higher_dim_adj_faces.begin(), af_higher_dim_adj_faces.end(), 00149 std::ostream_iterator< topo::face<D> > (std::cout, "\n")); 00150 std::cout << std::endl; 00151 00152 00153 /*------------. 00154 | Iteration. | 00155 `------------*/ 00156 00157 // FIXME: Possibly split this test (create a test for iterators). 00158 00159 // --------------- // 00160 // Iterator on C. // 00161 // --------------- // 00162 00163 // Iterators on a complex (not complex_image), or more precisely on 00164 // (all) the faces of complex C. 00165 topo::face_fwd_iter<D> fwd_f(c); 00166 topo::face_bkd_iter<D> bkd_f(c); 00167 for_all_2(fwd_f, bkd_f) 00168 std::cout << fwd_f << ' ' << bkd_f << std::endl; 00169 std::cout << std::endl; 00170 00171 // -------------------------- // 00172 // Iterator on n-faces of C. // 00173 // -------------------------- // 00174 00175 /* FIXME: There's probably useless code here; I (Roland) think that 00176 faces_{fwd,bkd}_iter<N, D> won't be really useful to work with 00177 actual complex processing since they are not really flexible --- 00178 but I'm not sure. */ 00179 00180 // Dynamic version. 00181 for (unsigned n = 0; n <= D; ++n) 00182 { 00183 topo::n_face_fwd_iter<D> fwd_nf(c, n); 00184 topo::n_face_fwd_iter<D> bkd_nf(c, n); 00185 std::cout << "test (dynamic) n_face_iters (n = " << n << "):" 00186 << std::endl; 00187 for_all_2(fwd_nf, bkd_nf) 00188 std::cout << fwd_nf << ' ' << bkd_nf << std::endl; 00189 std::cout << std::endl; 00190 } 00191 00192 // Static version. 00193 test_static_n_face_iter<0>(c); 00194 test_static_n_face_iter<1>(c); 00195 test_static_n_face_iter<2>(c); 00196 00197 // FIXME: Disabled (moved to the attic). 00198 # if 0 00199 /* Using faces_{fwd,bkd}_iter_<N, D>, which are proxies to 00200 n_faces<N, D>. */ 00201 test_faces_iter<0>(c); 00202 test_faces_iter<1>(c); 00203 test_faces_iter<2>(c); 00204 #endif 00205 00206 /*------------------------------. 00207 | Iterators on adjacent faces. | 00208 `------------------------------*/ 00209 00210 /* FIXME: Write and exercise more iterators (see 00211 milena/tests/core/complex_image.cc) and ticket #162 00212 (https://trac.lrde.org/olena/ticket/162) */ 00213 00214 // ------------------------------------------------------------ // 00215 // Iterate on the the set of (n-1)- and/or (n+1)-faces adjacent // 00216 // to the faces of C. // 00217 // ------------------------------------------------------------ // 00218 00219 /* Note: this can be solved with iterators where the dimension can 00220 be either static or dynamic. For the moment, our iterators are 00221 dynamic w.r.t. the dimensions of the faces (both the reference 00222 face and the iterated ones). 00223 00224 Static versions might be useful, and more efficient too, when 00225 flexibility is not needed. */ 00226 00227 // Iterate on the the set of (n-1)-faces adjacent to the faces of C. 00228 topo::adj_lower_face_fwd_iter<D> fwd_alf(fwd_f); 00229 topo::adj_lower_face_bkd_iter<D> bkd_alf(fwd_f); 00230 for_all(fwd_f) 00231 { 00232 std::cout << "Lower-dimension faces adjacent to " << fwd_f << ": " 00233 << std::endl; 00234 for_all_2(fwd_alf, bkd_alf) 00235 std::cout << " " << fwd_alf << '\t' << bkd_alf << std::endl; 00236 } 00237 std::cout << std::endl; 00238 00239 // Iterate on the the set of (n+1)-faces adjacent to the faces of C. 00240 topo::adj_higher_face_fwd_iter<D> fwd_ahf(fwd_f); 00241 topo::adj_higher_face_bkd_iter<D> bkd_ahf(fwd_f); 00242 for_all(fwd_f) 00243 { 00244 std::cout << "Higher-dimension faces adjacent to " << fwd_f << ": " 00245 << std::endl; 00246 for_all_2(fwd_ahf, bkd_ahf) 00247 std::cout << " " << fwd_ahf << '\t' << bkd_ahf << std::endl; 00248 } 00249 std::cout << std::endl; 00250 00251 // Iterate on the the set of (n+1)-faces *and* (n+1)-faces adjacent 00252 // to the faces of C. 00253 topo::adj_lower_higher_face_fwd_iter<D> fwd_alhf(fwd_f); 00254 topo::adj_lower_higher_face_bkd_iter<D> bkd_alhf(fwd_f); 00255 for_all(fwd_f) 00256 { 00257 std::cout << "Lower- and higher-dimension faces adjacent to " << fwd_f 00258 << ": " << std::endl; 00259 for_all_2(fwd_alhf, bkd_alhf) 00260 std::cout << " " << fwd_alhf << '\t' << bkd_alhf << std::endl; 00261 } 00262 std::cout << std::endl; 00263 00264 00265 // ------------------------------------------------------- // 00266 // Iterators on the the set of n-faces sharing an adjacent // 00267 // (n-1)-face or (n+1)-face with f, n being dynamic. // 00268 // ------------------------------------------------------- // 00269 00270 // For each face F of C, iterate on the the set of n-faces sharing 00271 // adjacent (n-1)-faces with F. 00272 topo::adj_lower_dim_connected_n_face_fwd_iter<D> fwd_aldcf(fwd_f); 00273 topo::adj_lower_dim_connected_n_face_bkd_iter<D> bkd_aldcf(fwd_f); 00274 for_all(fwd_f) 00275 { 00276 std::cout << "Lower-dim-connected faces adjacent to " << fwd_f 00277 << ": " << std::endl; 00278 for_all_2(fwd_aldcf, bkd_aldcf) 00279 std::cout << " " << fwd_aldcf << '\t' << bkd_aldcf << std::endl; 00280 } 00281 std::cout << std::endl; 00282 00283 // For each face F of C, iterate on the the set of n-faces sharing 00284 // adjacent (n+1)-faces with F. 00285 topo::adj_higher_dim_connected_n_face_fwd_iter<D> fwd_ahdcf(fwd_f); 00286 topo::adj_higher_dim_connected_n_face_bkd_iter<D> bkd_ahdcf(fwd_f); 00287 for_all(fwd_f) 00288 { 00289 std::cout << "Higher-dim-connected faces adjacent to " << fwd_f 00290 << ": " << std::endl; 00291 for_all_2(fwd_ahdcf, bkd_ahdcf) 00292 std::cout << " " << fwd_ahdcf << '\t' << bkd_ahdcf << std::endl; 00293 } 00294 std::cout << std::endl; 00295 00296 // For each face F of C, and for M in [0, D], iterate on the the set 00297 // of M-faces transitively adjacent to F. 00298 topo::adj_m_face_fwd_iter<D> fwd_amf(fwd_f, 0); 00299 topo::adj_m_face_bkd_iter<D> bkd_amf(fwd_f, 0); 00300 for_all(fwd_f) 00301 { 00302 for (unsigned m = 0; m <= D; ++m) 00303 { 00304 fwd_amf.set_m(m); 00305 bkd_amf.set_m(m); 00306 std::cout << m << "-faces (transitively) adjacent to " << fwd_f 00307 << ": " << std::endl; 00308 for_all_2(fwd_amf, bkd_amf) 00309 std::cout << " " << fwd_amf << '\t' << bkd_amf << std::endl; 00310 } 00311 std::cout << std::endl; 00312 } 00313 00314 00315 /* Next, write these: 00316 00317 ----------------------------------------------------------------- 00318 Name Definition 00319 ----------------------------------------------------------------- 00320 cell_fwd_iter<D>(c, f) | Iterators on the set of the 00321 cell_bkd_iter<D>(c, f) | faces in the « cell » 00322 | including p, i.e. the set of 00323 | all m-faces adjacent to p, 00324 | where m is in [0, n-1]; 00325 | this set is name « f-hat » 00326 00327 cell_boundary_fwd_iter<D>(c, f) | Likewise, but excluding p; 00328 cell_boundary_bkd_iter<D>(c, f) | this set is named « p-hat* » 00329 ----------------------------------------------------------------- 00330 00331 We could also have generic iterators based on predicated, and 00332 even use them to provide first (non efficient) implementations of 00333 the iterators from the previous list. 00334 00335 ----------------------------------------------------------------- 00336 Name Definition 00337 ----------------------------------------------------------------- 00338 generic_face_fwd_iter<D>(c, pred) | Generic face iterators on c 00339 generic_face_bkd_iter<D>(c, pred) | using predicate pred to 00340 | define the iterated subset. 00341 ----------------------------------------------------------------- 00342 00343 00344 I'm unsure about the old iterators on n-faces (with a static n) 00345 moved to the attic; should we keep them? What are they good for, 00346 except testing our code? At least, we should find better names 00347 for them, as we might confuse them with new iterators. 00348 00349 ----------------------------------------------------------------- 00350 Current name Definition 00351 ----------------------------------------------------------------- 00352 complex_faces_fwd_iter_<N, D> Iterators on N-faces, N being 00353 complex_faces_fwd_iter_<N, D> static, acting as proxies of 00354 n_face<N, D>'s. 00355 00356 faces_fwd_iter_<N, D> Iterators on N-faces, N being 00357 faces_fwd_iter_<N, D> static, acting as proxies of 00358 face<D>'s. 00359 ----------------------------------------------------------------- 00360 00361 See also https://trac.lrde.org/olena/wiki/Olena/ComplexBasedImages */ 00362 00363 00364 /*------------------. 00365 | Other iterators. | 00366 `------------------*/ 00367 00368 // For each face, iterate on itself. (This iterator is not 00369 // interesting as-is, but is useful when combined with others, 00370 // e.g. in topo::centered_iter_adapter). 00371 std::cout << "Center-only iterator:" << std::endl; 00372 topo::center_only_iter<D> center(fwd_f); 00373 for_all(fwd_f) 00374 for_all(center) 00375 std::cout << " " << center << std::endl; 00376 std::cout << std::endl; 00377 } 00378 00379 00380 template <unsigned N, unsigned D> 00381 void 00382 test_static_n_face_iter(topo::complex<D>& c) 00383 { 00384 std::cout << "test_static_n_face_iter<" << N << ", " << D << ">:" 00385 << std::endl; 00386 /* FIXME: Provide sugar. Maybe redefined mln_fwd_fiter and 00387 mln_bkd_fiter so that they expand as complex_faces_iters (instead 00388 of faces_iters). */ 00389 topo::static_n_face_fwd_iter<N, D> fwd_nf(c); 00390 topo::static_n_face_bkd_iter<N, D> bkd_nf(c); 00391 for_all_2(fwd_nf, bkd_nf) 00392 std::cout << fwd_nf << ' ' << bkd_nf << std::endl; 00393 std::cout << std::endl; 00394 } 00395 00396 // FIXME: Disabled (moved to the attic). 00397 # if 0 00398 template <unsigned N, unsigned D> 00399 void 00400 test_faces_iter(topo::complex<D>& c) 00401 { 00402 std::cout << "test_faces_iter<" << N << ", " << D << ">:" 00403 << std::endl; 00404 mln_fwd_fiter(N, topo::complex<D>) fwd_nf(c); 00405 mln_bkd_fiter(N, topo::complex<D>) bkd_nf(c); 00406 for_all_2(fwd_nf, bkd_nf) 00407 std::cout << fwd_nf << ' ' << bkd_nf << std::endl; 00408 std::cout << std::endl; 00409 } 00410 #endif