* apps/mesh-segm-skel/mesh-complex-2-collapse.cc: New.
* apps/mesh-segm-skel/test-mesh-complex-2-collapse.in: New.
* apps/mesh-segm-skel/Makefile.am (bin_PROGRAMS):
Add mesh-complex-2-collapse.
(mesh_complex_2_collapse_SOURCES): New.
(edit): New.
(test-mesh-complex-2-collapse): New target.
(TESTS, CLEANFILES): Add test-mesh-complex-2-collapse.
(MOSTLYCLEANFILES): Add pseudo-manifold-2-collapse.vtk.
---
milena/ChangeLog | 14 ++
milena/apps/mesh-segm-skel/Makefile.am | 34 ++++-
.../apps/mesh-segm-skel/mesh-complex-2-collapse.cc | 155 ++++++++++++++++++++
...max-curv.in => test-mesh-complex-2-collapse.in} | 4 +-
4 files changed, 203 insertions(+), 4 deletions(-)
create mode 100644 milena/apps/mesh-segm-skel/mesh-complex-2-collapse.cc
copy milena/apps/mesh-segm-skel/{test-mesh-max-curv.in => test-mesh-complex-2-collapse.in} (80%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 4998388..010bf56 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,19 @@
2011-03-14 Roland Levillain <roland(a)lrde.epita.fr>
+ New app performing a 2-collapse on a mesh.
+
+ * apps/mesh-segm-skel/mesh-complex-2-collapse.cc: New.
+ * apps/mesh-segm-skel/test-mesh-complex-2-collapse.in: New.
+ * apps/mesh-segm-skel/Makefile.am (bin_PROGRAMS):
+ Add mesh-complex-2-collapse.
+ (mesh_complex_2_collapse_SOURCES): New.
+ (edit): New.
+ (test-mesh-complex-2-collapse): New target.
+ (TESTS, CLEANFILES): Add test-mesh-complex-2-collapse.
+ (MOSTLYCLEANFILES): Add pseudo-manifold-2-collapse.vtk.
+
+2011-03-14 Roland Levillain <roland(a)lrde.epita.fr>
+
Prevent a site from being introduced twice in thinning's queues.
* mln/topo/skeleton/breadth_first_thinning.hh,
diff --git a/milena/apps/mesh-segm-skel/Makefile.am b/milena/apps/mesh-segm-skel/Makefile.am
index 5dda5ec..d68ae7c 100644
--- a/milena/apps/mesh-segm-skel/Makefile.am
+++ b/milena/apps/mesh-segm-skel/Makefile.am
@@ -179,8 +179,38 @@ MOSTLYCLEANFILES += \
socket-complex-pinv-curv-segm.off \
teapot-complex-pinv-curv-segm.off
-## Skeletonization.
-## ----------------
+## Collapses.
+## ----------
+
+## FIXME: Generalize the generation of tests by make instead of
+## configure.
+# Use Make to generate tests instead of `configure', as advised by
+# Autoconf's manual (see section ``Installation Directory
+# Variables'').
+edit = sed \
+ -e 's|@top_srcdir[@]|$(top_srcdir)|g' \
+ -e 's|@abs_srcdir[@]|$(abs_srcdir)|g' \
+ -e 's|@abs_builddir[@]|$(abs_builddir)|g' \
+ -e 's|@abs_top_builddir[@]|$(abs_top_builddir)|g'
+
+# Performing a 2-collapse on a pseudo-manifold.
+bin_PROGRAMS += mesh-complex-2-collapse
+mesh_complex_2_collapse_SOURCES = mesh-complex-2-collapse.cc
+
+test-mesh-complex-2-collapse: test-mesh-complex-2-collapse.in Makefile
+ rm -f $@ $@.tmp
+ srcdir=''; \
+ test -f ./$< || srcdir=$(srcdir)/; \
+ $(edit) $${srcdir}$< >>$@.tmp
+ chmod a-w,a+x $@.tmp
+ mv $@.tmp $@
+
+TESTS += test-mesh-complex-2-collapse
+CLEANFILES = test-mesh-complex-2-collapse
+MOSTLYCLEANFILES += pseudo-manifold-2-collapse.vtk
+
+## More complex skeletonization chains.
+## ------------------------------------
# Skeletonization program working on precomputed meshes with curvatures data.
bin_PROGRAMS += mesh-complex-skel
diff --git a/milena/apps/mesh-segm-skel/mesh-complex-2-collapse.cc b/milena/apps/mesh-segm-skel/mesh-complex-2-collapse.cc
new file mode 100644
index 0000000..acc053b
--- /dev/null
+++ b/milena/apps/mesh-segm-skel/mesh-complex-2-collapse.cc
@@ -0,0 +1,155 @@
+// Copyright (C) 2008, 2009, 2011 EPITA Research and Development
+// Laboratory (LRDE)
+//
+// This file is part of the Milena 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
+/// \brief A program computing the ultimate 2-collapse of a triangle
+/// mesh.
+
+#include <iostream>
+
+#include <mln/core/image/complex_image.hh>
+#include <mln/core/image/complex_neighborhoods.hh>
+
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/core/image/dmorph/sub_image.hh>
+#include <mln/core/image/dmorph/mutable_extension_ima.hh>
+#include <mln/core/routine/mutable_extend.hh>
+#include <mln/data/paste.hh>
+
+#include <mln/topo/is_n_face.hh>
+#include <mln/topo/is_simple_pair.hh>
+#include <mln/topo/detach_pair.hh>
+#include <mln/topo/skeleton/breadth_first_thinning.hh>
+
+#include <mln/io/vtk/load.hh>
+#include <mln/io/vtk/save.hh>
+
+
+int
+main(int argc, char* argv[])
+{
+ if (argc != 3)
+ {
+ std::cerr << "usage: " << argv[0] << " input.vtk output.vtk"
+ << std::endl;
+ std::exit(1);
+ }
+
+ std::string input_filename = argv[1];
+ std::string output_filename = argv[2];
+
+ /*----------------------.
+ | Complex input image. |
+ `----------------------*/
+
+ // Image type.
+ typedef mln::bin_2complex_image3df ima_t;
+ // Dimension of the image (and thus of the complex).
+ static const unsigned D = ima_t::dim;
+ // Geometry of the image.
+ typedef mln_geom_(ima_t) G;
+
+ ima_t ima;
+ mln::io::vtk::load(ima, input_filename);
+
+ /*-------------.
+ | 2-collapse. |
+ `-------------*/
+
+ // ------------------------------- //
+ // Image restricted to triangles. //
+ // ------------------------------- //
+
+ // Predicate type: is a face a triangle (2-face)?
+ typedef mln::topo::is_n_face<mln_psite_(ima_t), D> is_a_triangle_t;
+ is_a_triangle_t is_a_triangle;
+ // Surface image type, of which domain is restricted to triangles.
+ typedef mln::image_if<ima_t, is_a_triangle_t> triangle_only_ima_t;
+ // Surface image type, of which iteration (not domain) is restricted
+ // to triangles.
+ typedef mln::mutable_extension_ima<triangle_only_ima_t, ima_t>
+ triangle_ima_t;
+
+ // ------------------------ //
+ // Simple point predicate. //
+ // ------------------------ //
+
+ // Neighborhood type returning the set of (n-1)-faces adjacent to a
+ // an n-face.
+ typedef mln::complex_lower_neighborhood<D, G> lower_adj_nbh_t;
+ lower_adj_nbh_t lower_adj_nbh;
+ // Neighborhood type returning the set of (n+1)-faces adjacent to a
+ // an n-face.
+ typedef mln::complex_higher_neighborhood<D, G> higher_adj_nbh_t;
+ higher_adj_nbh_t higher_adj_nbh;
+ // Predicate type: is a triangle (2-face) simple?
+ typedef mln::topo::is_simple_pair< triangle_ima_t,
+ lower_adj_nbh_t,
+ higher_adj_nbh_t >
+ is_simple_triangle_t;
+ is_simple_triangle_t is_simple_triangle(lower_adj_nbh, higher_adj_nbh);
+
+ // ------------------------------- //
+ // Simple point detach procedure. //
+ // ------------------------------- //
+
+ // Functor detaching a cell.
+ typedef mln::topo::detach_pair< triangle_ima_t,
+ lower_adj_nbh_t,
+ higher_adj_nbh_t > detach_t;
+ detach_t detach(lower_adj_nbh, higher_adj_nbh);
+
+ // ------------------------ //
+ // Thinning by 2-collapse. //
+ // ------------------------ //
+
+ /// Adjacent triangles are connected by shared edges.
+ typedef mln::complex_lower_dim_connected_n_face_neighborhood<D, G> nbh_t;
+ nbh_t nbh;
+
+ mln_concrete_(ima_t) skel;
+ mln::initialize(skel, ima);
+ mln::data::paste
+ (mln::topo::skeleton::breadth_first_thinning
+ (mln::mutable_extend((ima | is_a_triangle).rw(), ima),
+ nbh,
+ is_simple_triangle,
+ detach)
+ /* Before pasting the result of the computation into SKEL,
+ re-expand its domain to the initial site set, to ensure data
+ from all faces (i.e., both the 2-faces, directly processed;
+ and the 1-faces from the extension, undirectly processed). */
+ | ima.domain(),
+ skel);
+
+ /*---------.
+ | Output. |
+ `---------*/
+
+ mln::io::vtk::save(skel, output_filename);
+}
diff --git a/milena/apps/mesh-segm-skel/test-mesh-max-curv.in b/milena/apps/mesh-segm-skel/test-mesh-complex-2-collapse.in
similarity index 80%
copy from milena/apps/mesh-segm-skel/test-mesh-max-curv.in
copy to milena/apps/mesh-segm-skel/test-mesh-complex-2-collapse.in
index e5eaf96..d2a286b 100644
--- a/milena/apps/mesh-segm-skel/test-mesh-max-curv.in
+++ b/milena/apps/mesh-segm-skel/test-mesh-complex-2-collapse.in
@@ -1,6 +1,6 @@
#! /bin/sh
-# Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE).
+# Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -20,4 +20,4 @@ set -ex
mesh_dir=@top_srcdir@/milena/mesh
-time ./mesh-max-curv $mesh_dir/teapot.off teapot-max-curv.off
+time ./mesh-complex-2-collapse $mesh_dir/pseudo-manifold.vtk pseudo-manifold-2-collapse.vtk
--
1.5.6.5
* mln/topo/is_simple_pair.hh,
* mln/topo/detach_pair.hh:
New.
* tests/topo/is_simple_pair.cc,
* tests/topo/detach_pair.cc:
New tests.
* tests/topo/Makefile.am (check_PROGRAMS): Add is_simple_pair and
detach_pair.
(detach_pair_SOURCES, is_simple_pair_SOURCES): New.
(MOSTLYCLEANFILES): New. Add detach_pair-out.vtk.
---
milena/ChangeLog | 15 ++
milena/mln/topo/detach_pair.hh | 191 +++++++++++++++++
milena/mln/topo/is_simple_pair.hh | 225 ++++++++++++++++++++
milena/tests/topo/Makefile.am | 8 +-
.../{io/vtk/load_bin.cc => topo/detach_pair.cc} | 55 +++--
.../{io/vtk/load_bin.cc => topo/is_simple_pair.cc} | 43 +++--
6 files changed, 500 insertions(+), 37 deletions(-)
create mode 100644 milena/mln/topo/detach_pair.hh
create mode 100644 milena/mln/topo/is_simple_pair.hh
copy milena/tests/{io/vtk/load_bin.cc => topo/detach_pair.cc} (51%)
copy milena/tests/{io/vtk/load_bin.cc => topo/is_simple_pair.cc} (53%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index b1b2d74..214ccdc 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,18 @@
+2011-03-14 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Add routines to identify and detach (collapse) simple pairs.
+
+ * mln/topo/is_simple_pair.hh,
+ * mln/topo/detach_pair.hh:
+ New.
+ * tests/topo/is_simple_pair.cc,
+ * tests/topo/detach_pair.cc:
+ New tests.
+ * tests/topo/Makefile.am (check_PROGRAMS): Add is_simple_pair and
+ detach_pair.
+ (detach_pair_SOURCES, is_simple_pair_SOURCES): New.
+ (MOSTLYCLEANFILES): New. Add detach_pair-out.vtk.
+
2011-03-01 Roland Levillain <roland(a)lrde.epita.fr>
Add preliminary VTK input for binary images.
diff --git a/milena/mln/topo/detach_pair.hh b/milena/mln/topo/detach_pair.hh
new file mode 100644
index 0000000..a40bd5c
--- /dev/null
+++ b/milena/mln/topo/detach_pair.hh
@@ -0,0 +1,191 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_TOPO_DETACH_PAIR_HH
+# define MLN_TOPO_DETACH_PAIR_HH
+
+/// \file
+/// \brief Detaching a simple pair from a binary (probably
+/// complex-based) image (elementary collapse operation).
+
+# include <mln/core/concept/function.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/topo/is_simple_pair.hh>
+
+
+namespace mln
+{
+
+ namespace topo
+ {
+
+ /** \ brief A functor detaching a simple pair from a binary
+ (probably complex-based) image (elementary collapse
+ operation).
+
+ \tparam I The type of the image.
+ \tparam NL The neighborhood type returning the set of
+ (n-1)-faces adjacent to a an n-face.
+ \tparam NH The neighborhood type returning the set of
+ (n+1)-faces adjacent to a an n-face. */
+ template <typename I, typename NL, typename NH>
+ class detach_pair
+ {
+ public:
+ /// Constructors.
+ /// \{
+ /** Construct an mln::topo::detach_pair from a couple of
+ neighborhoods.
+
+ \param lower_adj_nbh An adjacency relationship between faces
+ returning the set of (n-1)-faces
+ adjacent to a given n-face.
+ \param higher_adj_nbh An adjacency relationship between faces
+ returning the set of (n+1)-faces
+ adjacent to a given n-face. */
+ detach_pair(const Neighborhood<NL>& lower_adj_nbh,
+ const Neighborhood<NH>& higher_adj_nbh);
+
+ /** Construct an mln::topo::detach_pair from an image and a
+ couple of neighborhoods.
+
+ \pre \a ima is an image of Boolean values.
+
+ \param ima The input image from which the pair is
+ to be detached.
+ \param lower_adj_nbh An adjacency relationship between faces
+ returning the set of (n-1)-faces
+ adjacent to a given n-face.
+ \param higher_adj_nbh An adjacency relationship between faces
+ returning the set of (n+1)-faces
+ adjacent to a given n-face. */
+ detach_pair(mln::Image<I>& ima,
+ const Neighborhood<NL>& lower_adj_nbh,
+ const Neighborhood<NH>& higher_adj_nbh);
+ /// \}
+
+ /* FIXME: Rename as init() or something like this? See how other
+ functors are written. */
+ /// Set the underlying image.
+ void set_image(mln::Image<I>& ima);
+
+ /** Detach the pair (\a f, \a q) from \a ima_.
+
+ \param f An n-facet of \a ima
+ \param g An (n-1)-face ajacent to \a f. */
+ void operator()(const mln_psite(I)& f, const mln_psite(I)& g);
+
+ /** Detach a simple pair from \a ima_ containing the face \a f.
+
+ \param f An n-facet of \a ima. */
+ void operator()(const mln_psite(I)& f);
+
+ private:
+ I* ima_;
+ const NL& lower_adj_nbh_;
+ const NH& higher_adj_nbh_;
+ /// Simplicity citerion.
+ is_simple_pair<I, NL, NH> is_simple_;
+ };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I, typename NL, typename NH>
+ inline
+ detach_pair<I, NL, NH>::detach_pair(const Neighborhood<NL>& lower_adj_nbh,
+ const Neighborhood<NH>& higher_adj_nbh)
+ : ima_(0),
+ lower_adj_nbh_(exact(lower_adj_nbh)),
+ higher_adj_nbh_(exact(higher_adj_nbh)),
+ is_simple_(lower_adj_nbh, higher_adj_nbh)
+ {
+ mlc_equal(mln_value(I), bool)::check();
+ }
+
+ template <typename I, typename NL, typename NH>
+ inline
+ detach_pair<I, NL, NH>::detach_pair(mln::Image<I>& ima,
+ const Neighborhood<NL>& lower_adj_nbh,
+ const Neighborhood<NH>& higher_adj_nbh)
+ : ima_(exact(&ima)),
+ lower_adj_nbh_(exact(lower_adj_nbh)),
+ higher_adj_nbh_(exact(higher_adj_nbh)),
+ is_simple_(ima, lower_adj_nbh, higher_adj_nbh)
+ {
+ mlc_equal(mln_value(I), bool)::check();
+ }
+
+ template <typename I, typename NL, typename NH>
+ inline
+ void
+ detach_pair<I, NL, NH>::set_image(mln::Image<I>& ima)
+ {
+ ima_ = exact(&ima);
+ is_simple_.set_image(ima);
+ }
+
+ template <typename I, typename NL, typename NH>
+ inline
+ void
+ detach_pair<I, NL, NH>::operator()(const mln_psite(I)& f,
+ const mln_psite(I)& g)
+ {
+ mln_precondition(ima_);
+ mln_precondition(is_simple_(f, g));
+
+ // Shortcut.
+ // FIXME: Introduce an `ima()' accessor instead?
+ I& ima = *ima_;
+
+ ima(f) = false;
+ ima(g) = false;
+ }
+
+ // FIXME: What about moving this operator() into its own functor?
+ template <typename I, typename NL, typename NH>
+ inline
+ void
+ detach_pair<I, NL, NH>::operator()(const mln_psite(I)& f)
+ {
+ mln_niter(NL) g(lower_adj_nbh_, f);
+ for_all(g)
+ {
+ if (is_simple_(f, g))
+ // Delegate the detach operation to the binary operator().
+ return (*this)(f, g);
+ }
+ }
+
+# endif // MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::topo
+
+} // end of namespace mln
+
+#endif // ! MLN_TOPO_DETACH_PAIR_HH
diff --git a/milena/mln/topo/is_simple_pair.hh b/milena/mln/topo/is_simple_pair.hh
new file mode 100644
index 0000000..2b5d89b
--- /dev/null
+++ b/milena/mln/topo/is_simple_pair.hh
@@ -0,0 +1,225 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_TOPO_IS_SIMPLE_PAIR_HH
+# define MLN_TOPO_IS_SIMPLE_PAIR_HH
+
+/// \file
+/// \brief Testing whether a pair of faces is simple (or whether a
+/// face belongs to a simple pair)
+
+# include <mln/core/concept/function.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/topo/is_facet.hh>
+
+
+namespace mln
+{
+
+ namespace topo
+ {
+
+ /** \brief A predicate for the simplicity of a pair (or a face
+ that might belong to a simple pair).
+
+ The functor may either take a pair composed of an n-face F and
+ an (n-1)-face G (where F is a facet), or just a single facet
+ F. In this latter case, it tries to find an (n-1)-face G so
+ that (F, G) form a simple pair.
+
+ \tparam I The type of the image.
+ \tparam NL The neighborhood type returning the set of
+ (n-1)-faces adjacent to a an n-face.
+ \tparam NH The neighborhood type returning the set of
+ (n+1)-faces adjacent to a an n-face. */
+ template <typename I, typename NL, typename NH>
+ class is_simple_pair
+ : public mln::Function_v2b< is_simple_pair<I, NL, NH> >
+ {
+ public:
+ /// Result type of the functor.
+ typedef bool result;
+
+ /// Constructors.
+ /// \{
+ /** Construct an mln::topo::is_simple_pair from a couple of
+ neighborhoods.
+
+ \param lower_adj_nbh An adjacency relationship between faces
+ returning the set of (n-1)-faces
+ adjacent to a given n-face.
+ \param higher_adj_nbh An adjacency relationship between faces
+ returning the set of (n+1)-faces
+ adjacent to a given n-face. */
+ is_simple_pair(const Neighborhood<NL>& lower_adj_nbh,
+ const Neighborhood<NH>& higher_adj_nbh);
+
+ /** Construct an mln::topo::detach_pair from an image and a
+ couple of neighborhoods.
+
+ \pre \a ima is an image of Boolean values.
+
+ \param ima The input image the pair belongs to.
+ \param lower_adj_nbh An adjacency relationship between faces
+ returning the set of (n-1)-faces
+ adjacent to a given n-face.
+ \param higher_adj_nbh An adjacency relationship between faces
+ returning the set of (n+1)-faces
+ adjacent to a given n-face. */
+ is_simple_pair(const mln::Image<I>& ima,
+ const Neighborhood<NL>& lower_adj_nbh,
+ const Neighborhood<NH>& higher_adj_nbh);
+ /// \}
+
+ /* FIXME: Rename as init() or something like this? See how other
+ functors are written. */
+ /// Set the underlying image.
+ void set_image(const mln::Image<I>& ima);
+
+ /** \brief Test whether the pair (\a f, \a g) is simple.
+
+ If \a f is not a facet, return false.
+ If \a g is not a (n-1)-face adjacent to the n-face \a f,
+ return false. */
+ bool operator()(const mln_psite(I)& f, const mln_psite(I)& g) const;
+
+ /** \brief Test whether \a f is part of a simple pair.
+
+ If \a f is not a facet, return false. */
+ bool operator()(const mln_psite(I)& f) const;
+
+ private:
+ const I* ima_;
+ const NL& lower_adj_nbh_;
+ const NH& higher_adj_nbh_;
+ };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I, typename NL, typename NH>
+ inline
+ is_simple_pair<I, NL, NH>::is_simple_pair(const Neighborhood<NL>& lower_adj_nbh,
+ const Neighborhood<NH>& higher_adj_nbh)
+ : ima_(0),
+ lower_adj_nbh_(exact(lower_adj_nbh)),
+ higher_adj_nbh_(exact(higher_adj_nbh))
+ {
+ mlc_equal(mln_value(I), bool)::check();
+ }
+
+ template <typename I, typename NL, typename NH>
+ inline
+ is_simple_pair<I, NL, NH>::is_simple_pair(const mln::Image<I>& ima,
+ const Neighborhood<NL>& lower_adj_nbh,
+ const Neighborhood<NH>& higher_adj_nbh)
+ : ima_(exact(&ima)),
+ lower_adj_nbh_(exact(lower_adj_nbh)),
+ higher_adj_nbh_(exact(higher_adj_nbh))
+ {
+ mlc_equal(mln_value(I), bool)::check();
+ }
+
+ template <typename I, typename NL, typename NH>
+ inline
+ void
+ is_simple_pair<I, NL, NH>::set_image(const mln::Image<I>& ima)
+ {
+ ima_ = exact(&ima);
+ }
+
+ template <typename I, typename NL, typename NH>
+ inline
+ bool
+ is_simple_pair<I, NL, NH>::operator()(const mln_psite(I)& f,
+ const mln_psite(I)& g) const
+ {
+ mln_precondition(ima_);
+ // Shortcut.
+ // FIXME: Introduce an `ima()' accessor instead?
+ const I& ima = *ima_;
+
+ // (F, G) cannot be a simple pair unless they are part of
+ // objects in IMA.
+ if (!ima(f) || !ima(g))
+ return false;
+
+ // F cannot be part of a simple pair unless it is a facet.
+ if (!is_facet(ima, f, higher_adj_nbh_))
+ return false;
+
+ /* FIXME: It would be nice if we could skip this check when G is
+ passed by the unary operator(), since this one already
+ ensuress that F and G are adjacent. */
+ // Ensure the (n-1)-face G is adjacent to the n-face F.
+ {
+ bool f_g_adjacent = false;
+ mln_niter(NH) h(higher_adj_nbh_, g);
+ for_all(h)
+ if (h == f)
+ {
+ f_g_adjacent = true;
+ break;
+ }
+ if (!f_g_adjacent)
+ return false;
+ }
+
+ // Check whether G is stricly included in F.
+ mln_niter(NH) h(higher_adj_nbh_, g);
+ for_all(h)
+ if (h != f && ima.has(h) && ima(h))
+ return false;
+ return true;
+ }
+
+ // FIXME: What about moving this operator() into its own functor
+ // called e.g. mln::topo::is_in_simple_pair?
+ template <typename I, typename NL, typename NH>
+ inline
+ bool
+ is_simple_pair<I, NL, NH>::operator()(const mln_psite(I)& f) const
+ {
+ mln_niter(NL) g(lower_adj_nbh_, f);
+ for_all(g)
+ {
+ // Delegate the computation to the binary operator().
+ if ((*this)(f, g))
+ // (F, G) is a simple pair.
+ return true;
+ }
+ return false;
+ }
+
+# endif // MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::topo
+
+} // end of namespace mln
+
+#endif // ! MLN_TOPO_IS_SIMPLE_PAIR_HH
diff --git a/milena/tests/topo/Makefile.am b/milena/tests/topo/Makefile.am
index 6da7c28..608ac92 100644
--- a/milena/tests/topo/Makefile.am
+++ b/milena/tests/topo/Makefile.am
@@ -21,9 +21,15 @@ SUBDIRS = skeleton
check_PROGRAMS = \
complex \
- is_facet
+ detach_pair \
+ is_facet \
+ is_simple_pair
complex_SOURCES = complex.cc
+detach_pair_SOURCES = detach_pair.cc
is_facet_SOURCES = is_facet.cc
+is_simple_pair_SOURCES = is_simple_pair.cc
TESTS = $(check_PROGRAMS)
+
+MOSTLYCLEANFILES = detach_pair-out.vtk
diff --git a/milena/tests/io/vtk/load_bin.cc b/milena/tests/topo/detach_pair.cc
similarity index 51%
copy from milena/tests/io/vtk/load_bin.cc
copy to milena/tests/topo/detach_pair.cc
index a4ddf10..ac2133b 100644
--- a/milena/tests/io/vtk/load_bin.cc
+++ b/milena/tests/topo/detach_pair.cc
@@ -24,13 +24,15 @@
// executable file might be covered by the GNU General Public License.
/// \file
-/// \brief Exercise mln::io::vtk::load on binary mesh images.
+/// \brief Exercise mln::topo::detach_pair.
-#include <algorithm>
-#include <iterator>
-#include <iostream>
+#include <mln/core/alias/complex_image.hh>
+#include <mln/core/image/complex_neighborhoods.hh>
+
+#include <mln/topo/detach_pair.hh>
#include <mln/io/vtk/load.hh>
+#include <mln/io/vtk/save.hh>
#include "tests/data.hh"
@@ -38,23 +40,34 @@
int
main()
{
- using namespace mln;
+ // Image type.
+ typedef mln::bin_2complex_image3df ima_t;
+ // Dimension of the image (and thus of the complex).
+ static const unsigned D = ima_t::dim;
+ // Geometry of the image.
+ typedef mln_geom_(ima_t) G;
- typedef bin_2complex_image3df ima_t;
ima_t ima;
- io::vtk::load(ima, MLN_MESH_DIR "/tetrahedron.vtk");
-
- std::cout << ima.domain().cplx() << std::endl;
-
- mln_piter_(ima_t) p(ima.domain());
- for_all(p)
- {
- std::cout << "ima(" << p << ") = " << ima(p) << " ( ";
- // Print site(s).
- typedef mln_site_(ima_t) site_t;
- site_t s(p);
- std::copy (s.sites.begin(), s.sites.end(),
- std::ostream_iterator<site_t::location>(std::cout, " "));
- std::cout << ")" << std::endl;
- }
+ mln::io::vtk::load(ima, MLN_MESH_DIR "/pseudo-manifold.vtk");
+
+ // Neighborhood type returning the set of (n-1)-faces adjacent to a
+ // an n-face.
+ typedef mln::complex_lower_neighborhood<D, G> lower_adj_nbh_t;
+ lower_adj_nbh_t lower_adj_nbh;
+ // Neighborhood type returning the set of (n+1)-faces adjacent to a
+ // an n-face.
+ typedef mln::complex_higher_neighborhood<D, G> higher_adj_nbh_t;
+ higher_adj_nbh_t higher_adj_nbh;
+ // Functor detaching a simple pair.
+ typedef mln::topo::detach_pair< ima_t,
+ lower_adj_nbh_t,
+ higher_adj_nbh_t > detach_t;
+
+ // Detach simple 2-faces from IMA.
+ detach_t detach(ima, lower_adj_nbh, higher_adj_nbh);
+ mln::p_n_faces_fwd_piter<D, G> f(ima.domain(), 2);
+ for_all(f)
+ detach(f);
+
+ mln::io::vtk::save(ima, "detach_pair-out.vtk");
}
diff --git a/milena/tests/io/vtk/load_bin.cc b/milena/tests/topo/is_simple_pair.cc
similarity index 53%
copy from milena/tests/io/vtk/load_bin.cc
copy to milena/tests/topo/is_simple_pair.cc
index a4ddf10..55f46d4 100644
--- a/milena/tests/io/vtk/load_bin.cc
+++ b/milena/tests/topo/is_simple_pair.cc
@@ -24,11 +24,12 @@
// executable file might be covered by the GNU General Public License.
/// \file
-/// \brief Exercise mln::io::vtk::load on binary mesh images.
+/// \brief Exercise mln::topo::is_simple_pair.
-#include <algorithm>
-#include <iterator>
-#include <iostream>
+#include <mln/core/alias/complex_image.hh>
+#include <mln/core/image/complex_neighborhoods.hh>
+
+#include <mln/topo/is_simple_pair.hh>
#include <mln/io/vtk/load.hh>
@@ -38,23 +39,35 @@
int
main()
{
- using namespace mln;
+ // Image type.
+ typedef mln::bin_2complex_image3df ima_t;
+ // Dimension of the image (and thus of the complex).
+ static const unsigned D = ima_t::dim;
+ // Geometry of the image.
+ typedef mln_geom_(ima_t) G;
- typedef bin_2complex_image3df ima_t;
ima_t ima;
- io::vtk::load(ima, MLN_MESH_DIR "/tetrahedron.vtk");
+ mln::io::vtk::load(ima, MLN_MESH_DIR "/pseudo-manifold.vtk");
- std::cout << ima.domain().cplx() << std::endl;
+ // Neighborhood type returning the set of (n-1)-faces adjacent to a
+ // an n-face.
+ typedef mln::complex_lower_neighborhood<D, G> lower_adj_nbh_t;
+ lower_adj_nbh_t lower_adj_nbh;
+ // Neighborhood type returning the set of (n+1)-faces adjacent to a
+ // an n-face.
+ typedef mln::complex_higher_neighborhood<D, G> higher_adj_nbh_t;
+ higher_adj_nbh_t higher_adj_nbh;
+ // Predicate type: does a triangle (2-face) belongs to a simple pair?
+ typedef mln::topo::is_simple_pair< ima_t,
+ lower_adj_nbh_t,
+ higher_adj_nbh_t > is_simple_t;
+ // Check the simplicity of IMA's faces.
+ is_simple_t is_simple(ima, lower_adj_nbh, higher_adj_nbh);
mln_piter_(ima_t) p(ima.domain());
for_all(p)
{
- std::cout << "ima(" << p << ") = " << ima(p) << " ( ";
- // Print site(s).
- typedef mln_site_(ima_t) site_t;
- site_t s(p);
- std::copy (s.sites.begin(), s.sites.end(),
- std::ostream_iterator<site_t::location>(std::cout, " "));
- std::cout << ")" << std::endl;
+ if (is_simple(p))
+ std::cout << p << std::endl;
}
}
--
1.5.6.5
* apps/mesh-segm-skel/test-mesh-segm.in: Remove erroneous
execution permission.
* apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in:
Add a missing copyright header.
---
milena/ChangeLog | 9 +++++++++
.../test-mesh-complex-max-curv-extrema.in | 16 ++++++++++++++++
2 files changed, 25 insertions(+), 0 deletions(-)
mode change 100755 => 100644 milena/apps/mesh-segm-skel/test-mesh-segm.in
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 0f8afb9..5670671 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,12 @@
+2011-02-25 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Small corrections in apps/mesh-segm-skel.
+
+ * apps/mesh-segm-skel/test-mesh-segm.in: Remove erroneous
+ execution permission.
+ * apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in:
+ Add a missing copyright header.
+
2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
Exercise topology-related routines.
diff --git a/milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in b/milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in
index c6fa1e8..a056da1 100644
--- a/milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in
+++ b/milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in
@@ -1,5 +1,21 @@
#! /bin/sh
+# Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE).
+#
+# This file is part of Olena.
+#
+# Olena is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, version 2 of the License.
+#
+# Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+
set -ex
mesh_dir=@top_srcdir@/milena/mesh
diff --git a/milena/apps/mesh-segm-skel/test-mesh-segm.in b/milena/apps/mesh-segm-skel/test-mesh-segm.in
old mode 100755
new mode 100644
--
1.5.6.5
* tests/core/image/complex_image.hh
(make_test_bin_2complex_image2d): New function.
* tests/topo/is_facet.cc,
* tests/make/detachment.cc,
* tests/make/attachment.cc:
New.
* tests/topo/Makefile.am (check_PROGRAMS): Add is_facet.
(is_facet_SOURCES): New.
* tests/make/Makefile.am (check_PROGRAMS): Add attachment and
detachment.
(attachment_SOURCES, detachment_SOURCES): New.
---
milena/ChangeLog | 16 +++++
milena/tests/core/image/complex_image.hh | 20 ++++++-
milena/tests/make/Makefile.am | 6 ++-
milena/tests/make/attachment.cc | 77 +++++++++++++++++++++++
milena/tests/make/detachment.cc | 98 ++++++++++++++++++++++++++++++
milena/tests/topo/Makefile.am | 7 ++-
milena/tests/topo/is_facet.cc | 80 ++++++++++++++++++++++++
7 files changed, 299 insertions(+), 5 deletions(-)
create mode 100644 milena/tests/make/attachment.cc
create mode 100644 milena/tests/make/detachment.cc
create mode 100644 milena/tests/topo/is_facet.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index e2f6ec2..0f8afb9 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,21 @@
2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
+ Exercise topology-related routines.
+
+ * tests/core/image/complex_image.hh
+ (make_test_bin_2complex_image2d): New function.
+ * tests/topo/is_facet.cc,
+ * tests/make/detachment.cc,
+ * tests/make/attachment.cc:
+ New.
+ * tests/topo/Makefile.am (check_PROGRAMS): Add is_facet.
+ (is_facet_SOURCES): New.
+ * tests/make/Makefile.am (check_PROGRAMS): Add attachment and
+ detachment.
+ (attachment_SOURCES, detachment_SOURCES): New.
+
+2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
+
New complex image alias: mln::bin_2complex_image2d.
* mln/core/alias/complex_image.hh (mln::bin_2complex_image2d):
diff --git a/milena/tests/core/image/complex_image.hh b/milena/tests/core/image/complex_image.hh
index 5836147..030006a 100644
--- a/milena/tests/core/image/complex_image.hh
+++ b/milena/tests/core/image/complex_image.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// Copyright (C) 2008, 2009, 2011 EPITA Research and Development Laboratory
// (LRDE)
//
// This file is part of Olena.
@@ -34,6 +34,8 @@
# include <mln/core/alias/complex_image.hh>
# include <mln/value/int_u8.hh>
+# include <mln/data/fill.hh>
+
// FIXME: Keep this? (See below.)
# include <mln/core/site_set/p_faces.hh>
@@ -149,7 +151,7 @@ make_test_complex_image()
mln::metal::vec<D + 1, std::vector< int_u8 > > values;
// Assign 0 to 0-faces, 1 to 1-faces and 2 to 2-faces.
for (unsigned d = 0; d <= D; ++d)
- for (unsigned n = 0; n < pc.cplx().nfaces(d); ++n)
+ for (unsigned n = 0; n < pc.cplx().nfaces_of_dim(d); ++n)
values[d].push_back(d);
// Create and init an image based on PC.
@@ -161,4 +163,18 @@ make_test_complex_image()
return ima;
}
+
+/* FIXME: Quick and dirty implementation, based on
+ `make_test_complex_image'. Factor and revamp. */
+inline
+mln::bin_2complex_image2d
+make_test_bin_2complex_image2d()
+{
+ mln::int_u8_2complex_image2d model = make_test_complex_image();
+ mln::bin_2complex_image2d ima;
+ mln::initialize(ima, model);
+ mln::data::fill(ima, true);
+ return ima;
+}
+
#endif // ! TESTS_CORE_IMAGE_COMPLEX_IMAGE_HH
diff --git a/milena/tests/make/Makefile.am b/milena/tests/make/Makefile.am
index 34e0eff..5b28d6b 100644
--- a/milena/tests/make/Makefile.am
+++ b/milena/tests/make/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+# Copyright (C) 2007, 2008, 2009, 2011 EPITA Research and Development
# Laboratory (LRDE).
#
# This file is part of Olena.
@@ -18,6 +18,8 @@
include $(top_srcdir)/milena/tests/tests.mk
check_PROGRAMS = \
+ attachment \
+ detachment \
dual_neighb \
dummy_p_edges \
dummy_p_vertices \
@@ -33,6 +35,8 @@ check_PROGRAMS = \
w_window \
w_window_directional
+attachment_SOURCES = attachment.cc
+detachment_SOURCES = detachment.cc
dual_neighb_SOURCES = dual_neighb.cc
dummy_p_edges_SOURCES = dummy_p_edges.cc
dummy_p_vertices_SOURCES = dummy_p_vertices.cc
diff --git a/milena/tests/make/attachment.cc b/milena/tests/make/attachment.cc
new file mode 100644
index 0000000..2674727
--- /dev/null
+++ b/milena/tests/make/attachment.cc
@@ -0,0 +1,77 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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
+/// \brief Exercise mln::make::attachment.
+
+#include <mln/make/attachment.hh>
+
+#include "tests/core/image/complex_image.hh"
+
+
+int
+main()
+{
+ typedef mln::bin_2complex_image2d I;
+ typedef mln_psite_(I) P;
+
+ // Neighborhood (n-face to (n+1)-faces relationship) required by
+ // mln::is_facet.
+ mln::complex_lower_higher_neighborhood<I::dim, mln_geom_(I)> adj_nbh;
+
+ /* A 2-d (simplicial) complex and its adjacency graph.
+
+ c 0 1 2 3
+ r .------------------------
+ | v0 e3 v3
+ 0 | o-----------o v0----e3----v3
+ | / \ ,-----. / / \ | /
+ | / . \ \ t1/ / / \ t1 /
+ 1 | e0 / / \ e1\ / / e4 e0. ,e1Ž `e4
+ | / /t0 \ \ ' / / t0 \ /
+ | / `-----' \ / / | \ /
+ 2 | o-----------o v1----e2----v2
+ | v1 e2 v2
+
+ v = vertex
+ e = edge
+ t = triangle
+ */
+ I ima = make_test_bin_2complex_image2d();
+
+ // A few faces.
+ P v0(ima.domain(), 0, 0);
+ P v2(ima.domain(), 0, 2);
+ P e1(ima.domain(), 1, 1);
+ P t0(ima.domain(), 2, 0);
+
+ // The attachment of the cell corresponding to T0 from IMA yields a
+ // set containing E1, V0 and V1.
+ mln::p_set<P> attach_t0 = mln::make::attachment(ima, t0, adj_nbh);
+ mln_assertion(attach_t0.nsites() == 3);
+ mln_assertion(attach_t0.has(e1));
+ mln_assertion(attach_t0.has(v0));
+ mln_assertion(attach_t0.has(v2));
+}
diff --git a/milena/tests/make/detachment.cc b/milena/tests/make/detachment.cc
new file mode 100644
index 0000000..759c642
--- /dev/null
+++ b/milena/tests/make/detachment.cc
@@ -0,0 +1,98 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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
+/// \brief Exercise mln::make::detachment.
+
+#include <mln/make/detachment.hh>
+
+#include "tests/core/image/complex_image.hh"
+
+
+int
+main()
+{
+ typedef mln::bin_2complex_image2d I;
+ typedef mln_psite_(I) P;
+
+ // Neighborhood (n-face to (n+1)-faces relationship) required by
+ // mln::is_facet.
+ mln::complex_lower_higher_neighborhood<I::dim, mln_geom_(I)> adj_nbh;
+
+ /* A 2-d (simplicial) complex and its adjacency graph.
+
+ c 0 1 2 3
+ r .------------------------
+ | v0 e3 v3
+ 0 | o-----------o v0----e3----v3
+ | / \ ,-----. / / \ | /
+ | / . \ \ t1/ / / \ t1 /
+ 1 | e0 / / \ e1\ / / e4 e0. ,e1Ž `e4
+ | / /t0 \ \ ' / / t0 \ /
+ | / `-----' \ / / | \ /
+ 2 | o-----------o v1----e2----v2
+ | v1 e2 v2
+
+ v = vertex
+ e = edge
+ t = triangle
+ */
+ I ima = make_test_bin_2complex_image2d();
+
+ // A few faces.
+ P v0(ima.domain(), 0, 0);
+ P v1(ima.domain(), 0, 1);
+ P e0(ima.domain(), 1, 0);
+ P e2(ima.domain(), 1, 2);
+ P t0(ima.domain(), 2, 0);
+
+ /* Remember that `detachment' does not have the same meaning as in
+ couprie.08.pami.
+
+ mln::make::detachment(ima, f, adj_nbh)
+
+ does not correspond to the complex resulting from the collapsing
+ of the cell CELL associated to F onto IMA, but the part that is
+ removed, i.e., the detached part CELL - attachment(ima, f,
+ adj_nbh). (see mln/make/detachment). */
+
+ // Detaching the cell corresponding to T0 from IMA yields a set
+ // containing T0, E0, E2 and V1.
+ mln::p_set<P> detach_t0 = mln::make::detachment(ima, t0, adj_nbh);
+ mln_assertion(detach_t0.nsites() == 4);
+ mln_assertion(detach_t0.has(t0));
+ mln_assertion(detach_t0.has(e0));
+ mln_assertion(detach_t0.has(e2));
+ mln_assertion(detach_t0.has(v1));
+
+ // E0 is not a facet and thus its corresponding cell cannot be
+ // detached from IMA.
+ mln::p_set<P> detach_e0 = mln::make::detachment(ima, e0, adj_nbh);
+ mln_assertion(detach_e0.nsites() == 0);
+
+ // Likewise for V0.
+ mln::p_set<P> detach_v0 = mln::make::detachment(ima, v0, adj_nbh);
+ mln_assertion(detach_v0.nsites() == 0);
+}
diff --git a/milena/tests/topo/Makefile.am b/milena/tests/topo/Makefile.am
index b8684bf..6da7c28 100644
--- a/milena/tests/topo/Makefile.am
+++ b/milena/tests/topo/Makefile.am
@@ -1,4 +1,5 @@
-# Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE).
+# Copyright (C) 2008, 2009, 2011 EPITA Research and Development
+# Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -19,8 +20,10 @@ include $(top_srcdir)/milena/tests/tests.mk
SUBDIRS = skeleton
check_PROGRAMS = \
- complex
+ complex \
+ is_facet
complex_SOURCES = complex.cc
+is_facet_SOURCES = is_facet.cc
TESTS = $(check_PROGRAMS)
diff --git a/milena/tests/topo/is_facet.cc b/milena/tests/topo/is_facet.cc
new file mode 100644
index 0000000..36be66a
--- /dev/null
+++ b/milena/tests/topo/is_facet.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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
+/// \brief Exercise mln::topo::is_facet.
+
+#include <mln/topo/is_facet.hh>
+
+#include "tests/core/image/complex_image.hh"
+
+
+int
+main()
+{
+ typedef mln::bin_2complex_image2d I;
+ typedef mln_psite_(I) P;
+
+ // Neighborhood (n-face to (n+1)-faces relationship) required by
+ // mln::is_facet.
+ mln::complex_higher_neighborhood<I::dim, mln_geom_(I)> higher_adj_nbh;
+
+ /* A 2-d (simplicial) complex and its adjacency graph.
+
+ c 0 1 2 3
+ r .------------------------
+ | v0 e3 v3
+ 0 | o-----------o v0----e3----v3
+ | / \ ,-----. / / \ | /
+ | / . \ \ t1/ / / \ t1 /
+ 1 | e0 / / \ e1\ / / e4 e0. ,e1Ž `e4
+ | / /t0 \ \ ' / / t0 \ /
+ | / `-----' \ / / | \ /
+ 2 | o-----------o v1----e2----v2
+ | v1 e2 v2
+
+ v = vertex
+ e = edge
+ t = triangle
+ */
+ I ima = make_test_bin_2complex_image2d();
+
+ // The first triangle (2-face), t0;
+ P t0(ima.domain(), 2, 0);
+ mln_assertion(mln::topo::is_facet(ima, t0, higher_adj_nbh));
+
+ // E2 is not a facet in the initial image.
+ P e2(ima.domain(), 1, 2);
+ mln_assertion(!mln::topo::is_facet(ima, e2, higher_adj_nbh));
+
+ // ``Remove'' T0 and E0 (simple pair collapse).
+ P e0(ima.domain(), 1, 0);
+ ima(t0) = false;
+ ima(e0) = false;
+ // T0 is no longer a facet.
+ mln_assertion(!mln::topo::is_facet(ima, t0, higher_adj_nbh));
+ // E2 is now a facet.
+ mln_assertion(mln::topo::is_facet(ima, e2, higher_adj_nbh));
+}
--
1.5.6.5
* mln/core/alias/complex_image.hh (mln::bin_2complex_image2d):
New typedef.
---
milena/ChangeLog | 7 +++++++
milena/mln/core/alias/complex_image.hh | 10 +++++++++-
2 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 06b0478..e2f6ec2 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,12 @@
2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
+ New complex image alias: mln::bin_2complex_image2d.
+
+ * mln/core/alias/complex_image.hh (mln::bin_2complex_image2d):
+ New typedef.
+
+2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
+
Revamp mln::topo::is_simple_cell.
* mln/topo/is_simple_cell.hh
diff --git a/milena/mln/core/alias/complex_image.hh b/milena/mln/core/alias/complex_image.hh
index 89a8241..3e7fdd4 100644
--- a/milena/mln/core/alias/complex_image.hh
+++ b/milena/mln/core/alias/complex_image.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -65,6 +66,13 @@ namespace mln
| 2-d plane 2-complex aliases. |
`------------------------------*/
+ /// \brief Type alias for a binary image based on a
+ /// 2-complex, where 0-faces are located at discrete (integer)
+ /// 2-dimensional points.
+ typedef
+ mln::complex_image<2, mln::discrete_plane_2complex_geometry, bool>
+ bin_2complex_image2d;
+
/// \brief Type alias for an 8-bit gray-level image based on a
/// 2-complex, where 0-faces are located at discrete (integer)
/// 2-dimensional points.
--
1.5.6.5
* mln/topo/is_simple_cell.hh
(mln::topo::is_simple_cell<I, N, NL, NH>::operator()):
Replace ad hoc code by a call to is_facet.
---
milena/ChangeLog | 8 ++++++++
milena/mln/topo/is_simple_cell.hh | 21 +++++++--------------
2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index f1da3f6..06b0478 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,13 @@
2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
+ Revamp mln::topo::is_simple_cell.
+
+ * mln/topo/is_simple_cell.hh
+ (mln::topo::is_simple_cell<I, N, NL, NH>::operator()):
+ Replace ad hoc code by a call to is_facet.
+
+2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
+
Have is_facet take into account the values of a (complex) image.
* mln/topo/is_facet.hh (mln::topo::is_facet): Take a binary image
diff --git a/milena/mln/topo/is_simple_cell.hh b/milena/mln/topo/is_simple_cell.hh
index 0cf50fb..8796c16 100644
--- a/milena/mln/topo/is_simple_cell.hh
+++ b/milena/mln/topo/is_simple_cell.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -38,6 +39,7 @@
# include <mln/core/image/complex_neighborhoods.hh>
# include <mln/core/image/complex_neighborhood_piter.hh>
+# include <mln/topo/is_facet.hh>
# include <mln/make/attachment.hh>
@@ -132,21 +134,12 @@ namespace mln
// FIXME: Introduce `const I& ima = *ima_;' and use it instead of
// `ima_'. Or introduce an `ima()' accessor?
- // FIXME: We should be using topo::is_facet, but this routine is
- // too naive, and does not take the values of the image into
- // account.
+ // The cell corresponding to P cannot be simple unless P is
+ // facet.
{
- // This (part of) ``algorithm'' considers that looking for
- // faces of dimension n+1 is enough (which is the case
- // if the image is a complex).
NH higher_adj_nbh;
- mln_niter(NH) n(higher_adj_nbh, p);
- for_all(n)
- // If the higher-dim-faces neighborhood is not empty, then P
- // is included in a face of higher dimension.
- if (ima_->has(n) && (*ima_)(n))
- return false;
- // Otherwise, F is a facet; continue.
+ if (!is_facet(*ima_, p, higher_adj_nbh))
+ return false;
}
typedef p_set<mln_psite(I)> faces_t;
--
1.5.6.5
* mln/topo/is_facet.hh (mln::topo::is_facet): Take a binary image
and a neighborhood as arguments and take the image's values into
account.
---
milena/ChangeLog | 8 ++++++
milena/mln/topo/is_facet.hh | 54 ++++++++++++++++++++++++++++++++----------
2 files changed, 49 insertions(+), 13 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 6b55e2a..f1da3f6 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,13 @@
2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
+ Have is_facet take into account the values of a (complex) image.
+
+ * mln/topo/is_facet.hh (mln::topo::is_facet): Take a binary image
+ and a neighborhood as arguments and take the image's values into
+ account.
+
+2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
+
Revamp topology-related routines.
* mln/make/attachment.hh,
diff --git a/milena/mln/topo/is_facet.hh b/milena/mln/topo/is_facet.hh
index 675126c..f17b955 100644
--- a/milena/mln/topo/is_facet.hh
+++ b/milena/mln/topo/is_facet.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2011 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -29,6 +29,8 @@
/// \file
/// \brief Testing whether an mln::complex_psite is a facet.
+# include <mln/metal/equal.hh>
+
# include <mln/core/site_set/complex_psite.hh>
# include <mln/core/image/complex_neighborhoods.hh>
# include <mln/core/image/complex_neighborhood_piter.hh>
@@ -43,29 +45,55 @@ namespace mln
/* FIXME: Make this routine a method of mln::complex_psite? Or
better, a method of mln::topo::face? */
- /// Is \a f a facet, i.e., a face not ``included in'' (adjacent
- /// to) a face of higher dimension?
- template <unsigned D, typename G>
+ /* FIXME: Use a pix<I> object as input of is_facet instead of a
+ (psite, image) pair? */
+
+ /** \brief Is \a f a facet in \a image, i.e., a face not
+ ``included in'' (adjacent to) a face of higher dimension?
+
+ \tparam I The type of the image.
+ \tparam NH The neighborhood type returning the set of
+ (n+1)-faces adjacent to a an n-face.
+
+ \param ima The complex image.
+ \param f A psite pointing to the face to examine.
+ \param higher_adj_nbh Relationship between an n-facet and its
+ adjacent (n+1)-facets.
+ */
+ template <typename I, typename NH>
bool
- is_facet(const complex_psite<D, G>& f);
+ is_facet(const Image<I>& ima, const mln_psite(I)& f,
+ const Neighborhood<NH>& higher_adj_nbh);
+
# ifndef MLN_INCLUDE_ONLY
- // FIXME: Too naive: this code does not take the values of the
- // image into account.
- template <unsigned D, typename G>
+ template <typename I, typename NH>
inline
bool
- is_facet(const complex_psite<D, G>& f)
+ is_facet(const Image<I>& ima_, const mln_psite(I)& f,
+ const Neighborhood<NH>& higher_adj_nbh_)
{
- typedef complex_higher_neighborhood<D, G> higher_adj_nbh_t;
- higher_adj_nbh_t higher_adj_nbh;
- mln_niter(higher_adj_nbh_t) n(higher_adj_nbh, f);
+ // Ensure I is a binary image type.
+ /* FIXME: Not compatible with proxy/morphers on values. */
+ mlc_equal(mln_value(I), bool)::check();
+
+ const I& ima = exact(ima_);
+ const NH& higher_adj_nbh = exact(higher_adj_nbh_);
+
+ // F cannot be a facet if it does not belong to the complex.
+ if (!ima(f))
+ return false;
+
+ // This routine considers that looking for faces of dimension
+ // n+1 is enough (which is the case if the image is a complex).
+ mln_niter(NH) n(higher_adj_nbh, f);
for_all(n)
// If the neighborhood is not empty, then F is included in a face
// of higher dimension.
- return false;
+ if (ima.has(n) && ima(n))
+ return false;
// Otherwise, F is a facet.
return true;
}
--
1.5.6.5
* mln/make/attachment.hh,
* mln/make/cell.hh,
* mln/make/detachment.hh,
* mln/topo/detach_cell.hh:
Do not require the face passed as argument to be a facet.
---
milena/ChangeLog | 10 ++++++++++
milena/mln/make/attachment.hh | 15 +++++----------
milena/mln/make/cell.hh | 11 ++---------
milena/mln/make/detachment.hh | 17 ++++++-----------
milena/mln/topo/detach_cell.hh | 14 ++++----------
5 files changed, 27 insertions(+), 40 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index a4a1345..6b55e2a 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,15 @@
2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
+ Revamp topology-related routines.
+
+ * mln/make/attachment.hh,
+ * mln/make/cell.hh,
+ * mln/make/detachment.hh,
+ * mln/topo/detach_cell.hh:
+ Do not require the face passed as argument to be a facet.
+
+2011-02-24 Roland Levillain <roland(a)lrde.epita.fr>
+
Make the interface of thinning algorithms uniform w.r.t. functors.
* mln/topo/skeleton/priority_driven_thinning.hh
diff --git a/milena/mln/make/attachment.hh b/milena/mln/make/attachment.hh
index 63eca65..8247afe 100644
--- a/milena/mln/make/attachment.hh
+++ b/milena/mln/make/attachment.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -32,7 +33,6 @@
# include <mln/core/image/complex_image.hh>
# include <mln/make/cell.hh>
-# include <mln/topo/is_facet.hh>
namespace mln
{
@@ -41,10 +41,10 @@ namespace mln
{
/** \brief Compute the attachment of the cell corresponding to the
- facet \a f to the image \a ima.
+ face \a f to the image \a ima.
- \param ima The input image to which the facet is attached.
- \param f The psite corresponding to the attached facet.
+ \param ima The input image to which the face is attached.
+ \param f The psite corresponding to the attached face.
\param nbh An adjacency relationship between faces
(should return the set of (n-1)- and (n+1)-faces
adjacent to an n-face).
@@ -52,8 +52,6 @@ namespace mln
\return A set of faces containing the attachment.
\pre ima is an image of Boolean values.
- \pre \a f is a facet (it does not belong to any face of higher
- dimension).
We do not use the fomal definition of the attachment here (see
couprie.08.pami). We use the following (equivalent) definition:
@@ -74,9 +72,6 @@ namespace mln
attachment(const Image<I>& ima_, const mln_psite(I)& f,
const Neighborhood<N>& nbh_)
{
- // FIXME: The current implementation of topo::is_facet is too
- // naive: it does not take the values of the image into account.
- mln_precondition(topo::is_facet(f));
mlc_equal(mln_value(I), bool)::check();
I ima = exact(ima_);
diff --git a/milena/mln/make/cell.hh b/milena/mln/make/cell.hh
index 44c34ae..f873cbb 100644
--- a/milena/mln/make/cell.hh
+++ b/milena/mln/make/cell.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2011 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -34,8 +34,6 @@
# include <mln/core/image/complex_neighborhoods.hh>
# include <mln/core/image/complex_neighborhood_piter.hh>
-# include <mln/topo/is_facet.hh>
-
namespace mln
{
@@ -43,10 +41,7 @@ namespace mln
{
/** Compute the set of faces of the cell corresponding to the
- facet \a f.
-
- \pre \a f is a facet (it does not belong to any face of higher
- dimension).
+ face \a f.
\return An mln::p_set of sites (faces) containing the
attachment. */
@@ -62,8 +57,6 @@ namespace mln
p_set< complex_psite<D, G> >
cell(const complex_psite<D, G>& f)
{
- mln_precondition(topo::is_facet(f));
-
typedef complex_psite<D, G> psite;
typedef p_set<psite> faces_t;
diff --git a/milena/mln/make/detachment.hh b/milena/mln/make/detachment.hh
index 88b70a0..8feff54 100644
--- a/milena/mln/make/detachment.hh
+++ b/milena/mln/make/detachment.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -32,7 +33,6 @@
# include <mln/core/image/complex_image.hh>
# include <mln/make/cell.hh>
-# include <mln/topo/is_facet.hh>
namespace mln
{
@@ -41,19 +41,17 @@ namespace mln
{
/** \brief Compute the detachment of the cell corresponding to the
- facet \a f from the image \a ima.
+ face \a f from the image \a ima.
- \param ima The input image from which the facet is to be
+ \param ima The input image from which the face is to be
detached.
- \param f The psite corresponding to the facet to detach.
+ \param f The psite corresponding to the face to detach.
\param nbh An adjacency relationship between faces
(should return the set of (n-1)- and (n+1)-faces
adjacent to an n-face).
\return A set of faces containing the detachment.
- \pre \a f is a facet (it does not belong to any face of higher
- dimension).
\pre \a ima is an image of Boolean values.
We do not use the fomal definition of the detachment here (see
@@ -66,7 +64,7 @@ namespace mln
complex resulting from the collapsing of CELL onto IMA, but
the part that is removed, i.e., the detached part CELL -
ATTACHMENT. It would be wise to rename this routine to
- something else. */
+ something else, e.g., `detached'. */
template <typename I, typename N>
p_set<mln_psite(I)>
detachment(const Image<I>& ima, const mln_psite(I)& f,
@@ -81,9 +79,6 @@ namespace mln
detachment(const Image<I>& ima_, const mln_psite(I)& f,
const Neighborhood<N>& nbh_)
{
- // FIXME: The current implementation of topo::is_facet is too
- // naive: it does not take the values of the image into account.
- mln_precondition(topo::is_facet(f));
mlc_equal(mln_value(I), bool)::check();
I ima = exact(ima_);
diff --git a/milena/mln/topo/detach_cell.hh b/milena/mln/topo/detach_cell.hh
index 250babf..761142e 100644
--- a/milena/mln/topo/detach_cell.hh
+++ b/milena/mln/topo/detach_cell.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -32,7 +33,6 @@
# include <mln/core/site_set/p_set.hh>
# include <mln/core/image/complex_image.hh>
# include <mln/make/detachment.hh>
-# include <mln/topo/is_facet.hh>
namespace mln
{
@@ -65,7 +65,7 @@ namespace mln
\pre \a ima is an image of Boolean values.
- \param ima The input image from which the facet is to be
+ \param ima The input image from which the cell is to be
detached.
\param nbh An adjacency relationship between faces
(should return the set of (n-1)- and (n+1)-faces
@@ -82,10 +82,7 @@ namespace mln
/** Detach the cell corresponding to \a f from \a ima.
- \pre \a f is a facet (it does not belong to any face of
- higher dimension).
-
- \param f The psite corresponding to the facet to detach.
+ \param f The psite corresponding to the cell to detach.
\param nbh An adjacency relationship between faces
(should return the set of (n-1)- and (n+1)-faces
adjacent to an n-face). */
@@ -131,9 +128,6 @@ namespace mln
detach_cell<I, N>::operator()(const mln_psite(I)& f)
{
mln_precondition(ima_);
- // FIXME: The current implementation of topo::is_facet is too
- // naive: it does not take the values of the image into account.
- mln_precondition(topo::is_facet(f));
typedef p_set<mln_psite(I)> faces_t;
--
1.5.6.5