Olena-patches
  Threads by month 
                
            - ----- 2025 -----
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2024 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2023 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2022 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2021 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2020 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2019 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2018 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2017 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2016 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2015 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2014 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2013 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2012 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2011 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2010 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2009 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2008 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2007 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2006 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2005 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2004 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 
- 9625 discussions
 
                    
                        https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Handle fwd iterations on p_array.
	* tests/core/p_array.cc: Add iteration test.
	* mln/core/internal/site_iterator_base.hh: New; based upon...
	* mln/core/internal/pseudo_site_base.hh: ...this.
	* mln/core/internal/pseudo_site_base.hh
	(subject, q_subject): New; factor those definitions.
	* mln/core/p_array_piter.hh (p_array_fwd_piter_): Update.
	(p_array_bkd_piter_): Deactivate.
	* mln/core/p_array.hh
	(p_array): Change into constant proxy; move defs into guards.
	(to_site): Delete mutable version.
	(change_target): New.
	* mln/core/concept/site_iterator.hh (operator site): Remove;
	that was obsolete code.
 mln/core/concept/site_iterator.hh       |   20 -
 mln/core/internal/pseudo_site_base.hh   |    6 
 mln/core/internal/site_iterator_base.hh |   50 +++-
 mln/core/p_array.hh                     |  131 +++++++----
 mln/core/p_array_piter.hh               |  366 +++++++++++++++-----------------
 tests/core/p_array.cc                   |    8 
 6 files changed, 309 insertions(+), 272 deletions(-)
Index: tests/core/p_array.cc
--- tests/core/p_array.cc	(revision 1971)
+++ tests/core/p_array.cc	(working copy)
@@ -59,7 +59,15 @@
 	    << point2d(p)  << ' '
 	    << std::endl;
 
+
   std::copy(pa.vect().begin(), pa.vect().end(),
 	    std::ostream_iterator<point2d>(std::cout, " "));
   std::cout << std::endl;
+
+  {
+    mln_piter_(Arr) p(pa);
+    for_all(p)
+      std::cout << p << ' ';
+    std::cout << std::endl;
+  }
 }
Index: mln/core/internal/site_iterator_base.hh
--- mln/core/internal/site_iterator_base.hh	(revision 1971)
+++ mln/core/internal/site_iterator_base.hh	(working copy)
@@ -25,15 +25,15 @@
 // reasons why the executable file might be covered by the GNU General
 // Public License.
 
-#ifndef MLN_CORE_INTERNAL_PSEUDO_SITE_BASE_HH
-# define MLN_CORE_INTERNAL_PSEUDO_SITE_BASE_HH
+#ifndef MLN_CORE_INTERNAL_SITE_ITERATOR_BASE_HH
+# define MLN_CORE_INTERNAL_SITE_ITERATOR_BASE_HH
 
-/*! \file mln/core/internal/pseudo_site_base.hh
+/*! \file mln/core/internal/site_iterator_base.hh
  *
- * \brief Base class to factor code for pseudo site classes.
+ * \brief Base class to factor code for site iterator classes.
  */
 
-# include <mln/core/concept/pseudo_site.hh>
+# include <mln/core/concept/site_iterator.hh>
 
 
 namespace mln
@@ -42,16 +42,16 @@
   namespace internal
   {
 
-    /*! \internal A base class for pseudo sites.
+    /*! \internal A base class for site iterators.
      *
      * Parameter \c P is FIXME: a point site type.
      */
-    template <bool is_mutable, typename P, typename E>
-    struct pseudo_site_base_ : Pseudo_Site<E>,
+    template <typename P, typename E>
+    struct site_iterator_base_ : Site_Iterator<E>,
 
                                proxy_impl<P, E>,
 
-                               site_impl< is_mutable,
+                                 site_impl< false, // Constant access to site / subject.
 					  typename site_from<P>::ret,
 					  E >
     {
@@ -59,17 +59,41 @@
       // The associated site type.
       typedef typename internal::site_from<P>::ret site;
 
+      // The associated subject type (as a Proxy).
+      typedef P subject;
+
+      // The associated q_subject type (as a Proxy).
+      typedef const P& q_subject;
+
+      /*! \brief Conversion towards the site it designates.
+       *
+       * \warning This is a final method; iterator classes should not
+       * re-defined this method.
+       *
+       * \pre The iterator is valid.
+       */ 
+      operator site() const;
+
     protected:
-      pseudo_site_base_();
+      site_iterator_base_();
     };
 
 
 #ifndef MLN_INCLUDE_ONLY
 
-    template <bool is_mutable, typename P, typename E>
+    template <typename P, typename E>
+    inline
+    site_iterator_base_<P, E>::site_iterator_base_()
+    {
+    }
+
+    template <typename P, typename E>
     inline
-    pseudo_site_base_<is_mutable, P, E>::pseudo_site_base_()
+    site_iterator_base_<P, E>::operator site() const
     {
+      typedef proxy_impl<P, E> super;
+      mln_precondition(exact(this)->is_valid());
+      return this->super::operator site();
     }
 
 #endif // ! MLN_INCLUDE_ONLY
@@ -79,4 +103,4 @@
 } // end of namespace mln
 
 
-#endif // ! MLN_CORE_INTERNAL_PSEUDO_SITE_BASE_HH
+#endif // ! MLN_CORE_INTERNAL_SITE_ITERATOR_BASE_HH
Index: mln/core/internal/pseudo_site_base.hh
--- mln/core/internal/pseudo_site_base.hh	(revision 1971)
+++ mln/core/internal/pseudo_site_base.hh	(working copy)
@@ -59,6 +59,12 @@
       // The associated site type.
       typedef typename internal::site_from<P>::ret site;
 
+      // The associated subject type (as a Proxy).
+      typedef P subject;
+
+      // The associated q_subject type (as a Proxy).
+      typedef const P& q_subject;
+
     protected:
       pseudo_site_base_();
     };
Index: mln/core/p_array_piter.hh
--- mln/core/p_array_piter.hh	(revision 1971)
+++ mln/core/p_array_piter.hh	(working copy)
@@ -32,6 +32,7 @@
 /// \brief Definition of point iterators on mln::p_array.
 
 # include <mln/core/p_array.hh>
+# include <mln/core/internal/site_iterator_base.hh>
 
 
 namespace mln
@@ -39,32 +40,24 @@
 
   /// \brief Forward iterator on points of a p_array<P>.
   template <typename P>
-  struct p_array_fwd_piter_
-    : public internal::point_iterator_base_< P, p_array_fwd_piter_<P> >
+  class p_array_fwd_piter_
+    :
+    public internal::site_iterator_base_< p_array_psite<P>,
+					  p_array_fwd_piter_<P> >
   {
-    typedef p_array_fwd_piter_<P> self_;
-    typedef internal::point_iterator_base_< P, self_ > super_;
-  public:
-    /// The associated psite type.
-    typedef P psite;
-
-    /// The associated point type.
-    typedef mln_point(P) point;
-
-    enum { dim = super_::dim };
+    typedef p_array_fwd_piter_<P> self;
+    typedef internal::site_iterator_base_<p_array_psite<P>, self> super;
 
-    /// Coordinate associated type.
-    template <typename S>
-    p_array_fwd_piter_(const Site_Set<S>& s);
+  public:
 
-    /// Reference of the corresponding psite.
-    const psite& to_psite() const;
+    /// Constructor with no argument.
+    p_array_fwd_piter_();
 
-    /// Reference of the corresponding point.
-    const point& to_point() const;
+    /// Constructor.
+    p_array_fwd_piter_(const p_array<P>& arr);
 
-    /// Read-only access to the \p i-th coordinate.
-    mln_coord(point) operator[](unsigned i) const;
+    /// Change of site set target.
+    void change_target(const p_array<P>& arr);
 
     /// Test if the iterator is valid.
     bool is_valid() const;
@@ -78,73 +71,75 @@
     /// Go to the next point.
     void next_();
 
-    /// Convert the iterator into a psite.
-    operator psite() const;
-
-  protected:
-    const std::vector<P>& vect_;
-    // FIXME: Why it's unsigned in fwd iterator and signed in the bkd one ?
-    unsigned i_;
-    psite p_;
-  };
-
-
-
-  /// \brief Backward iterator on points of a p_array<P>.
-  template <typename P>
-  struct p_array_bkd_piter_
-    : public internal::point_iterator_base_< P, p_array_bkd_piter_<P> >
-  {
-    typedef p_array_bkd_piter_<P> self_;
-    typedef internal::point_iterator_base_< P, self_ > super_;
-  public:
-    /// The associated psite type.
-    typedef P psite;
-
-    /// The associated point type.
-    typedef mln_point(P) point;
-
-    enum { dim = super_::dim };
-
-    /// Coordinate associated type.
-    template <typename S>
-    p_array_bkd_piter_(const Site_Set<S>& s);
-
-    /// Reference of the corresponding psite.
-    const psite& to_psite() const;
-
-    /// Reference of the corresponding point.
-    const point& to_point() const;
+    /// Return the subject.
+    const p_array_psite<P>& unproxy() const;
 
-    /// Read-only access to the \p i-th coordinate.
-    mln_coord(point) operator[](unsigned i) const;
+    // As a Site_Proxy:
+    typedef typename super::site site;
+    const site& to_site() const;
 
-    /// Test if the iterator is valid.
-    bool is_valid() const;
-
-    /// Invalidate the iterator.
-    void invalidate();
+  protected:
 
-    /// Start an iteration.
-    void start();
+    p_array_psite<P> p_;
+  };
 
-    /// Go to the next point.
-    void next_();
 
-    /// Convert the iterator into a psite.
-    operator psite() const;
 
-  protected:
-    const std::vector<P>& vect_;
-    /* FIXME: See the comment on p_array_fwd_piter_<P>::i_ above.  We
-       could turn this `int' into an `unsigned'.  Then,
-       - setting the value of i_ to -1 (== UINT_MAX) in invalidate(),
-       - and having valid() test whether i_ is strictly smaller than
-         vect_.size()
-       should work in both iterators (fwd and bkd).  */
-    int i_;
-    psite p_;
-  };
+//   /// \brief Backward iterator on points of a p_array<P>.
+//   template <typename P>
+//   struct p_array_bkd_piter_
+//     : public internal::point_iterator_base_< P, p_array_bkd_piter_<P> >
+//   {
+//     typedef p_array_bkd_piter_<P> self_;
+//     typedef internal::point_iterator_base_< P, self_ > super_;
+//   public:
+//     /// The associated psite type.
+//     typedef P psite;
+
+//     /// The associated point type.
+//     typedef mln_point(P) point;
+
+//     enum { dim = super_::dim };
+
+//     /// Coordinate associated type.
+//     template <typename S>
+//     p_array_bkd_piter_(const Site_Set<S>& s);
+
+//     /// Reference of the corresponding psite.
+//     const psite& to_psite() const;
+
+//     /// Reference of the corresponding point.
+//     const point& to_point() const;
+
+//     /// Read-only access to the \p i-th coordinate.
+//     mln_coord(point) operator[](unsigned i) const;
+
+//     /// Test if the iterator is valid.
+//     bool is_valid() const;
+
+//     /// Invalidate the iterator.
+//     void invalidate();
+
+//     /// Start an iteration.
+//     void start();
+
+//     /// Go to the next point.
+//     void next_();
+
+//     /// Convert the iterator into a psite.
+//     operator psite() const;
+
+//   protected:
+//     const std::vector<P>& vect_;
+//     /* FIXME: See the comment on p_array_fwd_piter_<P>::i_ above.  We
+//        could turn this `int' into an `unsigned'.  Then,
+//        - setting the value of i_ to -1 (== UINT_MAX) in invalidate(),
+//        - and having valid() test whether i_ is strictly smaller than
+//          vect_.size()
+//        should work in both iterators (fwd and bkd).  */
+//     int i_;
+//     psite p_;
+//   };
 
 
 
@@ -155,38 +150,25 @@
   `------------------------*/
 
   template <typename P>
-  template <typename S>
   inline
-  p_array_fwd_piter_<P>::p_array_fwd_piter_(const Site_Set<S>& s)
-    : vect_(exact(s).vect())
+  p_array_fwd_piter_<P>::p_array_fwd_piter_()
   {
-    invalidate();
   }
 
   template <typename P>
   inline
-  const P&
-  p_array_fwd_piter_<P>::to_psite() const
+  p_array_fwd_piter_<P>::p_array_fwd_piter_(const p_array<P>& arr)
   {
-    return p_;
+    change_target(arr);
   }
 
   template <typename P>
   inline
-  const mln_point(P)&
-  p_array_fwd_piter_<P>::to_point() const
-  {
-    return p_.to_point();
-  }
-
-  template <typename P>
-  inline
-  mln_coord(mln_point_(P))
-  p_array_fwd_piter_<P>::operator[](unsigned i) const
+  void
+  p_array_fwd_piter_<P>::change_target(const p_array<P>& arr)
   {
-    mln_precondition(i < dim);
-    mln_precondition(is_valid());
-    return p_.to_point()[i];
+    p_.change_target(arr);
+    invalidate();
   }
 
   template <typename P>
@@ -194,7 +176,7 @@
   bool
   p_array_fwd_piter_<P>::is_valid() const
   {
-    return i_ < vect_.size();
+    return p_.target() != 0 && p_.index() < int(p_.target()->nsites());
   }
 
   template <typename P>
@@ -202,7 +184,8 @@
   void
   p_array_fwd_piter_<P>::invalidate()
   {
-    i_ = vect_.size();
+    if (p_.target() != 0)
+      p_.index() = p_.target()->nsites();
   }
 
   template <typename P>
@@ -210,9 +193,8 @@
   void
   p_array_fwd_piter_<P>::start()
   {
-    i_ = 0;
-    if (is_valid())
-      p_ = vect_[i_];
+    mln_precondition(p_.target() != 0);
+    p_.index() = 0;
   }
 
   template <typename P>
@@ -220,102 +202,108 @@
   void
   p_array_fwd_piter_<P>::next_()
   {
-    ++i_;
-    if (is_valid())
-      p_ = vect_[i_];
+    ++p_.index();
   }
 
   template <typename P>
   inline
-  p_array_fwd_piter_<P>::operator P() const
+  const p_array_psite<P>&
+  p_array_fwd_piter_<P>::unproxy() const
   {
-    mln_precondition(is_valid());
     return p_;
   }
 
-
-  /*------------------------.
-  | p_array_bkd_piter_<P>.  |
-  `------------------------*/
-
   template <typename P>
-  template <typename S>
   inline
-  p_array_bkd_piter_<P>::p_array_bkd_piter_(const Site_Set<S>& s)
-    : vect_(exact(s).vect())
+  const typename p_array_fwd_piter_<P>::site&
+  p_array_fwd_piter_<P>::to_site() const
   {
-    invalidate();
+    mln_precondition(p_.target() != 0);
+    return p_.to_site();
   }
 
-  template <typename P>
-  inline
-  const P&
-  p_array_bkd_piter_<P>::to_psite() const
-  {
-    return p_;
-  }
-
-  template <typename P>
-  inline
-  const mln_point(P)&
-  p_array_bkd_piter_<P>::to_point() const
-  {
-    return p_.to_point();
-  }
-
-  template <typename P>
-  inline
-  mln_coord(mln_point_(P))
-  p_array_bkd_piter_<P>::operator[](unsigned i) const
-  {
-    mln_precondition(i < dim);
-    mln_precondition(is_valid());
-    return p_.to_point()[i];
-  }
-
-  template <typename P>
-  inline
-  bool
-  p_array_bkd_piter_<P>::is_valid() const
-  {
-    return i_ >= 0;
-  }
-
-  template <typename P>
-  inline
-  void
-  p_array_bkd_piter_<P>::invalidate()
-  {
-    i_ = -1;
-  }
-
-  template <typename P>
-  inline
-  void
-  p_array_bkd_piter_<P>::start()
-  {
-    i_ = vect_.size() - 1;
-    if (is_valid())
-      p_ = vect_[i_];
-  }
-
-  template <typename P>
-  inline
-  void
-  p_array_bkd_piter_<P>::next_()
-  {
-    --i_;
-    if (is_valid())
-      p_ = vect_[i_];
-  }
+  /*------------------------.
+  | p_array_bkd_piter_<P>.  |
+  `------------------------*/
 
-  template <typename P>
-  inline
-  p_array_bkd_piter_<P>::operator P() const
-  {
-    mln_precondition(is_valid());
-    return p_;
-  }
+//   template <typename P>
+//   template <typename S>
+//   inline
+//   p_array_bkd_piter_<P>::p_array_bkd_piter_(const Site_Set<S>& s)
+//     : vect_(exact(s).vect())
+//   {
+//     invalidate();
+//   }
+
+//   template <typename P>
+//   inline
+//   const P&
+//   p_array_bkd_piter_<P>::to_psite() const
+//   {
+//     return p_;
+//   }
+
+//   template <typename P>
+//   inline
+//   const mln_point(P)&
+//   p_array_bkd_piter_<P>::to_point() const
+//   {
+//     return p_.to_point();
+//   }
+
+//   template <typename P>
+//   inline
+//   mln_coord(mln_point_(P))
+//   p_array_bkd_piter_<P>::operator[](unsigned i) const
+//   {
+//     mln_precondition(i < dim);
+//     mln_precondition(is_valid());
+//     return p_.to_point()[i];
+//   }
+
+//   template <typename P>
+//   inline
+//   bool
+//   p_array_bkd_piter_<P>::is_valid() const
+//   {
+//     return i_ >= 0;
+//   }
+
+//   template <typename P>
+//   inline
+//   void
+//   p_array_bkd_piter_<P>::invalidate()
+//   {
+//     i_ = -1;
+//   }
+
+//   template <typename P>
+//   inline
+//   void
+//   p_array_bkd_piter_<P>::start()
+//   {
+//     i_ = vect_.size() - 1;
+//     if (is_valid())
+//       p_ = vect_[i_];
+//   }
+
+//   template <typename P>
+//   inline
+//   void
+//   p_array_bkd_piter_<P>::next_()
+//   {
+//     --i_;
+//     if (is_valid())
+//       p_ = vect_[i_];
+//   }
+
+//   template <typename P>
+//   inline
+//   p_array_bkd_piter_<P>::operator P() const
+//   {
+//     mln_precondition(is_valid());
+//     return p_;
+//   }
 
 # endif // ! MLN_INCLUDE_ONLY
 
Index: mln/core/p_array.hh
--- mln/core/p_array.hh	(revision 1971)
+++ mln/core/p_array.hh	(working copy)
@@ -49,10 +49,10 @@
   template <typename P> struct p_array_bkd_piter_;
 
 
-  // HOT...
+  // p_array_psite<P>
 
   template <typename P>
-  class p_array_psite : public internal::pseudo_site_base_< true, // Mutable.
+  class p_array_psite : public internal::pseudo_site_base_< false, // Not mutable.
 							    P,
 							    p_array_psite<P> >
   {
@@ -63,59 +63,33 @@
 
     // As a Proxy:
 
-    typedef P subject;
-    typedef const P& q_subject;
-    q_subject unproxy() const;
-    P& unproxy();
+    const P& unproxy() const;
 
     // As a Site_Proxy:
 
     typedef typename super::site site;
 
-    const site& to_site() const
-    {
-      const site* s;
-      internal::get_adr(s, *this);
-      return *s;
-    }
-
-    site& to_site()
-    {
-      site* s;
-      internal::get_adr(s, *this);
-      return *s;
-    }
+    const site& to_site() const;
 
     // As Itself.
 
-    p_array_psite()
-      : arr_(0),
-	i_(0)
-    {
-    }
+    p_array_psite();
 
-    p_array_psite(p_array<P>& arr, unsigned i)
-      : arr_(&arr),
-	i_(int(i))
-    {
-    }
+    p_array_psite(const p_array<P>& arr, int i);
 
-    int index() const
-    {
-      return i_;
-    }
+    int index() const;
 
-    const p_array<P>* target() const
-    {
-      return arr_;
-    }
+    int& index();
 
-    void print() const
-    {
-      std::cout << i_ << "-th site of " << arr_ << " => site " << to_site() << std::endl;
-    }
+    const p_array<P>* target() const;
 
-    p_array<P>* arr_; // FIXME: Or const!
+    void change_target(const p_array<P>& arr);
+
+    void print() const;
+
+  private:
+
+    const p_array<P>* arr_;
     int i_;
   };
 
@@ -159,7 +133,7 @@
     typedef p_array_fwd_piter_<P> fwd_piter;
 
     /// Backward Point_Iterator associated type.
-    typedef p_array_bkd_piter_<P> bkd_piter;
+    typedef p_array_fwd_piter_<P> bkd_piter; // HOT: FIXME
 
     /// Constructor.
     p_array();
@@ -235,7 +209,7 @@
   p_array<P>::has(const psite& p) const
   {
     mln_precondition(p.target() == this); // FIXME: Refine.
-    if (p.index() < 0 || p.index() >= vect_.size())
+    if (p.index() < 0 || p.index() >= int(vect_.size()))
       return false;
     site s_ = (*this)[p.index()];
     mln_invariant(p.to_site() == s_);
@@ -308,17 +282,74 @@
 
   template <typename P>
   inline
-  const P&
-  p_array_psite<P>::unproxy() const
+  p_array_psite<P>::p_array_psite()
+    : arr_(0),
+      i_(0)
   {
-    mln_precondition(arr_ != 0);
-    return (*arr_)[i_];
   }
 
   template <typename P>
   inline
-  P&
-  p_array_psite<P>::unproxy()
+  p_array_psite<P>::p_array_psite(const p_array<P>& arr, int i)
+    : arr_(&arr),
+      i_(i)
+  {
+  }
+
+  template <typename P>
+  inline
+  const typename p_array_psite<P>::site&
+  p_array_psite<P>::to_site() const
+  {
+    const site* s;
+    internal::get_adr(s, *this);
+    return *s;
+  }
+
+  template <typename P>
+  inline
+  int
+  p_array_psite<P>::index() const
+  {
+    return i_;
+  }
+
+  template <typename P>
+  inline
+  int&
+  p_array_psite<P>::index()
+  {
+    return i_;
+  }
+
+  template <typename P>
+  inline
+  const p_array<P>*
+  p_array_psite<P>::target() const
+  {
+    return arr_;
+  }
+
+  template <typename P>
+  inline
+  void
+  p_array_psite<P>::change_target(const p_array<P>& arr)
+  {
+    arr_ = & arr;
+  }
+
+  template <typename P>
+  inline
+  void
+  p_array_psite<P>::print() const
+  {
+    std::cout << i_ << "-th site of " << arr_ << " => site " << to_site() << std::endl;
+  }
+
+  template <typename P>
+  inline
+  const P&
+  p_array_psite<P>::unproxy() const
   {
     mln_precondition(arr_ != 0);
     return (*arr_)[i_];
Index: mln/core/concept/site_iterator.hh
--- mln/core/concept/site_iterator.hh	(revision 1971)
+++ mln/core/concept/site_iterator.hh	(working copy)
@@ -71,18 +71,6 @@
      */ 
     void next(); // final
 
-    using Site_Proxy<E>::site;
-
-    /*! \brief Go to the next element.
-     *
-     * \warning This is a final method; iterator classes should not
-     * re-defined this method.  The actual "next" operation has to be
-     * defined through the \em next_ method.
-     *
-     * \pre The iterator is valid.
-     */ 
-    operator site() const;
-
   protected:
     Site_Iterator();
   };
@@ -101,14 +89,6 @@
 
   template <typename E>
   inline
-  Site_Iterator<E>::operator site() const
-  {
-    mln_precondition(exact(this)->is_valid());
-    return exact(this)->to_site();
-  }
-
-  template <typename E>
-  inline
   Site_Iterator<E>::Site_Iterator()
   {
     bool (E::*m1)() const = & E::is_valid;
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    23 May '08
                    
                        https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Add the basics for pseudo sites; test on p_array.
	* tests/core/p_array.cc: New.
	* doc/technical: New.
	* doc/technical/designs: New.
	* doc/technical/designs/site_psite_piter: New.
	* doc/technical/designs/site_psite_piter/README: New.
	* mln/core/macros.hh (mln_subject, mln_subject_): New.
	* mln/core/point.hh: New comment.
	* mln/core/internal/point_set_base.hh: .
	* mln/core/internal/pseudo_site_base.hh: New.
	* mln/core/p_array_bb.hh: New.
	* mln/core/point2d.hh
	(site_const_impl, site_mutable_impl): New specialization.
	* mln/core/p_array.hh (p_array_psite): New.
	(npoints): Rename as...
	(nsites): ...this.
	(bbox, bb_, bb_needs_update_, hook_): Remove.
	(has): Update sig with the new psite type; adapt body.
	* mln/core/concept/proxy.hh: New.
	* mln/core/concept/point_set.hh: .
	* mln/core/concept/site_proxy.hh: New.
	* mln/core/concept/pseudo_site.hh: New.
	* mln/core/concept/site_iterator.hh: New.
 doc/technical/designs/site_psite_piter/README |   39 ++++
 mln/core/concept/point_set.hh                 |    3 
 mln/core/concept/proxy.hh                     |  233 ++++++++++++++++++++++++++
 mln/core/concept/pseudo_site.hh               |   86 +++++++++
 mln/core/concept/site_iterator.hh             |   54 +++---
 mln/core/concept/site_proxy.hh                |  168 ++++++++++++++++++
 mln/core/internal/point_set_base.hh           |    8 
 mln/core/internal/pseudo_site_base.hh         |   82 +++++++++
 mln/core/macros.hh                            |    6 
 mln/core/p_array.hh                           |  213 ++++++++++++++++-------
 mln/core/point.hh                             |    2 
 mln/core/point2d.hh                           |   51 +++++
 tests/core/p_array.cc                         |   65 +++++++
 13 files changed, 920 insertions(+), 90 deletions(-)
Index: tests/core/p_array.cc
--- tests/core/p_array.cc	(revision 0)
+++ tests/core/p_array.cc	(revision 0)
@@ -0,0 +1,65 @@
+// Copyright (C) 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/core/p_array.cc
+ *
+ * \brief Tests on mln::p_array.
+ */
+
+#include <iterator>
+
+#include <mln/core/point2d.hh>
+#include <mln/core/p_array.hh>
+
+
+
+int main()
+{
+  using namespace mln;
+
+  typedef p_array<point2d> Arr;
+
+  Arr pa;
+  pa
+    .append(make::point2d(6, 9))
+    .append(make::point2d(4, 2))
+    .append(make::point2d(4, 2))
+    .append(make::point2d(5, 1));
+  mln_assertion(pa.nsites() == 4);
+
+  mlc_equal( mln_psite_(Arr)::site, point2d )::check();
+
+  mln_psite_(Arr) p(pa, 0);
+  std::cout << p.to_site() << ' '
+ 	    << p.row()     << ' '
+	    << point2d(p)  << ' '
+	    << std::endl;
+
+  std::copy(pa.vect().begin(), pa.vect().end(),
+	    std::ostream_iterator<point2d>(std::cout, " "));
+  std::cout << std::endl;
+}
Index: doc/technical/designs/site_psite_piter/README
--- doc/technical/designs/site_psite_piter/README	(revision 0)
+++ doc/technical/designs/site_psite_piter/README	(revision 0)
@@ -0,0 +1,39 @@
+
+	-*- outline -*-
+
+* design
+
+          Object
+             ^ 
+             |
+           Proxy
+            + subject
+             ^ 
+             |
+        Site_Proxy< Site, Exact >
+         + site : type = Site
+         + op site   
+             ^       
+       ______|______  
+     |              |
+Pseudo_Site    Site_Iterator
+     ^              ^
+     |              |
+
+
+
+       internal::psite_impl< Site, Exact >
+         // to be specialized...
+                   ^
+    ______________/
+   /
+pseudo_site_base_< Site, Exact >
+
+
+
+            internal::piter_impl
+                    + op psite, iff psite != site
+                      ^
+  ___________________/
+ /
+
Index: mln/core/macros.hh
--- mln/core/macros.hh	(revision 1970)
+++ mln/core/macros.hh	(working copy)
@@ -251,6 +251,12 @@
 # define mln_site_(T)              T::site
 /// \}
 
+/// Shortcuts to access the subject type associated to T.
+/// \{
+# define mln_subject(T)      typename T::subject
+# define mln_subject_(T)              T::subject
+/// \}
+
 
 // v
 
Index: mln/core/point.hh
--- mln/core/point.hh	(revision 1970)
+++ mln/core/point.hh	(working copy)
@@ -59,6 +59,8 @@
   namespace internal
   {
 
+    // Helper point_to_.
+
     template <typename M, typename C>
     struct point_to_
     {
Index: mln/core/internal/point_set_base.hh
--- mln/core/internal/point_set_base.hh	(revision 1970)
+++ mln/core/internal/point_set_base.hh	(working copy)
@@ -34,7 +34,10 @@
  */
 
 # include <mln/core/concept/point_set.hh>
+# include <mln/core/concept/site_proxy.hh>
 # include <mln/core/grids.hh>
+# include <mln/metal/is_a.hh>
+# include <mln/metal/if.hh>
 
 
 namespace mln
@@ -43,17 +46,16 @@
   namespace internal
   {
 
+
     /*! \internal A base class for site set classes.
      * \p P is a psite type.
      */
     template <typename P, typename E>
     struct site_set_base_ : public Site_Set<E>
     {
-      /// PSite associated type.
-      typedef P psite;
 
       /// Site associated type.
-      typedef mln_site(P) site;
+      typedef typename internal::site_from<P>::ret site;
 
     protected:
       site_set_base_();
Index: mln/core/internal/pseudo_site_base.hh
--- mln/core/internal/pseudo_site_base.hh	(revision 0)
+++ mln/core/internal/pseudo_site_base.hh	(revision 0)
@@ -0,0 +1,82 @@
+// Copyright (C) 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_INTERNAL_PSEUDO_SITE_BASE_HH
+# define MLN_CORE_INTERNAL_PSEUDO_SITE_BASE_HH
+
+/*! \file mln/core/internal/pseudo_site_base.hh
+ *
+ * \brief Base class to factor code for pseudo site classes.
+ */
+
+# include <mln/core/concept/pseudo_site.hh>
+
+
+namespace mln
+{
+
+  namespace internal
+  {
+
+    /*! \internal A base class for pseudo sites.
+     *
+     * Parameter \c P is FIXME: a point site type.
+     */
+    template <bool is_mutable, typename P, typename E>
+    struct pseudo_site_base_ : Pseudo_Site<E>,
+
+                               proxy_impl<P, E>,
+
+                               site_impl< is_mutable,
+					  typename site_from<P>::ret,
+					  E >
+    {
+
+      // The associated site type.
+      typedef typename internal::site_from<P>::ret site;
+
+    protected:
+      pseudo_site_base_();
+    };
+
+
+#ifndef MLN_INCLUDE_ONLY
+
+    template <bool is_mutable, typename P, typename E>
+    inline
+    pseudo_site_base_<is_mutable, P, E>::pseudo_site_base_()
+    {
+    }
+
+#endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace internal
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_INTERNAL_PSEUDO_SITE_BASE_HH
Index: mln/core/point2d.hh
--- mln/core/point2d.hh	(revision 1970)
+++ mln/core/point2d.hh	(working copy)
@@ -35,11 +35,62 @@
  */
 
 # include <mln/core/point.hh>
+# include <mln/core/concept/site_proxy.hh> // For site_const_impl and site_mutable_impl.
+# include <mln/core/internal/force_exact.hh>
 
 
 namespace mln
 {
 
+  namespace internal
+  {
+
+    // Specialization.
+
+    template <typename C, typename E>
+    struct site_const_impl< point_<grid::square, C>, E >
+    {
+      // Either unproxy() or to_site() can be used below.  In the
+      // former case, the unproxied features ind() because it is a
+      // point_ or another proxy to a point_.
+      C row() const
+      {
+	return internal::force_exact<const E>(*this).to_site().row();
+      }
+      C col() const
+      {
+	return internal::force_exact<const E>(*this).to_site().col();
+      }
+    };
+
+
+    // Specialization for point_<M,C>.
+
+    template <typename C, typename E>
+    struct site_mutable_impl< point_<grid::square, C>, E > :
+           site_const_impl  < point_<grid::square, C>, E >
+    {
+    private:
+      typedef site_const_impl< point_<grid::square, C>, E > super;
+    public:
+
+      using super::row;
+      using super::col;
+
+      C& row()
+      {
+	return internal::force_exact<E>(*this).to_site().row();
+      }
+      C& col()
+      {
+	return internal::force_exact<E>(*this).to_site().col();
+      }
+    };
+
+  } // end of namespace mln::internal
+
+
+
   /*! \brief Type alias for a point defined on the 2D square grid with
    * integer coordinates.
    */
Index: mln/core/p_array.hh
--- mln/core/p_array.hh	(revision 1970)
+++ mln/core/p_array.hh	(working copy)
@@ -36,6 +36,7 @@
 # include <vector>
 
 # include <mln/core/internal/point_set_base.hh>
+# include <mln/core/internal/pseudo_site_base.hh>
 # include <mln/accu/bbox.hh>
 
 
@@ -43,28 +44,116 @@
 {
 
   // Fwd decls.
+  template <typename P> class p_array;
   template <typename P> struct p_array_fwd_piter_;
   template <typename P> struct p_array_bkd_piter_;
 
 
-  /*! \brief Point set class based on std::vector.
-   *
-   * This is a multi-set of points.
-   *
-   * \warning We have some troubles with point set comparison based on
-   * a call to npoints().  FIXME: Explain!
+  // HOT...
+
+  template <typename P>
+  class p_array_psite : public internal::pseudo_site_base_< true, // Mutable.
+							    P,
+							    p_array_psite<P> >
+  {
+    typedef p_array_psite<P> self;
+    typedef internal::pseudo_site_base_<true, P, self> super;
+
+  public:
+
+    // As a Proxy:
+
+    typedef P subject;
+    typedef const P& q_subject;
+    q_subject unproxy() const;
+    P& unproxy();
+
+    // As a Site_Proxy:
+
+    typedef typename super::site site;
+
+    const site& to_site() const
+    {
+      const site* s;
+      internal::get_adr(s, *this);
+      return *s;
+    }
+
+    site& to_site()
+    {
+      site* s;
+      internal::get_adr(s, *this);
+      return *s;
+    }
+
+    // As Itself.
+
+    p_array_psite()
+      : arr_(0),
+	i_(0)
+    {
+    }
+
+    p_array_psite(p_array<P>& arr, unsigned i)
+      : arr_(&arr),
+	i_(int(i))
+    {
+    }
+
+    int index() const
+    {
+      return i_;
+    }
+
+    const p_array<P>* target() const
+    {
+      return arr_;
+    }
+
+    void print() const
+    {
+      std::cout << i_ << "-th site of " << arr_ << " => site " << to_site() << std::endl;
+    }
+
+    p_array<P>* arr_; // FIXME: Or const!
+    int i_;
+  };
+
+
+
+
+  namespace trait
+  {
+
+    template <typename P>
+    struct site_set_< p_array<P> >
+    {
+      typedef trait::site_set::nsites::known   nsites;
+      typedef trait::site_set::bbox::unknown   bbox;
+      typedef trait::site_set::contents::free  contents;
+      typedef trait::site_set::arity::multiple arity;
+    };
+
+  } // end of namespace trait
+
+
+
+
+  /*! \brief Site set class based on std::vector.
    *
-   * \todo Make it work with P being a Point_Site.
+   * This is a multi-set of sites.
    */
   template <typename P>
   class p_array : public internal::site_set_base_< P, p_array<P> >
   {
+    typedef internal::site_set_base_< P, p_array<P> > super;
   public:
+
     /// The associated psite type.
-    typedef P psite;
+    typedef p_array_psite<P> psite;
 
-    /// The associated point type.
-    typedef mln_point(P) point;
+    /// The associated site type.
+    typedef typename super::site site;
 
     /// Forward Point_Iterator associated type.
     typedef p_array_fwd_piter_<P> fwd_piter;
@@ -81,14 +170,13 @@
     /// Reserve \p n cells.
     void reserve(std::size_t n);
 
-    /// Test is \p p belongs to this point set.
+    /// Test is \p p belongs to this site set.
     bool has(const psite& p) const;
 
-    /// Give the number of points.
-    std::size_t npoints() const;
+    // FIXME: Add an overload "has(index)".
 
-    /// Give the exact bounding box.
-    const box_<point>& bbox() const;
+    /// Give the number of sites.
+    std::size_t nsites() const;
 
     /// Append a point \p p.
     p_array<P>& append(const P& p);
@@ -102,31 +190,28 @@
     /// Return the corresponding std::vector of points.
     const std::vector<P>& vect() const;
 
-    /// Return the \p i-th point.
+    /// Return the \p i-th site (constant).
     const P& operator[](unsigned i) const;
 
-    /// Hook to data.
-    std::vector<P>& hook_();
+    /// Return the \p i-th site (mutable).
+    P& operator[](unsigned i);
 
   protected:
 
     std::vector<P> vect_;
-    mutable accu::bbox<point> bb_;
-    mutable bool bb_needs_update_;
-
-    void update_bb_() const;
-    // FIXME: Add invariant  bb_.is_valid() <=> npoints() != 0
   };
 
 
 
 # ifndef MLN_INCLUDE_ONLY
 
+
+  // p_array<P>
+
   template <typename P>
   inline
   p_array<P>::p_array()
   {
-    bb_needs_update_ = false;
   }
 
   template <typename P>
@@ -134,7 +219,6 @@
   p_array<P>::p_array(const std::vector<P>& vect)
     : vect_(vect)
   {
-    bb_needs_update_ = true;
   }
 
   template <typename P>
@@ -147,61 +231,31 @@
 
   template <typename P>
   inline
-  std::vector<P>&
-  p_array<P>::hook_()
-  {
-    return vect_;
-  }
-
-  template <typename P>
-  inline
-  void
-  p_array<P>::update_bb_() const
-  {
-    bb_.init();
-    for (unsigned i = 0; i < vect_.size(); ++i)
-      bb_.take(vect_[i]);
-    bb_needs_update_ = false;
-  }
-
-  template <typename P>
-  inline
   bool
-  p_array<P>::has(const P& p) const
+  p_array<P>::has(const psite& p) const
   {
-    for (unsigned i = 0; i < vect_.size(); ++i)
-      if (vect_[i] == p)
-	return true;
+    mln_precondition(p.target() == this); // FIXME: Refine.
+    if (p.index() < 0 || p.index() >= vect_.size())
     return false;
+    site s_ = (*this)[p.index()];
+    mln_invariant(p.to_site() == s_);
+    return true;
   }
 
   template <typename P>
   inline
   std::size_t
-  p_array<P>::npoints() const
+  p_array<P>::nsites() const
   {
     return vect_.size();
   }
 
   template <typename P>
   inline
-  const box_<mln_point(P)>&
-  p_array<P>::bbox() const
-  {
-    mln_precondition(npoints() != 0);
-    if (bb_needs_update_)
-      update_bb_();
-    return bb_.to_result();
-  }
-
-  template <typename P>
-  inline
   p_array<P>&
   p_array<P>::append(const P& p)
   {
     vect_.push_back(p);
-    if (! bb_needs_update_)
-      bb_needs_update_ = true;
     return *this;
   }
 
@@ -212,8 +266,6 @@
   {
     vect_.insert(vect_.end(),
 		 other.vect().begin(), other.vect().end());
-    if (! bb_needs_update_)
-      bb_needs_update_ = true;
     return *this;
   }
 
@@ -223,7 +275,6 @@
   p_array<P>::clear()
   {
     vect_.clear();
-    bb_needs_update_ = false;
   }
 
   template <typename P>
@@ -239,10 +290,40 @@
   const P&
   p_array<P>::operator[](unsigned i) const
   {
-    mln_precondition(i < npoints());
+    mln_precondition(i < nsites());
     return vect_[i];
   }
 
+  template <typename P>
+  inline
+  P&
+  p_array<P>::operator[](unsigned i)
+  {
+    mln_precondition(i < nsites());
+    return vect_[i];
+  }
+
+
+  // p_array_psite<P>
+
+  template <typename P>
+  inline
+  const P&
+  p_array_psite<P>::unproxy() const
+  {
+    mln_precondition(arr_ != 0);
+    return (*arr_)[i_];
+  }
+
+  template <typename P>
+  inline
+  P&
+  p_array_psite<P>::unproxy()
+  {
+    mln_precondition(arr_ != 0);
+    return (*arr_)[i_];
+  }
+
 # endif // ! MLN_INCLUDE_ONLY
 
 } // end of namespace mln
Index: mln/core/concept/proxy.hh
--- mln/core/concept/proxy.hh	(revision 0)
+++ mln/core/concept/proxy.hh	(revision 0)
@@ -0,0 +1,233 @@
+// Copyright (C) 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_CONCEPT_PROXY_HH
+# define MLN_CORE_CONCEPT_PROXY_HH
+
+/*! \file mln/core/concept/proxy.hh
+ *
+ * \brief Definition of the concept of mln::Proxy.
+ */
+
+# include <mln/core/concept/object.hh>
+# include <mln/trait/all.hh>
+
+
+
+namespace mln
+{
+
+  // Fwd decls.
+  template <typename E> struct Proxy;
+
+
+  /*
+    FIXME: Re-activate.
+
+  namespace trait
+  {
+
+    template < typename Op, typename P1, typename P2 >
+    struct set_binary_< Op, mln::Proxy, P1, mln::Proxy, P2 >
+    {
+      typedef mln_trait_binary(Op, mln_subject(P1), mln_subject(P2)) ret;
+    };
+
+    template < typename Op, typename P, typename O >
+    struct set_binary_< Op, mln::Proxy, P, mln::Object, O >
+    {
+      typedef mln_trait_binary(Op, mln_subject(P), O) ret;
+    };
+
+    template < typename Op, typename E, typename P >
+    struct set_binary_< Op, mln::Object, E, mln::Proxy, P  >
+    {
+      typedef mln_trait_binary(Op, O, mln_subject(P)) ret;
+    };
+
+    template < typename Op, typename P >
+    struct set_binary_< Op, mln::Proxy, P >
+    {
+      typedef mln_trait_unary(Op, mln_subject(P)) ret;
+    };
+
+  } // end of namespace mln::trait
+
+  */
+
+
+
+  /// Proxy category flag type.
+  template <>
+  struct Proxy<void>
+  {
+    typedef Object<void> super;
+  };
+
+
+  /*! \brief Base class for implementation classes of the notion of
+   *  "proxy".
+   */
+  template <typename E>
+  struct Proxy : public Object<E>
+  {
+    typedef Proxy<void> category;
+
+    /*
+      typedef subject;
+      typedef q_subject;
+      q_subject unproxy() const;
+
+      // FIXME:
+      // return "const subject&"?
+      // overload with not-const method?
+      // add op subject() const?
+    */
+  protected:
+    Proxy();
+  };
+
+
+  namespace internal
+  {
+
+    // External way of getting an address of an object from/through a
+    // proxy.  This is a recursive implementation since we can have a
+    // proxy of proxy, etc.
+
+    // Case 1: Not found so unproxy.
+
+    template <typename T, typename P>
+    void get_adr(const T *& ptr, const Proxy<P>& obj)
+    {
+      get_adr(ptr, exact(obj).unproxy());
+    }
+
+    template <typename T, typename P>
+    void get_adr(      T *& ptr,       Proxy<P>& obj)
+    {
+      get_adr(ptr, exact(obj).unproxy());
+    }
+
+    // Case 2: Found.  (Note that T can also be a Proxy.)
+
+    template <typename T>
+    void get_adr(const T *& ptr, const Object<T>& obj)
+    {
+      ptr = & exact(obj);
+    }
+
+    template <typename T>
+    void get_adr(      T *& ptr,       Object<T>& obj)
+    {
+      ptr = & exact(obj);
+    }
+
+    // Case 3: Fail to found!
+
+    template <typename T, typename O>
+    void get_adr(const T *& ptr, const Object<O>& obj);
+
+    template <typename T, typename O>
+    void get_adr(      T *& ptr,       Object<O>& obj)
+    {
+      return 0;
+    }
+
+
+    // A proxy should convert towards its subject.  And, if we have a
+    // proxy of proxy, it should also convert towards its subject of
+    // subject, and so on.  It leads to a recursive implementation
+    // where conversions are automatically obtained through
+    // inheritance.
+    //
+    // E is a Proxy type; Subject is its subject type.
+
+    template <typename Subject, typename E> struct proxy_impl;
+
+    template <typename Subject, typename E, bool rec = true>
+    struct helper_proxy_impl : proxy_impl< mln_subject(Subject), E > // Rec.
+    {};
+
+    template <typename Subject, typename E>
+    struct helper_proxy_impl< Subject, E, false > // Stop rec.
+    {};
+
+    template <typename Subject, typename E>
+    struct proxy_impl : helper_proxy_impl< Subject, E,
+					   mlc_is_a(Subject, Proxy)::value >
+    {
+      operator Subject() const
+      {
+	const Subject* adr;
+	get_adr(adr, mln::internal::force_exact<const E>(*this));
+	return *adr;
+      }
+    };
+
+
+  } // end of namespace mln::internal
+
+
+  // FIXME:...
+
+//   template <typename L, typename R>
+//   bool operator==(const Proxy<L>& lhs, const Proxy<R>& rhs);
+
+  template <typename P>
+  std::ostream& operator<<(std::ostream& ostr, const Proxy<P>& p);
+
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+  template <typename E>
+  inline
+  Proxy<E>::Proxy()
+  {
+    typedef mln_subject(E) subject;
+    typedef typename E::q_subject q_subject;
+
+    q_subject (E::*m)() const = & E::unproxy;
+    m = 0;
+  }
+
+  template <typename P>
+  std::ostream& operator<<(std::ostream& ostr, const Proxy<P>& p)
+  {
+    return ostr << exact(p).unproxy();
+  }
+
+  // FIXME: Code operators...
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_CONCEPT_PROXY_HH
Index: mln/core/concept/point_set.hh
--- mln/core/concept/point_set.hh	(revision 1970)
+++ mln/core/concept/point_set.hh	(working copy)
@@ -39,6 +39,7 @@
 # include <mln/core/concept/point_iterator.hh>
 # include <mln/trait/site_sets.hh>
 # include <mln/metal/not_equal.hh>
+# include <mln/metal/is_a.hh>
 
 
 namespace mln
@@ -147,6 +148,8 @@
     mlc_not_equal( mln_trait_site_set_bbox(E),     mln::trait::undef )::check();
     mlc_not_equal( mln_trait_site_set_contents(E), mln::trait::undef )::check();
     mlc_not_equal( mln_trait_site_set_arity(E),    mln::trait::undef )::check();
+    // FIXME: also test something like
+    //        mlc_is_a( mln_trait_site_set_nsites(E),   mln::trait::site_set::nsites::any   )::check();
 
     // Check associated types.
     typedef mln_site(E)  site;
Index: mln/core/concept/site_proxy.hh
--- mln/core/concept/site_proxy.hh	(revision 0)
+++ mln/core/concept/site_proxy.hh	(revision 0)
@@ -0,0 +1,168 @@
+// Copyright (C) 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_CONCEPT_SITE_PROXY_HH
+# define MLN_CORE_CONCEPT_SITE_PROXY_HH
+
+/*! \file mln/core/concept/site_proxy.hh
+ *
+ * \brief Definition of the concept of mln::Site_Proxy.
+ */
+
+# include <mln/core/concept/proxy.hh>
+# include <mln/metal/is_a.hh>
+
+
+
+namespace mln
+{
+
+
+  // Fwd decl.
+  template <typename E> struct Site_Proxy;
+
+
+
+  namespace internal
+  {
+    // Every "Site_Proxy" class should derive from site_impl.  The
+    // couple of classes below are provided to be specialized so that
+    // an effective implementation (with the interface of the
+    // targetted site) can equip site proxy classes.
+
+    template <typename Site, typename E>
+    struct site_const_impl
+    {
+      // Default is none.
+    };
+
+    template <typename Site, typename E>
+    struct site_mutable_impl
+    {
+      // Default is none.
+    };
+
+    template <bool is_mutable, typename Site, typename E>
+    struct site_impl; // Is a selector w.r.t. to mutability.
+
+    template <typename Site, typename E>
+    struct site_impl</* is_mutable = */ true, Site, E> : site_mutable_impl<Site, E>
+    {
+    };
+
+    template <typename Site, typename E>
+    struct site_impl</* is_mutable = */ false, Site, E> : site_const_impl<Site, E>
+    {
+    };
+
+
+
+    // Meta-routine to get the site type from either a site or a site
+    // proxy.
+
+    template <typename P> struct site_from;
+
+    template <typename P, bool is_proxy = true>
+    struct helper_site_from
+    {
+      typedef typename P::subject P_;
+      typedef typename site_from<P_>::ret ret;
+    };
+
+    template <typename P>
+    struct helper_site_from<P, false>
+    {
+      typedef P ret;
+    };
+
+    template <typename P>
+    struct site_from
+    {
+      enum { is_proxy = mlc_is_a(P, Site_Proxy)::value };
+      typedef typename helper_site_from< P, is_proxy >::ret ret;
+    };
+
+
+
+  } // end of namespace internal
+
+
+
+
+  /// Site_Proxy category flag type.
+  template <>
+  struct Site_Proxy<void>
+  {
+    typedef Proxy<void> super;
+  };
+
+
+  /*! \brief Base class for implementation classes of the notion of
+   *  "site proxy".
+   *
+   * FIXME: Explain...
+   */
+  template <typename E>
+  struct Site_Proxy : public Proxy<E>
+  {
+    typedef Site_Proxy<void> category;
+
+    /*
+    typedef site;
+
+    const site& to_site() const;
+    operator site() const;
+
+    FIXME: Add if possible a mutable version of to_site().
+    FIXME: Or (?) just remove this method (!)
+    */
+
+  protected:
+    Site_Proxy();
+  };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+  template <typename E>
+  Site_Proxy<E>::Site_Proxy()
+  {
+    typedef mln_site(E) site;
+
+    const site& (E::*m1)() const = & E::to_site;
+    m1 = 0;
+
+    site (E::*m2)() const = & E::operator site;
+    m2 = 0;
+  }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_CONCEPT_SITE_PROXY_HH
Index: mln/core/concept/pseudo_site.hh
--- mln/core/concept/pseudo_site.hh	(revision 0)
+++ mln/core/concept/pseudo_site.hh	(revision 0)
@@ -0,0 +1,86 @@
+// Copyright (C) 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_CONCEPT_PSEUDO_SITE_HH
+# define MLN_CORE_CONCEPT_PSEUDO_SITE_HH
+
+/*! \file mln/core/concept/pseudo_site.hh
+ *
+ * \brief Definition of the concept of mln::Pseudo_Site.
+ */
+
+# include <mln/core/concept/site_proxy.hh>
+# include <mln/metal/is_a.hh>
+
+
+
+namespace mln
+{
+
+  // Fwd decl.
+  template <typename E> struct Pseudo_Site;
+
+
+
+  /// Pseudo_Site category flag type.
+  template <>
+  struct Pseudo_Site<void>
+  {
+    typedef Site_Proxy<void> super;
+  };
+
+
+  /*! \brief Base class for implementation classes of the notion of
+   *  "pseudo site".
+   *
+   * FIXME: Explain...
+   */
+  template <typename E>
+  struct Pseudo_Site : public Site_Proxy<E>
+  {
+    typedef Pseudo_Site<void> category;
+
+
+  protected:
+    Pseudo_Site();
+  };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+  template <typename E>
+  Pseudo_Site<E>::Pseudo_Site()
+  {
+    // FIXME
+  }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_CONCEPT_PSEUDO_SITE_HH
Index: mln/core/concept/site_iterator.hh
--- mln/core/concept/site_iterator.hh	(revision 1951)
+++ mln/core/concept/site_iterator.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
@@ -25,17 +25,17 @@
 // reasons why the executable file might be covered by the GNU General
 // Public License.
 
-#ifndef MLN_CORE_CONCEPT_POINT_ITERATOR_HH
-# define MLN_CORE_CONCEPT_POINT_ITERATOR_HH
+#ifndef MLN_CORE_CONCEPT_SITE_ITERATOR_HH
+# define MLN_CORE_CONCEPT_SITE_ITERATOR_HH
 
-/*! \file mln/core/concept/point_iterator.hh
+/*! \file mln/core/concept/site_iterator.hh
  *
- * \brief Definition of the concept of mln::Point_Iterator.
+ * \brief Definition of the concept of mln::Site_Iterator.
  *
- * \todo Fix mln/core/concept/doc/point_iterator.hh
+ * \todo Fix mln/core/concept/doc/site_iterator.hh
  */
 
-# include <mln/core/concept/point_site.hh>
+# include <mln/core/concept/site_proxy.hh>
 # include <mln/core/concept/iterator.hh> // To fetch the macros.
 
 
@@ -48,19 +48,17 @@
    * An iterator on points is an iterator that browse over a set of
    * points.
    *
-   * \see mln::doc::Point_Iterator for a complete documentation of this class
+   * \see mln::doc::Site_Iterator for a complete documentation of this class
    * contents.
    */
   template <typename E>
-  struct Point_Iterator : public Point_Site<E>
+  struct Site_Iterator : public Site_Proxy<E>
   {
     /*
-      typedef psite;
       bool is_valid() const;
       void invalidate();
       void start();
       void next_();
-      operator psite() const;
     */
 
     /*! \brief Go to the next element.
@@ -73,8 +71,20 @@
      */ 
     void next(); // final
 
+    using Site_Proxy<E>::site;
+
+    /*! \brief Go to the next element.
+     *
+     * \warning This is a final method; iterator classes should not
+     * re-defined this method.  The actual "next" operation has to be
+     * defined through the \em next_ method.
+     *
+     * \pre The iterator is valid.
+     */ 
+    operator site() const;
+
   protected:
-    Point_Iterator();
+    Site_Iterator();
   };
 
 
@@ -83,22 +93,24 @@
 
   template <typename E>
   void
-  Point_Iterator<E>::next() // final
+  Site_Iterator<E>::next() // final
   {
-    assert(exact(this)->is_valid());
+    mln_precondition(exact(this)->is_valid());
     exact(this)->next_();
   }
 
   template <typename E>
   inline
-  Point_Iterator<E>::Point_Iterator()
+  Site_Iterator<E>::operator site() const
   {
-    typedef mln_psite(E) psite;
-    mln::metal::is_a<psite, Point_Site>::check();
-
-    psite (E::*m)() const = & E::operator psite;
-    m = 0;
+    mln_precondition(exact(this)->is_valid());
+    return exact(this)->to_site();
+  }
 
+  template <typename E>
+  inline
+  Site_Iterator<E>::Site_Iterator()
+  {
     bool (E::*m1)() const = & E::is_valid;
     m1 = 0;
     void (E::*m2)() = & E::invalidate;
@@ -114,4 +126,4 @@
 } // end of namespace mln
 
 
-#endif // ! MLN_CORE_CONCEPT_POINT_ITERATOR_HH
+#endif // ! MLN_CORE_CONCEPT_SITE_ITERATOR_HH
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from  Roland Levillain  <roland(a)lrde.epita.fr>
	Add a sandbox directory for Aroune Aroumougame.
	* aroumougame/: New directory.
 0 files changed
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        
Attention à ne pas abuser de la commande `svn ignore' !! Vcs ne  
regarde pas si le fichier à ignorer est déjà présent dans les  
propriété (c'est un truc qu'il faudrait corriger) ; du coup, j'ai  
trouvé jusqu'à quatre occurrences de `.deps' dans certaines propriétés  
svn:ignore !
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
Property changes on: tests/histo
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/debug
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/core
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/math
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
    + Makefile.in
Makefile
.deps
Property changes on: tests/neighb
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/draw
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/metal/make
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
    + Makefile.in
Makefile
.deps
Property changes on: tests/level/approx
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/level/naive
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/level
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/arith
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/linear
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/accu
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/value/concept
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
    + Makefile.in
Makefile
.deps
Property changes on: tests/value/builtin
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/value
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/border
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/test
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/pw
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/geom
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/fun/i2v
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
    + Makefile.in
Makefile
.deps
Property changes on: tests/fun/x2x
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/fun/vv2v
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/fun/p2b
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
    + Makefile.in
Makefile
.deps
Property changes on: tests/fun/p2v
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
    + Makefile.in
Makefile
.deps
Property changes on: tests/fun/v2v
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/binarization
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/set
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/algebra
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/win
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/trace
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
    + Makefile.in
Makefile
.deps
Property changes on: tests/morpho
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/display
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/io/pfm
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
    + Makefile.in
Makefile
.deps
Property changes on: tests/io/pgm
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/io/fits
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/io/pnm
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
    + Makefile.in
Makefile
.deps
Property changes on: tests/io/ppm
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/io/pbm
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/logical
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/norm
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/canvas/morpho
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
    + Makefile.in
Makefile
.deps
Property changes on: tests/canvas/browsing
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/canvas
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/labeling
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
    + Makefile.in
Makefile
.deps
Property changes on: tests/util
___________________________________________________________________
Name: svn:ignore
    - Makefile.in
Makefile
.deps
.deps
.deps
    + Makefile.in
Makefile
.deps
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from  Alexandre Abraham  <abraham(a)lrde.epita.fr>
	Add a new Watershed algorithm.
	* abraham/tests/morpho/test_component_tree.cc: New.
	* abraham/tests/morpho/images: New (test images).
	* abraham/tests/morpho/images/+test_watershed.pgm: New.
	* abraham/tests/morpho/images/result_m_watershed.pgm: New.
	* abraham/tests/morpho/images/test_component_tree.pgm: New.
	* abraham/tests/morpho/images/test_2.pgm: New.
	* abraham/tests/morpho/images/test_3.pgm: New.
	* abraham/tests/morpho/images/test_4.pgm: New.
	* abraham/tests/morpho/images/result_topo_watershed.pgm: New.
	* abraham/tests/morpho/images/test_watershed.pgm: New.
	* abraham/tests/morpho/images/+irm6.pgm: New.
	* abraham/tests/morpho/images/test_component_mapping.pgm: New.
	* abraham/tests/morpho/test_watershed.cc: New.
	* abraham/tests/morpho/test_watershed_topo.cc: New.
	* abraham/tests/morpho/ref/src/lib/lwshedtopo.c:
	uncomment specific pieces of code to show debug.
	* abraham/tests/morpho/Makefile: Fix.
	* abraham/tests/io/tikz/Makefile: Fix.
	* abraham/mln/morpho/basic_najman.hh:
	Add the new watershed from Pink library.
	* abraham/mln/morpho/test_component_tree.cc: Remove.
	* abraham/mln/morpho/test_watershed.cc: Remove.
	* abraham/mln/morpho/test_watershed_topo.cc: Remove.
	* abraham/mln/morpho/Makefile: Remove.
	* abraham/mln/io/tikz/save.hh:
	Add the ability to tag values on images.
	* abraham/img/dots.pgm: New.
 mln/io/tikz/save.hh                   |   13 -
 mln/morpho/Makefile                   |   22 -
 mln/morpho/basic_najman.hh            |  396 +++++++++++++++++++++++++++++-----
 mln/morpho/test_component_tree.cc     |  230 -------------------
 mln/morpho/test_watershed.cc          |  103 --------
 mln/morpho/test_watershed_topo.cc     |   60 -----
 tests/io/tikz/Makefile                |    1 
 tests/morpho/Makefile                 |    1 
 tests/morpho/ref/src/lib/lwshedtopo.c |  140 ++++++------
 tests/morpho/test_component_tree.cc   |    2 
 tests/morpho/test_watershed.cc        |    2 
 tests/morpho/test_watershed_topo.cc   |    9 
 12 files changed, 424 insertions(+), 555 deletions(-)
Index: abraham/tests/morpho/test_component_tree.cc
--- abraham/tests/morpho/test_component_tree.cc	(revision 1935)
+++ abraham/tests/morpho/test_component_tree.cc	(working copy)
@@ -8,7 +8,7 @@
 #include <mln/io/pgm/load.hh>
 #include <mln/io/pgm/save.hh>
 
-#include "basic_najman.hh"
+#include <mln/morpho/basic_najman.hh>
 #include <string>
 #include <iostream>
 
Index: abraham/tests/morpho/images/+test_watershed.pgm
Cannot display: file marked as a binary type.
svn:mime-type = abraham/tests/morpho/images/+irm6.pgm
Property changes on: abraham/tests/morpho/images/+test_watershed.pgm
___________________________________________________________________
Name: svn:mime-type
   + abraham/tests/morpho/images/+irm6.pgm
Index: abraham/tests/morpho/images/result_m_watershed.pgm
Cannot display: file marked as a binary type.
svn:mime-type = abraham/tests/morpho/images/+irm6.pgm
Property changes on: abraham/tests/morpho/images/result_m_watershed.pgm
___________________________________________________________________
Name: svn:mime-type
   + abraham/tests/morpho/images/+irm6.pgm
Index: abraham/tests/morpho/images/test_component_tree.pgm
Cannot display: file marked as a binary type.
svn:mime-type = abraham/tests/morpho/images/+irm6.pgm
Property changes on: abraham/tests/morpho/images/test_component_tree.pgm
___________________________________________________________________
Name: svn:mime-type
   + abraham/tests/morpho/images/+irm6.pgm
Index: abraham/tests/morpho/images/test_2.pgm
Cannot display: file marked as a binary type.
svn:mime-type = abraham/tests/morpho/images/+irm6.pgm
Property changes on: abraham/tests/morpho/images/test_2.pgm
___________________________________________________________________
Name: svn:mime-type
   + abraham/tests/morpho/images/+irm6.pgm
Index: abraham/tests/morpho/images/test_3.pgm
Cannot display: file marked as a binary type.
svn:mime-type = abraham/tests/morpho/images/+irm6.pgm
Property changes on: abraham/tests/morpho/images/test_3.pgm
___________________________________________________________________
Name: svn:mime-type
   + abraham/tests/morpho/images/+irm6.pgm
Index: abraham/tests/morpho/images/test_4.pgm
Cannot display: file marked as a binary type.
svn:mime-type = abraham/tests/morpho/images/+irm6.pgm
Property changes on: abraham/tests/morpho/images/test_4.pgm
___________________________________________________________________
Name: svn:mime-type
   + abraham/tests/morpho/images/+irm6.pgm
Index: abraham/tests/morpho/images/result_topo_watershed.pgm
Cannot display: file marked as a binary type.
svn:mime-type = abraham/tests/morpho/images/+irm6.pgm
Property changes on: abraham/tests/morpho/images/result_topo_watershed.pgm
___________________________________________________________________
Name: svn:mime-type
   + abraham/tests/morpho/images/+irm6.pgm
Index: abraham/tests/morpho/images/test_watershed.pgm
Cannot display: file marked as a binary type.
svn:mime-type = abraham/tests/morpho/images/+irm6.pgm
Property changes on: abraham/tests/morpho/images/test_watershed.pgm
___________________________________________________________________
Name: svn:mime-type
   + abraham/tests/morpho/images/+irm6.pgm
Index: abraham/tests/morpho/images/+irm6.pgm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: abraham/tests/morpho/images/+irm6.pgm
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream
Index: abraham/tests/morpho/images/test_component_mapping.pgm
Cannot display: file marked as a binary type.
svn:mime-type = abraham/tests/morpho/images/+irm6.pgm
Property changes on: abraham/tests/morpho/images/test_component_mapping.pgm
___________________________________________________________________
Name: svn:mime-type
   + abraham/tests/morpho/images/+irm6.pgm
Index: abraham/tests/morpho/test_watershed.cc
--- abraham/tests/morpho/test_watershed.cc	(revision 1935)
+++ abraham/tests/morpho/test_watershed.cc	(working copy)
@@ -7,7 +7,7 @@
 #include <mln/io/pgm/load.hh>
 #include <mln/io/pgm/save.hh>
 
-#include "basic_najman.hh"
+#include <mln/morpho/basic_najman.hh>
 #include <string>
 #include <iostream>
 
Index: abraham/tests/morpho/test_watershed_topo.cc
--- abraham/tests/morpho/test_watershed_topo.cc	(revision 1935)
+++ abraham/tests/morpho/test_watershed_topo.cc	(working copy)
@@ -9,7 +9,7 @@
 #include <mln/io/pgm/load.hh>
 #include <mln/io/pgm/save.hh>
 
-#include "basic_najman.hh"
+#include <mln/morpho/basic_najman.hh>
 #include <string>
 #include <iostream>
 
@@ -32,7 +32,8 @@
 
   //   io::pgm::load(input, "./images/test_watershed.pgm");
   // io::pgm::load(input, "./images/little_test.pgm");
-  io::pgm::load(input, "./images/test_2.pgm");
+    io::pgm::load(input, "./images/test_4.pgm");
+  // io::pgm::load(input, "../../img/dots.pgm");
   // io::pgm::load(input, "./images/+irm6.pgm");
 
  //   io::pgm::load(input, "./images/lena_light.pgm");
Index: abraham/tests/morpho/ref/src/lib/lwshedtopo.c
--- abraham/tests/morpho/ref/src/lib/lwshedtopo.c	(revision 1966)
+++ abraham/tests/morpho/ref/src/lib/lwshedtopo.c	(working copy)
@@ -266,13 +266,13 @@
       }
     }
   }
-#ifdef _DEBUG_
+  //#ifdef _DEBUG_
   for (i=0; i<logn; i++) {
     for (j=0; j<nbRepresent; j++)
       printf("M[%d][%d] = %d - ", i, j, Minim[i][j]);
     printf("\n");
   }
-#endif
+  //#endif
   return Minim;
 }
 
@@ -491,10 +491,10 @@
         if (CT->tabnodes[c].nbsons > 1) // noeud
         {
         }
-#ifdef PARANO
+	//#ifdef PARANO
         else
           printf("%s : ERREUR COMPOSANTE BRANCHE!!!\n", F_NAME);
-#endif
+	//#endif
         // empile les c-voisins de x non marques MASSIF ni EN_FAH
 	switch (connex)
 	{
Index: abraham/tests/morpho/Makefile
--- abraham/tests/morpho/Makefile	(revision 1966)
+++ abraham/tests/morpho/Makefile	(working copy)
@@ -16,4 +16,6 @@
 .PHONY: clean distclean
 
 ## Depedencies
-tikz.o: ../../../mln/io/tikz/save.hh
\ No newline at end of file
+test_watershed_topo.cc: ../../mln/morpho/basic_najman.hh
+test_watershed.cc: ../../mln/morpho/basic_najman.hh
+test_componenet_tree.cc: ../../mln/morpho/basic_najman.hh
\ No newline at end of file
Index: abraham/tests/io/tikz/Makefile
--- abraham/tests/io/tikz/Makefile	(revision 1966)
+++ abraham/tests/io/tikz/Makefile	(working copy)
@@ -21,7 +21,6 @@
 	rm -rf *~
 	rm -rf *.log
 	rm -rf *.aux
-	rm -rf
 
 distclean: clean
 	rm -rf $(EXEC)
Index: abraham/mln/morpho/basic_najman.hh
--- abraham/mln/morpho/basic_najman.hh	(revision 1966)
+++ abraham/mln/morpho/basic_najman.hh	(working copy)
@@ -7,6 +7,7 @@
 #include <mln/math/sqr.hh>
 
 #include <queue>
+#include <vector>
 #include <set>
 
 namespace mln
@@ -158,14 +159,15 @@
 
 
 
-    template <typename I, typename N>
+    template <typename I, typename N, typename B>
     class my_lesser_psite
     {
     public:
       typedef mln_psite(I) psite;
 
       my_lesser_psite(const Image<I>& ima,
-		      const Neighborhood<N>& nbh);
+		      const Neighborhood<N>& nbh,
+		      const Image<B>& enqueued);
 
       /// Is \a x lesser than \a y?
       bool operator()(const psite& x, const psite& y);
@@ -173,30 +175,33 @@
     private:
       const I& ima_;
       const N& nbh_;
+      const B& enqueued_;
     };
 
 
-    template <typename I, typename N>
-    my_lesser_psite<I, N>
+    template <typename I, typename N, typename B>
+    my_lesser_psite<I, N, B>
     make_my_lesser_psite(const Image<I>& ima,
-			 const Neighborhood<N>& nbh);
+			 const Neighborhood<N>& nbh,
+			 const Image<B>& enqueued);
 
 
 # ifndef MLN_INCLUDE_ONLY
 
-    template <typename I, typename N>
-    my_lesser_psite<I, N>::my_lesser_psite(const Image<I>& ima,
-					   const Neighborhood<N>& nbh)
-      : ima_ (exact(ima)), nbh_(exact(nbh))
+    template <typename I, typename N, typename B>
+    my_lesser_psite<I, N, B>::my_lesser_psite(const Image<I>& ima,
+					      const Neighborhood<N>& nbh,
+					      const Image<B>& enqueued)
+      : ima_ (exact(ima)), nbh_(exact(nbh)), enqueued_(exact(enqueued))
     {
     }
 
-    template <typename I, typename N>
+    template <typename I, typename N, typename B>
     bool
-    my_lesser_psite<I, N>::operator()(const mln_psite(I)& x, const mln_psite(I)& y)
+    my_lesser_psite<I, N, B>::operator()(const mln_psite(I)& x, const mln_psite(I)& y)
     {
 
-#ifdef V1
+#if 0
 
       if (ima_(x) == ima_(y))
 	{
@@ -212,27 +217,47 @@
 	    if (ima_.has(b) and ima_(b) > ima_(y))
 	      ++my;
 
-	  return mx > my;
+	  return mx < my;
 	}
 
-#else
+#endif
 
 
+#if 0
       if (ima_(x) == ima_(y))
 	{
 	  mln_value(I) mx = ima_(x), my = ima_(y);
 
 	  mln_niter(N) a(nbh_, x);
 	  for_all(a)
-	    if (ima_.has(a) and ima_(a) > ima_(mx))
-	      mx = a;
+	    if (ima_.has(a) and ima_(a) > mx)
+	      mx = ima_(a);
+
+	  mln_niter(N) b(nbh_, y);
+	  for_all(b)
+	    if (ima_.has(b) and ima_(b) > my)
+	      my = ima_(b);
+
+	  return mx < my;
+	}
+#endif
+
+#if 1
+      if (ima_(x) == ima_(y))
+	{
+	  int mx = 0, my = 0;
+
+	  mln_niter(N) a(nbh_, x);
+	  for_all(a)
+	    if (ima_.has(a) and enqueued_(a))
+	      ++mx;
 
 	  mln_niter(N) b(nbh_, y);
 	  for_all(b)
-	    if (ima_.has(b) and ima_(b) > ima_(my))
-	      my = b;
+	    if (ima_.has(b) and enqueued_(b))
+	      ++my;
 
-	  return ima_(x) < ima(y);
+	  return mx > my;
 	}
 
 
@@ -243,16 +268,154 @@
     }
 
 
-    template <typename I, typename N>
-    my_lesser_psite<I, N>
+    template <typename I, typename N, typename B>
+    my_lesser_psite<I, N, B>
     make_my_lesser_psite(const Image<I>& ima,
-			 const Neighborhood<N>& nbh)
+			 const Neighborhood<N>& nbh,
+			 const Image<B>& enqueued)
     {
-      return my_lesser_psite<I, N>(ima);
+      return my_lesser_psite<I, N, B>(ima, nbh, enqueued);
     }
 
 # endif // ! MLN_INCLUDE_ONLY
 
+
+
+
+
+
+
+    // We need a custom queue in fact...
+
+    // #define NPRIO 65536
+
+    template <typename P, typename V>
+    class fah_queue {
+
+    public :
+
+      // Push
+      void push(P point,
+		V level)
+      {
+	if (!util_ || (level < level_))
+	  level_ = level;
+
+	++util_;
+	if (util_ > max_util_)
+	  max_util_ = util_;
+
+	if (is_empty(level))
+	  queues[level] = new pqueue();
+
+	queues[level]->push(point);
+
+      } // void push(P point, V level)
+
+
+      // Top
+      P top ()
+      {
+	if (!util_) {
+	  std::cerr << "Fah vide!" << std::endl;
+	  exit (1); // FIXME!
+	}
+	return top(level_);
+      } // P top ()
+
+
+      // Pop
+      void pop ()
+      {
+	if (!util_) {
+	  std::cerr << "Fah vide!" << std::endl;
+	  return;
+	}
+	pop(level_);
+      } // void pop ()
+
+
+      // Is Empty
+      bool is_empty () {
+	return !util_;
+      } // bool is_empty ()
+
+
+      // Ctor
+      fah_queue() :
+	level_(0),
+	util_(0),
+	max_util_(0)
+      { } // fah_queue()
+
+
+      // Dtor
+      ~fah_queue()
+      {
+	typename qmap::iterator i;
+
+	for (i = queues.begin(); i != queues.end(); ++i)
+	  delete (i->second);
+      }
+
+
+      // Print
+
+
+      // Flush
+
+
+    private :
+
+      V level_;               /* niveau a partir duquel des listes existent */
+      int util_;              /* nombre de points courant dans la fah */
+      int max_util_;          /* nombre de points utilises max (au cours du temps) */
+
+      typedef std::queue <P> pqueue;
+      typedef std::map <V, pqueue *> qmap;
+      qmap queues;
+
+
+      // Is Empty
+      bool is_empty (V level) {
+	return ((queues.find(level) == queues.end()) || queues[level]->empty());
+      } // bool is_empty (V level)
+
+
+      // Top
+      P top (V level)
+      {
+	if (is_empty(level))
+	  {
+	    std::cerr << "erreur Fah vide au niveau " << level << std::endl;
+	    exit (1); // FIXME!
+	  }
+	return queues[level]->front();
+      }
+
+
+      // Pop
+      void pop (V level)
+      {
+	if (is_empty(level))
+	  {
+	    std::cerr << "erreur Fah vide au niveau " << level << std::endl;
+	    return;
+	  }
+
+	util_--;
+	queues[level]->pop();
+
+	typename qmap::iterator i = queues.find(level);
+	for (; i != queues.end() && i->second->empty(); ++i)
+	  ;
+
+	level_ = i->first;
+      }
+
+    }; // class fah_queue
+
+
   } // end of namespace mln::util
 
 
@@ -713,8 +876,6 @@
 	mln_niter(N) q(nbh, p);
 	p_set<psite> v;
 
-	psite pmax = p;
-
 	for_all(q)
 	  if (pima.has(q) && pima(q) > pima(p))
 	    v.insert(Par_node(q));
@@ -726,16 +887,17 @@
 	  return v[0];
 
 	psite
-	  c = max(v);
+	  c = max(v),
+	  cmax = c;
 
 	typename p_set<psite>::fwd_piter it(v);
 	for_all(it)
 	{
 	  // Can't remove the point from the set
-	  if (it.to_point() == c)
+	  if (it.to_point() == cmax)
 	    continue;
 
-	  psite c1 = lca(c, it.to_point());
+	  psite c1 = lca_opt(c, it.to_point());
 	  if (c1 != it.to_point())
 	    c = c1;
 	}
@@ -919,7 +1081,9 @@
       {
 	init();
 
+	std::cout << "Build component tree..." << std::endl;
 	BuildComponentTree();
+	std::cout << "                       done" << std::endl;
 
 	mln_piter(I) p (pima.domain());
 	for_all(p)
@@ -927,7 +1091,17 @@
 
 	revert_tree(Root);
 
+	std::cout << "Build euler tour..." << std::endl;;
+	build_euler_tour();
+	std::cout << "                       done" << std::endl;
+
+	std::cout << "Build minim table..." << std::endl;;
+	build_minim();
+	std::cout << "                       done" << std::endl;
+
+	std::cout << "Watersheding..." << std::endl;;
 	topo_watershed();
+	std::cout << "                       done" << std::endl;
 
 	for_all(p)
 	  pima(p) = 255 - pima(p);
@@ -945,15 +1119,8 @@
 	// Not used
 	// level::fill(isproc, false);
 
-
-	typedef
-	  std::priority_queue< psite, std::vector<psite>, util::lesser_psite<I> >
-	  ordered_queue_type;
-
-	ordered_queue_type l(util::make_lesser_psite(pima));
-
-
-
+	util::fah_queue < psite, mln_value(I) > l;
+	mln_value(I) max = mln_max(mln_value(I));
 
 	// Flag C-maxima
 	level::fill(cmax, false);
@@ -962,16 +1129,6 @@
 	  if (nodes(Par_node(it.to_point())).children.npoints() == 0)
 	    cmax(it.to_point()) = true;
 
-#ifdef SLOW
-
-	// Enqueue all
-	for_all(it)
-	{
-	  enqueued(it.to_point()) = true;
-	  l.push(it.to_point());
-	}
-#else // !SLOW
-
 	// Optimisation : enqueue minima's neighbours
 	level::fill(enqueued, false);
 	for_all(it)
@@ -981,16 +1138,16 @@
 	    if (cmax.has(q) && cmax(q))
 	      {
 		enqueued(it.to_point()) = true;
-		l.push(it.to_point());
+
+		l.push(it.to_point(), max - pima(it.to_point()));
+
 		break;
 	      }
 	}
 
-#endif // SLOW
-
 
 	// Main loop
-	while(!l.empty())
+	while(!l.is_empty())
 	  {
 	    psite x = l.top();
 	    l.pop();
@@ -998,11 +1155,6 @@
 
 	    psite c = w_constructible(x);
 
-	    if (x == psite(3, 3))
-	      {
-		std::cout << "w-c : " << c << std::endl;
-		io::pgm::save(pima, "int.pgm");
-	      }
 
 	    if (c != psite(-1, -1))
 	      {
@@ -1017,14 +1169,15 @@
 		    {
 		    }
 		  else
-		    std::cerr << "ERREUR COMPOSANTE BRANCHE" << std::endl;
+		    std::cerr << "ERREUR COMPOSANTE BRANCHE " << nodes(c).children.npoints() << std::endl;
 
 		mln_niter(N) q(nbh, x);
 		for_all(q)
 		  if (pima.has(q) && !cmax(q) && !enqueued(q))
 		    {
 		      enqueued(q) = true;
-		      l.push(q);
+
+		      l.push(q, max - pima(q));
 		    }
 	      } // if (c != psite(-1, -1))
 	  } // while(!l.empty())
@@ -1032,6 +1185,133 @@
 	for_all(it)
 	  pima(it.to_point()) = nodes(Par_node(it.to_point())).level;
       }
+
+
+      // Optimized LCA Algorithm
+
+      int *euler;
+      int *depth;
+      int ctree_size;
+      std::map<psite, int> pos;
+      psite *repr;
+
+      int *minim;
+      int **Minim;
+
+      void compute_ctree_size (psite p)
+      {
+	ctree_size += 1;
+	node& n = nodes(p);
+
+	typename p_array<mln_psite(I)>::fwd_piter it(n.children);
+	for_all(it)
+	  compute_ctree_size(it.to_point());
+      }
+
+      void build_euler_tour_rec(psite p, int &position, int d)
+      {
+	if (pos.find(p) == pos.end())
+	  pos[p] = position;
+
+	repr[position] = p;
+	depth[position] = d;
+	euler[position] = pos[p];
+	position++;
+	node& n = nodes(p);
+
+	typename p_array<mln_psite(I)>::fwd_piter it(n.children);
+	for_all(it)
+	{
+	  build_euler_tour_rec(it.to_point(), position, d+1);
+	  depth[position] = d; // Not optimized
+	  euler[position] = pos[p];
+	  position++;
+	}
+
+      }
+
+      void build_euler_tour ()
+      {
+	ctree_size = 0;
+	compute_ctree_size(Root);
+
+	int size = 2 * ctree_size - 1;
+
+	// FIXME : free this
+	euler = new int[size];
+	depth = new int[size];
+	repr = new psite[size];
+
+	int position = 0;
+	build_euler_tour_rec(Root, position, 0);
+      }
+
+      void build_minim ()
+      {
+	// compute_tree_size(); // Already done in build_euler_tour
+	int size = 2 * ctree_size - 1;
+	int logn = (int)(ceil(log((double)(size))/log(2.0)));
+	// minim.reserve(size);
+	minim = new int [logn * size]; // FIXME : Think about freeing this
+	Minim = new int* [logn];
+
+	Minim[0] = minim;
+
+	// Init
+	for (int i = 0; i < size - 1; ++i)
+	  if (depth[euler[i]] < depth[euler[i+1]]) {
+	    Minim[0][i] = i;
+	  } else {
+	    Minim[0][i] = i+1;
+	  }
+
+	Minim[0][size - 1] = size - 1;
+
+	int k;
+	for (int j = 1; j < logn; j++) {
+	  k = 1 << (j - 1);
+	  Minim[j] = &minim[j * size];
+	  for (int i = 0; i < size; i++) {
+	    if ((i + (k << 1)) >= size) {
+	      Minim[j][i] = size - 1;
+	    }
+	    else {
+	      if (depth[euler[Minim[j - 1][i]]] <= depth[euler[Minim[j - 1][i + k]]])
+		Minim[j][i] = Minim[j - 1][i];
+	      else
+		Minim[j][i] = Minim[j - 1][i + k];
+	    }
+	  }
+	}
+
+      } // void build_minim ()
+
+      psite lca_opt (psite a, psite b)
+      {
+	int
+	  m = pos[a],
+	  n = pos[b],
+	  k;
+
+	if (m == n)
+	  return repr[m];
+
+	if (m > n)
+	  {
+	    k = n;
+	    n = m;
+	    m = k;
+	  }
+
+	k = (int)(log((double)(n - m))/log(2.));
+
+	if (depth[euler[Minim[k][m]]] < depth[euler[Minim[k][n - (1 << k)]]]) {
+	  return repr[euler[Minim[k][m]]];
+	} else {
+	  return repr[euler[Minim[k][n - (1 << k)]]];
+	}
+      }
+
     }; // struct basic_najman
 
   }; // namespace morpho
Index: abraham/mln/io/tikz/save.hh
--- abraham/mln/io/tikz/save.hh	(revision 1966)
+++ abraham/mln/io/tikz/save.hh	(working copy)
@@ -165,9 +165,7 @@
 	      {
 		file << "\\path (" << p.col() << "," << max_row - p.row() << ") node[fill=";
 		write_value(file, ima(p));
-		file << "] (p_" << p.row() << "_" << p.col() << ") { \\color{";
-		file << "black";
-		file << "}" << "};" << std::endl;
+		file << "] (p_" << p.row() << "_" << p.col() << ") { }" << "};" << std::endl;
 	      }
 	}
 
@@ -184,6 +182,10 @@
 	    min_col = geom::min_col(ima),
 	    max_col = geom::max_col(ima);
 
+	  typedef mln_value(I) ival;
+	  ival mid = (mln_max(ival) - mln_min(ival)) / 2;
+	  mid += mln_min(ival);
+
 	  point2d p;
 	  for (p.row() = min_row; p.row() <= max_row; ++p.row())
 	    for (p.col() = min_col; p.col() <= max_col; ++p.col())
@@ -191,7 +193,10 @@
 		file << "\\path (" << p.col() << "," << max_row - p.row() << ") node[fill=";
 		write_value(file, ima(p));
 		file << "] (p_" << p.row() << "_" << p.col() << ") { \\color{";
+		if (ima(p) > mid)
 		file << "black";
+		else
+		  file << "white";
 		file << "}" << val(p) << "};" << std::endl;
 	      }
 	}
Index: abraham/img/dots.pgm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: abraham/img/dots.pgm
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Ugo Jardonnet  <jardonnet(a)lrde.epita.fr>
	Fix algebra::quat::set_unit.
	set_unit(q):
	if q != 0
	  set_unit; postcondition(is_unit)
	else return
	* mln/algebra/quat.hh: .
  quat.hh |    6 ++++--
  1 file changed, 4 insertions(+), 2 deletions(-)
Index: mln/algebra/quat.hh
--- mln/algebra/quat.hh	(revision 1965)
+++ mln/algebra/quat.hh	(working copy)
@@ -409,9 +409,11 @@
      inline
      quat& quat::set_unit()
      {
-      v_.normalize();
+      if (about_equal(norm::l2(this->to_vec()), 0.f))
+        return *this;
-      assert(this->is_unit());
+      v_.normalize();
+      mln_postcondition(this->is_unit());
        return *this;
      }
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from  Ugo Jardonnet  <jardonnet(a)lrde.epita.fr>
	Update final_qk.
	Final_qk didn't use correct points.
	* jardonnet/test/icp.cc: .
	* jardonnet/registration/final_qk.hh: .
	* jardonnet/registration/icp.hh: .
	* jardonnet/test/no_final.ppm: New.
  registration/final_qk.hh |    6 +++---
  registration/icp.hh      |   11 ++++-------
  test/icp.cc              |    2 +-
  3 files changed, 8 insertions(+), 11 deletions(-)
Index: jardonnet/test/no_final.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: jardonnet/test/no_final.ppm
___________________________________________________________________
Name: svn:mime-type
    + application/octet-stream
Index: jardonnet/test/icp.cc
--- jardonnet/test/icp.cc	(revision 1963)
+++ jardonnet/test/icp.cc	(working copy)
@@ -78,9 +78,9 @@
    for (size_t i = 0; i < c.npoints(); i++)
      length[i] = norm::l2(algebra::vec<3,int> (c[i] - map(c[i])));
-
    // final transform
    quat7<3> fqk = registration::final_qk(c, map, 2 * stddev);
+  std::cout << fqk << std::endl;
    fqk.apply_on(c, c, c.npoints());
    //to 2d : projection (FIXME:if 3d)
Index: jardonnet/registration/final_qk.hh
--- jardonnet/registration/final_qk.hh	(revision 1963)
+++ jardonnet/registration/final_qk.hh	(working copy)
@@ -46,10 +46,10 @@
        for (size_t i = 0; i < c.npoints(); ++i)
  	{
-	  algebra::vec<3,float> xki = map(c[i]);
  	  algebra::vec<3,float> ci = c[i];
+	  algebra::vec<3,float> xki = map(c[i]);
-	  if (norm::l2(ci - xki) > nstddev)
+	  if (norm::l2(ci - xki) < nstddev)
  	    {
  	      newc.append(c[i]);
  	      mu_newc += ci;
@@ -59,7 +59,7 @@
        quat7<P::dim> qk = match(newc, mu_newc, newc, map, newc.npoints());
-      qk._qT = - qk._qT; // FIXME : why?
+      //qk._qT = - qk._qT; // FIXME : why?
        return qk;
      }
Index: jardonnet/registration/icp.hh
--- jardonnet/registration/icp.hh	(revision 1963)
+++ jardonnet/registration/icp.hh	(working copy)
@@ -133,12 +133,10 @@
            //update qk
-          /*
            if (k > 3)
              qk = update_qk(buf_qk, buf_dk);
            qk._qR.set_unit();
            buf_qk[0] = qk;
-          */
            //Ck+1 = qk(C)
            qk.apply_on(C, Ck, c_length);
@@ -180,7 +178,7 @@
      template <typename P, typename M>
      inline
      quat7<P::dim>
-    icp(p_array<P> cloud, //here reference implies low efficiency 
(FIXME:check again)
+    icp(p_array<P> cloud, // More efficient without reference
          const M& map,
          const float q,
          const unsigned nb_it,
@@ -199,7 +197,7 @@
  #ifndef NDEBUG       // FIXME: theo
-      image2d<value::rgb8> tmp(500,800);
+      image2d<value::rgb8> tmp(500,500); // FIXME :
        level::fill(tmp, literal::black);
        //write X
        mln_piter(p_array<P>) p(x);
@@ -207,7 +205,7 @@
        {
          point2d qp = make::point2d(p[0], p[1]);
          if (tmp.has(qp))
-          tmp(qp) = literal::white;
+          tmp(qp) = literal::green;
        }
  #endif
@@ -224,7 +222,7 @@
            {
              value::rgb8 c;
              switch (e) {
-            case 2: c = literal::green; break;
+            case 2: c = literal::white; break;
              case 1: c = literal::blue; break;
              case 0: c = literal::red; break;
              }
@@ -236,7 +234,6 @@
                if (tmp.has(qp))
                  tmp(qp) = c;
              }
-            //if (e == 0)
                io::ppm::save(tmp, "tmp.ppm");
            }
  #endif
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from  Ugo Jardonnet  <jardonnet(a)lrde.epita.fr>
	Up and add test files.
	Add test 5
	* jardonnet/test/img/c5.pbm: New.
	* jardonnet/test/img/x5.pbm: New.
	Update images. Mainly corrects orientation.
	* jardonnet/test/img/c2.pbm: Update.
	* jardonnet/test/img/x1.pbm: Update.
	* jardonnet/test/img/x3.pbm: Update.
  0 files changed
Index: jardonnet/test/img/c2.pbm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: jardonnet/test/img/c5.pbm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: jardonnet/test/img/c5.pbm
___________________________________________________________________
Name: svn:mime-type
    + application/octet-stream
Index: jardonnet/test/img/x1.pbm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: jardonnet/test/img/x3.pbm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: jardonnet/test/img/x5.pbm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: jardonnet/test/img/x5.pbm
___________________________________________________________________
Name: svn:mime-type
    + application/octet-stream
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from  Ugo Jardonnet  <jardonnet(a)lrde.epita.fr>
	Add results about final_qk.
	fun_k_cn_xn.ppm
	fun : final_qk v1 or v2
	k : nstddev == k * stdddev
	cn,xn : images from img/
	* jardonnet/test/final/final_qk_1.ppm: .
	* jardonnet/test/final/final_qk_3.ppm: New.
	* jardonnet/test/final/final_qk_1_c1_x1.ppm: New.
	* jardonnet/test/final/final_qk_2_c1_x1.ppm: New.
	* jardonnet/test/final/no_final_1_c1_x1.ppm: New.
  0 files changed
Index: jardonnet/test/final/final_qk_1.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: jardonnet/test/final/final_qk_3.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: jardonnet/test/final/final_qk_3.ppm
___________________________________________________________________
Name: svn:mime-type
    + application/octet-stream
Index: jardonnet/test/final/final_qk_1_c1_x1.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: jardonnet/test/final/final_qk_1_c1_x1.ppm
___________________________________________________________________
Name: svn:mime-type
    + application/octet-stream
Index: jardonnet/test/final/final_qk_2_c1_x1.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: jardonnet/test/final/final_qk_2_c1_x1.ppm
___________________________________________________________________
Name: svn:mime-type
    + application/octet-stream
Index: jardonnet/test/final/no_final_1_c1_x1.ppm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: jardonnet/test/final/no_final_1_c1_x1.ppm
___________________________________________________________________
Name: svn:mime-type
    + application/octet-stream
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                          URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2008-05-16  Matthieu Garrigues  <garrigues(a)lrde.epita.fr>
	* geraud/fllt.cc: FLLT : Finalize merge.
---
 fllt.cc |  297 +++++++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 211 insertions(+), 86 deletions(-)
Index: trunk/milena/sandbox/geraud/fllt.cc
===================================================================
--- trunk/milena/sandbox/geraud/fllt.cc	(revision 1960)
+++ trunk/milena/sandbox/geraud/fllt.cc	(revision 1961)
@@ -77,6 +77,7 @@
 # define fllt_branch_iter_ind(P, V)  mln::util::branch_iter_ind< fllt_node_elt<P, V> >
 # define fllt_branch_iter(P, V)  mln::util::branch_iter< fllt_node_elt<P, V> >
 
+# define stl_to_mln_iter(T) stl_iterator< T >
 
     //Fwd declarations.
     template <typename V> struct lower;
@@ -88,6 +89,7 @@
       V	value;
       p_array<P> points;
       p_array<P> holes;
+      std::vector<fllt_node(P, V)*> hole_shapes;
       /// Tell if his parent if brighter or not.  Nb : if the parent
       /// if brighter, the node come from the lower level set
       bool brighter;
@@ -238,12 +240,13 @@
     }
 
 
-    template <typename I, typename V>
-    void blob(const I& is,
+    template <typename I, typename P, typename V, typename Set>
+    void blob(const Set&,
+	      const I& is,
 	      p_array<mln_point(I)>* N[256],
 	      unsigned in_N,
 	      const box2d& N_box,
-	      fllt_node(mln_point(I), V)* current_cc)
+	      fllt_node(P, V)* current_cc)
     {
       typedef p_array<mln_point(I)> arr_t;
 
@@ -259,9 +262,8 @@
 	label++;
       }
 
-      typedef mln_psite(I) P;
       P cur;
-      mln_niter(neighb2d) n(c8(), cur);
+      mln_niter(neighb2d) n(Set::bdr_nbh(), cur);
       p_queue_fast<P> qu;
       p_array<P>& holes = current_cc->elt().holes;
 
@@ -296,6 +298,7 @@
 
 
       for (unsigned i = 0; i < 256; ++i)
+      //for (int i = 255; i >= 0; --i)
       {
 	mln_piter(arr_t) p(*N[i]);
 	for_all(p)
@@ -340,7 +343,8 @@
 		image2d< fllt_node(P, V)* >& smallest_shapes,
 		int in_R,
 		int in_N,
-		const V& g)
+		const V& g,
+		unsigned& n_comps)
     {
       typedef p_array<P> arr_t;
 
@@ -349,9 +353,10 @@
       {
 	mln_invariant(deja_vu(a) == in_N);
 	mln_invariant(smallest_shapes(a) != current_cc);
+// 	if (smallest_shapes(a) == current_cc)
+// 	  continue;
 
 	deja_vu(a) = in_R;
-	current_cc->elt().npoints++;
 	if (!smallest_shapes(a))
 	{
 	  smallest_shapes(a) = current_cc;
@@ -363,22 +368,27 @@
 	    {
 	      fllt_node(P, V)* to_delete = smallest_shapes(a);
 
+// 	      current_cc->elt().points.append(smallest_shapes(a)->elt().points);
+// 	      A.append(smallest_shapes(a)->elt().points);
+
 	      mln_piter(arr_t) p(smallest_shapes(a)->elt().points);
 	      // Todo optimization here.
 	      for_all(p)
+	      {
 		smallest_shapes(p) = 0;
+		// deja_vu(p) = in_R;
+		//smallest_shapes(p) = current_cc;
+	      }
 
 	      while(!to_delete->children().empty())
 		current_cc->add_child(*to_delete->children().begin());
 	      delete to_delete;
-
+	      n_comps--;
 	      smallest_shapes(a) = current_cc;
 	      current_cc->elt().points.append(a);
 	    }
 	    else
 	      smallest_shapes(a)->set_parent(current_cc);
-	// N_box is not re-computed so that we save time;
-	// N_box is always growing while looping from step 3.
       }
     }
 
@@ -449,7 +459,7 @@
 
       mln_assertion(input.domain() == smallest_shapes.domain());
 
-      unsigned l = 0, l_max;
+      unsigned l = 0, l_max = 0;
       mln_ch_value(I, unsigned) reg_min = Set::regional_extremum(input, Set::reg_nbh(), l_max);
       std::vector<bool> tag(l_max + 1, false);
       tag[0] = true;
@@ -476,7 +486,7 @@
       accu::bbox<P> N_box;
 
       bool touch_border_of_image = false;
-      unsigned n_step_1 = 0, n_step_3 = 0, n_comps = 0, n_holes = 0;
+      unsigned n_step_1 = 0, n_step_3 = 0, n_step_4c = 0, n_comps = 0, n_holes = 0;
 
       // Step 1.
     step_1:
@@ -491,6 +501,7 @@
 	++n_step_1;
 	x0 = p;
 	g = input(x0);
+	++n_comps;
 	current_cc = new node_type(Set::id);
 	current_cc->elt().value = g;
 	touch_border_of_image = false;
@@ -565,9 +576,9 @@
 	  ++n_comps;
 
 	  if (touch_border_of_image)
-	    blob(deja_vu, N, in_N, N_box.to_result().to_larger(1), current_cc);
+	    blob(Set(), deja_vu, N, in_N, N_box.to_result().to_larger(1), current_cc);
 	  else
-	    blob(deja_vu, N, in_N, N_box, current_cc);
+	    blob(Set(), deja_vu, N, in_N, N_box, current_cc);
 
 	  n_holes += current_cc->elt().holes.npoints();
 
@@ -581,7 +592,7 @@
 	  A = N[g];
 	  N[g] = tmp;
 	  N[g]->clear();
-	  move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g);
+	  move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
 	  goto step_3;
 	}
 	// b)
@@ -591,13 +602,14 @@
 	  A = N[g];
 	  N[g] = tmp;
 	  N[g]->clear();
-	  move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g);
+	  move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
 	  goto step_3;
 	}
 	// c)
 	else
 	{
 	  // FIXME: IDEA: this change might be performed while R is constructed(?)
+	  n_step_4c++;
 	  mln_piter(I) r(N_box);
 	  for_all(r)
 	    if (deja_vu(r) == in_R)
@@ -608,7 +620,7 @@
       }
 
     the_end:
-      std::cout << n_step_1 << ' ' << n_step_3 << std::endl;
+      std::cout <<  " n_step1 :  " << n_step_1 << " n_step3 : "  << n_step_3 << " n_step4c : "  << n_step_4c  << std::endl;
       std::cout << "n comps = " << n_comps << "  n holes = " << n_holes << std::endl;
 
       return *new tree_type(current_cc);
@@ -637,34 +649,42 @@
     }
 
     template <typename P, typename V>
-    bool shape_is_included(fllt_branch_iter_ind(P, V) A,
-			   fllt_branch_iter_ind(P, V) B)
+    bool shape_is_included(fllt_node(P, V)* A,
+			   fllt_node(P, V)* B)
+    {
+      return A->parent() == B || A == B;
+    }
+
+    template <typename P, typename V>
+    void find_all_holes(fllt_tree(P, V)& lower_tree,
+			fllt_tree(P, V)& upper_tree,
+			const image2d<fllt_node(P, V)*>& low_reg,
+			const image2d<fllt_node(P, V)*>& upp_reg)
     {
-      // TODO: optimize : take the smalest shape first.
       typedef p_array<P> arr_t;
+      typedef fllt_node(P, V) node_type;
 
-      for_all(A)
       {
-	bool found = false;
-	mln_piter(arr_t) pA((*A).elt().points);
-	for_all(pA)
-	  for_all(B)
-	{
-	  found = false;
-	  mln_piter(arr_t) pB((*B).elt().points);
-	  for_all(pB)
-	    if (pA == pB)
+	fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
+	for_all(node_)
 	    {
-	      found = true;
-	      break;
+	  node_type& node = *node_;
+	  mln_piter(arr_t) hole(node.elt().holes);
+	  for_all(hole)
+	    node.elt().hole_shapes.push_back(find_hole<P,V,upper<V> >(node, P(hole), upp_reg));
 	    }
-	  if (found)
-	    break;
 	}
-	if (!found)
-	  return false;
+
+      {
+	fllt_branch_iter_ind(P, V) node_(upper_tree.main_branch());
+	for_all(node_)
+	{
+	  node_type& node = *node_;
+	  mln_piter(arr_t) hole(node.elt().holes);
+	  for_all(hole)
+	    node.elt().hole_shapes.push_back(find_hole<P,V,lower<V> >(node, P(hole), low_reg));
+	}
       }
-      return true;
     }
 
     template <typename I>
@@ -684,6 +704,8 @@
       typedef fllt_tree(P, V) tree_type;
       typedef p_array<P> arr_t;
 
+
+      find_all_holes(lower_tree, upper_tree, low_reg, upp_reg);
       std::vector<node_type*> to_fill;
 
       fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
@@ -694,26 +716,27 @@
 	  continue;
 
 	// 	std::cout << "Fill " << &node << std::endl;
-
-	mln_piter(arr_t) hole_p(node.elt().holes);
-	for_all(hole_p)
+	typename std::vector<fllt_node(P, V)*>::iterator hole_;
+	for (hole_ = node.elt().hole_shapes.begin();
+	     hole_ != node.elt().hole_shapes.end();
+	     hole_++)
 	{
-	  fllt_node(P, V)* hole;
-	  hole = find_hole<P,V,upper<V> >(node, P(hole_p), upp_reg);
+	  fllt_node(P, V)* hole = *hole_;
 
  	  bool child_has_bigger_hole = false;
 	  typename fllt_node(P, V)::children_t::iterator it;
 	  for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
 	  {
 	    // Browse the holes of each child.
-	    mln_piter(arr_t) q((*it)->elt().holes);
-	    for_all(q)
+	    typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
+	    for (child_hole_ = (*it)->elt().hole_shapes.begin();
+		 child_hole_ != (*it)->elt().hole_shapes.end();
+		 child_hole_++)
 	    {
-	      fllt_node(P, V)* child_hole = find_hole<P,V,upper<V> >((**it), point2d(q), upp_reg);
+	      fllt_node(P, V)* child_hole = *child_hole_;
 	      // 	      std::cout << "hole : " << hole << " " << hole->elt().points << " " << std::endl;
 	      // 	      std::cout << "child hole : " << child_hole << " " << child_hole->elt().points << std::endl;
-	      if (shape_is_included(fllt_branch_iter_ind(P, V)(fllt_branch(P, V)(upper_tree, *hole)),
-				    fllt_branch_iter_ind(P, V)(fllt_branch(P, V)(upper_tree, *child_hole))))
+	      if (shape_is_included(hole, child_hole))
 	      {
 		child_has_bigger_hole = true;
 		break;
@@ -743,24 +766,26 @@
       	  if (node.elt().set_id != upper<V>::id)
       	    continue;
 
-      	  mln_piter(arr_t) hole_p(node.elt().holes);
-      	  for_all(hole_p)
+	  typename std::vector<fllt_node(P, V)*>::iterator hole_;
+	  for (hole_ = node.elt().hole_shapes.begin();
+	       hole_ != node.elt().hole_shapes.end();
+	       hole_++)
       	  {
-      	    fllt_node(P, V)* hole;
-      	    hole = find_hole<P,V,lower<V> >(node, P(hole_p), low_reg);
+	    fllt_node(P, V)* hole = *hole_;
 
       	    bool child_has_bigger_hole = false;
       	    typename fllt_node(P, V)::children_t::iterator it;
       	    for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
       	    {
       	      // Browse the holes of each child.
-      	      mln_piter(arr_t) q((*it)->elt().holes);
-      	      for_all(q)
+	      typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
+	      for (child_hole_ = (*it)->elt().hole_shapes.begin();
+		   child_hole_ != (*it)->elt().hole_shapes.end();
+		   child_hole_++)
       	      {
-      		fllt_node(P, V)* child_hole = find_hole<P,V,lower<V> >((**it), point2d(q), low_reg);
+		fllt_node(P, V)* child_hole = *child_hole_;
       		//if (hole->elt().points <= child_hole->elt().points)
-		if (shape_is_included(fllt_branch_iter_ind(P, V)(fllt_branch(P, V)(lower_tree, *hole)),
-				      fllt_branch_iter_ind(P, V)(fllt_branch(P, V)(lower_tree, *child_hole))))
+		if (shape_is_included(hole, child_hole))
       		{
       		  child_has_bigger_hole = true;
       		  break;
@@ -796,7 +821,7 @@
 
       std::cout << "1/ Compute the lower level set.----------------------------------------" << std::endl;
       lower_tree = level_set<I, lower<V> >(input, low_reg);
-       draw_tree(input, lower_tree);
+//       draw_tree(input, lower_tree);
 
       std::cout << "2/ Compute the upper level set.----------------------------------------" << std::endl;
       upper_tree = level_set<I, upper<V> >(input, upp_reg);
@@ -843,6 +868,92 @@
       }
     }
 
+
+    template <typename P, typename V, typename I>
+    unsigned
+    compute_area_rec(fllt_node(P, V)* node, I& ima)
+    {
+
+      if (!node)
+	return 0;
+
+      int area = 0;
+
+      for (int i = 0; i < node->children().size();i++)
+	area += compute_area_rec(node->children()[i], ima);
+
+      mln_piter(p_array<P>) p(node->elt().points);
+      for_all(p)
+	if (!ima(P(p)))
+	{
+	  ++area;
+	  ima(p) = true;
+	}
+
+      node->elt().npoints = area;
+      return area;
+    }
+
+    template <typename P, typename V, typename I>
+    void
+    compute_area(const Image<I>& input_, fllt_tree(P, V)& tree)
+    {
+      const I& input = exact(input_);
+
+      image2d<bool> ima(input.domain());
+      level::fill(ima, false);
+      compute_area_rec(tree.root(), ima);
+    }
+
+    void draw_shape(image2d<value::int_u8>& output,
+		    fllt_node(point2d, value::int_u8)* node)
+    {
+      typedef point2d P ;
+      typedef value::int_u8 V;
+
+      fllt_tree(P, V) subtree(node);
+      fllt_branch_iter_ind(P, V) s(fllt_branch(P, V)(subtree, *node));
+      for_all(s)
+	level::fill(inplace(output | (*s).elt().points), (*s).elt().value);
+    }
+
+    void area_filter(image2d<value::int_u8>& output,
+		     fllt_node(point2d, value::int_u8)* node,
+		     unsigned min_area,
+		     unsigned max_area,
+		     value::int_u8 bg)
+    {
+      typedef point2d P ;
+      typedef value::int_u8 V;
+
+      level::fill(output, bg);
+      fllt_tree(P, V) subtree(node);
+      fllt_branch_iter_ind(P, V) s(fllt_branch(P, V)(subtree, *node));
+      for_all(s)
+	if ((*s).elt().npoints > min_area && (*s).elt().npoints < max_area)
+	  draw_shape(output, &*s);
+    }
+
+    void area_filter_min(image2d<value::int_u8>& output,
+			 fllt_node(point2d, value::int_u8)* node,
+			 unsigned min_area,
+			 value::int_u8 g,
+			 unsigned accu)
+    {
+//       if ((*node).elt().npoints >= min_area)
+      if (accu > min_area)
+      {
+	accu = 0;
+	g = (*node).elt().value;
+      }
+
+      accu += (*node).elt().npoints;
+      level::fill(inplace(output | (*node).elt().points), g);
+
+      for (int i = 0; i < node->children().size();i++)
+	area_filter_min(output, node->children()[i], min_area, g, accu);
+    }
+
   } // end of namespace mln::my
 
 } // end of namespace mln
@@ -864,8 +975,8 @@
 //       return 1;
 //     }
 
-//   image2d<int_u8> lena;
-//   io::pgm::load(lena, argv[1]);
+  image2d<int_u8> lena;
+  io::pgm::load(lena, argv[1]);
 
 
 //   int vs[8][9] = { {0,0,0,0,0,0,0,0,0},
@@ -877,45 +988,59 @@
 // 		   {0,1,1,1,1,1,1,1,0},
 // 		   {0,0,0,0,0,0,0,0,0} };
 
-//   int vs[8][9] = { {2,2,2,2,2,2,2,2,2},
-// 		   {2,2,2,2,2,2,2,2,2},
-// 		   {2,1,1,1,1,1,1,1,2},
-// 		   {2,1,2,2,1,0,0,1,2},
-// 		   {2,1,2,2,1,0,0,1,2},
-// 		   {2,1,2,2,1,0,0,1,2},
-// 		   {2,1,1,1,1,1,1,1,2},
-// 		   {2,2,2,2,2,2,2,2,2} };
 
 
+//   int vs[8][9] = { {6,6,6,6,6,6,6,6,6},
+// 		   {6,6,6,6,6,6,6,6,6},
+// 		   {6,5,5,5,5,5,5,5,6},
+// 		   {6,5,6,6,5,3,3,5,6},
+// 		   {6,5,6,6,5,3,0,5,6},
+// 		   {6,5,6,6,5,3,3,5,6},
+// 		   {6,5,5,5,5,5,5,5,6},
+// 		   {6,6,6,6,6,6,6,6,6} };
+
 //   int vs[8][9] = { {2,2,2,2,2,2,2,2,2},
 // 		   {2,2,2,2,2,2,2,2,2},
 // 		   {2,1,1,1,1,1,1,1,2},
 // 		   {2,1,2,2,1,0,0,1,2},
-// 		   {2,1,2,2,1,0,4,1,2},
+// 		   {2,1,2,2,1,0,0,1,2},
 // 		   {2,1,2,2,1,0,0,1,2},
 // 		   {2,1,1,1,1,1,1,1,2},
 // 		   {2,2,2,2,2,2,2,2,2} };
 
- int vs[10][13] = { {1,1,1,1, 1,1,1,1, 1,1,1,1,1},
-		    {1,2,2,2,2,2,2,2,2,2,2,2,1},
-		    {1,2,2,2,2,2,2,2,2,2,2,2,1},
-		    {1,2,2,2,3,3,3,3,3,3,3,2,1},
-		    {1,2,2,2,3,3,3,2,2,2,3,2,1},
-		    {1,2,2,2,3,4,3,2,4,4,3,2,1},
-
-		    {1,2,2,2,3,3,3,2,2,2,3,2,1},
-		    {1,2,2,2,3,3,3,3,3,3,3,2,1},
-		    {1,2,2,2,2,2,2,2,2,2,2,2,1},
-		    {1,1,1,1,1,1,1,1,1,1,1,1,1}};
-
-
-  image2d<int> lena_(make::image2d(vs));
-  image2d<int_u8> lena(lena_.domain());
-  level::fill(lena, lena_);
+
+  int vs[8][9] = { {2,2,2,2,2,2,2,2,2},
+		   {2,2,2,2,2,2,2,2,2},
+		   {2,1,1,1,1,1,1,1,2},
+		   {2,1,2,2,1,0,0,1,2},
+		   {2,1,2,2,1,0,4,1,2},
+		   {2,1,2,2,1,0,0,1,2},
+		   {2,1,1,1,1,1,1,1,2},
+		   {2,2,2,2,2,2,2,2,2} };
+
+//  int vs[10][13] = { {1,1,1,1, 1,1,1,1, 1,1,1,1,1},
+// 		    {1,2,2,2,2,2,2,2,2,2,2,2,1},
+// 		    {1,2,2,2,2,2,2,2,2,2,2,2,1},
+// 		    {1,2,2,2,3,3,3,3,3,3,3,2,1},
+// 		    {1,2,2,2,3,3,3,2,2,2,3,2,1},
+// 		    {1,2,2,2,3,4,3,2,4,4,3,2,1},
+
+// 		    {1,2,2,2,3,3,3,2,2,2,3,2,1},
+// 		    {1,2,2,2,3,3,3,3,3,3,3,2,1},
+// 		    {1,2,2,2,2,2,2,2,2,2,2,2,1},
+// 		    {1,1,1,1,1,1,1,1,1,1,1,1,1}};
+
+
+//   image2d<int> lena_(make::image2d(vs));
+//   image2d<int_u8> lena(lena_.domain());
+//   level::fill(lena, lena_);
 
   tree_type tree = my::fllt(lena);
+   compute_area(lena, tree);
 
-  draw_tree(lena, tree);
+  image2d<value::int_u8> output (lena.domain ());
+  area_filter(output, tree.root(), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
+  io::pgm::save(output, "out.pgm");
 
-  io::pgm::save(lena, "./out.pgm");
+  //  draw_tree(lena, tree);
 }
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0