
https://svn.lrde.epita.fr/svn/oln/trunk/milena Of course, there's a lot of duplication with the entities of graph-based images, and we'll have to refactor, in particular when we'll implement simplicial complexes. Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Add the required entities to express line graph-based images. * mln/core/point_pair.hh: New. Used to represent the ``points'' of line graph-based images. * mln/core/line_graph_elt_window.hh, * mln/core/line_graph_image.hh, * mln/core/line_graph_psite.hh, * mln/core/line_graph_window_piter.hh, * mln/core/p_line_graph.hh, * mln/core/p_line_graph_piter.hh: New. Entities involved in line graph-based images. * tests/core/line_graph_elt_window.cc, * tests/core/line_graph_image.cc: New tests. * tests/core/Makefile.am: Reorder the lists of tests. (check_PROGRAMS): Add line_graph_elt_window and line_graph_image. (line_graph_elt_window_SOURCES, line_graph_image_SOURCES): New. mln/core/line_graph_elt_window.hh | 54 ++++---- mln/core/line_graph_image.hh | 138 +++++++++++++--------- mln/core/line_graph_psite.hh | 148 +++++++++++++++++------- mln/core/line_graph_window_piter.hh | 194 +++++++++++++++++++++++--------- mln/core/p_line_graph.hh | 97 +++++++++------- mln/core/p_line_graph_piter.hh | 114 +++++++++++------- mln/core/point_pair.hh | 217 ++++++++++++++++++++++++++++++++++++ tests/core/Makefile.am | 26 ++-- tests/core/line_graph_elt_window.cc | 18 +- tests/core/line_graph_image.cc | 99 +++++++--------- 10 files changed, 773 insertions(+), 332 deletions(-) Index: mln/core/point_pair.hh --- mln/core/point_pair.hh (revision 0) +++ mln/core/point_pair.hh (revision 0) @@ -0,0 +1,217 @@ +// 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_CORE_POINT_PAIR_HH +# define MLN_CORE_POINT_PAIR_HH + +/// \file mln/core/point_pair.hh +/// \brief Definition of the generic point_pair class mln::point_pair. + +// FIXME: Might be renamed to something else, like ``segment''. + +# include <utility> +# include <ostream> + +# include <mln/core/concept/point.hh> + + +namespace mln +{ + + /** \brief Generic point pair class. + + The sole parameter P is the type of the points of the pair. + + Pair points are mainly used to make a reference to a given edge + in an line graph-based image. */ + template <typename P> + struct point_pair : public Point< point_pair<P> > + { + /// \var dim + /// \brief Dimension of the space. + /// \invariant dim > 0 + enum { dim = P::dim }; + + /// Mesh associated type. + // FIXME: Dummy value. + typedef mln_mesh(P) mesh; + + /// Dpoint associated type. + // FIXME: Dummy value. + typedef void dpoint; + + /// Coordinate associated type. + typedef std::pair<typename P::coord, typename P::coord> coord; + + /// Constructors. + /// \{ + /// Constructor without argument. + point_pair(); + /// Constructor using two points. + point_pair(const P& first, const P& second); + /// Constructor using a pair of points. + point_pair(const std::pair<P, P>& points); + /// \} + + /// Accessors. + /// \{ + + /// \brief Read-only access to the \p i-th coordinate value. + /// \param[in] i The coordinate index. + /// \pre \p i < \c dim + coord operator[](unsigned i) const; + + /* FIXME: Providing this accessor requires the point pair to be + actually stored in this object, which both takes space and time + (updates). */ + +// /// \brief Read-write access to the \p i-th coordinate value. +// /// \param[in] i The coordinate index. +// /// \pre \p i < \c dim +// coord& operator[](unsigned i); + + /// Read-only access to the first point. + P first() const; + /// Read-write access to the first point. + P& first(); + + /// Read-only access to the second point. + P second() const; + /// Read-write access to the second point. + P& second(); + /// \} + + protected: + /// The pair of points. + // FIXME: Should we use an ordpair_ instead of as std::pair? + std::pair<P, P> points_; + }; + + template <typename P> + inline + std::ostream& + operator<<(std::ostream& ostr, const point_pair<P>& p); + + +# ifndef MLN_INCLUDE_ONLY + + /*------------. + | Accessors. | + `------------*/ + + template <typename P> + inline + typename point_pair<P>::coord + point_pair<P>::operator[](unsigned i) const + { + assert(i < dim); + return std::make_pair(points_.first[i], points_.second[i]); + } + +// template <typename P> +// inline +// typename point_pair<P>::coord& +// point_pair<P>::operator[](unsigned i) +// { +// assert(i < dim); +// return std::make_pair(points_.first[i], points_.second[i]); +// } + + template <typename P> + inline + P + point_pair<P>::first() const + { + return points_.first; + } + + template <typename P> + inline + P& + point_pair<P>::first() + { + return points_.first; + } + + template <typename P> + inline + P + point_pair<P>::second() const + { + return points_.second; + } + + template <typename P> + inline + P& + point_pair<P>::second() + { + return points_.second; + } + + /*---------------. + | Constructors. | + `---------------*/ + + template <typename P> + inline + point_pair<P>::point_pair() + { + } + + template <typename P> + inline + point_pair<P>::point_pair(const P& first, const P& second) + : points_(first, second) + { + } + + template <typename P> + inline + point_pair<P>::point_pair(const std::pair<P, P>& points) + : points_(points) + { + } + + /*----------. + | Display. | + `----------*/ + + template <typename P> + inline + std::ostream& + operator<<(std::ostream& ostr, const point_pair<P>& p) + { + return ostr << '(' << p.first() << " -- " << p.second() << ")"; + } + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + + +#endif // ! MLN_CORE_POINT_PAIR_HH Index: mln/core/line_graph_elt_window.hh --- mln/core/line_graph_elt_window.hh (revision 1714) +++ mln/core/line_graph_elt_window.hh (working copy) @@ -25,37 +25,37 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_WIN_GRAPH_ELT_WINDOW_HH -# define MLN_WIN_GRAPH_ELT_WINDOW_HH +#ifndef MLN_CORE_LINE_GRAPH_ELT_WINDOW_HH +# define MLN_CORE_LINE_GRAPH_ELT_WINDOW_HH -/*! \file mln/core/graph_elt_window.hh +/*! \file mln/core/line_graph_elt_window.hh * - * \brief Definition of the elementary ``window'' on a graph. + * \brief Definition of the elementary ``window'' on a line graph. * * \todo Make naming coherent: we have window (without '_') but * point_, neighb_, etc. */ # include <mln/core/concept/window.hh> -# include <mln/core/graph_psite.hh> -# include <mln/core/graph_window_piter.hh> +# include <mln/core/line_graph_psite.hh> +# include <mln/core/line_graph_window_piter.hh> namespace mln { // Fwd decls. - template <typename P> class graph_window_fwd_piter; - template <typename P> class graph_window_bkd_piter; + template <typename P> class line_graph_window_fwd_piter; + template <typename P> class line_graph_window_bkd_piter; - /*! \brief Elementary window on graph class. + /*! \brief Elementary window on line graph class. * * FIXME: Doc. */ template <typename P> - class graph_elt_window : public Window< graph_elt_window<P> > + class line_graph_elt_window : public Window< line_graph_elt_window<P> > { - typedef graph_elt_window<P> self_; + typedef line_graph_elt_window<P> self_; public: /// Associated types. @@ -71,19 +71,19 @@ /*! \brief Point_Iterator type to browse the points of a generic window * w.r.t. the ordering of delta-points. */ - typedef graph_window_fwd_piter<P> fwd_qiter; + typedef line_graph_window_fwd_piter<P> fwd_qiter; /*! \brief Point_Iterator type to browse the points of a generic window * w.r.t. the reverse ordering of delta-points. */ - typedef graph_window_bkd_piter<P> bkd_qiter; + typedef line_graph_window_bkd_piter<P> bkd_qiter; /// The default qiter type. typedef fwd_qiter qiter; /// \} - /// Construct an elementary graph window. - graph_elt_window(); + /// Construct an elementary line_graph window. + line_graph_elt_window(); /// Is the window is empty? bool is_empty() const; @@ -98,12 +98,12 @@ /// Return the maximum coordinate gap between the window center /// and a window point. /* FIXME: This method returns a dummy value (0), since the delta - of a window on a graph + of a window on a line_graph - 1. is not constant (graph nodes are not necessarily aligned on - a regular grid); + 1. is not constant (line graph edges are not necessarily + aligned on a regular grid); - 2. depends on the underlying graph, too. + 2. depends on the underlying line_graph, too. It raises another question: should delta() be part of the concept ``Window''? */ @@ -118,14 +118,14 @@ template <typename P> inline - graph_elt_window<P>::graph_elt_window() + line_graph_elt_window<P>::line_graph_elt_window() { } template <typename P> inline bool - graph_elt_window<P>::is_empty() const + line_graph_elt_window<P>::is_empty() const { return false; } @@ -133,7 +133,7 @@ template <typename P> inline bool - graph_elt_window<P>::is_centered() const + line_graph_elt_window<P>::is_centered() const { return false; } @@ -141,7 +141,7 @@ template <typename P> inline bool - graph_elt_window<P>::is_symmetric() const + line_graph_elt_window<P>::is_symmetric() const { return true; } @@ -149,7 +149,7 @@ template <typename P> inline unsigned - graph_elt_window<P>::delta() const + line_graph_elt_window<P>::delta() const { // Dummy value (see the interface of the method above). return 0; @@ -157,8 +157,8 @@ template <typename P> inline - graph_elt_window<P>& - graph_elt_window<P>::sym() + line_graph_elt_window<P>& + line_graph_elt_window<P>::sym() { return *this; } @@ -168,4 +168,4 @@ } // end of namespace mln -#endif // ! MLN_WIN_GRAPH_ELT_WINDOW_HH +#endif // ! MLN_CORE_LINE_GRAPH_ELT_WINDOW_HH Index: mln/core/line_graph_image.hh --- mln/core/line_graph_image.hh (revision 1714) +++ mln/core/line_graph_image.hh (working copy) @@ -25,40 +25,54 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_CORE_GRAPH_IMAGE_HH -# define MLN_CORE_GRAPH_IMAGE_HH +#ifndef MLN_CORE_LINE_GRAPH_IMAGE_HH +# define MLN_CORE_LINE_GRAPH_IMAGE_HH -/*! \file mln/core/graph_image.hh - * - * \brief Definition of a graph-based image. - */ +/// \file mln/core/line_graph_image.hh +/// \brief Definition of a line graph-based image. # include <mln/trait/images.hh> # include <mln/core/internal/image_primary.hh> # include <mln/metal/vec.hh> -# include <mln/core/p_graph.hh> -# include <mln/core/graph_psite.hh> +# include <mln/core/p_line_graph.hh> +# include <mln/core/line_graph_psite.hh> # include <mln/value/set.hh> # include <vector> +/* FIXME: This class shares a lot with graph_image. Factor as much as + possible. */ + +/* FIXME: This is only a very naive prototype. For instance, this + image associates values to both the nodes and the edges of the + graph, but only values on edges are accessible. We probably want + to fork this class to have a pure image of line graph (with no data + on nodes) and one having data on both nodes and edges. + + Moreover, in the current implementation, the type of values on + nodes and edges is necessarily the same (V). We should allow + different data types for nodes and edges. */ + + namespace mln { // Fwd decl. - template <typename P, typename V> struct graph_image; + template <typename P, typename V> struct line_graph_image; namespace internal { - /// \internal Data structure for \c mln::graph_image<P,V>. + /// \internal Data structure for \c mln::line_graph_image<P,V>. template <typename P, typename V> - struct data_< graph_image<P, V> > + struct data_< line_graph_image<P, V> > { - data_(p_graph<P>& g, std::vector<V>& val); + data_(p_line_graph<P>& g, + std::vector<V>& node_val, std::vector<V>& edge_val); - std::vector<V> val_; - p_graph<P>& pg_; + std::vector<V> node_val_; + std::vector<V> edge_val_; + p_line_graph<P>& plg_; }; } // end of namespace mln::internal @@ -68,7 +82,8 @@ { template <typename P, typename V> - struct image_< graph_image<P, V> > : default_image_< V, graph_image<P, V> > + struct image_< line_graph_image<P, V> > + : default_image_< V, line_graph_image<P, V> > { typedef trait::image::category::primary category; @@ -91,11 +106,12 @@ * */ template <typename P, typename V> - struct graph_image : - public internal::image_primary_< p_graph<P>, graph_image<P, V> > + struct line_graph_image : + public internal::image_primary_< p_line_graph<P>, line_graph_image<P, V> > { - typedef mln::internal::image_base_< p_graph<P>, graph_image<P, V> > super_; + typedef mln::internal::image_base_< p_line_graph<P>, + line_graph_image<P, V> > super_; /// Value associated type. typedef V value; @@ -111,20 +127,22 @@ /// Skeleton. - typedef graph_image< tag::psite_<P>, tag::value_<V> > skeleton; + typedef line_graph_image< tag::psite_<P>, tag::value_<V> > skeleton; /// Constructors. - graph_image(p_graph<P>& g, std::vector<V>& val); - graph_image(); + line_graph_image(p_line_graph<P>& g, + std::vector<V>& node_val, std::vector<V>& edge_val); + line_graph_image(); /// Initialize an empty image. - void init_(p_graph<P>& g, std::vector<V>& val); + void init_(p_line_graph<P>& g, + std::vector<V>& node_val, std::vector<V>& edge_val); /// Read-only access of pixel value at point site \p p. - const V& operator()(const graph_psite<P>& p) const; + const V& operator()(const line_graph_psite<P>& p) const; /// Read-write access of pixel value at point site \p p. - V& operator()(const graph_psite<P>& p); + V& operator()(const line_graph_psite<P>& p); /// Give the set of values of the image. const vset& values() const; @@ -132,7 +150,9 @@ // FIXME: Keep this name? const std::vector<V>& data_values () const; - const p_graph<P>& domain() const; + const p_line_graph<P>& domain() const; + + // FIXME: Do we want to provide these two methods? /// Return the point of the first node adjacent to the edge with /// id \a e. @@ -145,7 +165,8 @@ // Fwd decl. template <typename P, typename V> void init_(tag::image_t, - graph_image<P, V>& target, const graph_image<P, V>& model); + line_graph_image<P, V>& target, + const line_graph_image<P, V>& model); # ifndef MLN_INCLUDE_ONLY @@ -157,7 +178,8 @@ template <typename P, typename V> inline void init_(tag::image_t, - graph_image<P, V>& target, const graph_image<P, V>& model) + line_graph_image<P, V>& target, + const line_graph_image<P, V>& model) { /* FIXME: Unfortunately, we cannot simply use @@ -165,9 +187,9 @@ here, since domain() and data_values() return const data, and init_ expects non mutable data. These constness problems exist - also in graph_psite (see uses of const_cast<>). Hence the + also in line_graph_psite (see uses of const_cast<>). Hence the inelegant use of const_cast<>'s. */ - target.init_(const_cast<p_graph<P>&> (model.domain()), + target.init_(const_cast<p_line_graph<P>&>(model.domain()), const_cast<std::vector<V>&> (model.data_values ())); } @@ -179,9 +201,12 @@ { template <typename P, typename V> inline - data_< graph_image<P, V> >::data_(p_graph<P>& g, std::vector<V>& val) - : val_ (val), - pg_ (g) + data_< line_graph_image<P, V> >::data_(p_line_graph<P>& g, + std::vector<V>& node_val, + std::vector<V>& edge_val) + : node_val_(node_val), + edge_val_(edge_val), + plg_(g) { } @@ -193,28 +218,33 @@ template <typename P, typename V> inline - graph_image<P, V>::graph_image(p_graph<P>& g, std::vector<V>& val) + line_graph_image<P, V>::line_graph_image(p_line_graph<P>& g, + std::vector<V>& node_val, + std::vector<V>& edge_val) { - init_(g, val); + init_(g, node_val, edge_val); } template <typename P, typename V> inline - graph_image<P, V>::graph_image() + line_graph_image<P, V>::line_graph_image() { } template <typename P, typename V> inline void - graph_image<P, V>::init_(p_graph<P>& g, std::vector<V>& val) + line_graph_image<P, V>::init_(p_line_graph<P>& g, + std::vector<V>& node_val, + std::vector<V>& edge_val) { /* FIXME: We leak memory here: calling init_ twice loses the previous content pointed by data_. We should definitely write down formal guidelines on initialization and memory management in general! */ - this->data_ = new internal::data_< graph_image<P, V> > (g, val); + this->data_ = + new internal::data_< line_graph_image<P, V> >(g, node_val, edge_val); } /*---------------. @@ -224,27 +254,27 @@ template <typename P, typename V> inline const V& - graph_image<P, V>::operator()(const graph_psite<P>& p) const + line_graph_image<P, V>::operator()(const line_graph_psite<P>& p) const { - mln_precondition(&p.pg() == &this->data_->pg_); - mln_precondition(p.id() < this->data_->val_.size()); - return this->data_->val_[p.id()]; + mln_precondition(&p.plg() == &this->data_->plg_); + mln_precondition(p.id() < this->data_->edge_val_.size()); + return this->data_->edge_val_[p.id()]; } template <typename P, typename V> inline V& - graph_image<P, V>::operator()(const graph_psite<P>& p) + line_graph_image<P, V>::operator()(const line_graph_psite<P>& p) { - mln_precondition(&p.pg() == &this->data_->pg_); - mln_precondition(p.id() < this->data_->val_.size()); - return this->data_->val_[p.id()]; + mln_precondition(&p.plg() == &this->data_->plg_); + mln_precondition(p.id() < this->data_->edge_val_.size()); + return this->data_->edge_val_[p.id()]; } template <typename P, typename V> inline const mln::value::set<V> & - graph_image<P, V>::values() const + line_graph_image<P, V>::values() const { return vset::the(); } @@ -252,24 +282,24 @@ template <typename P, typename V> inline const std::vector<V>& - graph_image<P, V>::data_values () const + line_graph_image<P, V>::data_values() const { - return this->data_->val_; + return this->data_->edge_val_; } template <typename P, typename V> inline - const p_graph<P>& - graph_image<P, V>::domain() const + const p_line_graph<P>& + line_graph_image<P, V>::domain() const { mln_precondition(this->has_data()); - return this->data_->pg_; + return this->data_->plg_; } template <typename P, typename V> inline const P& - graph_image<P, V>::node1(const util::edge_id& e) const + line_graph_image<P, V>::node1(const util::edge_id& e) const { // FIXME: Improve the interface of graph to avoid these low-level // manipulations. @@ -280,7 +310,7 @@ template <typename P, typename V> inline const P& - graph_image<P, V>::node2(const util::edge_id& e) const + line_graph_image<P, V>::node2(const util::edge_id& e) const { // FIXME: Improve the interface of graph to avoid these low-level // manipulations. @@ -293,4 +323,4 @@ } // end of namespace mln -#endif // ! MLN_CORE_GRAPH_IMAGE_HH +#endif // ! MLN_CORE_LINE_GRAPH_IMAGE_HH Index: mln/core/line_graph_psite.hh --- mln/core/line_graph_psite.hh (revision 1714) +++ mln/core/line_graph_psite.hh (working copy) @@ -25,134 +25,200 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_CORE_GRAPH_PSITE_HH -# define MLN_CORE_GRAPH_PSITE_HH +#ifndef MLN_CORE_LINE_GRAPH_PSITE_HH +# define MLN_CORE_LINE_GRAPH_PSITE_HH -/// \file mln/core/graph_psite.hh -/// \brief Definition of a graph-based point site. +/// \file mln/core/line_graph_psite.hh +/// \brief Definition of a line graph-based point site. -# include <mln/core/p_graph.hh> +# include <mln/core/p_line_graph.hh> +# include <mln/core/point_pair.hh> + +/* FIXME: This class shares a lot with graph_psite. Factor as much as + possible. */ namespace mln { // Fwd decl. - template<typename P> class p_graph; + template<typename P> class p_line_graph; /// \brief Point site associated to a mln::graph_image. template<typename P> - class graph_psite : public Point_Site< graph_psite<P> > + class line_graph_psite : public Point_Site< line_graph_psite<P> > { - typedef graph_psite<P> self_; + typedef line_graph_psite<P> self_; public: - typedef mln_mesh(P) mesh; - enum { dim = P::dim }; - typedef P point; - typedef mln_dpoint(P) dpoint; - typedef mln_coord(P) coord; + typedef point_pair<P> point; + typedef mln_mesh(point) mesh; + enum { dim = point::dim }; + typedef mln_dpoint(point) dpoint; + typedef mln_coord(point) coord; /// Construction and assignment. /// \{ - graph_psite(const p_graph<P>& pg_, unsigned id); - graph_psite(const self_& rhs); + line_graph_psite(const p_line_graph<P>& plg_, unsigned id); + line_graph_psite(const self_& rhs); self_& operator= (const self_& rhs); /// \} /// Access to point/psite. /// \{ - operator P() const; + operator point() const; const point& to_point() const; coord operator[](unsigned id) const; /// \} - /// Return the mln::p_graph this point site belongs to. - const p_graph<P>& pg() const; + /// Return the mln::p_line_graph this point site belongs to. + const p_line_graph<P>& plg() const; /// Return the node id of this point site. util::node_id id() const; private: - const p_graph<P>& pg_; - util::node_id id_; + /// Update \a p_. + void update_(); + /// Is this psite valid? + bool is_valid_() const; + + private: + /// The p_line_graph this point site belongs to. + const p_line_graph<P>& plg_; + /// The id of the edge this psite is pointing towards. + util::edge_id id_; + /** \brief The point associated to this psite. + + Contrary to mln::graph_psite, this information is actually + stored in the mln::line_graph_psite. In mln::graph_psite, the + point is retrieved from the data associated with the + corresponding node in the graph. We cannot do this here, + since points associated to edges are computed on the fly + (storing them in the graph could be possible, but too costly + in space). */ + point p_; }; + /* FIXME: This hand-made delegation is painful. We should rely on + the general mechanism provided by Point_Site. But then again, we + need to refine/adjust the interface of Point_Site w.r.t. the + mandatory conversions to points. */ + template <typename P> + inline + std::ostream& + operator<<(std::ostream& ostr, const line_graph_psite<P>& p); # ifndef MLN_INCLUDE_ONLY + /* Careful, the current interface of line_graph_psite allows the + construction of ill-formed psites (i.e., whose edge is is beyond + bounds). Actually, p_line_graph_piters *do* create ill-formed + psites at their initialization. */ + template<typename P> inline - graph_psite<P>::graph_psite(const p_graph<P>& g, util::node_id id) - : pg_(g), - id_(id) + line_graph_psite<P>::line_graph_psite(const p_line_graph<P>& g, + util::edge_id id) + : plg_(g), + id_(id), + p_() { } template<typename P> inline - graph_psite<P>::graph_psite(const graph_psite<P>& rhs) - : pg_(rhs.pg_), + line_graph_psite<P>::line_graph_psite(const line_graph_psite<P>& rhs) + : plg_(rhs.plg_), id_(rhs.id_) { } template<typename P> inline - graph_psite<P>& - graph_psite<P>::operator= (const graph_psite<P>& rhs) + line_graph_psite<P>& + line_graph_psite<P>::operator= (const line_graph_psite<P>& rhs) { if (&rhs == this) return *this; // FIXME: Could we get rid of this cast? - const_cast< p_graph<P>& >(pg_) = rhs.pg_; + const_cast< p_line_graph<P>& >(plg_) = rhs.plg_; id_ = rhs.id_; + update_(); return *this; } template<typename P> inline - graph_psite<P>::operator P() const + line_graph_psite<P>::operator point_pair<P>() const + { + mln_assertion (is_valid_()); + return p_; + } + + template<typename P> + inline + bool + line_graph_psite<P>::is_valid_() const { - return pg_.gr_.node_data(id_); + return id_ < plg_.gr_.nedges(); } template<typename P> inline - const P& - graph_psite<P>::to_point() const + const point_pair<P>& + line_graph_psite<P>::to_point() const { - return pg_.gr_.node_data(id_); + return p_; } template<typename P> inline - mln_coord(P) - graph_psite<P>::operator[](util::node_id id) const + mln_coord(point_pair<P>) + line_graph_psite<P>::operator[](unsigned i) const { - return to_point()[id]; + mln_assertion (is_valid_()); + return to_point()[i]; } template<typename P> inline - const p_graph<P>& - graph_psite<P>::pg() const + void + line_graph_psite<P>::update_() { - return pg_; + p_ = point(plg_.gr_.node_data(plg_.gr_.edge(id_).n1()), + plg_.gr_.node_data(plg_.gr_.edge(id_).n2())); + } + + template<typename P> + inline + const p_line_graph<P>& + line_graph_psite<P>::plg() const + { + return plg_; } template<typename P> inline util::node_id - graph_psite<P>::id() const + line_graph_psite<P>::id() const { return id_; } + + template <typename P> + inline + std::ostream& + operator<<(std::ostream& ostr, const line_graph_psite<P>& p) + { + return ostr << p.to_point(); + } + # endif // ! MLN_INCLUDE_ONLY } // end of mln -#endif // MLN_CORE_GRAPH_PSITE_HH +#endif // MLN_CORE_LINE_GRAPH_PSITE_HH Index: mln/core/line_graph_window_piter.hh --- mln/core/line_graph_window_piter.hh (revision 1714) +++ mln/core/line_graph_window_piter.hh (working copy) @@ -25,51 +25,56 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_CORE_GRAPH_WINDOW_PITER_HH -# define MLN_CORE_GRAPH_WINDOW_PITER_HH +#ifndef MLN_CORE_LINE_GRAPH_WINDOW_PITER_HH +# define MLN_CORE_LINE_GRAPH_WINDOW_PITER_HH -/// \file mln/core/graph_window_piter.hh -/// \brief Definition of a point iterator on a graph window. +/// \file mln/core/line_graph_window_piter.hh +/// \brief Definition of a point iterator on a line_graph window. # include <mln/core/concept/point_iterator.hh> -# include <mln/core/p_graph.hh> -# include <mln/core/graph_psite.hh> +# include <mln/core/p_line_graph.hh> +# include <mln/core/line_graph_psite.hh> +# include <mln/core/point_pair.hh> /* FIXME: Doc. */ -/* FIXME: Due to the poor interface of mln::p_graph and +/* FIXME: Due to the poor interface of mln::p_line_graph and mln::util::graph, we show to much implementation details here. Enrich their interfaces to avoid that. */ namespace mln { // Fwd decls. - template <typename P> class p_graph; - template <typename P> class graph_psite; + template <typename P> class p_line_graph; + template <typename P> class line_graph_psite; + /*---------------------------------. + | line_graph_window_fwd_piter<P>. | + `---------------------------------*/ + template <typename P> - class graph_window_fwd_piter : - public Point_Iterator< graph_window_fwd_piter<P> > // or Iterator<...>? + class line_graph_window_fwd_piter : + public Point_Iterator< line_graph_window_fwd_piter<P> > // or Iterator<...>? { - typedef graph_window_fwd_piter<P> self_; + typedef line_graph_window_fwd_piter<P> self_; typedef Point_Iterator< self_ > super_; public: - typedef graph_psite<P> psite; + typedef line_graph_psite<P> psite; enum { dim = P::dim }; // FIXME: Dummy value. typedef void mesh; - typedef P point; + typedef point_pair<P> point; // FIXME: Dummy typedef. typedef void dpoint; - typedef mln_coord(P) coord; + typedef mln_coord(point) coord; public: template <typename W, typename Pref> - graph_window_fwd_piter(const W& win, const Point_Site<Pref>& p_ref); + line_graph_window_fwd_piter(const W& win, const Point_Site<Pref>& p_ref); bool is_valid() const; void invalidate(); @@ -77,23 +82,44 @@ void next_(); bool adjacent_or_equal_to_p_ref_() const; + /// Update the internal data of the iterator. + void update_(); - // FIXME: In fact, this method should be named `to_psite', since - // it returns a mln::graph_psite<P> object, not a P object. const point& to_point() const; + const psite& to_psite() const; + + operator point() const; operator psite () const; + /// Return the \a i th coordinate of the (iterated) point. coord operator[](unsigned i) const; private: - /// The ``central'' point of the window. + /// The ``central'' psite of the window. const psite& p_ref_; - - /// An internal iterator on the set of nodes of the underlying graph. - util::node_id id_; + /// An internal iterator on the set of edges of the underlying graph. + util::edge_id id_; + /// The psite corresponding to this iterator. + psite psite_; + /// The point corresponding to this iterator. + point p_; }; - // FIXME: Implement graph_window_bkd_piter. + /* FIXME: This hand-made delegation is painful. We should rely on + the general mechanism provided by Point_Site. But then again, we + need to refine/adjust the interface of Point_Site w.r.t. the + mandatory conversions to points. */ + template <typename P> + inline + std::ostream& + operator<<(std::ostream& ostr, const line_graph_window_fwd_piter<P>& p); + + + /*---------------------------------. + | line_graph_window_bkd_piter<P>. | + `---------------------------------*/ + + // FIXME: Implement line_graph_window_bkd_piter. # ifndef MLN_INCLUDE_ONLY @@ -101,61 +127,76 @@ // FIXME: Currently, argument win is ignored. template <typename P> template <typename W, typename Pref> - graph_window_fwd_piter<P>::graph_window_fwd_piter(const W& /* win */, + inline + line_graph_window_fwd_piter<P>::line_graph_window_fwd_piter(const W& /* win */, const Point_Site<Pref>& p_ref) - : p_ref_(exact(p_ref).to_psite()) + : p_ref_(exact(p_ref).to_psite()), + // Initialize psite_ to a dummy value. + psite_(p_ref_.plg(), p_ref_.plg().nlines()), + p_() { // Invalidate id_. invalidate(); } template <typename P> + inline bool - graph_window_fwd_piter<P>::is_valid() const + line_graph_window_fwd_piter<P>::is_valid() const { // FIXME: We depend too much on the implementation of util::graph // here. The util::graph should provide the service to abstract // these manipulations. - return id_ < p_ref_.pg().gr_.nnodes(); + return id_ < p_ref_.plg().gr_.nedges(); } template <typename P> + inline void - graph_window_fwd_piter<P>::invalidate() + line_graph_window_fwd_piter<P>::invalidate() { - id_ = p_ref_.pg().gr_.nnodes(); + id_ = p_ref_.plg().gr_.nedges(); } template <typename P> + inline void - graph_window_fwd_piter<P>::start() + line_graph_window_fwd_piter<P>::start() { id_ = 0; if (!adjacent_or_equal_to_p_ref_()) next_(); + /* FIXME: This is redundant with the end of next_(), but we might + change the implementation of start_() when we'll fix it later, + and no longer use next_(). */ + if (is_valid()) + update_(); } template <typename P> + inline void - graph_window_fwd_piter<P>::next_() + line_graph_window_fwd_piter<P>::next_() { /* FIXME: This is inefficient. The graph structure should be able - to produce the set of adjacent nodes fast. Boost Graphs + to produce the set of adjacent edges fast. Boost Graphs probably provides adequates structures to fetch these neighbors in constant time. */ /* FIXME: Moreover, the behavior of next shall depend on the - window, which is not the case now! */ + window, which is not the case now! (Currently, next_() behaves + as win was always an elementary window.) */ do ++id_; while (is_valid() && !adjacent_or_equal_to_p_ref_()); + if (is_valid()) + update_(); } template <typename P> + inline bool - graph_window_fwd_piter<P>::adjacent_or_equal_to_p_ref_() const + line_graph_window_fwd_piter<P>::adjacent_or_equal_to_p_ref_() const { - // FIXME: Likewise, this is inefficient. - // Check wether the iterator points to P_REF_. if (id_ == p_ref_.id()) return true; @@ -163,15 +204,19 @@ // Check whether the iterator is among the neighbors of P_REF_. { // Paranoid assertion. - assert (p_ref_.id() < p_ref_.pg().gr_.nnodes()); - // FIXME: This is too low-level. Yet another service the graph - // should provide. - typedef std::vector<util::node_id> adjacency_type; - const adjacency_type& p_ref_neighbs = - p_ref_.pg().gr_.nodes()[p_ref_.id()]->edges; - adjacency_type::const_iterator j = - std::find (p_ref_neighbs.begin(), p_ref_neighbs.end(), id_); - if (j != p_ref_neighbs.end()) + assert (p_ref_.id() < p_ref_.plg().gr_.nedges()); + /* FIXME: We should have a convenient shortcut for these + repetitive accesses to p_ref_.plg().gr_ (e.g., a method gr() + or g() in this class. */ + const typename p_line_graph<P>::graph& gr = p_ref_.plg().gr_; + // Check whether the edge this iterator points to is adjacent to + // the one p_ref points to, by comparing their ajacent nodes. + /* FIXME: This is too low-level. Yet another service the graph + // should provide. */ + if (gr.edge(id_).n1() == gr.edge(p_ref_.id()).n1() || + gr.edge(id_).n1() == gr.edge(p_ref_.id()).n2() || + gr.edge(id_).n2() == gr.edge(p_ref_.id()).n1() || + gr.edge(id_).n2() == gr.edge(p_ref_.id()).n2()) return true; } @@ -180,29 +225,70 @@ } template <typename P> - const P& - graph_window_fwd_piter<P>::to_point() const + inline + void + line_graph_window_fwd_piter<P>::update_() { - return p_ref_.pg().gr_.node_data(id_); + // Update psite_. + psite_ = line_graph_psite<P>(p_ref_.plg(), id_); + // Update p_. + // FIXME: These repeated assignments might be very costly. + /* FIXME: Likewise, it's hard to read. Simplify accesses to the graph. */ + p_ = point(p_ref_.plg().gr_.node_data(p_ref_.plg().gr_.edge(id_).n1()), + p_ref_.plg().gr_.node_data(p_ref_.plg().gr_.edge(id_).n2())); } template <typename P> - graph_window_fwd_piter<P>::operator graph_psite<P> () const + inline + const point_pair<P>& + line_graph_window_fwd_piter<P>::to_point() const { - return graph_psite<P>(p_ref_.pg(), id_); + return p_; } template <typename P> inline - mln_coord(P) - graph_window_fwd_piter<P>::operator[](unsigned i) const + const line_graph_psite<P>& + line_graph_window_fwd_piter<P>::to_psite() const + { + return psite_; + } + + template <typename P> + inline + line_graph_window_fwd_piter<P>::operator point_pair<P>() const + { + mln_precondition(is_valid()); + return p_; + } + + template <typename P> + inline + line_graph_window_fwd_piter<P>::operator line_graph_psite<P> () const + { + mln_precondition(is_valid()); + return psite_; + } + + template <typename P> + inline + mln_coord(point_pair<P>) + line_graph_window_fwd_piter<P>::operator[](unsigned i) const { assert(i < dim); - return to_point()[i]; + return p_[i]; + } + + template <typename P> + inline + std::ostream& + operator<<(std::ostream& ostr, const line_graph_window_fwd_piter<P>& p) + { + return ostr << p.to_point(); } # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln -#endif // ! MLN_CORE_GRAPH_WINDOW_PITER_HH +#endif // ! MLN_CORE_LINE_GRAPH_WINDOW_PITER_HH Index: mln/core/p_line_graph.hh --- mln/core/p_line_graph.hh (revision 1714) +++ mln/core/p_line_graph.hh (working copy) @@ -25,41 +25,58 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_CORE_GRAPH_P_HH -# define MLN_CORE_GRAPH_P_HH +#ifndef MLN_CORE_LINE_GRAPH_P_HH +# define MLN_CORE_LINE_GRAPH_P_HH # include <mln/core/concept/point_site.hh> # include <mln/core/internal/point_set_base.hh> # include <mln/accu/bbox.hh> # include <mln/util/graph.hh> -# include <mln/core/graph_psite.hh> -# include <mln/core/p_graph_piter.hh> +# include <mln/core/line_graph_psite.hh> +# include <mln/core/p_line_graph_piter.hh> +# include <mln/core/point_pair.hh> -/// \file mln/core/p_graph.hh -/// \brief Definition of a point set based on graph. +/* FIXME: This class shares a lot with p_graph. Factor as much as + possible. */ + + +/// \file mln/core/p_line_graph.hh +/// \brief Definition of a point set based on line graph. namespace mln { - template<typename P> class p_graph_piter_; + // FIXME: Dummy specialization, only to have this first version of + // our code compile. + template <typename P> + struct box_< point_pair<P> > : public Box< box_<P> > + { + // Nothing. + }; + + + template<typename P> class p_line_graph_piter_; template<typename P> - struct p_graph - : public internal::point_set_base_< graph_psite<P>, p_graph<P> > + struct p_line_graph + : public internal::point_set_base_< line_graph_psite<P>, p_line_graph<P> > { typedef util::graph<P> graph; - /// Construct a graph psite set from a graph of points. - p_graph (graph& gr); + /// Construct a line graph psite set from a graph of points. + p_line_graph (graph& gr); /// Point_Site associated type. - typedef graph_psite<P> psite; + typedef line_graph_psite<P> psite; + + /// Point associated type. + typedef point_pair<P> point; /// Forward Point_Iterator associated type. - typedef p_graph_piter_<P> fwd_piter; + typedef p_line_graph_piter_<P> fwd_piter; /// Backward Point_Iterator associated type. - typedef p_graph_piter_<P> bkd_piter; + typedef p_line_graph_piter_<P> bkd_piter; /// Return The number of points (i.e., nodes) in the graph. std::size_t npoints() const; @@ -68,32 +85,37 @@ std::size_t nlines() const; /// Give the exact bounding box. - const box_<P>& bbox() const; + // FIXME: Dummy. + const box_<point>& bbox() const; bool has(const psite& p) const; // FIXME: Should be private. graph gr_; // FIXME: (Roland) Is it really useful/needed? - /* 2007-12-19: It seems so, since graph_image must implement a method - named bbox(). Now the question is: should each image type have a - bounding box? */ - box_<P> bb_; + /* 2007-12-19: It seems so, since graph_image must implement a + method named bbox(). Now the question is: should each image + type have a bounding box? In particular, an image whose sites + are actually /pairs of points/! */ + // FIXME: Dummy. + box_<point> bb_; }; # ifndef MLN_INCLUDE_ONLY template<typename P> inline - p_graph<P>::p_graph (util::graph<P>& gr) + p_line_graph<P>::p_line_graph (util::graph<P>& gr) : gr_ (gr) { - // FIXME: Warning: if the underlying graph is updated later, this - // won't be taken into account by this p_graph! - accu::bbox<P> a; - for (unsigned i = 0; i < npoints(); ++i) - a.take(gr_.node_data(i)); - bb_ = a.to_result(); + // FIXME: Dummy initialization of bb_. +// // FIXME: Warning: if the underlying graph is updated later, this +// // won't be taken into account by this p_line_graph! +// accu::bbox<point> a; +// for (util::edge_id e = 0; e < nlines(); ++e) +// a.take(point(gr_.node_data(gr_.edge(e).n1()), +// gr_.node_data(gr_.edge(e).n2()))); +// bb_ = a.to_result(); } // FIXME: Rename to npsites? In fact, this depends on the @@ -101,7 +123,7 @@ template<typename P> inline std::size_t - p_graph<P>::npoints() const + p_line_graph<P>::npoints() const { return this->gr_.nnodes(); } @@ -109,15 +131,15 @@ template<typename P> inline std::size_t - p_graph<P>::nlines() const + p_line_graph<P>::nlines() const { return this->gr_.nedges(); } template<typename P> inline - const box_<P>& - p_graph<P>::bbox() const + const box_< point_pair<P> >& + p_line_graph<P>::bbox() const { return bb_; } @@ -125,16 +147,13 @@ template<typename P> inline bool - p_graph<P>::has(const psite& p) const + p_line_graph<P>::has(const psite& p) const { - // FIXME: util::graph (or util::internal::graph_base) should - // provide the iteration facility (iterators, find, etc.) - const typename graph::nodes_t& nodes = gr_.nodes(); - for (typename graph::nodes_t::const_iterator n = nodes.begin(); - n != nodes.end(); ++n) - if ((*n)->data == p) - return true; - return false; + return + // Check whether P is compatible with this psite set. + (&p.plg() == this) && + // Check that the edge id of P belongs to the range of valid edge ids. + (p.id() < gr_.nedges()); } # endif // ! MLN_INCLUDE_ONLY Index: mln/core/p_line_graph_piter.hh --- mln/core/p_line_graph_piter.hh (revision 1714) +++ mln/core/p_line_graph_piter.hh (working copy) @@ -25,14 +25,15 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_CORE_P_GRAPH_PITER_HH -# define MLN_CORE_P_GRAPH_PITER_HH +#ifndef MLN_CORE_P_LINE_GRAPH_PITER_HH +# define MLN_CORE_P_LINE_GRAPH_PITER_HH # include <mln/core/internal/point_iterator_base.hh> -# include <mln/core/p_graph.hh> -# include <mln/core/graph_psite.hh> +# include <mln/core/p_line_graph.hh> +# include <mln/core/line_graph_psite.hh> +# include <mln/core/point_pair.hh> -/*! \file mln/core/p_graph_piter.hh +/*! \file mln/core/p_line_graph_piter.hh * * \brief Definition of point iterator on graph-based point set. */ @@ -40,30 +41,32 @@ namespace mln { // Fwd decls. - template<typename P> class p_graph; - template<typename P> class graph_psite; + template<typename P> class p_line_graph; + template<typename P> class line_graph_psite; - // FIXME: Why `p_graph_piter_' and not `p_graph_piter' (without `_')? + // FIXME: Why `p_line_graph_piter_' and not `p_line_graph_piter' + // (without `_')? template<typename P> - class p_graph_piter_ - : public internal::point_iterator_base_< P, p_graph_piter_<P> > + class p_line_graph_piter_ + : public internal::point_iterator_base_< P, p_line_graph_piter_<P> > { - typedef p_graph_piter_<P> self_; + typedef p_line_graph_piter_<P> self_; typedef internal::point_iterator_base_< P, self_ > super_; public: // Make definitions from super class available. enum { dim = super_::dim }; - typedef graph_psite<P> psite; - typedef P point; + typedef line_graph_psite<P> psite; + typedef point_pair<P> point; + typedef mln_coord(point_pair<P>) coord; - p_graph_piter_(const p_graph<P>& pg); + p_line_graph_piter_(const p_line_graph<P>& plg); /// Read-only access to the \p i-th coordinate. - mln_coord(P) operator[](unsigned i) const; + mln_coord(point) operator[](unsigned i) const; /// Test if the iterator is valid. bool is_valid() const; @@ -93,32 +96,44 @@ operator psite() const; protected: - const p_graph<P>& pg_; - unsigned i_; - P p_; + /// The p_line_graph this point site belongs to. + const p_line_graph<P>& plg_; + /// The id of the edge this psite is pointing towards. + util::edge_id id_; + /// The psite corresponding to this iterator. psite psite_; + /// The psite corresponding to this iterator. + point p_; }; + /* FIXME: This hand-made delegation is painful. We should rely on + the general mechanism provided by Point_Site. But then again, we + need to refine/adjust the interface of Point_Site w.r.t. the + mandatory conversions to points. */ + template <typename P> + inline + std::ostream& + operator<<(std::ostream& ostr, const p_line_graph_piter_<P>& p); # ifndef MLN_INCLUDE_ONLY template<typename P> inline - p_graph_piter_<P>::p_graph_piter_(const p_graph<P>& pg) - : pg_(pg), - p_(), + p_line_graph_piter_<P>::p_line_graph_piter_(const p_line_graph<P>& plg) + : plg_(plg), // Initialize psite_ to a dummy value. - psite_(pg, pg_.npoints()) + psite_(plg, plg_.nlines()), + p_() { - // Invalidate i_. + // Invalidate id_. invalidate(); } template<typename P> inline - mln_coord(P) - p_graph_piter_<P>::operator[](unsigned i) const + mln_coord(point_pair<P>) + p_line_graph_piter_<P>::operator[](unsigned i) const { return p_[i]; } @@ -126,25 +141,25 @@ template<typename P> inline bool - p_graph_piter_<P>::is_valid() const + p_line_graph_piter_<P>::is_valid() const { - return i_ < pg_.npoints(); + return id_ < plg_.nlines(); } template<typename P> inline void - p_graph_piter_<P>::invalidate() + p_line_graph_piter_<P>::invalidate() { - i_ = pg_.npoints(); + id_ = plg_.nlines(); } template<typename P> inline void - p_graph_piter_<P>::start() + p_line_graph_piter_<P>::start() { - i_ = 0; + id_ = 0; if (is_valid()) update_(); } @@ -152,9 +167,9 @@ template<typename P> inline void - p_graph_piter_<P>::next_() + p_line_graph_piter_<P>::next_() { - ++i_; + ++id_; if (is_valid()) update_(); } @@ -162,18 +177,20 @@ template<typename P> inline void - p_graph_piter_<P>::update_() + p_line_graph_piter_<P>::update_() { - // Update p_. - p_ = pg_.gr_.node_data(i_); // Update psite_. - psite_ = graph_psite<P>(pg_, i_); + psite_ = line_graph_psite<P>(plg_, id_); + // Update p_. + // FIXME: These repeated assignments might be very costly. + p_ = point(plg_.gr_.node_data(plg_.gr_.edge(id_).n1()), + plg_.gr_.node_data(plg_.gr_.edge(id_).n2())); } template<typename P> inline - const P& - p_graph_piter_<P>::to_point() const + const point_pair<P>& + p_line_graph_piter_<P>::to_point() const { /* We don't check whether the iterator is valid before returning the value using @@ -191,8 +208,8 @@ template<typename P> inline - const graph_psite<P>& - p_graph_piter_<P>::to_psite() const + const line_graph_psite<P>& + p_line_graph_piter_<P>::to_psite() const { /* We don't check whether the iterator is valid before returning the value using @@ -210,7 +227,7 @@ template<typename P> inline - p_graph_piter_<P>::operator P() const + p_line_graph_piter_<P>::operator point_pair<P>() const { mln_precondition(is_valid()); return p_; @@ -218,15 +235,24 @@ template<typename P> inline - p_graph_piter_<P>::operator graph_psite<P>() const + p_line_graph_piter_<P>::operator line_graph_psite<P>() const { mln_precondition(is_valid()); return psite_; } + + template <typename P> + inline + std::ostream& + operator<<(std::ostream& ostr, const p_line_graph_piter_<P>& p) + { + return ostr << p.to_point(); + } + # endif // ! MLN_INCLUDE_ONLY } // end of mln -#endif // MLN_P_GRAPH_PITER_HH +#endif // MLN_P_LINE_GRAPH_PITER_HH Index: tests/core/line_graph_elt_window.cc --- tests/core/line_graph_elt_window.cc (revision 1715) +++ tests/core/line_graph_elt_window.cc (working copy) @@ -25,15 +25,15 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/core/graph_elt_window.cc +/*! \file tests/core/line_graph_elt_window.cc * - * \brief Tests on mln::win::graph_elt_window. + * \brief Tests on mln::line_graph_elt_window. */ #include <vector> #include <mln/core/point2d.hh> -#include <mln/core/graph_elt_window.hh> +#include <mln/core/line_graph_elt_window.hh> #include <mln/debug/iota.hh> #include <mln/debug/println.hh> @@ -73,10 +73,10 @@ | Graph and window. | `------------------*/ - // Graph psite set. - p_graph<p_t> pg(g); - // Graph point site. - graph_psite<p_t> psite(pg, 0); - // ``Sliding'' window (in fact, neighborhood) of a psite of PG. - graph_elt_window<p_t> win; + // Line graph psite set. + p_line_graph<p_t> plg(g); + // Line graph point site. + line_graph_psite<p_t> psite(plg, 0); + // ``Sliding'' window of a psite of PLG. + line_graph_elt_window<p_t> win; } Index: tests/core/line_graph_image.cc --- tests/core/line_graph_image.cc (revision 1714) +++ tests/core/line_graph_image.cc (working copy) @@ -31,9 +31,9 @@ #include <vector> #include <mln/core/point2d.hh> -#include <mln/core/graph_image.hh> -#include <mln/core/graph_elt_window.hh> -#include <mln/core/graph_window_piter.hh> +#include <mln/core/line_graph_image.hh> +#include <mln/core/line_graph_elt_window.hh> +#include <mln/core/line_graph_window_piter.hh> #include <mln/morpho/dilation.hh> @@ -74,44 +74,26 @@ | Graph. | `-------*/ - p_graph<point2d> pg(g); - - /*-------------. - | Graph image. | - `-------------*/ - - // Values ("empty" vector). - std::vector<int> values(5); - // Graph image. - typedef graph_image<point2d, int> ima_t; - ima_t ima(pg, values); - // Initialize values. - debug::iota(ima); - // Print the image. - /* FIXME: Unfortunately, displaying graph images is not easy right - now (2008-02-05). We could use - - debug::println(ima); - - but there's not specialization working for graph_image; the one - selected by the compiler is based on a 2-D bbox, and expects the - interface of graph_image to work with points (not psites). - Moreover, this implementation only shows *values*, not the graph - itslef. - - An alternative is to use draw::graph (which, again, is misnamed), - but it doesn't show the values, only the nodes and edges of the - graph. - - The current solution is a mix between draw::graph and hand-made - iterations. */ - image2d<int> ima_rep(ima.bbox()); - // We use the value 9 in draw::graph instead of the default (which is - // 1) to represent edges to distinguish it from nodes holding a - // value of 1. - draw::graph (ima_rep, ima, 9); - debug::println (ima_rep); + p_line_graph<point2d> plg(g); + /*-------------------. + | Line graph image. | + `-------------------*/ + + // Values ("empty" vectors). + std::vector<int> node_values(5); + std::vector<int> edge_values(5); + // FIXME: hand-made iota's. + for (unsigned i = 0; i < node_values.size(); ++i) + node_values[i] = i; + for (unsigned i = 0; i < edge_values.size(); ++i) + edge_values[i] = i; + + // Line graph image. + /* FIXME: We probably don't want to build line_graph_images by hand; + provide helpers and/or conversion functions. */ + typedef line_graph_image<point2d, int> ima_t; + ima_t ima(plg, node_values, edge_values); /*------------. | Iterators. | @@ -123,7 +105,7 @@ std::cout << "ima (" << p << ") = " << ima(p) << std::endl; // Manual iterations over the neighborhoods of each point site of IMA. - typedef graph_elt_window<point2d> win_t; + typedef line_graph_elt_window<point2d> win_t; win_t win; mln_qiter_(win_t) q(win, p); for_all (p) @@ -131,19 +113,30 @@ std::cout << "neighbors of " << p << " (" << ima(p) << "), " << "including the site itself:" << std::endl; for_all (q) - std::cout << " " << q << " (level = " << ima(q) << ")" << std::endl; + std::cout << " " << q << " (level = " << ima(q) << ")" + << std::endl; } std::cout << std::endl; - /*-------------------------. - | Processing graph images. | - `-------------------------*/ - - graph_image<point2d, int> ima_dil = morpho::dilation(ima, win); - draw::graph(ima_rep, ima_dil, 9); - debug::println(ima_rep); - - graph_image<point2d, int> ima_ero = morpho::erosion(ima, win); - draw::graph(ima_rep, ima_ero, 9); - debug::println(ima_rep); + +// /* FIXME: When implementing convert::to_line_graph_image, don't +// forget to give a second argument defaulting to something like +// fun::vv2v::max(). This second argument is a functor used to +// compute the values of the edges of the line graph image. */ +// image2d ima; // = ... +// lg_ima_t lg_ima = convert::to_line_graph_image (ima); + +// // Image2d representation. +// image2d<value_t> out = convert::to_image2d (lg_ima); +// io::pgm::save(out, "out.pgm"); + +// /* FIXME: Then, add some real processing on the line graph image +// before converting to an image2d: +// - erosion/dilation, +// - Beucher's gradient, +// - Meyer's WST (on the gradient of LG_IMA?), +// - attribute filters (see my notes on Laurent's remarks about +// attributes), +// - etc. +// Creating seperate tests for all these would be wise. */ } Index: tests/core/Makefile.am --- tests/core/Makefile.am (revision 1717) +++ tests/core/Makefile.am (working copy) @@ -10,19 +10,21 @@ initialize \ graph_elt_window \ graph_image \ + line_graph_elt_window \ + line_graph_image \ mono_obased_rle_image \ mono_rle_image \ obased_rle_image \ - p_runs \ - rle_image \ - sparse_image \ - t_image \ - tr_image \ p_priority_queue \ p_priority_queue_fast \ p_priority_queue_fast_with_array \ p_queue \ - p_queue_fast + p_queue_fast \ + p_runs \ + rle_image \ + sparse_image \ + t_image \ + tr_image category_SOURCES = category.cc clone_SOURCES = clone.cc @@ -31,18 +33,20 @@ initialize_SOURCES = initialize.cc graph_elt_window_SOURCES = graph_elt_window.cc graph_image_SOURCES = graph_image.cc +line_graph_elt_window_SOURCES = line_graph_elt_window.cc +line_graph_image_SOURCES = line_graph_image.cc mono_obased_rle_image_SOURCES = mono_obased_rle_image.cc mono_rle_image_SOURCES = mono_rle_image.cc obased_rle_image_SOURCES = obased_rle_image.cc -p_runs_SOURCES = p_runs.cc -rle_image_SOURCES = rle_image.cc -sparse_image_SOURCES = sparse_image.cc -t_image_SOURCES = t_image.cc -tr_image_SOURCES = tr_image.cc p_priority_queue_SOURCES = p_priority_queue.cc p_priority_queue_fast_SOURCES = p_priority_queue_fast.cc p_priority_queue_fast_with_array_SOURCES = p_priority_queue_fast.cc p_queue_SOURCES = p_priority_queue_fast.cc p_queue_fast_SOURCES = p_priority_queue_fast.cc +p_runs_SOURCES = p_runs.cc +rle_image_SOURCES = rle_image.cc +sparse_image_SOURCES = sparse_image.cc +t_image_SOURCES = t_image.cc +tr_image_SOURCES = tr_image.cc TESTS = $(check_PROGRAMS)