https://svn.lrde.epita.fr/svn/oln/trunk/milena
Now, mln::p_set<P>'s and mln::p_array<P>'s implementations are much
closer
one another.
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Make the computation of the bbox of an mln::p_set<P> lazy.
* mln/core/p_set.hh (mln::p_set<P>::point): New typedef.
Use it...
(mln::p_set<P>::bbox): ...in the declaration of this method.
(mln::p_set<P>::bb_): Make it mutable.
Change type from `accu::bbox<P>' to `accu::bbox<point>'.
(mln::p_set<P>::bb_needs_update_): New attribute.
(mln::p_set<P>::update_bb_): New method.
(p_set<P>::p_set): Adjust ctor.
(mln::p_set<P>::insert)
(mln::p_set<P>::remove)
(mln::p_set<P>::clear)
(mln::p_set<P>::bbox):
Adjust methods.
* tests/core/point_set_compatibility.cc: Exercise
p_set< graph_psite<point2d> >.
mln/core/p_set.hh | 66 ++++++++++++++++++++++++----------
tests/core/point_set_compatibility.cc | 35 ++++++++++++++----
2 files changed, 75 insertions(+), 26 deletions(-)
Index: mln/core/p_set.hh
--- mln/core/p_set.hh (revision 2077)
+++ mln/core/p_set.hh (working copy)
@@ -28,10 +28,9 @@
#ifndef MLN_CORE_P_SET_HH
# define MLN_CORE_P_SET_HH
-/*! \file mln/core/p_set.hh
- *
- * \brief Definition of a point set class based on std::set.
- */
+/// \file mln/core/p_set.hh
+/// \brief Definition of a point set class based on std::set, that can
+/// behave also as a vector.
# include <mln/core/internal/point_set_base.hh>
# include <mln/core/internal/set_of.hh>
@@ -42,13 +41,14 @@
namespace mln
{
- /*! \brief Point set class based on std::set.
- *
- * This is a mathematical set of points (not a multi-set). The
- * parameter \p P shall be a Point type.
- *
- * \todo Test if \p P being a Point_Site is ok.
- */
+ /// \brief Point set class based on std::set.
+ ///
+ /// This is a mathematical set of points (not a multi-set). The
+ /// parameter \p P shall be a Point type or a Point_Site.
+ ///
+ /// FIXME: If \p is a Point_Site, but not a Point, the method
+ /// mln::p_set<P>::bbox will not compile (see below). (Will be fixed
+ /// with the merge with branch cleanup-2008.)
template <typename P>
class p_set : public internal::point_set_base_< P, p_set<P> >,
private internal::set_of_<P>
@@ -56,6 +56,16 @@
typedef internal::set_of_<P> super_;
public:
+ /* FIXME: Should be removed as soon as branch cleanup-2008 is
+ merged with the trunk. */
+ typedef mln_point(P) point;
+
+ /* FIXME: mln::p_set uses the same iterators as mln::p_array,
+ because mln::p_set also have the interface of an array. We
+ might want to keep this, but we should change the name of the
+ iterator, either by using an alias (typedef), of by giving them
+ their own type (which could share code with
+ mln::p_array_{fwd,bkd}_piter_, of course). */
/// Forward Point_Iterator associated type.
typedef p_array_fwd_piter_<P> fwd_piter;
@@ -87,12 +97,16 @@
/// Clear this set.
void clear();
+ /* FIXME: Won't work if P is not (implicitly) convertible to
+ mln_point(P). */
/// Give the exact bounding box.
- const box_<mln_point(P)>& bbox() const;
+ const box_<point>& bbox() const;
protected:
+ mutable accu::bbox<point> bb_;
+ mutable bool bb_needs_update_;
- accu::bbox<P> bb_;
+ void update_bb_() const;
// FIXME: Add invariant bb_.is_valid() <=> npoints() != 0
};
@@ -102,11 +116,24 @@
template <typename P>
inline
p_set<P>::p_set()
+ : bb_needs_update_(false)
{
}
template <typename P>
inline
+ void
+ p_set<P>::update_bb_() const
+ {
+ bb_.init();
+ for (typename std::set<P>::const_iterator i = this->s_.begin();
+ i != this->s_.end(); ++i)
+ bb_.take(*i);
+ bb_needs_update_ = false;
+ }
+
+ template <typename P>
+ inline
bool
p_set<P>::has(const P& p) const
{
@@ -127,7 +154,8 @@
p_set<P>::insert(const P& p)
{
this->super_::insert(p);
- bb_.take(p);
+ if (! bb_needs_update_)
+ bb_needs_update_ = true;
return *this;
}
@@ -137,11 +165,8 @@
p_set<P>::remove(const P& p)
{
this->super_::remove(p);
- // Rebuild the bounding box.
- bb_.init();
- for (typename std::set<P>::const_iterator i = this->s_.begin();
- i != this->s_.end(); ++i)
- bb_.take(*i);
+ if (! bb_needs_update_)
+ bb_needs_update_ = true;
return *this;
}
@@ -161,6 +186,7 @@
{
this->super_::clear();
bb_.init();
+ bb_needs_update_ = false;
}
template <typename P>
@@ -169,6 +195,8 @@
p_set<P>::bbox() const
{
mln_precondition(npoints() != 0);
+ if (bb_needs_update_)
+ update_bb_();
return bb_.to_result();
}
Index: tests/core/point_set_compatibility.cc
--- tests/core/point_set_compatibility.cc (revision 2077)
+++ tests/core/point_set_compatibility.cc (working copy)
@@ -32,6 +32,7 @@
#include <mln/core/point2d.hh>
#include <mln/core/p_array.hh>
+#include <mln/core/p_set.hh>
#include <mln/core/graph_psite.hh>
#include <mln/core/p_graph_piter.hh>
@@ -69,21 +70,41 @@
// Graph point set.
+ typedef p_graph<point2d> pg_t;
p_graph<point2d> pg(g);
-
-
- // Array of graph point sites.
typedef graph_psite<point2d> gpsite_t;
- p_array<gpsite_t> pa;
+ {
+ // Array of graph point sites.
+ typedef p_array<gpsite_t> pa_t;
+ pa_t pa;
// Tests: copying all psites from PG to PA.
- p_graph_fwd_piter_<point2d> p(pg);
+ mln_piter_(pg_t) p(pg);
for_all (p)
pa.append (p);
// Test: create and use an iterator over PA.
- p_array_fwd_piter_<gpsite_t> p2(pa);
+ mln_piter_(pa_t) p2(pa);
for_all (p2)
- std::cout << p2 << std::endl;
+ std::cout << p2 << ' ';
+ std::cout << std::endl;
+ }
+
+ {
+ // Set of graph point sites.
+ typedef p_set<gpsite_t> ps_t;
+ ps_t ps;
+
+ // Tests: copying all psites from PG to PS.
+ mln_piter_(pg_t) p(pg);
+ for_all (p)
+ ps.insert(p);
+
+ // Test: create and use an iterator over PS.
+ mln_piter_(ps_t) p2(ps);
+ for_all (p2)
+ std::cout << p2 << ' ';
+ std::cout << std::endl;
+ }
}