https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog from Roland Levillain roland@lrde.epita.fr
Catch up with the new interface of mln::util::graph and improve graph-based entities.
* mln/core/p_graph.hh: Store points associated to nodes in the graph itself, not in an separate array. (p_graph<P>::graph): Set this typedef from `util::graph<void>' to `util::graph<P>'. (p_graph<P>::loc_): Remove. (p_graph<P>::graph): Adjust ctor. (p_graph<P>::npoints, p_graph<P>::nlines, p_graph<P>::has): Use the new interface of mln::util::graph. * mln/core/graph_psite.hh (graph_psite<P>::i_): Rename as (graph_psite<P>::id_): ...this. Make it a private argument. (graph_psite<P>::pg_): Likewise. (graph_psite<P>::id, graph_psite<P>::pg): New accessors. Adjust users. * mln/core/graph_image.hh (graph_image<P, V>::access_location_link_node1) (graph_image<P, V>::access_location_link_node2): Rename as... (graph_image<P, V>::node1) (graph_image<P, V>::node2): ...these. Use the new interface of mln::util::graph. (graph_image<P, V>::operator()) Use the new interface of mln::graph_psite. * mln/core/graph_window_piter.hh (graph_window_fwd_piter<P>::i_): Rename as... (graph_window_fwd_piter<P>::id_): ...this. Set its to type from `unsigned' to `util::node_id'. Adjust users. (graph_window_fwd_piter<P>::is_valid) (graph_window_fwd_piter<P>::invalidate) (graph_window_fwd_piter<P>::adjacent_or_equal_to_p_ref_) (graph_window_fwd_piter<P>::to_point) (graph_window_fwd_piter<P>::operator graph_psite<P>): Use the new interface of mln::util::graph. * mln/core/p_graph_piter.hh (p_graph_piter_<P>::psite_set_): Rename as... (p_graph_piter_<P>::pg_): ...this. Use the new interface of mln::p_graph. (p_graph_piter_<P>::is_valid) (p_graph_piter_<P>::invalidate) (p_graph_piter_<P>::update_): Likewise. * mln/draw/graph.hh (draw::graph): Update to the new interfaces of mln::util::graph and mln::p_graph. * mln/draw/all.hh: Adjust and complete the list of included headers. * tests/core/graph_elt_window.cc, * tests/core/graph_image.cc, * tests/draw/graph.cc: Update tests.
mln/core/graph_image.hh | 39 +++++++++++++---------- mln/core/graph_psite.hh | 68 ++++++++++++++++++++++++----------------- mln/core/graph_window_piter.hh | 51 +++++++++++++----------------- mln/core/p_graph.hh | 37 +++++++++++++--------- mln/core/p_graph_piter.hh | 18 +++++----- mln/draw/all.hh | 4 +- mln/draw/graph.hh | 33 ++++++++++--------- tests/core/graph_elt_window.cc | 6 +-- tests/core/graph_image.cc | 6 +-- tests/draw/graph.cc | 8 +--- 10 files changed, 145 insertions(+), 125 deletions(-)
Index: mln/core/graph_psite.hh --- mln/core/graph_psite.hh (revision 1713) +++ mln/core/graph_psite.hh (working copy) @@ -28,12 +28,8 @@ #ifndef MLN_CORE_GRAPH_PSITE_HH # define MLN_CORE_GRAPH_PSITE_HH
-/*! \file mln/core/graph_psite.hh - * - * \brief Definition of a graph-based point site. - * - * \todo Clean-up! - */ +/// \file mln/core/graph_psite.hh +/// \brief Definition of a graph-based point site.
# include <mln/core/p_graph.hh>
@@ -45,11 +41,7 @@ template<typename P> class p_graph;
- /*! - * \brief Point site associate to graph_image. - * - * \todo Fix access to member. - */ + /// \brief Point site associated to a mln::graph_image. template<typename P> class graph_psite : public Point_Site< graph_psite<P> > { @@ -64,27 +56,37 @@
/// Construction and assignment. /// { - graph_psite(const p_graph<P>& pg_, unsigned i); + graph_psite(const p_graph<P>& pg_, unsigned id); graph_psite(const self_& rhs); self_& operator= (const self_& rhs); /// }
+ /// Access to point/psite. + /// { operator P() const; const point& to_point() const; - coord operator[](unsigned i) const; + coord operator[](unsigned id) const; + /// }
- // FIXME: These shouldn't be public. + /// Return the mln::p_graph this point site belongs to. + const p_graph<P>& pg() const; + /// Return the node id of this point site. + util::node_id id() const; + + private: const p_graph<P>& pg_; - unsigned i_; + util::node_id id_; };
+ + # ifndef MLN_INCLUDE_ONLY
template<typename P> inline - graph_psite<P>::graph_psite(const p_graph<P>& g, unsigned i) + graph_psite<P>::graph_psite(const p_graph<P>& g, util::node_id id) : pg_(g), - i_(i) + id_(id) { }
@@ -92,7 +94,7 @@ inline graph_psite<P>::graph_psite(const graph_psite<P>& rhs) : pg_(rhs.pg_), - i_(rhs.i_) + id_(rhs.id_) { }
@@ -105,7 +107,7 @@ return *this; // FIXME: Could we get rid of this cast? const_cast< p_graph<P>& >(pg_) = rhs.pg_; - i_ = rhs.i_; + id_ = rhs.id_; return *this; }
@@ -113,9 +115,7 @@ inline graph_psite<P>::operator P() const { - // FIXME: This is quite unsafe: we should check that i_ is a valid - // index before dereferencing loc_ to ensure clear error messages. - return pg_.loc_[i_]; + return pg_.gr_.node_data(id_); }
template<typename P> @@ -123,17 +123,31 @@ const P& graph_psite<P>::to_point() const { - // FIXME: This is quite unsafe: we should check that i_ is a valid - // index before dereferencing loc_ to ensure clear error messages. - return pg_.loc_[i_]; + return pg_.gr_.node_data(id_); }
template<typename P> inline mln_coord(P) - graph_psite<P>::operator[](unsigned i) const + graph_psite<P>::operator[](util::node_id id) const + { + return to_point()[id]; + } + + template<typename P> + inline + const p_graph<P>& + graph_psite<P>::pg() const + { + return pg_; + } + + template<typename P> + inline + util::node_id + graph_psite<P>::id() const { - return to_point()[i]; + return id_; }
# endif // ! MLN_INCLUDE_ONLY Index: mln/core/p_graph.hh --- mln/core/p_graph.hh (revision 1713) +++ mln/core/p_graph.hh (working copy) @@ -44,12 +44,13 @@ template<typename P> class p_graph_piter_;
template<typename P> - struct p_graph : public internal::point_set_base_< graph_psite<P>, p_graph<P> > + struct p_graph + : public internal::point_set_base_< graph_psite<P>, p_graph<P> > { - typedef util::graph<void> graph; + typedef util::graph<P> graph;
- /// Construct a graph psite set from a graph and an array of locations. - p_graph (graph& gr, std::vector<P>& loc); + /// Construct a graph psite set from a graph of points. + p_graph (graph& gr);
/// Point_Site associated type. typedef graph_psite<P> psite; @@ -71,8 +72,8 @@
bool has(const psite& p) const;
+ // FIXME: Should be private. graph gr_; - std::vector<P> loc_; // 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 @@ -84,22 +85,25 @@
template<typename P> inline - p_graph<P>::p_graph (util::graph<void>& gr, std::vector<P>& loc) - : gr_ (gr), - loc_ (loc) + p_graph<P>::p_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 < loc.size(); ++i) - a.take(loc[i]); + for (unsigned i = 0; i < npoints(); ++i) + a.take(gr_.node_data(i)); bb_ = a.to_result(); }
+ // FIXME: Rename to npsites? In fact, this depends on the + // interface expected from models of Point_Sets. template<typename P> inline std::size_t p_graph<P>::npoints() const { - return this->gr_.nb_node_; + return this->gr_.nnodes(); }
template<typename P> @@ -107,7 +111,7 @@ std::size_t p_graph<P>::nlines() const { - return this->gr_.nb_link_; + return this->gr_.nedges(); }
template<typename P> @@ -123,13 +127,16 @@ bool p_graph<P>::has(const psite& p) const { - for (unsigned i = 0; i < loc_.size(); ++i) - if (loc_[i] == p) + // 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; }
- # endif // ! MLN_INCLUDE_ONLY
} // end of mln Index: mln/core/graph_window_piter.hh --- mln/core/graph_window_piter.hh (revision 1713) +++ mln/core/graph_window_piter.hh (working copy) @@ -82,6 +82,7 @@ // it returns a mln::graph_psite<P> object, not a P object. const point& to_point() const; operator psite () const; + /// Return the \a i th coordinate of the (iterated) point. coord operator[](unsigned i) const;
private: @@ -89,7 +90,7 @@ const psite& p_ref_;
/// An internal iterator on the set of nodes of the underlying graph. - unsigned i_; + util::node_id id_; };
// FIXME: Implement graph_window_bkd_piter. @@ -104,7 +105,7 @@ const Point_Site<Pref>& p_ref) : p_ref_(exact(p_ref).to_psite()) { - // Invalidate i_. + // Invalidate id_. invalidate(); }
@@ -115,21 +116,21 @@ // FIXME: We depend too much on the implementation of util::graph // here. The util::graph should provide the service to abstract // these manipulations. - return i_ >= 0 && i_ < p_ref_.pg_.gr_.nb_node_; + return id_ < p_ref_.pg().gr_.nnodes(); }
template <typename P> void graph_window_fwd_piter<P>::invalidate() { - i_ = p_ref_.pg_.gr_.nb_node_; + id_ = p_ref_.pg().gr_.nnodes(); }
template <typename P> void graph_window_fwd_piter<P>::start() { - i_ = 0; + id_ = 0; if (!adjacent_or_equal_to_p_ref_()) next_(); } @@ -138,12 +139,14 @@ void 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 - // probably provides adequates structures to fetch these - // neighbors in constant time. + /* FIXME: This is inefficient. The graph structure should be able + to produce the set of adjacent nodes 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! */ do - ++i_; + ++id_; while (is_valid() && !adjacent_or_equal_to_p_ref_()); }
@@ -154,34 +157,24 @@ // FIXME: Likewise, this is inefficient.
// Check wether the iterator points to P_REF_. - if (i_ == p_ref_.i_) + if (id_ == p_ref_.id()) return true;
- typedef std::list<unsigned> adjacency_type; - // Check whether the iterator is among the neighbors of P_REF_. { // Paranoid assertion. - assert (p_ref_.i_ >= 0 && - p_ref_.i_ < p_ref_.pg_.gr_.nodes_.size ()); + assert (p_ref_.id() < p_ref_.pg().gr_.nnodes()); + // FIXME: This is too low-level. Yet another service the graph + // should provide. + typedef std::vectorutil::node_id adjacency_type; const adjacency_type& p_ref_neighbs = - p_ref_.pg_.gr_.nodes_[p_ref_.i_]->links; + p_ref_.pg().gr_.nodes()[p_ref_.id()]->edges; adjacency_type::const_iterator j = - std::find (p_ref_neighbs.begin(), p_ref_neighbs.end(), i_); + std::find (p_ref_neighbs.begin(), p_ref_neighbs.end(), id_); if (j != p_ref_neighbs.end()) return true; }
- // Check whether P_REF_ is among the neighbors of the iterator. - { - assert (is_valid ()); - const adjacency_type& i_neighbs = p_ref_.pg_.gr_.nodes_[i_]->links; - adjacency_type::const_iterator k = - std::find (i_neighbs.begin(), i_neighbs.end(), p_ref_.i_); - if (k != i_neighbs.end()) - return true; - } - // Otherwise, the iterator is not adjacent to P_REF_. return false; } @@ -190,13 +183,13 @@ const P& graph_window_fwd_piter<P>::to_point() const { - return p_ref_.pg_.loc_[i_]; + return p_ref_.pg().gr_.node_data(id_); }
template <typename P> graph_window_fwd_piter<P>::operator graph_psite<P> () const { - return graph_psite<P>(p_ref_.pg_, i_); + return graph_psite<P>(p_ref_.pg(), id_); }
template <typename P> Index: mln/core/graph_image.hh --- mln/core/graph_image.hh (revision 1713) +++ mln/core/graph_image.hh (working copy) @@ -134,11 +134,12 @@
const p_graph<P>& domain() const;
- /// Return the first node of the link at i from loc - const P& access_location_link_node1 (const unsigned& i) const; - - /// Return the second node of the link at i from loc - const P& access_location_link_node2 (const unsigned& i) const; + /// Return the point of the first node adjacent to the edge with + /// id \a e. + const P& node1(const util::edge_id& e) const; + /// Return the point of the second node adjacent to the edge with + /// id \a e. + const P& node2(const util::edge_id& e) const; };
// Fwd decl. @@ -225,9 +226,9 @@ const V& graph_image<P, V>::operator()(const graph_psite<P>& p) const { - mln_precondition(&p.pg_ == &this->data_->pg_); - mln_precondition(p.i_ < this->data_->val_.size()); - return this->data_->val_[p.i_]; + mln_precondition(&p.pg() == &this->data_->pg_); + mln_precondition(p.id() < this->data_->val_.size()); + return this->data_->val_[p.id()]; }
template <typename P, typename V> @@ -235,9 +236,9 @@ V& graph_image<P, V>::operator()(const graph_psite<P>& p) { - mln_precondition(&p.pg_ == &this->data_->pg_); - mln_precondition(p.i_ < this->data_->val_.size()); - return this->data_->val_[p.i_]; + mln_precondition(&p.pg() == &this->data_->pg_); + mln_precondition(p.id() < this->data_->val_.size()); + return this->data_->val_[p.id()]; }
template <typename P, typename V> @@ -268,19 +269,23 @@ template <typename P, typename V> inline const P& - graph_image<P, V>::access_location_link_node1 (const unsigned& i) const + graph_image<P, V>::node1(const util::edge_id& e) const { - // FIXME: This is ugly! Too much implementation details are shown here. - return this->domain().loc_[this->domain().gr_.links_[i]->pair_node_.first]; + // FIXME: Improve the interface of graph to avoid these low-level + // manipulations. + util::node_id n1 = this->domain().gr_.edge(e).n1(); + return this->domain().gr_.node_data(n1); }
template <typename P, typename V> inline const P& - graph_image<P, V>::access_location_link_node2 (const unsigned& i) const + graph_image<P, V>::node2(const util::edge_id& e) const { - // FIXME: This is ugly! Too much implementation details are shown here. - return this->domain().loc_[this->domain().gr_.links_[i]->pair_node_.second]; + // FIXME: Improve the interface of graph to avoid these low-level + // manipulations. + util::node_id n2 = this->domain().gr_.edge(e).n2(); + return this->domain().gr_.node_data(n2); }
# endif // ! MLN_INCLUDE_ONLY Index: mln/core/p_graph_piter.hh --- mln/core/p_graph_piter.hh (revision 1713) +++ mln/core/p_graph_piter.hh (working copy) @@ -60,7 +60,7 @@ typedef graph_psite<P> psite; typedef P point;
- p_graph_piter_(const p_graph<P>& psite_set); + p_graph_piter_(const p_graph<P>& pg);
/// Read-only access to the \p i-th coordinate. mln_coord(P) operator[](unsigned i) const; @@ -93,7 +93,7 @@ operator psite() const;
protected: - const p_graph<P>& psite_set_; + const p_graph<P>& pg_; unsigned i_; P p_; psite psite_; @@ -105,11 +105,11 @@
template<typename P> inline - p_graph_piter_<P>::p_graph_piter_(const p_graph<P>& psite_set) - : psite_set_(psite_set), + p_graph_piter_<P>::p_graph_piter_(const p_graph<P>& pg) + : pg_(pg), p_(), // Initialize psite_ to a dummy value. - psite_(psite_set, psite_set_.loc_.size()) + psite_(pg, pg_.npoints()) { // Invalidate i_. invalidate(); @@ -128,7 +128,7 @@ bool p_graph_piter_<P>::is_valid() const { - return i_ != psite_set_.loc_.size(); + return i_ < pg_.npoints(); }
template<typename P> @@ -136,7 +136,7 @@ void p_graph_piter_<P>::invalidate() { - i_ = psite_set_.loc_.size(); + i_ = pg_.npoints(); }
template<typename P> @@ -165,9 +165,9 @@ p_graph_piter_<P>::update_() { // Update p_. - p_ = psite_set_.loc_[i_]; + p_ = pg_.gr_.node_data(i_); // Update psite_. - psite_ = graph_psite<P>(psite_set_, i_); + psite_ = graph_psite<P>(pg_, i_); }
template<typename P> Index: mln/draw/graph.hh --- mln/draw/graph.hh (revision 1713) +++ mln/draw/graph.hh (working copy) @@ -92,16 +92,19 @@ graph(Image<I>& ima, const p_graph<P>& pg, mln_value(I) node_v, mln_value(I) link_v) { + // Draw the background. level::fill(ima, 0); - - for (unsigned i = 0; i < pg.nlines(); ++i) + // Draw the lines (edges). + for (size_t l = 0; l < pg.nlines(); ++l) line (exact(ima), - pg.loc_[pg.gr_.links_[i]->pair_node_.first], - pg.loc_[pg.gr_.links_[i]->pair_node_.second], + // FIXME: Too low-level. See similar remarks + // in mln/core/graph_image.hh + pg.gr_.node_data(pg.gr_.edge(l).n1()), + pg.gr_.node_data(pg.gr_.edge(l).n2()), link_v); - - for (unsigned i = 0; i < pg.npoints(); ++i) - exact(ima)(pg.loc_[i]) = node_v; + // Draw the points (nodes). + for (size_t p = 0; p < pg.npoints(); ++p) + exact(ima)(pg.gr_.node_data(p)) = node_v; }
template <typename I, typename P, typename V> @@ -110,16 +113,14 @@ graph(Image<I>& ima, const graph_image<P, V>& gi, mln_value(I) link_v) { + // Draw the background. level::fill(ima, 0); - - for (unsigned i = 0; i < gi.domain().nlines(); ++i) - line (exact(ima), - gi.access_location_link_node1 (i), - gi.access_location_link_node2 (i), - link_v); - - for (unsigned i = 0; i < gi.domain().npoints(); ++i) - exact(ima)(gi.domain().loc_[i]) = gi.data_values ()[i]; + // Draw the lines (edges). + for (size_t l = 0; l < gi.domain().nlines(); ++l) + line (exact(ima), gi.node1(l), gi.node2(l), link_v); + // Draw the points (nodes). + for (size_t p = 0; p < gi.domain().npoints(); ++p) + exact(ima)(gi.domain().gr_.node_data(p)) = gi.data_values()[p]; }
# endif // ! MLN_INCLUDE_ONLY Index: mln/draw/all.hh --- mln/draw/all.hh (revision 1713) +++ mln/draw/all.hh (working copy) @@ -42,7 +42,9 @@
}
+# include <mln/draw/box.hh> +# include <mln/draw/graph.hh> +# include <mln/draw/label.hh> # include <mln/draw/line.hh> -# include <mln/draw/mesh.hh>
#endif // ! MLN_DRAW_ALL_HH Index: tests/core/graph_elt_window.cc --- tests/core/graph_elt_window.cc (revision 1713) +++ tests/core/graph_elt_window.cc (working copy) @@ -58,10 +58,10 @@ points.push_back(make::point2d(4,4)); // Point associated to node 4.
// Edges. - mln::util::graph<void> g; + mln::util::graph<p_t> g; // Populate the graph with nodes. for (unsigned i = 0; i < points.size(); ++i) - g.add_node (); + g.add_node (points[i]); // Populate the graph with edges. g.add_edge(0, 1); g.add_edge(1, 2); @@ -74,7 +74,7 @@ `------------------*/
// Graph psite set. - p_graph<p_t> pg(g, points); + 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. Index: tests/core/graph_image.cc --- tests/core/graph_image.cc (revision 1713) +++ tests/core/graph_image.cc (working copy) @@ -59,10 +59,10 @@ points.push_back(make::point2d(4,4)); // Point associated to node 4.
// Edges. - util::graph<void> g; + util::graph<point2d> g; // Populate the graph with nodes. for (unsigned i = 0; i < points.size(); ++i) - g.add_node (); + g.add_node (points[i]); // Populate the graph with edges. g.add_edge(0, 1); g.add_edge(1, 2); @@ -74,7 +74,7 @@ | Graph. | `-------*/
- p_graph<point2d> pg(g, points); + p_graph<point2d> pg(g);
/*-------------. | Graph image. | Index: tests/draw/graph.cc --- tests/draw/graph.cc (revision 1713) +++ tests/draw/graph.cc (working copy) @@ -61,17 +61,15 @@ unsigned nrows, unsigned ncols, const mln::image2d<int>& ref) { // Graph. - util::graph<void> g; + util::graphmln::point2d g; // Populate the graph with nodes. for (unsigned i = 0; i < points.size(); ++i) - g.add_node (); + g.add_node (points[i]); // Populate the graph with edges. for (edges_type::const_iterator i = edges.begin(); i != edges.end(); ++i) g.add_edge (i->first, i->second); - // Check its consistency. - g.consistency ();
- mln::p_graph<point2d> pg(g, points); + mln::p_graph<point2d> pg(g);
image2d<int> ima(nrows, ncols); draw::graph (ima, pg, 2, 1);