https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
Add pset_array class for image encoded by values.
* tests/level/paste.cc: Add tests.
* tests/core/image3d.cc,
* tests/core/pset_array.cc: New tests.
* tests/core/Makefile.am: Add the new tests.
* mln/core/pset_array.hh: pset_array class.
* mln/core/rle_image.hh,
* mln/core/p_runs.hh,
* mln/core/runs_psite.hh: Update the license..
* mln/core/pset_array_psite.hh: Psite associated to the pset_arry.
* mln/level/memcpy_.hh: Clean up.
* sandbox/ballas/doc/image_tours.txt: Update Documentation.
mln/core/p_runs.hh | 77 ++++++--
mln/core/pset_array.hh | 353 +++++++++++++++++++++++++++++++++++++
mln/core/pset_array_psite.hh | 152 +++++++++++++++
mln/core/rle_image.hh | 2
mln/core/runs_psite.hh | 2
mln/level/memcpy_.hh | 6
sandbox/ballas/doc/image_tours.txt | 100 ++++++++--
tests/core/Makefile.am | 2
tests/core/image3d.cc | 73 +++++++
tests/core/pset_array.cc | 93 +++++++++
tests/level/paste.cc | 28 ++
11 files changed, 846 insertions(+), 42 deletions(-)
Index: tests/level/paste.cc
--- tests/level/paste.cc (revision 1903)
+++ tests/level/paste.cc (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -31,8 +31,12 @@
*/
#include <mln/core/image2d.hh>
+#include <mln/core/image3d.hh>
+#include <mln/core/sub_image.hh>
+
#include <mln/level/fill.hh>
#include <mln/level/paste.hh>
+#include <mln/level/compare.hh>
#include <mln/debug/iota.hh>
#include <mln/debug/println.hh>
@@ -42,6 +46,8 @@
{
using namespace mln;
+ // tests in two dimension
+ {
box2d b(make::point2d(1,2), make::point2d(2,4));
image2d<int> ima(b, 2);
debug::iota(ima);
@@ -51,6 +57,26 @@
debug::iota(ima2);
level::paste(ima, ima2); // Fast version.
+ assert(ima == (ima2 | b));
level::impl::generic::paste_(ima, ima2); // Not so fast version...
+ assert(ima == (ima2 | b));
+ }
+
+ // tests in three dimension
+ {
+ box3d b(make::point3d(1,2, 1), make::point3d(2,4, 3));
+ image3d<int> ima(b, 2);
+ debug::iota(ima);
+
+ box3d b2(make::point3d(-1,-2, -1), make::point3d(3,6, 3));
+ image3d<int> ima2(b2, 2);
+ debug::iota(ima2);
+
+ level::paste(ima, ima2); // Fast version.
+ assert(ima == (ima2 | b));
+
+ level::impl::generic::paste_(ima, ima2); // Not so fast version...
+ assert(ima == (ima2 | b));
+ }
}
Index: tests/core/image3d.cc
--- tests/core/image3d.cc (revision 0)
+++ tests/core/image3d.cc (revision 0)
@@ -0,0 +1,73 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+//
+// 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/level/image3d.cc
+ *
+ * \brief Tests on Image3d pixter
+ */
+
+
+#include <mln/core/image3d.hh>
+#include <mln/core/image2d.hh>
+
+#include <mln/debug/iota.hh>
+
+int main()
+{
+ using namespace mln;
+
+
+ // Working test
+ {
+ box3d b(make::point3d(1,2, 1), make::point3d(2,4, 3));
+ image3d<int> ima(b, 2);
+
+ mln_pixter_(image3d<int>) p(ima);
+ for_all(p)
+ std::cout << p << std::endl;
+ }
+
+
+ {
+ box3d b(make::point3d(1,2, 1), make::point3d(3,6, 3));
+ image3d<int> ima(b, 0);
+
+ mln_piter_(image3d<int>) pi(ima.domain());
+ mln_pixter_(image3d<int>) p(ima);
+
+ debug::iota(ima);
+
+ pi.start();
+ p.start();
+ while (pi.is_valid())
+ {
+ assert(ima(pi) == p.val());
+ pi.next();
+ p.next();
+ }
+ }
+}
Index: tests/core/pset_array.cc
--- tests/core/pset_array.cc (revision 0)
+++ tests/core/pset_array.cc (revision 0)
@@ -0,0 +1,93 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+//
+// 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 mln/core/pset_array.hh
+ *
+ * \brief Tests for the pset array.
+ */
+
+#include <mln/core/pset_array.hh>
+#include <mln/core/image2d.hh>
+#include <mln/core/p_runs.hh>
+
+#include <iostream>
+
+int main()
+{
+ using namespace mln;
+
+ typedef p_runs_<point2d> runs;
+
+ p_runs_<point2d> pruns0;
+ p_runs_<point2d> pruns1;
+ p_runs_<point2d> pruns2;
+
+ pruns0.insert(p_run<point2d>(make::point2d(0, 0), 2));
+
+ pruns2.insert(p_run<point2d>(make::point2d(10,10), 5));
+
+ pruns1.insert(p_run<point2d>(make::point2d(2, 4), 7));
+ pruns1.insert(p_run<point2d>(make::point2d(18, 42), 5));
+ pruns1.insert(p_run<point2d>(make::point2d(50, 76), 2));
+ pruns1.insert(p_run<point2d>(make::point2d(17,40), 6));
+
+
+
+ /// Declare the pset_array
+ pset_array<runs> array;
+
+ /// Add elements in the array
+ assert(array.npsets() == 0);
+ array.insert(pruns0);
+ assert(array.npsets() == 1);
+ assert(array.npoints() == 2);
+
+ array.insert(pruns2);
+ assert(array.npsets() == 2);
+ assert(array.npoints() == 7);
+
+ array.insert(pruns1);
+
+ /// Psite tests
+ typedef pset_array<runs>::psite psite;
+ runs_psite<point2d> run_psite1(pruns0, 1, 0);
+ runs_psite<point2d> run_psite2(pruns1, 5, 1);
+
+ psite ps(run_psite1, 0);
+ assert(array.has(ps));
+
+ psite ps2(run_psite2, 2);
+ assert(array.has(ps2));
+
+ // Iterator test:
+ pset_array<runs>::fwd_piter piter(array);
+
+ for (piter.start(); piter.is_valid(); piter.next())
+ {
+ std::cout << piter << std::endl;
+ }
+}
Index: tests/core/Makefile.am
--- tests/core/Makefile.am (revision 1903)
+++ tests/core/Makefile.am (working copy)
@@ -8,6 +8,7 @@
exact \
h_vec \
initialize \
+ image3d \
graph_elt_neighborhood \
graph_elt_window \
graph_image \
@@ -26,6 +27,7 @@
p_queue_fast \
p_runs \
point_set_compatibility \
+ pset_array \
rle_image \
sparse_image \
t_image \
Index: mln/core/pset_array.hh
--- mln/core/pset_array.hh (revision 0)
+++ mln/core/pset_array.hh (revision 0)
@@ -0,0 +1,353 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+//
+// 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_PSET_ARRAY_HH_
+# define MLN_CORE_PSET_ARRAY_HH_
+
+
+/*! \file mln/core/pset_array.hh
+ *
+ * \brief Definition of the pset array class.
+ */
+
+# include <mln/core/internal/point_set_base.hh>
+# include <mln/core/internal/point_iterator_base.hh>
+
+# include <vector>
+# include <mln/accu/bbox.hh>
+# include <mln/core/pset_array_psite.hh>
+
+
+
+
+namespace mln
+{
+
+ // Forward declaration
+ template <typename Pset> struct pset_array_fwd_piter_;
+
+
+ /*! \brief Point Set Class based on a collection of Point Set
+ ** This class is based on a std::vector.
+ ** This class is parametrized by \p Pset which is the Point Set
+ ** type of the collection.
+ **
+ ** The iterator type associated to Pset must satisfy some constraints:
+ ** * Iterator type must have a constructor which takes no argument
+ ** * Iterator type must have a method
+ ** void assign(const Pset&)
+ ** which change the Pset associated to the iterator
+ **
+ **
+ ** FIXME: Add a backward iterator.
+ */
+ template <typename Pset>
+ class pset_array:
+ public internal::point_set_base_<pset_array_psite<Pset>, pset_array<Pset> >
+ {
+ public:
+
+ // Container
+ typedef std::vector<Pset> container;
+
+ typedef pset_array_fwd_piter_<Pset> fwd_piter;
+ typedef pset_array_fwd_piter_<Pset> bkd_piter;
+
+ typedef pset_array_psite<typename Pset::psite> psite;
+ typedef typename Pset::point point;
+
+ /// Constructor without arguments.
+ pset_array();
+
+ /// Test is \p p belongs to this point set.
+ bool has(const psite& ps) const;
+
+ /// Give the exact bounding box.
+ const box_<point>& bbox() const;
+
+ /// Give the number of points.
+ typename std::size_t npoints() const;
+
+ /// Give the number of pset
+ typename std::size_t npsets() const;
+
+ /// Insert a new Point Set in the Point Sets Collections
+ void insert(const Pset& ps);
+
+ /// Return the i-th pset of the Point Sets Colletion
+ const Pset& operator[](unsigned i) const;
+ Pset& operator[](unsigned i);
+
+ protected:
+
+ /// Number of points.
+ typename std::size_t npoints_;
+
+ /// Points container
+ container con_;
+
+ /// Exact bounding box.
+ accu::bbox<point> fb_;
+
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename Pset>
+ inline
+ pset_array<Pset>::pset_array() :
+ npoints_(0)
+ {
+ }
+
+ template <typename Pset>
+ inline
+ bool
+ pset_array<Pset>::has(const typename pset_array<Pset>::psite& ps) const
+ {
+ mln_precondition(ps.to_index() < con_.size());
+ return con_[ps.to_index()].has(ps.to_psite());
+ }
+
+ template <typename Pset>
+ inline
+ const box_<typename pset_array<Pset>::point>&
+ pset_array<Pset>::bbox() const
+ {
+ return fb_.to_result();
+ }
+
+ template <typename Pset>
+ inline
+ typename std::size_t
+ pset_array<Pset>::npoints() const
+ {
+ return npoints_;
+ }
+
+ template <typename Pset>
+ inline
+ typename std::size_t
+ pset_array<Pset>::npsets() const
+ {
+ return con_.size();
+ }
+
+ template <typename Pset>
+ inline
+ void
+ pset_array<Pset>::insert(const Pset& ps)
+ {
+ // update box
+ fb_.take(ps.bbox().pmin());
+ fb_.take(ps.bbox().pmax());
+
+ // update size
+ npoints_ += ps.npoints();
+
+ // update the container
+ con_.push_back(ps);
+ }
+
+ template <typename Pset>
+ inline
+ const Pset&
+ pset_array<Pset>::operator[](unsigned i) const
+ {
+ return con_[i];
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ /*! \brief Forward Iterator on a Pset array.
+ ** \p Pset is the type of Point Set in the Point Sets collection.
+ **
+ */
+ template <typename Pset>
+ class pset_array_fwd_piter_ : public
+ internal::point_iterator_base_<pset_array_psite<typename Pset::psite>,
+ pset_array_fwd_piter_<Pset> >
+ {
+ public:
+
+ /// Access types
+ typedef pset_array_psite<typename Pset::psite> psite;
+ typedef typename Pset::point point;
+
+ /// Constructor
+ pset_array_fwd_piter_(const pset_array<Pset>& pset);
+
+ /// Test the iterator validity.
+ bool is_valid() const;
+
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next point.
+ void next_();
+
+
+ /// Convertion into a point.
+ operator point () const;
+
+ /// Reference to the corresponding point.
+ const point& to_point() const;
+
+ /// Convertion into a point-site.
+ operator psite () const;
+
+ /// Access to the current point coordinates.
+ mln_coord(point) operator[](unsigned i) const;
+
+ protected:
+
+ /// Change the Point Set associated with the wrapped piter.
+ void assign_piter_();
+
+ private:
+
+ typedef typename Pset::fwd_piter pset_fwd_piter_;
+
+
+ const pset_array<Pset>* pset_;
+ pset_fwd_piter_ piter_;
+ unsigned pos_;
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename Pset>
+ pset_array_fwd_piter_<Pset>::pset_array_fwd_piter_(const pset_array<Pset>& pset) :
+ pset_(&pset),
+ piter_(),
+ pos_(pset_->npsets())
+ {
+ invalidate();
+ }
+
+ template <typename Pset>
+ inline
+ bool
+ pset_array_fwd_piter_<Pset>::is_valid() const
+ {
+ return pos_ < pset_->npsets();
+ }
+
+ template <typename Pset>
+ inline
+ void
+ pset_array_fwd_piter_<Pset>::invalidate()
+ {
+ pos_ = pset_->npsets();
+ }
+
+ template <typename Pset>
+ inline
+ void
+ pset_array_fwd_piter_<Pset>::assign_piter_()
+ {
+ piter_.assign((*pset_)[pos_]);
+ piter_.start();
+ }
+
+ template <typename Pset>
+ inline
+ void
+ pset_array_fwd_piter_<Pset>::start()
+ {
+ mln_precondition(pset_->npsets() > 0);
+
+ pos_ = 0;
+ assign_piter_();
+ }
+
+ template <typename Pset>
+ inline
+ void
+ pset_array_fwd_piter_<Pset>::next_()
+ {
+ mln_precondition(is_valid());
+
+ piter_.next();
+ if (!piter_.is_valid())
+ {
+ ++pos_;
+ if (is_valid())
+ assign_piter_();
+ else
+ piter_.invalidate();
+ }
+ }
+
+ template <typename Pset>
+ pset_array_fwd_piter_<Pset>::operator
+ typename pset_array_fwd_piter_<Pset>::point() const
+ {
+ return to_point();
+ }
+
+ template <typename Pset>
+ const typename pset_array_fwd_piter_<Pset>::point&
+ pset_array_fwd_piter_<Pset>::to_point() const
+ {
+ mln_precondition(is_valid());
+ mln_precondition(piter_.is_valid());
+
+ return piter_.to_point();
+ }
+
+ template <typename Pset>
+ pset_array_fwd_piter_<Pset>::operator
+ typename pset_array_fwd_piter_<Pset>::psite ()
+ const
+ {
+ mln_precondition(is_valid());
+
+ return pset_array_psite<typename Pset::psite>(piter_, pos_);
+ }
+
+ template <typename Pset>
+ mln_coord_(typename pset_array_fwd_piter_<Pset>::point)
+ pset_array_fwd_piter_<Pset>::operator[](unsigned i) const
+ {
+ mln_precondition(is_valid());
+
+ return piter_[i];
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_PSET_ARRAY_HH_
Index: mln/core/rle_image.hh
--- mln/core/rle_image.hh (revision 1903)
+++ mln/core/rle_image.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
Index: mln/core/runs_psite.hh
--- mln/core/runs_psite.hh (revision 1903)
+++ mln/core/runs_psite.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
Index: mln/core/pset_array_psite.hh
--- mln/core/pset_array_psite.hh (revision 0)
+++ mln/core/pset_array_psite.hh (revision 0)
@@ -0,0 +1,152 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+//
+// 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_PSET_ARRAY_PSITE_HH_
+# define MLN_CORE_PSET_ARRAY_PSITE_HH_
+
+/*! \file mln/core/runs_psite.hh
+ *
+ * \brief Definition of the psite associated to the pset_array type.
+ */
+
+# include <mln/core/concept/point_site.hh>
+# include <mln/util/tracked_ptr.hh>
+
+
+namespace mln
+{
+ /*! \brief Psite class associated to pset_array.
+ **
+ ** Parameter \c Psite is the type of the underlying psite.
+ */
+ template <typename Psite>
+ class pset_array_psite : public Point_Site< pset_array_psite<Psite> >
+ {
+ public:
+
+ typedef mln_point(Psite) point;
+ typedef mln_dpoint(Psite) dpoint;
+ typedef mln_coord(point) coord;
+
+ typedef Psite psite;
+
+ typedef mln_mesh(point) mesh;
+ enum { dim = point::dim };
+
+ pset_array_psite(const psite& psite, unsigned index);
+
+ operator point () const;
+
+ /// Reference to the corresponding point.
+ const point& to_point() const;
+
+
+ /// Useful method for the access
+ unsigned to_index() const;
+ unsigned& to_index();
+ const psite& to_psite() const;
+
+ /// Give the i-th coordinate of the corresponding point.
+ mln_coord(point) operator[](unsigned i) const;
+
+ protected:
+
+ /// Psite which allows us to access to the images
+ const psite& psite_;
+
+ /// Position in the pset_array.
+ unsigned index_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename Psite>
+ pset_array_psite<Psite>::pset_array_psite(const psite& psite,
+ unsigned index) :
+ psite_(psite),
+ index_(index)
+ {
+ }
+
+ template <typename Psite>
+ inline
+ pset_array_psite<Psite>::operator typename pset_array_psite<Psite>::point ()
+ const
+ {
+ return to_point();
+ }
+
+ template <typename Psite>
+ inline
+ const typename pset_array_psite<Psite>::point&
+ pset_array_psite<Psite>::to_point() const
+ {
+ return psite_.to_point();
+ }
+
+ template <typename Psite>
+ inline
+ unsigned
+ pset_array_psite<Psite>::to_index() const
+ {
+ return index_;
+ }
+
+ template <typename Psite>
+ inline
+ unsigned&
+ pset_array_psite<Psite>::to_index()
+ {
+ return index_;
+ }
+
+ template <typename Psite>
+ inline
+ const Psite&
+ pset_array_psite<Psite>::to_psite() const
+ {
+ return psite_;
+ }
+
+ template <typename Psite>
+ inline
+ mln_coord(pset_array_psite<Psite>::point)
+ pset_array_psite<Psite>::operator[] (unsigned i) const
+ {
+ return psite_[i];
+ }
+
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+# include <mln/core/pset_array.hh>
+
+#endif // ! MLN_CORE_INTERNAL_PSET_ARRAY_PSITE_HH
Index: mln/core/p_runs.hh
--- mln/core/p_runs.hh (revision 1903)
+++ mln/core/p_runs.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -269,15 +269,19 @@
/// Access to the current point coordinates.
mln_coord(P) operator[](unsigned i) const;
+ /// Assign a new pset to the iterator
+ void assign(const p_runs_<P>& pset);
+
protected:
/// Current point.
P p_;
/// Point set container.
- const p_runs_<P>& con_;
+ const p_runs_<P>* con_;
p_runs_piter_(const p_runs_<P>& pset);
+ p_runs_piter_();
};
@@ -286,7 +290,14 @@
template <typename P, typename E>
inline
p_runs_piter_<P, E>::p_runs_piter_(const p_runs_<P>& pset) :
- con_(pset)
+ con_(&pset)
+ {
+ }
+
+ template <typename P, typename E>
+ inline
+ p_runs_piter_<P, E>::p_runs_piter_() :
+ con_(0)
{
}
@@ -315,6 +326,14 @@
return p_[i];
}
+ template <typename P, typename E>
+ inline
+ void
+ p_runs_piter_<P, E>::assign(const p_runs_<P>& pset)
+ {
+ con_ = &pset;
+ }
+
# endif // ! MLN_INCLUDE_ONLY
@@ -328,6 +347,7 @@
typedef p_runs_piter_<P, p_runs_fwd_piter_<P> > super;
public:
+ p_runs_fwd_piter_();
p_runs_fwd_piter_(const p_runs_<P>& pset);
/// Test the iterator validity.
@@ -357,6 +377,12 @@
template <typename P>
inline
+ p_runs_fwd_piter_<P>::p_runs_fwd_piter_()
+ {
+ }
+
+ template <typename P>
+ inline
p_runs_fwd_piter_<P>::p_runs_fwd_piter_(const p_runs_<P>& pset) :
super(pset)
{
@@ -368,7 +394,7 @@
bool
p_runs_fwd_piter_<P>::is_valid() const
{
- return i_ < this->con_.nruns();
+ return this->con_ != 0 && i_ < this->con_->nruns();
}
template <typename P>
@@ -376,7 +402,9 @@
void
p_runs_fwd_piter_<P>::invalidate()
{
- i_ = this->con_.nruns();
+ mln_precondition(this->con_ != 0);
+
+ i_ = this->con_->nruns();
}
template <typename P>
@@ -384,8 +412,10 @@
void
p_runs_fwd_piter_<P>::start()
{
+ mln_precondition(this->con_ != 0);
+
i_ = 0;
- it_.assign_run(this->con_[i_]);
+ it_.assign_run((*this->con_)[i_]);
it_.start();
this->p_ = it_;
}
@@ -396,13 +426,15 @@
p_runs_fwd_piter_<P>::next_()
{
mln_precondition(this->is_valid());
+ mln_precondition(this->con_ != 0);
+
it_.next();
if (!it_.is_valid())
{
++i_;
if (is_valid())
{
- it_.assign_run(this->con_[i_]);
+ it_.assign_run( (*this->con_)[i_]);
it_.start();
}
else
@@ -414,7 +446,9 @@
template <typename P>
p_runs_fwd_piter_<P>::operator runs_psite<P> () const
{
- return runs_psite<P>(this->con_, it_.ind(), i_);
+ mln_precondition(this->con_ != 0);
+
+ return runs_psite<P>(*this->con_, it_.ind(), i_);
}
# endif // ! MLN_INCLUDE_ONLY
@@ -430,6 +464,7 @@
typedef p_runs_piter_<P, p_runs_bkd_piter_<P> > super;
public:
+ p_runs_bkd_piter_();
p_runs_bkd_piter_(const p_runs_<P>& pset);
/// Test the iterator validity.
@@ -458,6 +493,13 @@
# ifndef MLN_INCLUDE_ONLY
+
+ template <typename P>
+ inline
+ p_runs_bkd_piter_<P>::p_runs_bkd_piter_()
+ {
+ }
+
template <typename P>
inline
p_runs_bkd_piter_<P>::p_runs_bkd_piter_(const p_runs_<P>& pset) :
@@ -471,7 +513,7 @@
bool
p_runs_bkd_piter_<P>::is_valid() const
{
- return i_ < this->con_.nruns();
+ return this->con_ != 0 &&i_ < this->con_->nruns();
}
template <typename P>
@@ -479,7 +521,9 @@
void
p_runs_bkd_piter_<P>::invalidate()
{
- i_ = this->con_.nruns();
+ mln_precondition(this->con_ != 0);
+
+ i_ = this->con_->nruns();
}
template <typename P>
@@ -487,8 +531,10 @@
void
p_runs_bkd_piter_<P>::start()
{
- i_ = this->con_.nruns() - 1;
- it_.assign_run(this->con_[i_]);
+ mln_precondition(this->con_ != 0);
+
+ i_ = this->con_->nruns() - 1;
+ it_.assign_run((*this->con_)[i_]);
it_.start();
this->p_ = it_;
}
@@ -499,13 +545,15 @@
p_runs_bkd_piter_<P>::next_()
{
mln_precondition(this->is_valid());
+ mln_precondition(this->con_ != 0);
+
it_.next();
if (!it_.is_valid())
{
--i_;
if (is_valid())
{
- it_.assign_run(this->con_[i_]);
+ it_.assign_run((*this->con_)[i_]);
it_.start();
}
else
@@ -517,7 +565,8 @@
template <typename P>
p_runs_bkd_piter_<P>::operator runs_psite<P> () const
{
- return runs_psite<P>(this->con_, it_.ind(), i_);
+ mln_precondition(this->con_ != 0);
+ return runs_psite<P>((*this->con_), it_.ind(), i_);
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/level/memcpy_.hh
--- mln/level/memcpy_.hh (revision 1903)
+++ mln/level/memcpy_.hh (working copy)
@@ -78,11 +78,8 @@
typedef mln_image(Pd) Id;
typedef mln_image(Ps) Is;
-
if (n == 0)
- {
return; // no-op
- }
if (n == 1)
{
@@ -111,7 +108,8 @@
template <typename Pd, typename Ps>
inline
- void memcpy_(Generalized_Pixel<Pd>& dest_, const Generalized_Pixel<Ps>& src_,
+ void memcpy_(Generalized_Pixel<Pd>& dest_,
+ const Generalized_Pixel<Ps>& src_,
std::size_t n)
{
trace::entering("level::memcpy_");
Index: sandbox/ballas/doc/image_tours.txt
--- sandbox/ballas/doc/image_tours.txt (revision 1903)
+++ sandbox/ballas/doc/image_tours.txt (working copy)
@@ -42,7 +42,7 @@
** Semantic
-Properties are a way to classify the images depends or their type.
+Properties are a way to classify the images depends or their types.
*** Static Checking
@@ -50,14 +50,66 @@
check that the operator's input types respect the operator requirements.
*** Specialization of an Algorithm
- (ex: dilatation/erosion).
-TODO: detail the example.
+
+Example:
+
+Here are the differents method which implement the morphologic erosion
+in Milena.
+
+All these functions implements the erosion in different ways.
+Each implemtation of the erosion is dedicated to image
+
+
+
+This is the generic implementation of the erosion.
+It works with all the image types.
+Indeed, this function works with all the image types which have their traits
+kind and speed set to the value any. And any is a superclass of all the values
+for these traits. So, it works with all the image types.
+However, this is not the most efficient implementation of the erosion.
+
+template <typename I, typename W>
+inline
+mln_concrete(I)
+erosion_iterative_(trait::image::kind::any,
+ trait::image::speed::any,
+ const I& input, const W& win);
+
+
+
+This version of the erosion is dedicated to image types which have their
+traits speed set to fastest.
+This implementation is more efficient than the previous one, however
+the image must specific caracteristics (like a border...),
+
+So it only work with image the "fastest" image types.
+
+
+template <typename I, typename W>
+mln_concrete(I)
+erosion_iterative_(trait::image::kind::any,
+ trait::image::speed::fastest,
+ const I& input, const W& win);
+
+
+
+This function automatically call the erosion function which is the more
+adapted to the erosion.
+So the efficient erosion will be automatically called for the fastest image
+types.
+This function act likes a facade, and hide the implementation details from
+an user point of view.
+
+template <typename I, typename W>
+mln_concrete(I)
+erosion_iterative_(const I& input, const W& win);
+
*** Implementation inheritance
Milena image types are property driven.
It is possible to get a special behavior (not describe in the Image Concept)
-depends on the property define in the property associated for the image
+depends on the property defined in the property associated to the image
type. So, it is possible to recover some piece of interface depending on the
image type properties.
@@ -163,18 +215,21 @@
Primitive image are images which are not based on another image type.
-A primitive image type property can be either declared or automatically get
-back with the help of associated types.
-
+A primitive image type property can be either declared or automatically deduce
+from the help of associated types.
FIXME: find a good notation...
** Image nD
-Image on regular grid where grid nodes are points.
-To gain efficiency, Images nD have a virtual borders.
+Image based on a regular grid where the grid nodes are points.
+To gain efficiency, Images nD have a virtual border.
All these image are templated by T, the image value type.
+**** Specific interface:
+
+ Image nd is a able to provide index access through its interfaces.
+
*** Common Associated type//properties between imageND
@@ -219,8 +274,6 @@
space = one_d
-**** Specific interface:
- FIXME....
*** Image2d<T>
@@ -248,10 +301,6 @@
space = three_d
-**** Specific interface:
- FIXME....
-
-
** Image based on function
@@ -296,12 +345,9 @@
Is there any lvalue for image with computed data?
lvalue just for image with stored//read_only data?
-**** Specific interface:
- FIXME....
-
** Run based Encoded image
-All the run based encoded images have their definition domains encoded by runs.
+All the run encoded images have their definition domains encoded by runs.
These images types are not morpher types since these do not lie on another
image type.
All the run based encoded images are templated by P, T where P is a site type
@@ -311,7 +357,6 @@
type one shot (const)!!!
Do we store the the null value in the rle encoding.
( <=> Do we compress all the images values, or only the image objects...)
-Is there any restriction on P and T?
*** Notation used:
(a, b) represents a pair composed by two elements..
@@ -389,7 +434,6 @@
So we must be able to convert a site and i_run index to another site.
ex:
-
(0, 4) + 3 give us the site (0, 7).
It has two consequences:
@@ -642,6 +686,15 @@
(4, {((3, 3), 3)} )
}
+**** Specific Methods:
+
+With this type of image, we can easily access to all the site corresponding
+to a value (method site_from_values(V value) : p_runs?).
+
+Furthermore, we can easily change the value of all the
+site which share the same value in a constant time.
+(method: cell(V value) : V&).
+
*** Image based on Lut
@@ -659,6 +712,11 @@
FIXME: How do we deal with the dimensions of the images?
+**** Specific Method:
+
+As value encoded image, here we can easily change the value of all
+the site which share the same value (method: cell(V value) : V&).
+
**** Associated type
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Fix the computation of neighbors in mln::line_graph_elt_neighborhood.
* mln/core/line_graph_elt_neighborhood.hh
(compute_neighbors_): Don't add the reference point to the set of
neighbors.
line_graph_elt_neighborhood.hh | 10 ++++++++++
1 file changed, 10 insertions(+)
Index: mln/core/line_graph_elt_neighborhood.hh
--- mln/core/line_graph_elt_neighborhood.hh (revision 1899)
+++ mln/core/line_graph_elt_neighborhood.hh (working copy)
@@ -40,6 +40,10 @@
- mln::line_graph_elt_window
- mln::line_graph_elt_neighborhood. */
+/* 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. */
+
# include <set>
# include <mln/core/concept/neighborhood.hh>
@@ -105,6 +109,7 @@
line_graph_elt_neighborhood<P>::compute_neighbors_(Point_Iterator<Piter>& piter_) const
{
Piter& piter = exact(piter_);
+ util::edge_id ref_edge_id = piter.p_ref().id();
neighbors_t& neighbors = piter.neighbors();
neighbors.clear();
/* FIXME: Move this computation out of the window. In fact,
@@ -116,6 +121,9 @@
const util::node<P>& node1 = piter.plg().gr_->node(id1);
for (std::vector<util::edge_id>::const_iterator e =
node1.edges.begin(); e != node1.edges.end(); ++e)
+ /* We explicitely enforce that the reference piter edge id is
+ not inserted into NEIGHBORS. */
+ if (*e != ref_edge_id)
neighbors.insert(*e);
// Ajacent edges connected through node 2.
// FIXME: Likewise.
@@ -123,6 +131,8 @@
const util::node<P>& node2 = piter.plg().gr_->node(id2);
for (std::vector<util::edge_id>::const_iterator e =
node2.edges.begin(); e != node2.edges.end(); ++e)
+ // Same remark as above.
+ if (*e != ref_edge_id)
neighbors.insert(*e);
}
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Speed up iterations on line graph windows.
* mln/core/line_graph_window_piter.hh
(mln::line_graph_window_fwd_piter<P>::sites_t)
(mln::line_graph_window_bkd_piter<P>::sites_t):
New typedefs.
(mln::line_graph_window_fwd_piter<P>::adjacent_or_equal_to_p_ref_)
(mln::line_graph_window_bkd_piter<P>::adjacent_or_equal_to_p_ref_)
(mln::line_graph_window_fwd_piter<P>::first_)
(mln::line_graph_window_bkd_piter<P>::first_)
(mln::line_graph_window_fwd_piter<P>::step_)
(mln::line_graph_window_bkd_piter<P>::step_)
(mln::line_graph_window_fwd_piter<P>::id_)
(mln::line_graph_window_bkd_piter<P>::id_):
Remove.
(mln::line_graph_window_fwd_piter<P>::p_ref)
(mln::line_graph_window_bkd_piter<P>::p_ref)
(mln::line_graph_window_fwd_piter<P>::plg)
(mln::line_graph_window_bkd_piter<P>::plg)
(mln::line_graph_window_fwd_piter<P>::sites)
(mln::line_graph_window_bkd_piter<P>::sites):
New accessors.
(mln::line_graph_window_fwd_piter<P>::saved_p_ref_)
(mln::line_graph_window_bkd_piter<P>::saved_p_ref_)
(mln::line_graph_window_fwd_piter<P>::sites_)
(mln::line_graph_window_bkd_piter<P>::sites_)
(mln::line_graph_window_fwd_piter<P>::i_)
(mln::line_graph_window_bkd_piter<P>::i_):
New attributes.
(mln::line_graph_window_fwd_piter<P, W>::is_valid)
(mln::line_graph_window_bkd_piter<P, W>::is_valid)
(mln::line_graph_window_fwd_piter<P, W>::invalidate)
(mln::line_graph_window_bkd_piter<P, W>::invalidate)
(mln::line_graph_window_fwd_piter<P, W>::start)
(mln::line_graph_window_bkd_piter<P, W>::start)
(mln::line_graph_window_fwd_piter<P, W>::next)
(mln::line_graph_window_bkd_piter<P, W>::next):
Change the algorithms used in these routines, so that they use a
list of computed window sites (new member sites_) instead of
iterating over the whole set of edges.
(mln::line_graph_window_fwd_piter<P, W>::update_)
(mln::line_graph_window_bkd_piter<P, W>::update_):
Adjust.
* mln/core/line_graph_elt_window.hh: Catch up with the new
interface of piters on line graph windows.
(mln::line_graph_elt_window<P>::sites_t): New typedef.
(mln::line_graph_elt_window<P>::line_graph_elt_window): Remove
useless ctor.
(mln::line_graph_elt_window<P>::start)
(mln::line_graph_elt_window<P>::next_):
Remove methods.
(mln::line_graph_elt_window<P>::compute_sites_):
New method.
* mln/core/line_graph_neighborhood_piter.hh
(line_graph_neighborhood_fwd_piter<P, N>::adjacent_or_equal_to_p_ref_)
(line_graph_neighborhood_bkd_piter<P, N>::adjacent_or_equal_to_p_ref_):
Remove spurious method declarations.
line_graph_elt_window.hh | 60 +++------
line_graph_neighborhood_piter.hh | 4
line_graph_window_piter.hh | 256 ++++++++++++++++++---------------------
3 files changed, 146 insertions(+), 174 deletions(-)
Index: mln/core/line_graph_window_piter.hh
--- mln/core/line_graph_window_piter.hh (revision 1895)
+++ mln/core/line_graph_window_piter.hh (working copy)
@@ -80,6 +80,9 @@
// FIXME: Dummy typedef.
typedef void mesh;
+ // The type of the set of window sites (adjacent edge ids).
+ typedef std::set<util::edge_id> sites_t;
+
public:
/// Construction.
/// \{
@@ -99,8 +102,6 @@
/// Go to the next point.
void next_();
- /// Is the piter adjacent or equal to the reference point?
- bool adjacent_or_equal_to_p_ref_() const;
/// Update the internal data of the iterator.
void update_();
/// \}
@@ -114,27 +115,30 @@
/// Convert the iterator into a line graph psite.
operator psite() const;
+ /// Return the reference psite.
+ const psite& p_ref() const;
+ /// Return the mln::p_line_graph corresponding to this piter.
+ const p_line_graph<P>& plg() const;
+ /// Return the set of sites (adjacent edge ids).
+ sites_t& sites();
+
/// Read-only access to the \a i-th coordinate.
coord operator[](unsigned i) const;
/// \}
- /// Internals, used by the window.
- /// \{
- public:
- /// Set the iterator to the first site of the graph.
- void first_();
- /// Advance the position of the iterator by one step.
- void step_();
-
- /// An internal iterator on the set of edges of the underlying graph.
- util::edge_id id_;
- /// \}
-
private:
/// The window.
const W& win_;
/// The ``central'' psite of the window.
const psite& p_ref_;
+
+ /// The last reference psite whose ajacent psites have been computed.
+ psite saved_p_ref_;
+ /// The set of edge ids adjacent to the reference psite.
+ sites_t sites_;
+ /// An iterator on the set of adjacent edges.
+ sites_t::const_iterator i_;
+
/// The psite corresponding to this iterator.
psite psite_;
/// The point corresponding to this iterator.
@@ -176,6 +180,9 @@
// FIXME: Dummy typedef.
typedef void mesh;
+ // The type of the set of window sites (adjacent edge ids).
+ typedef std::set<util::edge_id> sites_t;
+
public:
/// Construction.
/// \{
@@ -195,8 +202,6 @@
/// Go to the next point.
void next_();
- /// Is the piter adjacent or equal to the reference point?
- bool adjacent_or_equal_to_p_ref_() const;
/// Update the internal data of the iterator.
void update_();
/// \}
@@ -210,27 +215,30 @@
/// Convert the iterator into a line graph psite.
operator psite() const;
+ /// Return the reference psite.
+ const psite& p_ref() const;
+ /// Return the mln::p_line_graph corresponding to this piter.
+ const p_line_graph<P>& plg() const;
+ /// Return the set of sites (adjacent edge ids).
+ sites_t& sites();
+
/// Read-only access to the \a i-th coordinate.
coord operator[](unsigned i) const;
/// \}
- /// Internals, used by the window.
- /// \{
- public:
- /// Set the iterator to the first site of the graph.
- void first_();
- /// Advance the position of the iterator by one step.
- void step_();
-
- /// An internal iterator on the set of edges of the underlying graph.
- util::edge_id id_;
- /// \}
-
private:
/// The window.
const W& win_;
/// The ``central'' psite of the window.
const psite& p_ref_;
+
+ /// The last reference psite whose ajacent psites have been computed.
+ psite saved_p_ref_;
+ /// The set of edge ids adjacent to the reference psite.
+ sites_t sites_;
+ /// An iterator on the set of adjacent edges.
+ sites_t::const_reverse_iterator i_;
+
/// The psite corresponding to this iterator.
psite psite_;
/// The point corresponding to this iterator.
@@ -275,10 +283,13 @@
bool
line_graph_window_fwd_piter<P, W>::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 p_ref_.is_valid() && id_ < p_ref_.plg().gr_->nedges();
+ return
+ // The reference point must be valid...
+ p_ref_.is_valid()
+ // ...and must not have changed since the window has been computed...
+ && p_ref_ == saved_p_ref_
+ // ...and the iterator i_ must point a valid value.
+ && i_ != sites_.end();
}
template <typename P, typename W>
@@ -286,7 +297,7 @@
void
line_graph_window_fwd_piter<P, W>::invalidate()
{
- id_ = -1;
+ i_ = sites_.end();
}
template <typename P, typename W>
@@ -294,7 +305,15 @@
void
line_graph_window_fwd_piter<P, W>::start()
{
- win_.start(*this);
+ mln_precondition(p_ref_.is_valid());
+ // Update the sites, if needed.
+ if (!saved_p_ref_.is_valid() || p_ref_ != saved_p_ref_)
+ {
+ saved_p_ref_ = p_ref_;
+ win_.compute_sites_(*this);
+ }
+ i_ = sites_.begin();
+ // FIXME: We might move the is_valid condition within update_.
if (is_valid())
update_();
}
@@ -304,7 +323,10 @@
void
line_graph_window_fwd_piter<P, W>::next_()
{
- win_.next_(*this);
+ // Ensure the p_ref_ has not changed.
+ mln_precondition(p_ref_ == saved_p_ref_);
+ ++i_;
+ // FIXME: We might move the is_valid condition within update_.
if (is_valid())
update_();
}
@@ -312,84 +334,58 @@
template <typename P, typename W>
inline
void
- line_graph_window_fwd_piter<P, W>::first_()
+ line_graph_window_fwd_piter<P, W>::update_()
{
- id_ = 0;
+ // Update psite_.
+ psite_ = line_graph_psite<P>(plg(), *i_);
}
template <typename P, typename W>
inline
- void
- line_graph_window_fwd_piter<P, W>::step_()
+ const P&
+ line_graph_window_fwd_piter<P, W>::to_point() const
{
- ++id_;
+ return p_;
}
-
template <typename P, typename W>
inline
- bool
- line_graph_window_fwd_piter<P, W>::adjacent_or_equal_to_p_ref_() const
+ const line_graph_psite<P>&
+ line_graph_window_fwd_piter<P, W>::to_psite() const
{
- // Check wether the iterator points to P_REF_.
- if (id_ == p_ref_.id())
- return true;
-
- // Check whether the iterator is among the neighbors of P_REF_.
- {
- // Paranoid assertion.
- 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 util::tracked_ptr<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;
- }
-
- // Otherwise, the iterator is not adjacent to P_REF_.
- return false;
+ return psite_;
}
template <typename P, typename W>
inline
- void
- line_graph_window_fwd_piter<P, W>::update_()
+ line_graph_window_fwd_piter<P, W>::operator line_graph_psite<P> () const
{
- // Update psite_.
- psite_ = line_graph_psite<P>(p_ref_.plg(), id_);
+ mln_precondition(is_valid());
+ return psite_;
}
template <typename P, typename W>
inline
- const P&
- line_graph_window_fwd_piter<P, W>::to_point() const
+ const line_graph_psite<P>&
+ line_graph_window_fwd_piter<P, W>::p_ref() const
{
- return p_;
+ return p_ref_;
}
template <typename P, typename W>
inline
- const line_graph_psite<P>&
- line_graph_window_fwd_piter<P, W>::to_psite() const
+ const p_line_graph<P>&
+ line_graph_window_fwd_piter<P, W>::plg() const
{
- return psite_;
+ return p_ref_.plg();
}
template <typename P, typename W>
inline
- line_graph_window_fwd_piter<P, W>::operator line_graph_psite<P> () const
+ std::set<util::edge_id>&
+ line_graph_window_fwd_piter<P, W>::sites()
{
- mln_precondition(is_valid());
- return psite_;
+ return sites_;
}
template <typename P, typename W>
@@ -434,10 +430,13 @@
bool
line_graph_window_bkd_piter<P, W>::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 p_ref_.is_valid() && id_ < p_ref_.plg().gr_->nedges();
+ return
+ // The reference point must be valid...
+ p_ref_.is_valid()
+ // ...and must not have changed since the window has been computed...
+ && p_ref_ == saved_p_ref_
+ // ...and the iterator i_ must point a valid value.
+ && i_ != sites_.rend();
}
template <typename P, typename W>
@@ -445,7 +444,7 @@
void
line_graph_window_bkd_piter<P, W>::invalidate()
{
- id_ = -1;
+ i_ = sites_.rend();
}
template <typename P, typename W>
@@ -453,7 +452,15 @@
void
line_graph_window_bkd_piter<P, W>::start()
{
- win_.start(*this);
+ mln_precondition(p_ref_.is_valid());
+ // Update the sites, if needed.
+ if (!saved_p_ref_.is_valid() || p_ref_ != saved_p_ref_)
+ {
+ saved_p_ref_ = p_ref_;
+ win_.compute_sites_(*this);
+ }
+ i_ = sites_.rbegin();
+ // FIXME: We might move the is_valid condition within update_.
if (is_valid())
update_();
}
@@ -463,7 +470,10 @@
void
line_graph_window_bkd_piter<P, W>::next_()
{
- win_.next_(*this);
+ // Ensure the p_ref_ has not changed.
+ mln_precondition(p_ref_ == saved_p_ref_);
+ ++i_;
+ // FIXME: We might move the is_valid condition within update_.
if (is_valid())
update_();
}
@@ -471,84 +481,58 @@
template <typename P, typename W>
inline
void
- line_graph_window_bkd_piter<P, W>::first_()
+ line_graph_window_bkd_piter<P, W>::update_()
{
- id_ = p_ref_.plg().gr_->nedges() - 1;
+ // Update psite_.
+ psite_ = line_graph_psite<P>(plg(), *i_);
}
template <typename P, typename W>
inline
- void
- line_graph_window_bkd_piter<P, W>::step_()
+ const P&
+ line_graph_window_bkd_piter<P, W>::to_point() const
{
- --id_;
+ return p_;
}
-
template <typename P, typename W>
inline
- bool
- line_graph_window_bkd_piter<P, W>::adjacent_or_equal_to_p_ref_() const
+ const line_graph_psite<P>&
+ line_graph_window_bkd_piter<P, W>::to_psite() const
{
- // Check wether the iterator points to P_REF_.
- if (id_ == p_ref_.id())
- return true;
-
- // Check whether the iterator is among the neighbors of P_REF_.
- {
- // Paranoid assertion.
- 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 util::tracked_ptr<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;
- }
-
- // Otherwise, the iterator is not adjacent to P_REF_.
- return false;
+ return psite_;
}
template <typename P, typename W>
inline
- void
- line_graph_window_bkd_piter<P, W>::update_()
+ line_graph_window_bkd_piter<P, W>::operator line_graph_psite<P> () const
{
- // Update psite_.
- psite_ = line_graph_psite<P>(p_ref_.plg(), id_);
+ mln_precondition(is_valid());
+ return psite_;
}
template <typename P, typename W>
inline
- const P&
- line_graph_window_bkd_piter<P, W>::to_point() const
+ const line_graph_psite<P>&
+ line_graph_window_bkd_piter<P, W>::p_ref() const
{
- return p_;
+ return p_ref_;
}
template <typename P, typename W>
inline
- const line_graph_psite<P>&
- line_graph_window_bkd_piter<P, W>::to_psite() const
+ const p_line_graph<P>&
+ line_graph_window_bkd_piter<P, W>::plg() const
{
- return psite_;
+ return p_ref_.plg();
}
template <typename P, typename W>
inline
- line_graph_window_bkd_piter<P, W>::operator line_graph_psite<P> () const
+ std::set<util::edge_id>&
+ line_graph_window_bkd_piter<P, W>::sites()
{
- mln_precondition(is_valid());
- return psite_;
+ return sites_;
}
template <typename P, typename W>
Index: mln/core/line_graph_elt_window.hh
--- mln/core/line_graph_elt_window.hh (revision 1895)
+++ mln/core/line_graph_elt_window.hh (working copy)
@@ -65,6 +65,9 @@
typedef P point;
/// The type of psite corresponding to the window.
typedef line_graph_psite<P> psite;
+ // The type of the set of window sites (edge ids adjacent to the
+ // reference psite).
+ typedef std::set<util::edge_id> sites_t;
// FIXME: This is a dummy value.
typedef void dpoint;
@@ -81,17 +84,10 @@
typedef fwd_qiter qiter;
/// \}
- /// Construct an elementary line_graph window.
- line_graph_elt_window();
-
/// Services for iterators.
/// \{
- /// Move \a piter to the beginning of the iteration on this window.
- template <typename Piter>
- void start(Point_Iterator<Piter>& piter) const;
- /// Move \a piter to the next site on this window.
template <typename Piter>
- void next_(Point_Iterator<Piter>& piter) const;
+ void compute_sites_(Point_Iterator<Piter>& piter) const;
/// \}
/// Interface of the concept Window.
@@ -125,37 +121,33 @@
# ifndef MLN_INCLUDE_ONLY
template <typename P>
- inline
- line_graph_elt_window<P>::line_graph_elt_window()
- {
- }
-
- template <typename P>
- template <typename Piter>
- inline
- void
- line_graph_elt_window<P>::start(Point_Iterator<Piter>& piter_) const
- {
- Piter& piter = exact(piter_);
- piter.first_();
- if (!piter.adjacent_or_equal_to_p_ref_())
- next_(piter);
- }
-
- template <typename P>
template <typename Piter>
inline
void
- line_graph_elt_window<P>::next_(Point_Iterator<Piter>& piter_) const
+ line_graph_elt_window<P>::compute_sites_(Point_Iterator<Piter>& piter_) const
{
Piter& piter = exact(piter_);
- /* 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. */
- do
- piter.step_();
- while (piter.is_valid() && !piter.adjacent_or_equal_to_p_ref_());
+ sites_t& sites = piter.sites();
+ sites.clear();
+ /* FIXME: Move this computation out of the window. In fact,
+ this should be a service of the graph, also proposed by the
+ p_line_graph. */
+ // Add the reference piter itself.
+ sites.insert(piter.p_ref().id());
+ // Ajacent edges connected through node 1.
+ // FIXME: Far too low-level.
+ util::node_id id1 = piter.p_ref().first_id();
+ const util::node<P>& node1 = piter.plg().gr_->node(id1);
+ for (std::vector<util::edge_id>::const_iterator e =
+ node1.edges.begin(); e != node1.edges.end(); ++e)
+ sites.insert(*e);
+ // Ajacent edges connected through node 2.
+ // FIXME: Likewise.
+ util::node_id id2 = piter.p_ref().second_id();
+ const util::node<P>& node2 = piter.plg().gr_->node(id2);
+ for (std::vector<util::edge_id>::const_iterator e =
+ node2.edges.begin(); e != node2.edges.end(); ++e)
+ sites.insert(*e);
}
template <typename P>
Index: mln/core/line_graph_neighborhood_piter.hh
--- mln/core/line_graph_neighborhood_piter.hh (revision 1895)
+++ mln/core/line_graph_neighborhood_piter.hh (working copy)
@@ -104,8 +104,6 @@
/// Go to the next point.
void next_();
- /// Is the piter adjacent or equal to the reference point?
- bool adjacent_or_equal_to_p_ref_() const;
/// Update the internal data of the iterator.
void update_();
/// \}
@@ -208,8 +206,6 @@
/// Go to the next point.
void next_();
- /// Is the piter adjacent or equal to the reference point?
- bool adjacent_or_equal_to_p_ref_() const;
/// Update the internal data of the iterator.
void update_();
/// \}