• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

complex.cc

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

Generated on Fri Sep 16 2011 16:33:24 for Milena (Olena) by  doxygen 1.7.1