* tests/io/off/load_save_bin.cc: New test.
* tests/io/off/Makefile.am (check_PROGRAMS): Add load_save_bin.
(load_save_bin_SOURCES): New.
---
milena/ChangeLog | 8 +++++
milena/tests/io/off/Makefile.am | 4 ++-
milena/tests/io/off/load_save_bin.cc | 50 ++++++++++++++++++++++++++++++++++
3 files changed, 61 insertions(+), 1 deletions(-)
create mode 100644 milena/tests/io/off/load_save_bin.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 50ba108..00d6b64 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -24,6 +24,14 @@
2008-10-22 Roland Levillain <roland(a)lrde.epita.fr>
+ Exercise mln::io::off:save.
+
+ * tests/io/off/load_save_bin.cc: New test.
+ * tests/io/off/Makefile.am (check_PROGRAMS): Add load_save_bin.
+ (load_save_bin_SOURCES): New.
+
+2008-10-22 Roland Levillain <roland(a)lrde.epita.fr>
+
Add a routine to save a complex-based image to an OFF file.
* mln/io/off/save.hh: New.
diff --git a/milena/tests/io/off/Makefile.am b/milena/tests/io/off/Makefile.am
index 4b592ce..30f4824 100644
--- a/milena/tests/io/off/Makefile.am
+++ b/milena/tests/io/off/Makefile.am
@@ -3,8 +3,10 @@
include $(top_srcdir)/milena/tests/tests.mk
check_PROGRAMS = \
- load_bin
+ load_bin \
+ load_save_bin
load_bin_SOURCES = load_bin.cc
+load_save_bin_SOURCES = load_save_bin.cc
TESTS = $(check_PROGRAMS)
diff --git a/milena/tests/io/off/load_save_bin.cc b/milena/tests/io/off/load_save_bin.cc
new file mode 100644
index 0000000..2dbbdcb
--- /dev/null
+++ b/milena/tests/io/off/load_save_bin.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/io/off/load_save_bin.cc
+/// \brief Test mln::io::off::load with and mln::io::off::save with an
+/// mln::bin_2complex_image3df.
+
+#include <algorithm>
+#include <iterator>
+#include <iostream>
+
+#include <mln/io/off/load.hh>
+#include <mln/io/off/save.hh>
+
+#include "tests/data.hh"
+
+
+int main()
+{
+ using namespace mln;
+
+ typedef bin_2complex_image3df ima_t;
+ ima_t ima;
+ io::off::load(ima, MLN_MESH_DIR "/tetrahedron.off");
+ io::off::save(ima, "out.off");
+}
--
1.6.0.1
* mln/io/off/save.hh: New.
---
milena/ChangeLog | 6 ++
milena/mln/io/off/save.hh | 197 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 203 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/io/off/save.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index cfd2a4f..50ba108 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -24,6 +24,12 @@
2008-10-22 Roland Levillain <roland(a)lrde.epita.fr>
+ Add a routine to save a complex-based image to an OFF file.
+
+ * mln/io/off/save.hh: New.
+
+2008-10-22 Roland Levillain <roland(a)lrde.epita.fr>
+
Enrich the interface of mln::util::multi_site.
* mln/util/multi_site.hh (mln::util::multi_site<P>::front):
diff --git a/milena/mln/io/off/save.hh b/milena/mln/io/off/save.hh
new file mode 100644
index 0000000..eba2aeb
--- /dev/null
+++ b/milena/mln/io/off/save.hh
@@ -0,0 +1,197 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_IO_OFF_SAVE_HH
+# define MLN_IO_OFF_SAVE_HH
+
+/// \file mln/io/off/save.hh
+/// \brief Input saving function for OFF files.
+///
+/// \see http://shape.cs.princeton.edu/benchmark/documentation/off_format.html
+
+# include <cstdlib>
+
+# include <iostream>
+# include <fstream>
+# include <sstream>
+
+# include <string>
+
+# include <mln/core/alias/bin_2complex_image3df.hh>
+# include <mln/core/image/complex_neighborhoods.hh>
+# include <mln/core/image/complex_neighborhood_piter.hh>
+
+
+namespace mln
+{
+
+ namespace io
+ {
+
+ namespace off
+ {
+
+ /** \brief Save a (binary) OFF image into a complex image.
+
+ \param[in] ima The image to save.
+ \param[in] filename The name of the file where to save the image.
+
+ The image is said binary since data only represent the
+ existence of faces. */
+ void save(const bin_2complex_image3df& ima, const std::string& filename);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ void save(const bin_2complex_image3df& ima, const std::string& filename)
+ {
+ const std::string me = "mln::io::off::save";
+
+ std::ofstream ostr(filename.c_str());
+ if (!ostr)
+ {
+ std::cerr << me << ": `" << filename << "' invalid file."
+ << std::endl;
+ /* FIXME: Too violent. We should allow the use of
+ exceptions, at least to have Milena's code behave
+ correctly in interpreted environments (std::exit() or
+ std::abort() causes the termination of a Python
+ interpreter, for instance!). */
+ std::exit(1);
+ }
+
+ /*---------.
+ | Header. |
+ `---------*/
+
+ /* ``The .off files in the Princeton Shape Benchmark conform
+ to the following standard. */
+
+ /* OFF files are all ASCII files beginning with the keyword
+ OFF. '' */
+ ostr << "OFF" << std::endl;
+
+ // A comment.
+ ostr << "# Generated by Milena 1.0 http://olena.lrde.epita.fr\n"
+ << "# EPITA Research and Development Laboratory (LRDE)"
+ << std::endl;
+
+ /* ``The next line states the number of vertices, the number
+ of faces, and the number of edges. The number of edges can
+ be safely ignored.'' */
+ /* FIXME: This is too long. We shall be able to write
+
+ ima.domain().nfaces<0>()
+
+ or even
+
+ ima.nfaces<0>().
+ */
+ ostr << ima.domain().cplx().nfaces<0>() << ' '
+ << ima.domain().cplx().nfaces<1>() << ' '
+ << ima.domain().cplx().nfaces<2>() << std::endl;
+
+ /*-------.
+ | Data. |
+ `-------*/
+
+ // --------- //
+ // Complex. //
+ // --------- //
+
+ typedef mln::bin_2complex_image3df I;
+ const unsigned D = I::dim;
+ typedef mln_geom_(I) G;
+
+ // ------------------------------------------ //
+ // Vertices & geometry (vertices locations). //
+ // ------------------------------------------ //
+
+ /* ``The vertices are listed with x, y, z coordinates, written
+ one per line. */
+
+ // Traverse the 0-faces (vertices).
+ p_n_faces_fwd_piter<D, G> v(ima.domain(), 0);
+ for_all(v)
+ {
+ mln_invariant(v.to_site().size() == 1);
+ ostr << v.to_site().front()[0] << ' '
+ << v.to_site().front()[1] << ' '
+ << v.to_site().front()[2] << std::endl;
+ }
+
+ // --------------- //
+ // Faces & edges. //
+ // --------------- //
+
+ /* After the list of vertices, the faces are listed, with one
+ face per line. For each face, the number of vertices is
+ specified, followed by indices into the list of
+ vertices.'' */
+
+ // Traverse the 2-faces (polygons).
+ p_n_faces_fwd_piter<D, G> f(ima.domain(), 2);
+
+ typedef complex_m_face_neighborhood<D, G> nbh_t;
+ // A neighborhood where neighbors are the set of 0-faces
+ // transitively adjacent to the reference point.
+ nbh_t nbh;
+ mln_fwd_niter_(nbh_t) u(nbh, f);
+ /* FIXME: We should be able to pas this value (m) either at
+ the construction of the neighborhood or at the construction
+ of the iterator. */
+ u.iter().set_m(0);
+
+ // For each (2-)face, iterate on (transitively) ajacent
+ // vertices (0-faces).
+ for_all(f)
+ {
+ unsigned nvertices = 0;
+ std::ostringstream vertices;
+ for_all(u)
+ {
+ // FIXME: Likewise, this is a bit too long...
+ vertices << ' ' << u.unproxy_().face().face_id();
+ ++nvertices;
+ }
+ ostr << nvertices << vertices.str() << std::endl;
+ }
+
+ ostr.close();
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::io::off
+
+ } // end of namespace mln::io
+
+} // end of namespace mln
+
+
+#endif // ! MLN_IO_OFF_SAVE_HH
--
1.6.0.1
* mln/geom/complex_geometry.hh
(mln::geom::complex_geometry<D, P>::operator()):
Use mln::topo::adj_m_face_fwd_iter to simplify the implementation
of this operator.
---
milena/ChangeLog | 9 ++++++
milena/mln/geom/complex_geometry.hh | 52 +++++-----------------------------
2 files changed, 17 insertions(+), 44 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 736c0cc..6c52239 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -24,6 +24,15 @@
2008-10-22 Roland Levillain <roland(a)lrde.epita.fr>
+ Simplify mln::geom::complex_geometry.
+
+ * mln/geom/complex_geometry.hh
+ (mln::geom::complex_geometry<D, P>::operator()):
+ Use mln::topo::adj_m_face_fwd_iter to simplify the implementation
+ of this operator.
+
+2008-10-22 Roland Levillain <roland(a)lrde.epita.fr>
+
Exercise iterators on transitively adjacent m-faces.
* tests/topo/complex.cc: Here.
diff --git a/milena/mln/geom/complex_geometry.hh b/milena/mln/geom/complex_geometry.hh
index 2e44ad4..1634a65 100644
--- a/milena/mln/geom/complex_geometry.hh
+++ b/milena/mln/geom/complex_geometry.hh
@@ -38,6 +38,7 @@
# include <set>
# include <mln/topo/face.hh>
+# include <mln/topo/adj_m_face_iter.hh>
# include <mln/util/multi_site.hh>
# include <mln/util/tracked_ptr.hh>
@@ -162,56 +163,19 @@ namespace mln
}
else
{
- // F is an n-face, with n > 0.
- typedef std::vector < topo::face<D> > faces_t;
- typedef std::set < topo::face<D> > faces_set_t;
-
- // The adjacent m-faces.
- faces_t m_faces = f.lower_dim_adj_faces();
- // The set of (m-1)-face being built.
- /* FIXME: This pattern is recurring in Milena---using an
- std::set (or any fast associative container) to improve
- the lookup speed of an std::vector; we should create a
- class for this, a bit like mln::util::set, but with a
- garantee on the order of insertion. */
- faces_t work_faces;
- faces_set_t work_faces_set;
-
- // Iteratively compute the set of locations.
- for (unsigned m = f.n() - 1; m > 0; --m)
- {
- for (typename faces_t::const_iterator g = m_faces.begin();
- g != m_faces.end(); ++g)
- {
- faces_t m_minus_one_faces = g->lower_dim_adj_faces();
- // Don't insert a face twice.
- for (typename faces_t::const_iterator h =
- m_minus_one_faces.begin();
- h != m_minus_one_faces.end(); ++h)
- if (work_faces_set.find(*h) == work_faces_set.end())
- {
- work_faces.push_back(*h);
- work_faces_set.insert(*h);
- }
- }
- work_faces.swap(m_faces);
- work_faces.clear();
- work_faces_set.clear();
- }
- for (typename faces_t::const_iterator g = m_faces.begin();
- g != m_faces.end(); ++g)
- {
- mln_assertion(g->face_id() < data_->zero_faces.size());
- s.push_back(data_->zero_faces[g->face_id()]);
- }
+ /* F is an n-face, with n > 0.
+ Compute the set of 0-faces transitively adjacent to F. */
+ topo::adj_m_face_fwd_iter<D> g(f, 0);
+ for_all(g)
+ s.push_back(data_->zero_faces[g.face().face_id()]);
}
return s;
}
# endif // ! MLN_INCLUDE_ONLY
- } // end of mln::geom
+ } // end of mln::geom
- } // end of mln
+} // end of mln
#endif // MLN_GEOM_COMPLEX_GEOMETRY_HH
--
1.6.0.1
* mln/topo/adj_m_face_iter.hh: New.
Include this file...
* mln/topo/complex_iterators.hh: ...here.
Include also mln/topo/center_only_iter.hh.
---
milena/ChangeLog | 9 +
milena/mln/topo/adj_m_face_iter.hh | 342 ++++++++++++++++++++++++++++++++++
milena/mln/topo/complex_iterators.hh | 17 ++
3 files changed, 368 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/topo/adj_m_face_iter.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 16ddcbb..dbe1c06 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -24,6 +24,15 @@
2008-10-22 Roland Levillain <roland(a)lrde.epita.fr>
+ Add a complex relative iterator on transitively adjacent m-faces.
+
+ * mln/topo/adj_m_face_iter.hh: New.
+ Include this file...
+ * mln/topo/complex_iterators.hh: ...here.
+ Include also mln/topo/center_only_iter.hh.
+
+2008-10-22 Roland Levillain <roland(a)lrde.epita.fr>
+
Supplement complex-based image.
* mln/core/image/complex_image.hh
diff --git a/milena/mln/topo/adj_m_face_iter.hh b/milena/mln/topo/adj_m_face_iter.hh
new file mode 100644
index 0000000..f54a341
--- /dev/null
+++ b/milena/mln/topo/adj_m_face_iter.hh
@@ -0,0 +1,342 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_TOPO_ADJ_M_FACE_ITER_HH
+# define MLN_TOPO_ADJ_M_FACE_ITER_HH
+
+/// \file mln/topo/adj_m_face_iter.hh
+
+/// \brief Definition of forward and backward iterators on all the
+/// m-faces transitively adjacent to a (reference) n-face in a
+/// complex.
+
+# include <set>
+
+# include <mln/topo/internal/complex_relative_iterator_base.hh>
+# include <mln/topo/face.hh>
+
+
+namespace mln
+{
+
+ namespace topo
+ {
+
+ // Forward declarations.
+ template <unsigned D> class complex;
+ namespace internal
+ {
+ template <unsigned D> class adj_m_face_iterator;
+ }
+
+
+ /*-------------------------------.
+ | topo::adj_m_face_fwd_iter<D>. |
+ `-------------------------------*/
+
+ /** \brief Forward iterator on all the m-faces transitively
+ adjacent to a (reference) n-face in a complex.
+
+ \tparam D The dimension of the complex this iterator belongs to.
+
+ The dimension parameter (\a m_) must be lower or equal to D.
+
+ If \a m_ is equal to the dimension of the reference face, then
+ the iterated set is empty. */
+ template <unsigned D>
+ class adj_m_face_fwd_iter
+ : public internal::forward_complex_relative_iterator_base< face<D>,
+ adj_m_face_fwd_iter<D> >,
+ public internal::adj_m_face_iterator<D>
+ {
+ private:
+ typedef adj_m_face_fwd_iter<D> self_;
+ typedef internal::forward_complex_relative_iterator_base< face<D>,
+ self_ > super_;
+ typedef internal::adj_m_face_iterator<D> impl_;
+
+ public:
+ /// Construction.
+ /// \{
+ /// Construct an iterator, with an invalid reference face, and
+ /// a target dimension equal to 0.
+ adj_m_face_fwd_iter();
+ /// Constructs an iterator, with \a f_ref as reference face, and
+ /// a target dimension equal to \a m.
+ template <typename Fref>
+ adj_m_face_fwd_iter(const Fref& f_ref, unsigned m);
+ /// \}
+
+ /// \brief Compute the set of faces adjacent to the reference face.
+ ///
+ /// The computation is delegated to
+ /// mln::topo::internal::adj_m_face_iterator.
+ void update_adj_faces_();
+ };
+
+
+ /*-------------------------------.
+ | topo::adj_m_face_bkd_iter<D>. |
+ `-------------------------------*/
+
+ /** \brief Backward iterator on all the m-faces transitively
+ adjacent to a (reference) n-face in a complex.
+
+ \tparam D The dimension of the complex this iterator belongs to.
+
+ The dimension parameter (\a m_) must be lower or equal to D.
+
+ If \a m_ is equal to the dimension of the reference face, then
+ the iterated set is empty. */
+ template <unsigned D>
+ class adj_m_face_bkd_iter
+ : public internal::backward_complex_relative_iterator_base< face<D>,
+ adj_m_face_bkd_iter<D> >,
+ public internal::adj_m_face_iterator<D>
+ {
+ private:
+ typedef adj_m_face_bkd_iter<D> self_;
+ typedef internal::backward_complex_relative_iterator_base< face<D>,
+ self_ > super_;
+ typedef internal::adj_m_face_iterator<D> impl_;
+
+ public:
+ /// Construction.
+ /// \{
+ /// Construct an iterator, with an invalid reference face, and
+ /// a target dimension equal to 0.
+ adj_m_face_bkd_iter();
+ /// Constructs an iterator, with \a f_ref as reference face, and
+ /// a target dimension equal to \a m.
+ template <typename Fref>
+ adj_m_face_bkd_iter(const Fref& f_ref, unsigned m);
+ /// \}
+
+ /// \brief Compute the set of faces adjacent to the reference face.
+ ///
+ /// The computation is delegated to
+ /// mln::topo::internal::adj_m_face_iterator.
+ void update_adj_faces_();
+ };
+
+
+ /*-----------------------------------------.
+ | topo::internal::adj_m_face_iterator<D>. |
+ `-----------------------------------------*/
+
+ namespace internal
+ {
+
+ template <unsigned D>
+ class adj_m_face_iterator
+ {
+ protected:
+ adj_m_face_iterator();
+ adj_m_face_iterator(unsigned m);
+
+ public:
+ /// Get the target dimension.
+ unsigned m() const;
+ /// Set the target dimension.
+ void set_m(unsigned m);
+
+ protected:
+ /// The actual implementation of the computation of the set of
+ /// faces adjacent to the reference face.
+ void update_adj_faces__(const face<D>& center,
+ std::vector< face<D> >& adj_faces);
+
+ /// The dimension of the iterated faces.
+ unsigned m_;
+ };
+
+ } // end of namespace mln::topo::internal
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ /*-------------------------------.
+ | topo::adj_m_face_fwd_iter<D>. |
+ `-------------------------------*/
+
+ template <unsigned D>
+ inline
+ adj_m_face_fwd_iter<D>::adj_m_face_fwd_iter()
+ {
+ }
+
+ template <unsigned D>
+ template <typename Fref>
+ inline
+ adj_m_face_fwd_iter<D>::adj_m_face_fwd_iter(const Fref& f_ref, unsigned m)
+ : super_(f_ref), impl_(m)
+ {
+ }
+
+ template <unsigned D>
+ inline
+ void
+ adj_m_face_fwd_iter<D>::update_adj_faces_()
+ {
+ mln_precondition(this->c_);
+ // Delegate computation to base class.
+ this->update_adj_faces__(*this->c_, this->adj_faces_);
+ }
+
+
+ /*-------------------------------.
+ | topo::adj_m_face_bkd_iter<D>. |
+ `-------------------------------*/
+
+ template <unsigned D>
+ inline
+ adj_m_face_bkd_iter<D>::adj_m_face_bkd_iter()
+ {
+ }
+
+ template <unsigned D>
+ template <typename Fref>
+ inline
+ adj_m_face_bkd_iter<D>::adj_m_face_bkd_iter(const Fref& f_ref, unsigned m)
+ : super_(f_ref), impl_(m)
+ {
+ }
+
+ template <unsigned D>
+ inline
+ void
+ adj_m_face_bkd_iter<D>::update_adj_faces_()
+ {
+ mln_precondition(this->c_);
+ // Delegate computation to base class.
+ this->update_adj_faces__(*this->c_, this->adj_faces_);
+ }
+
+
+ /*-----------------------------------------.
+ | topo::internal::adj_m_face_iterator<D>. |
+ `-----------------------------------------*/
+
+ namespace internal
+ {
+
+ template <unsigned D>
+ inline
+ adj_m_face_iterator<D>::adj_m_face_iterator()
+ : m_(0)
+ {
+ }
+
+ template <unsigned D>
+ inline
+ adj_m_face_iterator<D>::adj_m_face_iterator(unsigned m)
+ : m_(m)
+ {
+ mln_precondition(m <= D);
+ }
+
+ template <unsigned D>
+ unsigned
+ adj_m_face_iterator<D>::m() const
+ {
+ return m_;
+ }
+
+ template <unsigned D>
+ void
+ adj_m_face_iterator<D>::set_m(unsigned m)
+ {
+ m_ = m;
+ }
+
+ template <unsigned D>
+ inline
+ void
+ adj_m_face_iterator<D>::update_adj_faces__(const face<D>& center,
+ std::vector< face<D> >& adj_faces)
+ {
+ adj_faces.clear();
+
+ if (center.n() == m_)
+ return;
+
+ typedef std::vector < topo::face<D> > faces_t;
+ typedef std::set < topo::face<D> > faces_set_t;
+
+ /* FIXME: p_faces is redundant; we could use adj_faces
+ directly. */
+ /* The adjacent p-faces being built; initialized with CENTER,
+ and filled with q-faces at each step, until q reaches
+ m_. */
+ faces_t p_faces(1, center);
+ // The set of faces being built.
+ /* FIXME: This pattern is recurring in Milena---using an
+ std::set (or any fast associative container) to improve
+ the lookup speed of an std::vector; we should create a
+ class for this, a bit like mln::util::set, but with a
+ garantee on the order of insertion. */
+ faces_t work_faces;
+ faces_set_t work_faces_set;
+
+ // Iteratively compute the set of locations.
+ for (unsigned p = center.n(); p != m_; (p < m_ ? ++p : --p) )
+ {
+ mln_invariant (p != m_);
+ for (typename faces_t::const_iterator g = p_faces.begin();
+ g != p_faces.end(); ++g)
+ {
+ mln_invariant (g->n() != m_);
+ faces_t q_faces = g->n() < m_ ?
+ g->higher_dim_adj_faces() :
+ g->lower_dim_adj_faces();
+ // Don't insert a face twice.
+ for (typename faces_t::const_iterator h = q_faces.begin();
+ h != q_faces.end(); ++h)
+ if (work_faces_set.find(*h) == work_faces_set.end())
+ {
+ work_faces.push_back(*h);
+ work_faces_set.insert(*h);
+ }
+ }
+ work_faces.swap(p_faces);
+ work_faces.clear();
+ work_faces_set.clear();
+ }
+
+ adj_faces = p_faces;
+ }
+
+ } // end of namespace mln::topo::internal
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::topo
+
+} // end of namespace mln
+
+#endif // ! MLN_TOPO_ADJ_LOWER_DIM_CONNECTED_N_FACE_ITER_HH
diff --git a/milena/mln/topo/complex_iterators.hh b/milena/mln/topo/complex_iterators.hh
index 0db739c..8a01b78 100644
--- a/milena/mln/topo/complex_iterators.hh
+++ b/milena/mln/topo/complex_iterators.hh
@@ -33,6 +33,10 @@
///
/// This file includes all iterators on faces.
+/*-----------------------------.
+| Iterators on sets of faces. |
+`-----------------------------*/
+
# include <mln/topo/face_iter.hh>
# include <mln/topo/n_face_iter.hh>
# include <mln/topo/static_n_face_iter.hh>
@@ -41,10 +45,23 @@
# include <mln/topo/faces_iter.hh>
# endif
+/*---------------------.
+| Relative iterators. |
+`---------------------*/
+
# include <mln/topo/adj_lower_face_iter.hh>
# include <mln/topo/adj_higher_face_iter.hh>
# include <mln/topo/adj_lower_higher_face_iter.hh>
+
# include <mln/topo/adj_lower_dim_connected_n_face_iter.hh>
# include <mln/topo/adj_higher_dim_connected_n_face_iter.hh>
+# include <mln/topo/adj_m_face_iter.hh>
+
+/*--------------------.
+| Special iterators. |
+`--------------------*/
+
+# include <mln/topo/center_only_iter.hh>
+
#endif // ! MLN_TOPO_COMPLEX_ITERATORS_HH
--
1.6.0.1