
* mln/make/influence_zone_adjacency_graph.hh, * mln/make/region_adjacency_graph.hh: make use of this new structure. * mln/util/adjacency_matrix.hh: new structure. * tests/util/Makefile.am, * tests/util/adjacency_matrix.cc: associated test. --- milena/ChangeLog | 12 + milena/mln/make/influence_zone_adjacency_graph.hh | 17 +- milena/mln/make/region_adjacency_graph.hh | 15 +- milena/mln/util/adjacency_matrix.hh | 335 +++++++++++++++++++++ milena/tests/util/Makefile.am | 3 + milena/tests/util/adjacency_matrix.cc | 76 +++++ 6 files changed, 440 insertions(+), 18 deletions(-) create mode 100644 milena/mln/util/adjacency_matrix.hh create mode 100644 milena/tests/util/adjacency_matrix.cc diff --git a/milena/ChangeLog b/milena/ChangeLog index d68a7e9..ff6c707 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,5 +1,17 @@ 2009-05-06 Guillaume Lazzara <lazzara@lrde.epita.fr> + Add adjacency matrix. + + * mln/make/influence_zone_adjacency_graph.hh, + * mln/make/region_adjacency_graph.hh: make use of this new structure. + + * mln/util/adjacency_matrix.hh: new structure. + + * tests/util/Makefile.am, + * tests/util/adjacency_matrix.cc: associated test. + +2009-05-06 Guillaume Lazzara <lazzara@lrde.epita.fr> + Small fixes. * doc/tutorial/tutorial.tex: fix compilation. diff --git a/milena/mln/make/influence_zone_adjacency_graph.hh b/milena/mln/make/influence_zone_adjacency_graph.hh index 7113962..6cbaa4c 100644 --- a/milena/mln/make/influence_zone_adjacency_graph.hh +++ b/milena/mln/make/influence_zone_adjacency_graph.hh @@ -44,6 +44,8 @@ # include <mln/core/alias/box2d.hh> # include <mln/extension/adjust_fill.hh> # include <mln/util/graph.hh> +# include <mln/util/adjacency_matrix.hh> + namespace mln { @@ -104,8 +106,7 @@ namespace mln const I& iz = exact(iz_); const N& nbh = exact(nbh_); - mln::image2d<bool> adj(mln::box2d(nlabels.next(), nlabels.next())); - data::fill(adj, false); + util::adjacency_matrix<> adj(nlabels.next()); extension::adjust_fill(iz, nbh, 0u); typedef mln_value(I) L; @@ -120,13 +121,7 @@ namespace mln { L l2 = iz(n); if (iz(n) != iz((p))) - { - // l2 is adjacent to l1 - if (l2 < l1) - adj(point2d(l1,l2)) = true; - else - adj(point2d(l2,l1)) = true; - } + adj.add(l1, l2); } } } @@ -134,9 +129,9 @@ namespace mln // Construct graph. util::graph g; g.add_vertices(nlabels.next()); - for (unsigned i = 0; i < geom::nrows(adj); ++i) + for (unsigned i = 0; i < nlabels.next(); ++i) for (unsigned j = 0; j < i; ++j) - if (adj(point2d(i,j))) + if (adj.are_adjacent(i, j)) g.add_edge(i, j); trace::exiting("make::impl::generic::influence_zone_adjacency_graph"); diff --git a/milena/mln/make/region_adjacency_graph.hh b/milena/mln/make/region_adjacency_graph.hh index 695174d..b930367 100644 --- a/milena/mln/make/region_adjacency_graph.hh +++ b/milena/mln/make/region_adjacency_graph.hh @@ -33,6 +33,8 @@ /// Create a region_adjacency_graph from a watershed image. /// /// \sa morpho::meyer_wst. +/// +/// \todo add dispatch. # include <mln/core/concept/image.hh> # include <mln/core/concept/neighborhood.hh> @@ -40,6 +42,8 @@ # include <mln/core/alias/box2d.hh> # include <mln/extension/adjust_fill.hh> # include <mln/util/graph.hh> +# include <mln/util/adjacency_matrix.hh> + namespace mln { @@ -100,8 +104,7 @@ namespace mln const I& wshd = exact(wshd_); const N& nbh = exact(nbh_); - mln::image2d<bool> adj(mln::box2d(nbasins.next(), nbasins.next())); - data::fill(adj, false); + util::adjacency_matrix<> adj(nbasins.next()); extension::adjust_fill(wshd, nbh, 0u); typedef mln_value(I) L; @@ -129,19 +132,17 @@ namespace mln } if (l2 == 0u || l1 == 0u) continue; - if (l2 < l1) - std::swap(l1, l2); // adjacency l1 l2 - adj(point2d(l2,l1)) = true; + adj.add(l2, l1); } // Construct graph. util::graph g; g.add_vertices(nbasins.next()); - for (unsigned i = 1; i < geom::nrows(adj); ++i) + for (unsigned i = 1; i < nbasins.next(); ++i) for (unsigned j = 1; j < i; ++j) - if (adj(point2d(i,j))) + if (adj.are_adjacent(i, j)) g.add_edge(i, j); diff --git a/milena/mln/util/adjacency_matrix.hh b/milena/mln/util/adjacency_matrix.hh new file mode 100644 index 0000000..dfda26f --- /dev/null +++ b/milena/mln/util/adjacency_matrix.hh @@ -0,0 +1,335 @@ +// Copyright (C) 2009 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_UTIL_ADJACENCY_MATRIX_HH +# define MLN_UTIL_ADJACENCY_MATRIX_HH + +/// \file mln/util/adjacency_matrix.hh +/// +/// A class of adjacency matrix. +/// +/// FIXME: the underlying data structure is chosen according +/// to the value type quantification however we may like to make it +/// depend on the number of elements. + +# include <mln/core/image/image2d.hh> +# include <mln/util/set.hh> +# include <mln/util/ord_pair.hh> +# include <mln/trait/value_.hh> +# include <mln/metal/converts_to.hh> +# include <mln/debug/println.hh> + +namespace mln +{ + + namespace util + { + + namespace internal + { + + // Implementation for low quantification. + + template <typename V, typename Q> + struct adjacency_matrix_impl_selector + { + /// Data structure used to store adjacency information. + typedef image2d<bool> adj_t; + + /// Constructor. + adjacency_matrix_impl_selector(const V& nelements); + + /// Make \p e1 and \p e2 adjacent. + void add(const V& e1, const V& e2); + + /// Remove adjacency between \p e1 and \p e2. + void remove(const V& e1, const V& e2); + + /// Clear all adjacencies. + void clear(); + + /// Check whether \p e1 and \p e2 are adjacent. + bool are_adjacent(const V& e1, const V& e2) const; + + /// Print data to std::out. + std::ostream& print_data_(std::ostream& ostr) const; + + protected: + adj_t adj_; + }; + + + // Implementation for high quantification. + + template <typename V> + struct adjacency_matrix_impl_selector<V, metal::bool_<false> > + { + /// Data structure used to store adjacency information. + typedef util::set< util::ord_pair<V> > adj_t; + + /// Constructor. + adjacency_matrix_impl_selector(const V& nelements); + + /// Make \p e1 and \p e2 adjacent. + void add(const V& e1, const V& e2); + + /// Remove adjacency between \p e1 and \p e2. + void remove(const V& e1, const V& e2); + + /// Clear all adjacencies. + void clear(); + + /// Check whether \p e1 and \p e2 are adjacent. + bool are_adjacent(const V& e1, const V& e2) const; + + /// Print data to std::out. + std::ostream& print_data_(std::ostream& ostr) const; + + protected: + adj_t adj_; + +# ifndef NDEBUG + unsigned nelements_; +# endif // ! NDEBUG + }; + + + } // end of namespace mln::util::internal + + + /// A class of adjacency matrix. + /// + /// Support low and high quantification value types. + /// In case of low quantification value type, it uses + /// an image2d to store adjacency information. + /// In case of high quantification value type, it uses + /// a util::set to store the adjacency information. + /// + /// \ingroup modutil + // + template <typename V = def::coord> + class adjacency_matrix + : private mlc_converts_to(V,unsigned)::check_t, + public internal::adjacency_matrix_impl_selector<V, typename mlc_equal(mln_trait_value_quant(V),trait::value::quant::low)::eval> + { + typedef internal::adjacency_matrix_impl_selector<V, typename mlc_equal(mln_trait_value_quant(V),trait::value::quant::low)::eval> + impl_t; + + typedef typename impl_t::adj_t adj_t; + + public: + /// Constructors. + /// \@{ + /// + /// Default + adjacency_matrix(); + /// Construct an adjacency matrix with \p nelements elements + /// maximum. + adjacency_matrix(const V& nelements); + /// + /// \@} + + /// Hook member used to retrieve the underlying data structure. + const adj_t& hook_data_() const; + }; + + + // << + + template <typename V> + std::ostream& + operator<<(std::ostream& ostr, const adjacency_matrix<V>& adj); + + + +# ifndef MLN_INCLUDE_ONLY + + + namespace internal + { + + // Low quantification. + + template <typename V, typename Q> + adjacency_matrix_impl_selector<V, Q>::adjacency_matrix_impl_selector(const V& nelements) + : adj_(nelements, nelements) + { + clear(); + } + + template <typename V, typename Q> + void + adjacency_matrix_impl_selector<V, Q>::add(const V& e1, const V& e2) + { + mln_precondition(adj_.is_valid()); + mln_precondition(e1 < adj_.nrows()); + mln_precondition(e2 < adj_.nrows()); + + if (e1 > e2) + opt::at(adj_, e2, e1) = true; + else + opt::at(adj_, e1, e2) = true; + } + + template <typename V, typename Q> + void + adjacency_matrix_impl_selector<V, Q>::remove(const V& e1, const V& e2) + { + mln_precondition(adj_.is_valid()); + mln_precondition(e1 < adj_.nrows()); + mln_precondition(e2 < adj_.nrows()); + + if (e1 > e2) + opt::at(adj_, e2, e1) = false; + else + opt::at(adj_, e1, e2) = false; + } + + template <typename V, typename Q> + void + adjacency_matrix_impl_selector<V, Q>::clear() + { + mln_precondition(adj_.is_valid()); + data::fill(adj_, false); + } + + template <typename V, typename Q> + bool + adjacency_matrix_impl_selector<V, Q>::are_adjacent(const V& e1, + const V& e2) const + { + mln_precondition(adj_.is_valid()); + mln_precondition(e1 < adj_.nrows()); + mln_precondition(e2 < adj_.nrows()); + + if (e1 > e2) + return opt::at(adj_, e2, e1); + return opt::at(adj_, e1, e2); + } + + template <typename V, typename Q> + std::ostream& + adjacency_matrix_impl_selector<V, Q>::print_data_(std::ostream& ostr) const + { + mln_precondition(adj_.is_valid()); + debug::println(adj_); + return ostr; + } + + + + + // High quantification. + + template <typename V> + adjacency_matrix_impl_selector<V, metal::bool_<false> > + ::adjacency_matrix_impl_selector(const V& nelements) + { + (void) nelements; +# ifndef DNDEBUG + nelements_ = nelements; +# endif // ! DNDEBUG + } + + template <typename V> + void + adjacency_matrix_impl_selector<V, metal::bool_<false> > + ::add(const V& e1, const V& e2) + { + mln_precondition(e1 < nelements_); + mln_precondition(e2 < nelements_); + adj_.insert(make::ord_pair(e1, e2)); + } + + template <typename V> + void + adjacency_matrix_impl_selector<V, metal::bool_<false> > + ::remove(const V& e1, const V& e2) + { + mln_precondition(e1 < nelements_); + mln_precondition(e2 < nelements_); + mln_precondition(adj_.has(make::ord_pair(e1, e2))); + adj_.remove(make::ord_pair(e1, e2)); + } + + template <typename V> + void + adjacency_matrix_impl_selector<V, metal::bool_<false> >::clear() + { + adj_.clear(); + } + + template <typename V> + bool + adjacency_matrix_impl_selector<V, metal::bool_<false> > + ::are_adjacent(const V& e1, const V& e2) const + { + mln_precondition(e1 < nelements_); + mln_precondition(e2 < nelements_); + return adj_.has(make::ord_pair(e1, e2)); + } + + template <typename V> + std::ostream& + adjacency_matrix_impl_selector<V, metal::bool_<false> >::print_data_(std::ostream& ostr) const + { + return ostr << adj_; + } + + } // end of namespace mln::internal + + + template <typename V> + adjacency_matrix<V>::adjacency_matrix() + : impl_t() + { + } + + + template <typename V> + adjacency_matrix<V>::adjacency_matrix(const V& nelements) + : impl_t(nelements) + { + } + + + template <typename V> + std::ostream& + operator<<(std::ostream& ostr, const adjacency_matrix<V>& adj) + { + return adj.print_data_(ostr); + } + + +# endif // ! MLN_UTIL_ADJACENCY_MATRIX_HH + + } // end of namespace mln::util + +} // end of namespace mln + + +#endif // ! MLN_UTIL_ADJACENCY_MATRIX_HH diff --git a/milena/tests/util/Makefile.am b/milena/tests/util/Makefile.am index c1d6c4d..07b6018 100644 --- a/milena/tests/util/Makefile.am +++ b/milena/tests/util/Makefile.am @@ -4,6 +4,7 @@ include $(top_srcdir)/milena/tests/tests.mk check_PROGRAMS = \ + adjacency_matrix \ branch_iter \ branch_iter_ind \ eat \ @@ -21,6 +22,8 @@ check_PROGRAMS = \ tree_to_fast \ tree_to_image + +adjacency_matrix_SOURCES = adjacency_matrix.cc branch_iter_SOURCES = branch_iter.cc branch_iter_ind_SOURCES = branch_iter_ind.cc eat_SOURCES = eat.cc diff --git a/milena/tests/util/adjacency_matrix.cc b/milena/tests/util/adjacency_matrix.cc new file mode 100644 index 0000000..e67f659 --- /dev/null +++ b/milena/tests/util/adjacency_matrix.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2009 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/util/adjacency_matrix.cc +/// +/// test of mln::util::adjacency_matrix + +#include <mln/util/adjacency_matrix.hh> +#include <mln/value/int_u8.hh> +#include <mln/value/int_u16.hh> + +int main() +{ + using namespace mln; + + // The underlying data structure is a image2d. + { + util::adjacency_matrix<value::int_u8> adj(5); + adj.add(3, 4); + adj.add(2, 3); + adj.add(1, 2); + + mln_assertion(adj.are_adjacent(2,3)); + mln_assertion(adj.are_adjacent(4,3)); + mln_assertion(adj.are_adjacent(2,1)); + mln_assertion(adj.are_adjacent(1,2)); + mln_assertion(!adj.are_adjacent(1,4)); + + adj.remove(2,3); + mln_assertion(!adj.are_adjacent(2,3)); + mln_assertion(!adj.are_adjacent(2,2)); + } + + // The underlying data structure is a util::set + { + util::adjacency_matrix<value::int_u16> adj(5); + adj.add(3, 4); + adj.add(2, 3); + adj.add(1, 2); + + mln_assertion(adj.are_adjacent(2,3)); + mln_assertion(adj.are_adjacent(4,3)); + mln_assertion(adj.are_adjacent(2,1)); + mln_assertion(adj.are_adjacent(1,2)); + mln_assertion(!adj.are_adjacent(1,4)); + + adj.remove(2,3); + mln_assertion(!adj.are_adjacent(2,3)); + mln_assertion(!adj.are_adjacent(2,2)); + } + +} -- 1.6.1.2

Roland Levillain <roland@lrde.epita.fr> writes:
* mln/make/influence_zone_adjacency_graph.hh, * mln/make/region_adjacency_graph.hh: make use of this new structure.
* mln/util/adjacency_matrix.hh: new structure.
* tests/util/Makefile.am, * tests/util/adjacency_matrix.cc: associated test.
Same problem as in [PATCH 01/31] sent just before; sorry.
participants (1)
-
Roland Levillain