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
 
                    
                        	* mln/registration/icp2.hh: Add two new variants.
---
 milena/ChangeLog                |    6 +
 milena/mln/registration/icp2.hh |  565 +++++++++++++++++++++++++++++++--------
 2 files changed, 457 insertions(+), 114 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 8960f74..e6b8418 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,4 +1,10 @@
 2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
+	Add new ICP variants.
+
+	* mln/registration/icp2.hh: Add two new variants.
+
+2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
     
 	Small changes in transformation related classes.
 
diff --git a/milena/mln/registration/icp2.hh b/milena/mln/registration/icp2.hh
index 2993caa..070b4d9 100644
--- a/milena/mln/registration/icp2.hh
+++ b/milena/mln/registration/icp2.hh
@@ -32,6 +32,8 @@
 ///
 /// Register an image over an another using the ICP algorithm.
 
+# include <algorithm>
+
 # include <mln/core/alias/vec3d.hh>
 # include <mln/math/jacobi.hh>
 # include <mln/fun/x2x/all.hh>
@@ -49,6 +51,24 @@
 # include <mln/canvas/distance_geodesic.hh>
 # include <mln/pw/all.hh>
 
+# include <mln/io/ppm/save.hh>
+# include <mln/io/pbm/save.hh>
+# include <mln/debug/colorize.hh>
+
+# include <mln/literal/black.hh>
+# include <mln/literal/white.hh>
+# include <mln/literal/colors.hh>
+
+# include <mln/core/image/slice_image.hh>
+# include <mln/util/timer.hh>
+
+#include <mln/core/image/tr_image.hh>
+#include <mln/core/image/extension_fun.hh>
+
+#include <mln/accu/histo.hh>
+#include <mln/debug/histo.hh>
+
+
 namespace mln
 {
 
@@ -61,8 +81,8 @@ namespace mln
     /*! Register point in \p c using a function of closest points
      * \p closest_point.
      *
-     * \param[in] data_P The cloud of points.
-     * \param[in] model_X the reference surface.
+     * \param[in] P_ The cloud of points.
+     * \param[in] X the reference surface.
      * \param[in] closest_point The function of closest points.
      * \param[out] qk The rigid transformation obtained.
      *
@@ -73,54 +93,84 @@ namespace mln
      * vector as arguments. Otherwise the resulting transformation may be
      * wrong due to the truncation of the vector coordinate values.
      *
-     * \pre \p data_p and \p model_X must not be empty.
+     * \pre \p P_ and \p X must not be empty.
      *
      * Reference article: "A Method for Registration of 3-D Shapes", Paul J.
      * Besl and Neil D. McKay, IEEE, 2, February 1992.
      *
      */
     template <typename P, typename F>
-    composed< rotation<P::dim,float>,translation<P::dim,float> >
-    icp(const p_array<P>& data_P,
-	const p_array<P>& model_X,
+//    composed< translation<P::dim,float>,rotation<P::dim,float> >
+    std::pair<algebra::quat,mln_vec(P)>
+    icp(const p_array<P>& P_,
+	const p_array<P>& X,
 	const F& closest_point,
 	const algebra::quat& initial_rot,
 	const mln_vec(P)& initial_translation);
 
     template <typename P, typename F>
-    composed< rotation<P::dim,float>,translation<P::dim,float> >
-    icp(const p_array<P>& data_P,
-	const p_array<P>& model_X,
+    composed< translation<P::dim,float>,rotation<P::dim,float> >
+    icp(const p_array<P>& P_,
+	const p_array<P>& X,
 	const F& closest_point);
 
 # ifndef MLN_INCLUDE_ONLY
 
     /// Closest point functor based on map distance.
     template <typename P>
-    class cp_with_map_t
+    class closest_point_with_map
     {
       typedef mln_image_from_grid(mln_grid(P), P) I;
       typedef mln_ch_value(I, P) cp_ima_t;
+      typedef mln_ch_value(I,value::int_u8) dmap_t;
 
     public:
 
-      cp_with_map_t(const p_array<P>& model_X)
+      closest_point_with_map(const p_array<P>& X)
       {
-	box3d box = geom::bbox(model_X);
-	box.enlarge(50);
+	box3d box = geom::bbox(X);
+	box.enlarge(1, box.nrows() / 2);
+	box.enlarge(2, box.ncols() / 2);
+	std::cout << "Map image defined on " << box << std::endl;
 
 	typedef mln_ch_value(I, bool) model_t;
 	model_t model(box);
 	data::fill(model, false);
-	data::fill((model | model_X).rw(), true);
+	data::fill((model | X).rw(), true);
 
-	transform::internal::closest_point_functor<I> f;
-	typedef mln_ch_value(I,value::int_u16) dmap_t;
-	dmap_t dmap_X = canvas::distance_geodesic(model, c6(),
-						  mln_max(value::int_u16),
-						  f);
+	transform::internal::closest_point_functor<model_t> f;
+	util::timer t;
+	t.start();
+	dmap_X_ = canvas::distance_geodesic(model, c6(),
+					    mln_max(value::int_u8),
+					    f);
+	std::cout << "canvas::distance_geodesic - " << t << "s" << std::endl;
 
 	cp_ima_ = f.cp_ima;
+
+#ifndef NDEBUG
+	mln_ch_value(I, bool) debug2(box);
+	data::fill(debug2, false);
+	mln_ch_value(I, value::rgb8) debug(box);
+	mln_piter(p_array<P>) p(X);
+	for_all(p)
+	{
+	  debug(p) = debug::internal::random_color(value::rgb8());
+	  debug2(p) = true;
+	}
+	io::pbm::save(slice(debug2,0), "debug2-a.ppm");
+
+	mln_piter(I) pi(cp_ima_.domain());
+	for_all(pi)
+	{
+	  debug(pi) = debug(cp_ima_(pi));
+	  debug2(pi) = debug2(cp_ima_(pi));
+	}
+
+	io::pbm::save(slice(debug2,0), "debug2-b.ppm");
+	io::ppm::save(slice(debug,0), "debug.ppm");
+	std::cout << "map saved" << std::endl;
+#endif
       }
 
       mln_site(I) operator()(const mln_site(I)& p) const
@@ -128,6 +178,7 @@ namespace mln
 	return cp_ima_(p);
       }
 
+      dmap_t dmap_X_;
     private:
       cp_ima_t cp_ima_;
     };
@@ -135,40 +186,27 @@ namespace mln
 
     /// Closest point functor based on map distance.
     template <typename P>
-    class basic_closest_point
+    class closest_point_basic
     {
       typedef mln_image_from_grid(mln_grid(P), P) I;
       typedef p_array<P> X_t;
 
     public:
 
-      basic_closest_point(const p_array<P>& X)
+      closest_point_basic(const p_array<P>& X)
 	: X_(X)
       {
       }
 
-      float
-      l2_distance(const vec3d_f& vec1, const vec3d_f& vec2) const
-      {
-	typedef float D;
-	D d = 0;
-	for (unsigned i = 0; i < 3; ++i)
-	  {
-	    D sqr_v1_v2 = static_cast<D>(mln::math::sqr(vec1[i] - vec2[i]));
-	    d = static_cast<D>(d + sqr_v1_v2);
-	  }
-	return d;
-      }
-
       mln_site(I) operator()(const vec3d_f& v) const
       {
 	vec3d_f best_x = convert::to<vec3d_f>(X_[0].to_vec());
 
-	float best_d = l2_distance(v, best_x);
+	float best_d = norm::l2_distance(v, best_x);
 	mln_piter(X_t) X_i(X_);
 	for_all(X_i)
 	{
-	  float d = l2_distance(v, convert::to<vec3d_f>(X_i));
+	  float d = norm::l2_distance(v, convert::to<vec3d_f>(X_i));
 	  if (d < best_d)
 	  {
 	    best_d = d;
@@ -183,61 +221,146 @@ namespace mln
     };
 
 
+    template <typename P>
+    void
+    draw_last_run(const box3d& box, const p_array<P>& kept,
+		  const p_array<P>& removed, const p_array<P>& X,
+		  const algebra::quat& qR, const vec3d_f qT)
+    {
+      typedef image3d<value::rgb8> result_t;
+      result_t result(box);
+      typedef extension_fun<result_t,pw::cst_<mln_value(result_t)> > ext_result_t;
+      ext_result_t ext_result(result, pw::cst(value::rgb8(0,0,0)));
+
+      data::fill(ext_result, literal::black);
+      data::fill((ext_result | X).rw(), literal::white);
+
+      mln_piter(p_array<P>) p(kept);
+      for_all(p)
+	ext_result(qR.rotate(p.to_vec()) + qT) = literal::green;
+
+      mln_piter(p_array<P>) p2(removed);
+      for_all(p2)
+	ext_result(qR.rotate(p2.to_vec()) + qT) = literal::red;
+
+      io::ppm::save(slice(ext_result,0), "registered-2.ppm");
+    }
+
+
+
     template <typename P, typename F>
-    inline
-    float
-    compute_d_k(const p_array<P>& data_P,
-		const F& closest_point,
-		const algebra::quat& qR,
-		const algebra::quat& qR_old,
-		const vec3d_f& qT,
-		const vec3d_f& qT_old)
+    float compute_standard_deviation(const p_array<P>& P_,
+				     const std::pair<algebra::quat,mln_vec(P)>& pair,
+				     const F& closest_point)
     {
-      accu::rms<vec3d_f, float> accu;
-      mln_piter(p_array<P>) p(data_P);
+      accu::rms<vec3d_f,float> e_k_accu;
+
+      // Standard Deviation
+      float sd;
+      mln_piter(p_array<P>) p(P_);
       for_all(p)
       {
-	// yk_i - pk+1_i
-	vec3d_f Pk_i = qR_old.rotate(p.to_vec()) + qT_old;
-	vec3d_f Pk_1_i = qR.rotate(p.to_vec()) + qT;
-        accu.take(closest_point(Pk_i).to_vec() - Pk_1_i);
+	vec3d_f Pk_i = pair.first.rotate(p.to_vec()) + pair.second;
+	vec3d_f Yk_i = closest_point(Pk_i).to_vec();
+	// yk_i - pk_i
+	e_k_accu.take(Yk_i - Pk_i);
       }
-      return accu.to_result();
+
+      float d = e_k_accu.to_result();
+      sd = math::sqrt((e_k_accu.hook_value_() - 2.5 * math::sqr(d)) / P_.nsites());
+      return sd;
     }
 
+
+    template <typename P, typename F>
+    p_array<P>
+    remove_too_far_sites(image3d<value::rgb8>& out, const p_array<P>& P_bak,
+			 const F& closest_point,
+			 const std::pair<algebra::quat,mln_vec(P)>& pair,
+			 const p_array<P>& X, p_array<P>& removed_set,
+			 unsigned r)
+    {
+      float sd = compute_standard_deviation(P_bak, pair, closest_point);
+      std::cout << "Standard deviation = " << sd << std::endl;
+
+      p_array<P> tmp;
+      unsigned removed = 0;
+
+      data::fill(out, literal::white);
+      data::fill((out | X).rw(), literal::black);
+
+      accu::histo<value::int_u8> h;
+      mln_piter(p_array<P>) p(P_bak);
+      for_all(p)
+      {
+	vec3d_f Pk_i = pair.first.rotate(p.to_vec()) + pair.second;
+	vec3d_f Yk_i = closest_point(Pk_i).to_vec();
+
+	float norm = norm::l2_distance(Yk_i, Pk_i);
+	h.take(closest_point.dmap_X_(Pk_i));
+	if (norm < sd && norm > sd / 2)
+	{
+	  tmp.append(p);
+	  out(Pk_i) = literal::green;
+	}
+	else
+	{
+	  ++removed;
+	  removed_set.append(p);
+	  out(Pk_i) = literal::red;
+	}
+      }
+
+      std::ostringstream ss1;
+      ss1 << "histo_" << r << ".dat";
+      debug::histo_plot(h, ss1.str());
+      std::cout << h << std::endl;
+
+      std::ostringstream ss2;
+      ss2 << "out_0" << r << ".ppm";
+      io::ppm::save(mln::slice(out,0), ss2.str());
+
+      std::cout << "Points removed: " << removed << std::endl;
+
+      return tmp;
+    }
+
+
     template <typename P, typename F>
     inline
     float
-    compute_e_k(const p_array<P>& data_P,
+    compute_d_k(const p_array<P>& P_,
 		const F& closest_point,
 		const algebra::quat& qR,
-		const vec3d_f& qT)
+		const algebra::quat& qR_old,
+		const vec3d_f& qT,
+		const vec3d_f& qT_old)
     {
       accu::rms<vec3d_f, float> accu;
-      mln_piter(p_array<P>) p(data_P);
+      mln_piter(p_array<P>) p(P_);
       for_all(p)
       {
-	// yk_i - pk_i
-	vec3d_f Pk_i = qR.rotate(p.to_vec()) + qT;
-        accu.take(closest_point(Pk_i).to_vec() - Pk_i);
+	// yk_i - pk+1_i
+	vec3d_f Pk_i = qR_old.rotate(p.to_vec()) + qT_old;
+	vec3d_f Pk_1_i = qR.rotate(p.to_vec()) + qT;
+        accu.take(closest_point(Pk_i).to_vec() - Pk_1_i);
       }
       return accu.to_result();
     }
 
-
     /// FIXME: work only for 3d images.
     template <typename P, typename F>
     algebra::quat
-    get_rot(const p_array<P>& data_P,
+    get_rot(const p_array<P>& P_,
             const vec3d_f& mu_P,
             const vec3d_f& mu_Yk,
 	    const F& closest_point,
 	    const algebra::quat& qR,
 	    const vec3d_f& qT)
     {
-      /// Mk: cross-covariance matrix.
-      algebra::mat<3u,3u,float> Mk;
-      mln_piter(p_array<P>) p(data_P);
+      /// Spx: cross-covariance matrix.
+      algebra::mat<3u,3u,float> Spx;
+      mln_piter(p_array<P>) p(P_);
 
       // FIXME: could we use an accu?
       for_all(p)
@@ -245,17 +368,17 @@ namespace mln
 	vec3d_f P_i  = p.to_vec();
 	vec3d_f Pk_i = qR.rotate(p.to_vec()) + qT;
 	vec3d_f Yk_i = closest_point(Pk_i).to_vec();
-	Mk += make::mat(P_i - mu_P) * trans(make::mat(Yk_i - mu_Yk));
+	Spx += make::mat(P_i - mu_P) * trans(make::mat(Yk_i - mu_Yk));
       }
-      Mk /= data_P.nsites();
+      Spx /= P_.nsites();
 
       vec3d_f A;
-      A[0] = Mk(1,2) - Mk(2,1);
-      A[1] = Mk(2,0) - Mk(0,2);
-      A[2] = Mk(0,1) - Mk(1,0);
+      A[0] = Spx(1,2) - Spx(2,1);
+      A[1] = Spx(2,0) - Spx(0,2);
+      A[2] = Spx(0,1) - Spx(1,0);
 
       algebra::mat<4u,4u,float> Qk;
-      float t = tr(Mk);
+      float t = tr(Spx);
 
       Qk(0,0) = t;
       for (int i = 1; i < 4; ++i)
@@ -264,17 +387,17 @@ namespace mln
         Qk(0,i) = A[i - 1];
         for (int j = 1; j < 4; ++j)
           if (i == j)
-            Qk(i,j) = 2 * Mk(i - 1,i - 1) - t;
+            Qk(i,j) = 2 * Spx(i - 1,i - 1) - t;
       }
 
-      Qk(1,2) = Mk(0,1) + Mk(1,0);
-      Qk(2,1) = Mk(0,1) + Mk(1,0);
+      Qk(1,2) = Spx(0,1) + Spx(1,0);
+      Qk(2,1) = Spx(0,1) + Spx(1,0);
 
-      Qk(1,3) = Mk(0,2) + Mk(2,0);
-      Qk(3,1) = Mk(0,2) + Mk(2,0);
+      Qk(1,3) = Spx(0,2) + Spx(2,0);
+      Qk(3,1) = Spx(0,2) + Spx(2,0);
 
-      Qk(2,3) = Mk(1,2) + Mk(2,1);
-      Qk(3,2) = Mk(1,2) + Mk(2,1);
+      Qk(2,3) = Spx(1,2) + Spx(2,1);
+      Qk(3,2) = Spx(1,2) + Spx(2,1);
 
       return mln::math::jacobi(Qk);
     }
@@ -284,63 +407,83 @@ namespace mln
     template <typename P, typename F>
     inline
     vec3d_f
-    get_mu_yk(const p_array<P>& data_P,
+    get_mu_yk(const p_array<P>& P_,
 	      const F& closest_point,
 	      const algebra::quat& qR,
-	      const vec3d_f& qT)
+	      const vec3d_f& qT,
+	      float& e_k)
     {
-      accu::center<P,vec3d_f> accu;
+      accu::rms<vec3d_f,float> e_k_accu;
+      accu::center<P,vec3d_f> mu_yk;
 
-      mln_piter(p_array<P>) p(data_P);
+      mln_piter(p_array<P>) p(P_);
       for_all(p)
       {
+	// yk_i - pk_i
 	vec3d_f Pk_i = qR.rotate(p.to_vec()) + qT;
-	accu.take(closest_point(Pk_i).to_vec());
+	vec3d_f Yk_i = closest_point(Pk_i).to_vec();
+	mu_yk.take(Yk_i);
+        e_k_accu.take(Yk_i - Pk_i);
       }
-      return accu.to_result();
+
+      e_k = e_k_accu.to_result();
+      return mu_yk.to_result();
     }
 
 
+
+    /// Base version of the ICP algorithm. It is called in other variants.
     template <typename P, typename F>
     inline
-    composed< rotation<P::dim,float>,translation<P::dim,float> >
-    icp(const p_array<P>& data_P,
-	const p_array<P>& model_X,
+//    composed< translation<P::dim,float>,rotation<P::dim,float> >
+    std::pair<algebra::quat,mln_vec(P)>
+    icp(const p_array<P>& P_,
+	const p_array<P>& X,
 	const F& closest_point,
 	const algebra::quat& initial_rot,
 	const mln_vec(P)& initial_translation)
     {
       trace::entering("registration::icp");
 
+      (void) X;
       mln_precondition(P::dim == 3);
-      mln_precondition(!data_P.is_empty());
-      mln_precondition(!model_X.is_empty());
+      mln_precondition(!P_.is_empty());
+      mln_precondition(!X.is_empty());
       mln_precondition(!initial_rot.is_null());
 
       typedef p_array<P> cloud_t;
 
-      vec3d_f mu_P = set::compute(accu::center<P,vec3d_f>(), data_P);
+      vec3d_f mu_P = set::compute(accu::center<P,vec3d_f>(), P_);
 
       vec3d_f qT_old, qT = initial_translation;
       algebra::quat qR_old, qR = initial_rot;
-      float ek, ek_old = mln_max(float);
-      float dk, dk_old = mln_max(float);
+      float e_k, e_k_old = mln_max(float);
+      float d_k, d_k_old = mln_max(float);
       unsigned k = 0;
+
+# ifndef NDEBUG
+      box3d box = geom::bbox(X);
+      //FIXME: too large?
+      box.enlarge(1, box.nrows() / 2);
+      box.enlarge(2, box.ncols() / 2);
+      image3d<value::rgb8> debug(box);
+      data::fill(debug, literal::black);
+      data::fill((debug | X).rw(), literal::white);
+# endif
+
       do
       {
 	qT_old = qT;
 	qR_old = qR;
 
-	// Compute error ek = d(Pk,Yk)
-	ek = compute_e_k(data_P, closest_point, qR, qT);
-
       /// Compute transformation
       ///
 	// mu_Yk - Pk's mass center.
-	vec3d_f mu_Yk = get_mu_yk(data_P, closest_point, qR_old, qT_old);
+	// + Compute error ek = d(Pk,Yk)
+	vec3d_f mu_Yk = get_mu_yk(P_, closest_point, qR_old, qT_old, e_k);
 
 	// quaternion qR - rotation
-	qR = get_rot(data_P, mu_P, mu_Yk, closest_point, qR_old, qT_old);
+	qR = get_rot(P_, mu_P, mu_Yk, closest_point, qR_old, qT_old);
 	vec3d_f tmp = qR.v();
 
 	// vector qT - translation
@@ -349,42 +492,236 @@ namespace mln
       /// End of "compute transformation"
 
 	// Distance dk = d(Pk+1, Yk)
-	dk = compute_d_k(data_P, closest_point, qR, qR_old, qT, qT_old);
-
-	// Check property according the related paper.
-	mln_assertion(0 <= dk);
-	mln_assertion(dk <= ek);
-	mln_assertion(ek <= dk_old);
-	mln_assertion(dk_old <= ek_old);
+	d_k = compute_d_k(P_, closest_point, qR, qR_old, qT, qT_old);
+
+
+#ifndef NDEBUG
+	image3d<value::rgb8> tmp_ = duplicate(debug);
+	mln_piter(p_array<P>) p_dbg(P_);
+	for_all(p_dbg)
+	  tmp_(qR_old.rotate(p_dbg.to_vec()) + qT_old) = literal::green;
+	std::ostringstream ss;
+	ss << "reg/tmp_0";
+	if (k < 10)
+	  ss << "0";
+	ss << k << ".ppm";
+	io::ppm::save(mln::slice(tmp_,0), ss.str());
+#endif
+
+	std::cout << "e_" << k << "=" << e_k << std::endl;
+	std::cout << "d_" << k << "=" << d_k << std::endl;
+
+	// Check distance and error according to the related paper.
+	mln_assertion(0 <= d_k);
+	mln_assertion(d_k <= e_k);
+
+	// Disabled because of the following 'if'
+//	mln_assertion(e_k <= d_k_old);
+//	mln_assertion(d_k_old <= e_k_old);
+
+	if (d_k > d_k_old)
+	{
+	  qR = qR_old;
+	  qT = qT_old;
+	  break;
+	}
 
 	// Backing up results.
-	dk_old = dk;
-	ek_old = ek;
+	d_k_old = d_k;
+	e_k_old = e_k;
 
 	++k;
 
       } while ((k < 3)
-	  || norm::l2((qT - qT_old)) + norm::l2((qR - qR_old).to_vec()) > 1e-5);
+	  || norm::l2((qT - qT_old)) + norm::l2((qR - qR_old).to_vec()) > 1e-3);
+
+      trace::exiting("registration::icp");
+      return std::make_pair(qR, qT);
+    }
+
+
+
+    /// Single call to ICP with all sites.
+    template <typename P, typename F>
+    inline
+    composed< translation<P::dim,float>,rotation<P::dim,float> >
+    icp(const p_array<P>& P_,
+	const p_array<P>& X,
+	const F& closest_point)
+    {
+      util::timer t;
+      t.start();
+
+      std::pair<algebra::quat,mln_vec(P)> pair = icp(P_, X, closest_point,
+						     algebra::quat(1,0,0,0),
+						     literal::zero);
+      std::cout << "icp = " << t << std::endl;
 
       typedef rotation<3u,float> rot_t;
-      rot_t tqR(qR);
+      rot_t tqR(pair.first);
       typedef translation<3u,float> trans_t;
-      trans_t tqT(qT);
-      composed<rot_t,trans_t> result(tqR, tqT);
+      trans_t tqT(pair.second);
+      composed<trans_t, rot_t> result(tqT, tqR);
 
-      trace::exiting("registration::icp");
       return result;
     }
 
+
+    /// Shuffle the sites in P_.
+    /// Use one third of P_'s sites for each run.
+    /// For each run, it removes sites which are too close or too far.
     template <typename P, typename F>
     inline
-    composed< rotation<P::dim,float>,translation<P::dim,float> >
-    icp(const p_array<P>& data_P,
-	const p_array<P>& model_X,
-	const F& closest_point)
+    composed< translation<P::dim,float>,rotation<P::dim,float> >
+    icp_clean(const p_array<P>& P_,
+	      const p_array<P>& X,
+	      const F& closest_point)
     {
-      return icp(data_P, model_X, closest_point,
-		 algebra::quat(1,0,0,0), literal::zero);
+      util::timer t;
+      t.start();
+
+      // P_bak is shuffled.
+      p_array<P> P_bak = P_;
+      std::vector<mln_element(p_array<P>)>& v = P_bak.hook_std_vector_();
+      std::random_shuffle(v.begin(), v.end());
+
+      // P_sub = 1/3 * P_bak;
+      p_array<P> P_sub = P_bak;
+      P_sub.hook_std_vector_().resize(P_bak.nsites() / 3);
+
+      unsigned r = 0;
+      std::pair<algebra::quat,mln_vec(P)> pair;
+      pair.first = algebra::quat(1,0,0,0);
+      pair.second = literal::zero;
+      box3d box = geom::bbox(X);
+      box.enlarge(40);
+      image3d<value::rgb8> out(box);
+      p_array<P> removed_set;
+      do
+      {
+	/// Compute transformation.
+	pair = icp(P_sub, X, closest_point,
+		   pair.first,
+		   pair.second);
+
+	pair = icp(P_sub, X, closest_point,
+		   pair.first,
+		   pair.second);
+
+	P_sub = remove_too_far_sites(out, P_sub,
+				     closest_point, pair, X, removed_set, r);
+
+
+	++r;
+
+	//Add more data
+	if (r < 3)
+	  for (unsigned i = (P_bak.nsites() / 3) * r;
+	      i < (P_bak.nsites() / 3) * (r + 1); ++i)
+	  {
+	    P_sub.append(P_bak[i]);
+	  }
+
+      } while (r < 4);
+      std::cout << "icp = " << t << std::endl;
+
+      typedef rotation<3u,float> rot_t;
+      rot_t tqR(pair.first);
+      typedef translation<3u,float> trans_t;
+      trans_t tqT(pair.second);
+      composed<trans_t,rot_t> result(tqT, tqR);
+
+      return result;
+    }
+
+
+    /// Shuffle sites in P_.
+    /// Do the first run with all sites.
+    /// For each run, remove sites which are too far or too close.
+    template <typename P, typename F>
+    inline
+    composed< translation<P::dim,float>,rotation<P::dim,float> >
+    icp_clean2(const p_array<P>& P_,
+	      const p_array<P>& X,
+	      const F& closest_point)
+    {
+      util::timer t;
+      t.start();
+
+      // P_bak is shuffled.
+      p_array<P> P_bak = P_;
+
+      unsigned r = 0;
+      std::pair<algebra::quat,mln_vec(P)> pair;
+      pair.first = algebra::quat(1,0,0,0);
+      pair.second = literal::zero;
+      box3d box = geom::bbox(X);
+      box.enlarge(40);
+      image3d<value::rgb8> out(box);
+      p_array<P> removed_set;
+      do
+      {
+	pair = icp(P_bak, X, closest_point,
+		   pair.first,
+		   pair.second);
+
+	P_bak = remove_too_far_sites(out, P_bak,
+				     closest_point, pair, X, removed_set, r);
+
+	++r;
+
+      } while (r < 4);
+      std::cout << "icp = " << t << std::endl;
+
+      draw_last_run(box, P_bak, removed_set, X, pair.first, pair.second);
+
+      typedef rotation<3u,float> rot_t;
+      rot_t tqR(pair.first);
+      typedef translation<3u,float> trans_t;
+      trans_t tqT(pair.second);
+      composed<trans_t,rot_t> result(tqT, tqR);
+
+      return result;
+    }
+
+
+
+    /// Run icp once with 1/10 of the sites and run it once again with the
+    /// resulting tranformation and all the sites.
+    template <typename P, typename F>
+    inline
+    composed< translation<P::dim,float>,rotation<P::dim,float> >
+    icp_fast(const p_array<P>& P_,
+	     const p_array<P>& X,
+	     const F& closest_point)
+    {
+      typedef std::pair<algebra::quat,mln_vec(P)> pair_t;
+
+      p_array<P> P_sub = P_;
+      std::vector<mln_element(p_array<P>)>& v = P_sub.hook_std_vector_();
+      std::random_shuffle(v.begin(), v.end());
+      v.resize(P_.nsites() / 10);
+
+      util::timer t;
+      t.start();
+      pair_t tmp = icp(P_sub, X, closest_point,
+		     algebra::quat(1,0,0,0), literal::zero);
+
+      std::cout << "icp_1 - " << t << "s" << std::endl;
+      t.restart();
+
+      pair_t tmp2 = icp(P_, X, closest_point,
+			tmp.first, tmp.second);
+
+      std::cout << "icp_2 - " << t << "s" << std::endl;
+
+      typedef rotation<3u,float> rot_t;
+      rot_t tqR(tmp2.first);
+      typedef translation<3u,float> trans_t;
+      trans_t tqT(tmp2.second);
+      composed<rot_t,trans_t> result(tqR, tqT);
+
+      return result;
     }
 
 # endif // ! MLN_INCLUDE_ONLY
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        	* mln/algebra/quat.hh: use mln_precondition instead of assert.
	* mln/core/image/interpolated.hh: add a fixme.
	* mln/fun/x2x/translation.hh: add a missing accessor to the
	translation vector.
	* mln/transform/internal/closest_point_functor.hh: fix wrong update of
	the closest point image.
---
 milena/ChangeLog                                   |   14 ++++++++++++++
 milena/mln/algebra/quat.hh                         |    2 +-
 milena/mln/core/image/interpolated.hh              |    1 +
 milena/mln/fun/x2x/translation.hh                  |   11 +++++++++++
 .../transform/internal/closest_point_functor.hh    |    2 +-
 5 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 25aa240..8960f74 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,4 +1,18 @@
 2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
+    
+	Small changes in transformation related classes.
+
+	* mln/algebra/quat.hh: use mln_precondition instead of assert.
+
+	* mln/core/image/interpolated.hh: add a fixme.
+
+	* mln/fun/x2x/translation.hh: add a missing accessor to the
+	translation vector.
+
+	* mln/transform/internal/closest_point_functor.hh: fix wrong update of
+	the closest point image.
+
+2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
 	Fix make::h_mat.
 
diff --git a/milena/mln/algebra/quat.hh b/milena/mln/algebra/quat.hh
index 9dee769..33e7d07 100644
--- a/milena/mln/algebra/quat.hh
+++ b/milena/mln/algebra/quat.hh
@@ -410,7 +410,7 @@ namespace mln
     inline
     quat quat::inv() const
     {
-      assert(! is_null());
+      mln_precondition(! is_null());
       float f = norm::l2(v_);
       return conj().to_vec() / (f * f);
     }
diff --git a/milena/mln/core/image/interpolated.hh b/milena/mln/core/image/interpolated.hh
index 5b37eb5..70250f6 100644
--- a/milena/mln/core/image/interpolated.hh
+++ b/milena/mln/core/image/interpolated.hh
@@ -105,6 +105,7 @@ namespace mln
 
 
     /// Constructors.
+    ///FIXME: don't we want a 'const' here?
     interpolated(I& ima);
     interpolated();
 
diff --git a/milena/mln/fun/x2x/translation.hh b/milena/mln/fun/x2x/translation.hh
index 6d1e707..4101d77 100644
--- a/milena/mln/fun/x2x/translation.hh
+++ b/milena/mln/fun/x2x/translation.hh
@@ -75,6 +75,9 @@ namespace mln
         /// Set a net translation vector.
         void set_t(const algebra::vec<n,C>& t);
 
+	/// Return the translation vector.
+	const algebra::vec<n,C>& t() const;
+
       protected:
         void update();
 
@@ -127,6 +130,14 @@ namespace mln
 
       template <unsigned n, typename C>
       inline
+      const algebra::vec<n,C>&
+      translation<n,C>::t() const
+      {
+        return this->t_;
+      }
+
+      template <unsigned n, typename C>
+      inline
       void
       translation<n,C>::update()
       {
diff --git a/milena/mln/transform/internal/closest_point_functor.hh b/milena/mln/transform/internal/closest_point_functor.hh
index 02b3401..eff0e96 100644
--- a/milena/mln/transform/internal/closest_point_functor.hh
+++ b/milena/mln/transform/internal/closest_point_functor.hh
@@ -98,7 +98,7 @@ namespace mln
       inline
       void closest_point_functor<I>::process(const P& p, const P& n)
       {
-	cp_ima(n) = p;
+	cp_ima(n) = cp_ima(p);
       }
 
 # endif // ! MLN_INCLUDE_ONLY
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        	* mln/make/h_mat.hh: fix wrong loop.
	* tests/make/Makefile.am,
	* tests/make/h_mat.cc: add a missing test.
---
 milena/ChangeLog              |    9 ++++++
 milena/mln/make/h_mat.hh      |   13 ++++----
 milena/tests/make/Makefile.am |    2 +
 milena/tests/make/h_mat.cc    |   65 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 83 insertions(+), 6 deletions(-)
 create mode 100644 milena/tests/make/h_mat.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 219f400..25aa240 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,14 @@
 2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	Fix make::h_mat.
+
+	* mln/make/h_mat.hh: fix wrong loop.
+
+	* tests/make/Makefile.am,
+	* tests/make/h_mat.cc: add a missing test.
+	
+2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	Fix wrong comments in fun::x2x:composed.
 
 	* mln/fun/x2x/composed.hh: Comments were wrong, they are fixed. The
diff --git a/milena/mln/make/h_mat.hh b/milena/mln/make/h_mat.hh
index 930c133..243278d 100644
--- a/milena/mln/make/h_mat.hh
+++ b/milena/mln/make/h_mat.hh
@@ -78,22 +78,23 @@ namespace mln
     template <typename T, unsigned d>
     inline
     algebra::h_mat<d,T>
-    h_mat(const T (&tab)[(d+1)*(d+1)])
+    h_mat(const T (&tab)[(d)*(d)])
     {
+      std::cout << "plap" << std::endl;
       algebra::h_mat<d,T> tmp;
-      for (unsigned i = 0; i <= d; ++i)
-	tmp(i / (d+1), i % (d+1)) = tab[i];
+      for (unsigned i = 0; i < d; ++i)
+	tmp(i / (d), i % (d)) = tab[i];
       return tmp;
     }
 
 
     template <typename T, unsigned d>
     algebra::h_mat<d,T>
-    h_mat(const T (&tab)[d+1][d+1])
+    h_mat(const T (&tab)[d][d])
     {
       algebra::h_mat<d,T> tmp;
-      for (unsigned i = 0; i <= d; ++i)
-        for (unsigned j = 0; j <= d; ++j)
+      for (unsigned i = 0; i < d; ++i)
+        for (unsigned j = 0; j < d; ++j)
 	  tmp(i, j) = tab[i][j];
       return tmp;
     }
diff --git a/milena/tests/make/Makefile.am b/milena/tests/make/Makefile.am
index 7d0c2f5..913867c 100644
--- a/milena/tests/make/Makefile.am
+++ b/milena/tests/make/Makefile.am
@@ -4,6 +4,7 @@ include $(top_srcdir)/milena/tests/tests.mk
 
 check_PROGRAMS =				\
   dual_neighb					\
+  h_mat 					\
   image2d					\
   image3d					\
   mat						\
@@ -11,6 +12,7 @@ check_PROGRAMS =				\
   w_window_directional
 
 dual_neighb_SOURCES = dual_neighb.cc
+h_mat_SOURCES = h_mat.cc
 image2d_SOURCES = image2d.cc
 image3d_SOURCES = image3d.cc
 mat_SOURCES = mat.cc
diff --git a/milena/tests/make/h_mat.cc b/milena/tests/make/h_mat.cc
new file mode 100644
index 0000000..a8df474
--- /dev/null
+++ b/milena/tests/make/h_mat.cc
@@ -0,0 +1,65 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/make/h_mat.cc
+///
+/// Tests on mln::make::h_mat.
+
+#include <mln/make/h_mat.hh>
+
+
+static const int result[4][4] = { { 2, 3,  4, 0 },
+				  { 5, 6,  7, 0 },
+				  { 8, 9, 10, 0 },
+				  { 0, 0,  0, 1 } };
+
+int main()
+{
+  using namespace mln;
+
+  {
+    int vals[9] = { 2, 3,  4,
+      5, 6,  7,
+      8, 9, 10 };
+    algebra::h_mat<3,int> m = make::h_mat(vals);
+
+    for (unsigned i = 0; i < 4; ++i)
+      for (unsigned j = 0; j < 4; ++j)
+	mln_assertion(m(i,j) == result[i][j]);
+  }
+
+  {
+    int vals[3][3] = { { 2, 3,  4 },
+		       { 5, 6,  7 },
+		       { 8, 9, 10 } };
+    algebra::h_mat<3,int> m = make::h_mat(vals);
+
+    for (unsigned i = 0; i < 4; ++i)
+      for (unsigned j = 0; j < 4; ++j)
+	mln_assertion(m(i,j) == result[i][j]);
+  }
+}
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        	* mln/fun/x2x/composed.hh: Comments were wrong, they are fixed. The
	template parameter names are also more explicit.
---
 milena/ChangeLog               |    7 ++
 milena/mln/fun/x2x/composed.hh |  146 +++++++++++++++++++--------------------
 2 files changed, 78 insertions(+), 75 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 772b56b..219f400 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,12 @@
 2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	Fix wrong comments in fun::x2x:composed.
+
+	* mln/fun/x2x/composed.hh: Comments were wrong, they are fixed. The
+	template parameter names are also more explicit.
+
+2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	Add is_valid() to window and neighborhood.
 
 	* mln/core/internal/neighborhood_base.hh,
diff --git a/milena/mln/fun/x2x/composed.hh b/milena/mln/fun/x2x/composed.hh
index b8df088..1509f1c 100644
--- a/milena/mln/fun/x2x/composed.hh
+++ b/milena/mln/fun/x2x/composed.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -28,10 +29,9 @@
 #ifndef MLN_FUN_X2X_COMPOSED_HH
 # define MLN_FUN_X2X_COMPOSED_HH
 
-/*! \file mln/fun/x2x/composed.hh
- *
- * \brief Definition of a composed transformation.
- */
+/// \file mln/fun/x2x/composed.hh
+///
+/// Definition of a composed transformation.
 
 # include <mln/core/concept/function.hh>
 # include <mln/fun/internal/x2x_linear_impl.hh>
@@ -50,102 +50,99 @@ namespace mln
     namespace x2x
     {
 
-      // Fwd decl.
-      template <typename F, typename G>
+      // Forward declaration.
+      template <typename T2, typename T1>
       struct composed;
 
       namespace internal
       {
-        template <typename F, typename G, typename E, bool is_bij>
+        template <typename T2, typename T1, typename E, bool is_bij>
         struct helper_composed_;
 
 
         /// Helper for describing a bijective composition.
-        template <typename F, typename G, typename E>
-        struct helper_composed_< F, G, E, true>
-          : public fun::internal::x2x_linear_impl_<mln_result(F), E >,
+        template <typename T2, typename T1, typename E>
+        struct helper_composed_<T2,T1,E,true>
+          : public fun::internal::x2x_linear_impl_<mln_result(T2), E >,
             public Bijection_x2x<E>
         {
-          typedef fun::internal::x2x_linear_impl_<typename F::result, E > super_;
+          typedef fun::internal::x2x_linear_impl_<typename T2::result, E > super_;
 
           using super_::dim;
 
           /// Constructor without argument.
           helper_composed_();
           /// Constructor with the two transformation to be composed.
-          helper_composed_(const F& f, const G& g);
+          helper_composed_(const T2& f, const T1& g);
 
           using super_::operator();
 
-          /// Set the new first transformation.
-          void set_first(const F& f);
           /// Set the new second transformation.
-          void set_second(const G& g);
+          void set_first(const T2& f);
+          /// Set the new first transformation.
+          void set_second(const T1& g);
 
           /// Type of the inverse function.
-          typedef composed<mln_invert(G),mln_invert(F)> invert;
+          typedef composed<mln_invert(T1),mln_invert(T2)> invert;
           /// Return the inverse function.
           invert inv() const;
 
           //protected:
 
-          F f_;
-          G g_;
+          T2 f_;
+          T1 g_;
         };
 
         /// Helper for describing a non bijective composition.
-        template <typename F, typename G, typename E>
-        struct helper_composed_< F, G, E, false>
-          : public fun::internal::x2x_linear_impl_<mln_result(F), E >,
+        template <typename T2, typename T1, typename E>
+        struct helper_composed_<T2,T1,E,false>
+          : public fun::internal::x2x_linear_impl_<mln_result(T2), E >,
             public Function_x2x<E>
         {
-          typedef fun::internal::x2x_linear_impl_<typename F::result, E > super_;
+          typedef fun::internal::x2x_linear_impl_<typename T2::result, E > super_;
 
           using super_::dim;
 
           /// Constructor without argument.
           helper_composed_();
           /// Constructor with the two transformation to be composed.
-          helper_composed_(const F& f, const G& g);
+          helper_composed_(const T2& f, const T1& g);
 
           using super_::operator();
 
-          /// Set the new first transformation.
-          void set_first(const F& f);
           /// Set the new second transformation.
-          void set_second(const G& g);
+          void set_first(const T2& f);
+          /// Set the new first transformation.
+          void set_second(const T1& g);
 
           //protected:
 
-          F f_;
-          G g_;
+          T2 f_;
+          T1 g_;
         };
 
       } // end of namespace mln::fun::x2x::internal
 
 
-        /*! \brief Represent a composition of two transformations.
-         *
-         */
-      template <typename F, typename G>
+      /// Represent a composition of two transformations.
+      template <typename T2, typename T1>
       struct composed
-        : public internal::helper_composed_<F, G, composed<F,G>,
-                                            mlc_is(F, Bijection_x2x<F>)::value &&
-                                            mlc_is(G, Bijection_x2x<G>)::value>,
-          private metal::and_< metal::bool_<(F::dim == G::dim)>,
-                               metal::is<mln_argument(F), mln_result(G)>
+        : public internal::helper_composed_<T2,T1,composed<T2,T1>,
+                                            mlc_is(T2, Bijection_x2x<T2>)::value &&
+                                            mlc_is(T1, Bijection_x2x<T1>)::value>,
+          private metal::and_< metal::bool_<(T2::dim == T1::dim)>,
+                               metal::is<mln_argument(T2), mln_result(T1)>
                                >::check_t
       {
         /// Constructor without argument.
         composed() {}
 
         /// Constructor with the two transformation to be composed.
-        composed(const F& f, const G& g)
-          : internal::helper_composed_<F, G, composed<F,G>,
-                                       mlc_is(F, Bijection_x2x<F>)::value &&
-                                       mlc_is(G, Bijection_x2x<G>)::value>(f, g)
-                                       {
-                                       }
+        composed(const T2& f, const T1& g)
+          : internal::helper_composed_<T2,T1,composed<T2,T1>,
+                                       mlc_is(T2, Bijection_x2x<T2>)::value &&
+                                       mlc_is(T1, Bijection_x2x<T1>)::value>(f, g)
+        {}
 };
 
 } // end of namespace mln::fun::x2x
@@ -153,15 +150,14 @@ namespace mln
   } // end of namespace mln::fun
 
 
-  /*! \brief Do a composition of two transformations
-   *
-   * \param[in] f The first transformation.
-   * \param[in] g The second transformation.
-   *
-   * \return The composed transformation fog.
-   */
-  template <typename F, typename G>
-  fun::x2x::composed<F,G> compose(F f, G g);
+  /// Do a composition of two transformations
+  ///
+  /// \param[in] f The second transformation.
+  /// \param[in] g The first transformation.
+  ///
+  /// \return The composed transformation fog.
+  template <typename T2, typename T1>
+  fun::x2x::composed<T2,T1> compose(T2 f, T1 g);
 
 # ifndef MLN_INCLUDE_ONLY
 
@@ -176,76 +172,76 @@ namespace mln
 
         // Implementation of the bijective version.
 
-        template <typename F, typename G, typename E>
+        template <typename T2, typename T1, typename E>
         inline
-        helper_composed_<F,G,E,true>::helper_composed_()
+        helper_composed_<T2,T1,E,true>::helper_composed_()
         {
         }
 
-        template <typename F, typename G, typename E>
+        template <typename T2, typename T1, typename E>
         inline
-        helper_composed_<F,G,E,true>::helper_composed_(const F& f, const G& g)
+        helper_composed_<T2,T1,E,true>::helper_composed_(const T2& f, const T1& g)
           :f_(f),
            g_(g)
         {
           this->m_ = f_.mat() * g_.mat();
         }
 
-        template <typename F, typename G, typename E>
+        template <typename T2, typename T1, typename E>
         inline
-        typename helper_composed_<F,G,E,true>::invert
-        helper_composed_<F,G,E,true>::inv() const
+        typename helper_composed_<T2,T1,E,true>::invert
+        helper_composed_<T2,T1,E,true>::inv() const
         {
           return compose(g_.inv(), f_.inv());
         }
 
-        template <typename F, typename G, typename E>
+        template <typename T2, typename T1, typename E>
         inline
         void
-        helper_composed_<F,G,E,true>::set_first(const F& f)
+        helper_composed_<T2,T1,E,true>::set_first(const T2& f)
         {
           this->f_ = f;
           this->m_ = this->f_.mat() * this->g_.mat();
         }
 
-        template <typename F, typename G, typename E>
+        template <typename T2, typename T1, typename E>
         inline
         void
-        helper_composed_<F,G,E,true>::set_second(const G& g)
+        helper_composed_<T2,T1,E,true>::set_second(const T1& g)
         {
           this->g_ = g;
           this->m_ = this->f_.mat() * this->g_.mat();
         }
 
         // Implementation of the non bijective version.
-        template <typename F, typename G, typename E>
+        template <typename T2, typename T1, typename E>
         inline
-        helper_composed_<F,G,E,false>::helper_composed_()
+        helper_composed_<T2,T1,E,false>::helper_composed_()
         {
         }
 
-        template <typename F, typename G, typename E>
+        template <typename T2, typename T1, typename E>
         inline
-        helper_composed_<F,G,E,false>::helper_composed_(const F& f, const G& g)
+        helper_composed_<T2,T1,E,false>::helper_composed_(const T2& f, const T1& g)
           :f_(f),
            g_(g)
         {
           this->m_ = f_.mat() * g_.mat();
         }
 
-        template <typename F, typename G, typename E>
+        template <typename T2, typename T1, typename E>
         inline
         void
-        helper_composed_<F,G,E,false>::set_first(const F& f)
+        helper_composed_<T2,T1,E,false>::set_first(const T2& f)
         {
           this->f_ = f;
           this->m_ = this->f_.mat() * this->g_.mat();
         }
 
-        template <typename F, typename G, typename E>
+        template <typename T2, typename T1, typename E>
         inline
         void
-        helper_composed_<F,G,E,false>::set_second(const G& g)
+        helper_composed_<T2,T1,E,false>::set_second(const T1& g)
         {
           this->g_ = g;
           this->m_ = this->f_.mat() * this->g_.mat();
@@ -257,12 +253,12 @@ namespace mln
 
   } // end of namespace mln::fun
 
-  template <typename F, typename G>
+  template <typename T2, typename T1>
   inline
-  fun::x2x::composed<F,G> compose(F f, G g)
+  fun::x2x::composed<T2,T1> compose(T2 f, T1 g)
   {
     trace::entering("fun::x2x::compose");
-    fun::x2x::composed<F,G> comp(f, g);
+    fun::x2x::composed<T2,T1> comp(f, g);
     trace::exiting("fun::x2x::compose");
     return comp;
   }
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        	* mln/core/internal/neighborhood_base.hh,
	* mln/core/internal/window_base.hh: add is_valid()
	* mln/accu/transform.hh,
	* mln/accu/transform_diagonal.hh,
	* mln/accu/transform_directional.hh,
	* mln/accu/transform_snake.hh,
	* mln/accu/transform_stop.hh,
	* mln/canvas/distance_front.hh,
	* mln/canvas/distance_geodesic.hh,
	* mln/canvas/labeling.hh,
	* mln/convert/to_image.hh,
	* mln/core/concept/neighborhood.hh,
	* mln/core/concept/window.hh,
	* mln/core/w_window.hh,
	* mln/geom/delta.hh,
	* mln/labeling/background.hh,
	* mln/labeling/foreground.hh,
	* mln/labeling/level.hh,
	* mln/level/median.hh,
	* mln/linear/convolve.hh,
	* mln/morpho/elementary/closing.hh,
	* mln/morpho/elementary/dilation.hh,
	* mln/morpho/elementary/erosion.hh,
	* mln/morpho/elementary/gradient.hh,
	* mln/morpho/elementary/gradient_external.hh,
	* mln/morpho/elementary/gradient_internal.hh,
	* mln/morpho/elementary/laplacian.hh,
	* mln/morpho/elementary/opening.hh,
	* mln/morpho/elementary/top_hat.hh,
	* mln/morpho/general.hh,
	* mln/morpho/tree/compute_parent.hh,
	* mln/morpho/tree/max.hh,
	* mln/transform/distance_front.hh,
	* mln/transform/distance_geodesic.hh,
	* mln/transform/influence_zone_front.hh,
	* mln/transform/influence_zone_geodesic.hh,
	* mln/win/sym.hh: enable preconditions.
---
 milena/ChangeLog                                  |   43 +++++++++++++++++++++
 milena/mln/accu/transform.hh                      |   25 ++++++------
 milena/mln/accu/transform_diagonal.hh             |    5 +-
 milena/mln/accu/transform_directional.hh          |    5 +-
 milena/mln/accu/transform_snake.hh                |    5 +-
 milena/mln/accu/transform_stop.hh                 |   21 +++++-----
 milena/mln/canvas/distance_front.hh               |    5 +-
 milena/mln/canvas/distance_geodesic.hh            |    5 +-
 milena/mln/canvas/labeling.hh                     |    6 +-
 milena/mln/convert/to_image.hh                    |    6 +-
 milena/mln/core/concept/neighborhood.hh           |    2 +-
 milena/mln/core/concept/window.hh                 |   10 ++---
 milena/mln/core/internal/neighborhood_base.hh     |   10 +++++
 milena/mln/core/internal/window_base.hh           |   29 ++++++++++----
 milena/mln/core/w_window.hh                       |    2 +-
 milena/mln/geom/delta.hh                          |    8 ++--
 milena/mln/labeling/background.hh                 |    2 +-
 milena/mln/labeling/foreground.hh                 |    2 +-
 milena/mln/labeling/level.hh                      |    2 +-
 milena/mln/level/median.hh                        |    6 +-
 milena/mln/linear/convolve.hh                     |    6 +-
 milena/mln/morpho/elementary/closing.hh           |   12 +++---
 milena/mln/morpho/elementary/dilation.hh          |    7 ++-
 milena/mln/morpho/elementary/erosion.hh           |    4 +-
 milena/mln/morpho/elementary/gradient.hh          |    4 +-
 milena/mln/morpho/elementary/gradient_external.hh |    7 ++-
 milena/mln/morpho/elementary/gradient_internal.hh |    7 ++-
 milena/mln/morpho/elementary/laplacian.hh         |    5 +-
 milena/mln/morpho/elementary/opening.hh           |   12 +++---
 milena/mln/morpho/elementary/top_hat.hh           |   20 +++++-----
 milena/mln/morpho/general.hh                      |    2 +-
 milena/mln/morpho/tree/compute_parent.hh          |    2 +-
 milena/mln/morpho/tree/max.hh                     |    2 +-
 milena/mln/transform/distance_front.hh            |    4 +-
 milena/mln/transform/distance_geodesic.hh         |    2 +-
 milena/mln/transform/influence_zone_front.hh      |    4 +-
 milena/mln/transform/influence_zone_geodesic.hh   |    2 +-
 milena/mln/win/sym.hh                             |    4 +-
 38 files changed, 189 insertions(+), 116 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 5debdb3..772b56b 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,4 +1,47 @@
 2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
+	Add is_valid() to window and neighborhood.
+
+	* mln/core/internal/neighborhood_base.hh,
+	* mln/core/internal/window_base.hh: add is_valid()
+
+	* mln/accu/transform.hh,
+	* mln/accu/transform_diagonal.hh,
+	* mln/accu/transform_directional.hh,
+	* mln/accu/transform_snake.hh,
+	* mln/accu/transform_stop.hh,
+	* mln/canvas/distance_front.hh,
+	* mln/canvas/distance_geodesic.hh,
+	* mln/canvas/labeling.hh,
+	* mln/convert/to_image.hh,
+	* mln/core/concept/neighborhood.hh,
+	* mln/core/concept/window.hh,
+	* mln/core/w_window.hh,
+	* mln/geom/delta.hh,
+	* mln/labeling/background.hh,
+	* mln/labeling/foreground.hh,
+	* mln/labeling/level.hh,
+	* mln/level/median.hh,
+	* mln/linear/convolve.hh,
+	* mln/morpho/elementary/closing.hh,
+	* mln/morpho/elementary/dilation.hh,
+	* mln/morpho/elementary/erosion.hh,
+	* mln/morpho/elementary/gradient.hh,
+	* mln/morpho/elementary/gradient_external.hh,
+	* mln/morpho/elementary/gradient_internal.hh,
+	* mln/morpho/elementary/laplacian.hh,
+	* mln/morpho/elementary/opening.hh,
+	* mln/morpho/elementary/top_hat.hh,
+	* mln/morpho/general.hh,
+	* mln/morpho/tree/compute_parent.hh,
+	* mln/morpho/tree/max.hh,
+	* mln/transform/distance_front.hh,
+	* mln/transform/distance_geodesic.hh,
+	* mln/transform/influence_zone_front.hh,
+	* mln/transform/influence_zone_geodesic.hh,
+	* mln/win/sym.hh: enable preconditions.
+
+2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
   
 	Cleanup accu::rms.
 
diff --git a/milena/mln/accu/transform.hh b/milena/mln/accu/transform.hh
index f5f9096..b673549 100644
--- a/milena/mln/accu/transform.hh
+++ b/milena/mln/accu/transform.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -47,13 +48,13 @@ namespace mln
 
     template <typename I, typename A, typename W>
     mln_ch_value(I, mln_result(A))
-      transform(const Image<I>& input, 
+      transform(const Image<I>& input,
 		const Accumulator<A>& a,
 		const Window<W>& win);
 
     template <typename I, typename A, typename W>
     mln_ch_value(I, mln_accu_with(A, mln_value(I))::result)
-      transform(const Image<I>& input, 
+      transform(const Image<I>& input,
 		const Meta_Accumulator<A>& a,
 		const Window<W>& win);
 
@@ -69,7 +70,7 @@ namespace mln
 
       namespace generic
       {
-	
+
 	template <typename I, typename A, typename W>
 	mln_ch_value(I, mln_result(A))
 	  transform(const Image<I>& input_,
@@ -83,10 +84,10 @@ namespace mln
 	  A a = exact(a_);
 
 	  mln_precondition(input.is_valid());
-	  // mln_precondition(win.is_valid());
+	  mln_precondition(win.is_valid());
 
 	  extension::adjust(input, win);
-	  
+
 	  mln_ch_value(I, mln_result(A)) output;
 	  initialize(output, input);
 
@@ -106,7 +107,7 @@ namespace mln
 
       } // end of namespace mln::accu::impl::generic
 
-	
+
       // Fastest version.
 
       template <typename I, typename A, typename W>
@@ -120,10 +121,10 @@ namespace mln
 	A a = exact(a_);
 
 	mln_precondition(input.is_valid());
-	// mln_precondition(win.is_valid());
+	mln_precondition(win.is_valid());
 
 	extension::adjust(input, win);
-	  
+
 	typedef mln_ch_value(I, mln_result(A)) O;
 	O output;
 	initialize(output, input);
@@ -143,7 +144,7 @@ namespace mln
 	return output;
       }
 
-      
+
     } // end of namespace mln::accu::impl
 
 
@@ -189,7 +190,7 @@ namespace mln
       trace::entering("accu::transform");
 
       mln_precondition(exact(input).is_valid());
-      // mln_precondition(exact(win).is_valid());
+      mln_precondition(exact(win).is_valid());
 
       mln_ch_value(I, mln_result(A)) output;
       output = internal::transform_dispatch(input, a, win);
@@ -205,7 +206,7 @@ namespace mln
       trace::entering("accu::transform");
 
       mln_precondition(exact(input).is_valid());
-      // mln_precondition(exact(win).is_valid());
+      mln_precondition(exact(win).is_valid());
 
       typedef mln_accu_with(A, mln_value(I)) A_;
       A_ a_ = accu::unmeta(exact(a), mln_value(I)());
diff --git a/milena/mln/accu/transform_diagonal.hh b/milena/mln/accu/transform_diagonal.hh
index 18d396b..c8788e6 100644
--- a/milena/mln/accu/transform_diagonal.hh
+++ b/milena/mln/accu/transform_diagonal.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -90,7 +91,7 @@ namespace mln
 
 	mln_precondition(input.is_valid());
 	mln_precondition(! win.is_empty());
-	// mln_precondition(! win.is_valid());
+	mln_precondition(! win.is_valid());
 
 	(void) input;
 	(void) win;
diff --git a/milena/mln/accu/transform_directional.hh b/milena/mln/accu/transform_directional.hh
index 16f5dd0..6a78fcd 100644
--- a/milena/mln/accu/transform_directional.hh
+++ b/milena/mln/accu/transform_directional.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -88,7 +89,7 @@ namespace mln
 
 	mln_precondition(input.is_valid());
 	mln_precondition(! win.is_empty());
-	// mln_precondition(! win.is_valid());
+	mln_precondition(! win.is_valid());
 
 	(void) input;
 	(void) win;
diff --git a/milena/mln/accu/transform_snake.hh b/milena/mln/accu/transform_snake.hh
index fa3da5b..98bcf93 100644
--- a/milena/mln/accu/transform_snake.hh
+++ b/milena/mln/accu/transform_snake.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -83,7 +84,7 @@ namespace mln
 
 	mln_precondition(input.is_valid());
 	mln_precondition(! win.is_empty());
-	// mln_precondition(! win.is_valid());
+	mln_precondition(! win.is_valid());
 
 	(void) input;
 	(void) win;
diff --git a/milena/mln/accu/transform_stop.hh b/milena/mln/accu/transform_stop.hh
index 1978b32..bfbc3a4 100644
--- a/milena/mln/accu/transform_stop.hh
+++ b/milena/mln/accu/transform_stop.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -65,7 +66,7 @@ namespace mln
 
       namespace generic
       {
-	
+
 	template <typename I, typename A, typename W>
 	mln_ch_value(I, mln_result(A))
 	transform_stop(const Image<I>& input_,
@@ -79,10 +80,10 @@ namespace mln
 	  A a = exact(a_);
 
 	  mln_precondition(input.is_valid());
-	  // mln_precondition(win.is_valid());
+	  mln_precondition(win.is_valid());
 
 	  extension::adjust(input, win);
-	  
+
 	  mln_ch_value(I, mln_result(A)) output;
 	  initialize(output, input);
 
@@ -106,7 +107,7 @@ namespace mln
 
       } // end of namespace mln::accu::impl::generic
 
-	
+
       // Fastest version.
 
       template <typename I, typename A, typename W>
@@ -120,10 +121,10 @@ namespace mln
 	A a = exact(a_);
 
 	mln_precondition(input.is_valid());
-	// mln_precondition(win.is_valid());
+	mln_precondition(win.is_valid());
 
 	extension::adjust(input, win);
-	  
+
 	typedef mln_ch_value(I, mln_result(A)) O;
 	O output;
 	initialize(output, input);
@@ -147,7 +148,7 @@ namespace mln
 	return output;
       }
 
-      
+
     } // end of namespace mln::accu::impl
 
 
@@ -193,7 +194,7 @@ namespace mln
       trace::entering("accu::transform_stop");
 
       mln_precondition(exact(input).is_valid());
-      // mln_precondition(exact(win).is_valid());
+      mln_precondition(exact(win).is_valid());
 
       mln_ch_value(I, mln_result(A)) output;
       output = internal::transform_stop_dispatch(input, a, win);
@@ -209,7 +210,7 @@ namespace mln
       trace::entering("accu::transform_stop");
 
       mln_precondition(exact(input).is_valid());
-      // mln_precondition(exact(win).is_valid());
+      mln_precondition(exact(win).is_valid());
 
       typedef mln_accu_with(A, mln_value(I)) A_;
       A_ a_ = accu::unmeta(exact(a), mln_value(I)());
diff --git a/milena/mln/canvas/distance_front.hh b/milena/mln/canvas/distance_front.hh
index caefa91..ac02d2c 100644
--- a/milena/mln/canvas/distance_front.hh
+++ b/milena/mln/canvas/distance_front.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -75,7 +76,7 @@ namespace mln
       const W& w_win = exact(w_win_);
 
       mln_precondition(input.is_valid());
-      // mln_precondition(w_win.is_valid());
+      mln_precondition(w_win.is_valid());
 
       typedef mln_site(I) P;
       typedef std::vector<P> bucket_t;
diff --git a/milena/mln/canvas/distance_geodesic.hh b/milena/mln/canvas/distance_geodesic.hh
index 123bb24..f51e900 100644
--- a/milena/mln/canvas/distance_geodesic.hh
+++ b/milena/mln/canvas/distance_geodesic.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -70,7 +71,7 @@ namespace mln
       const N& nbh   = exact(nbh_);
 
       mln_precondition(input.is_valid());
-      // mln_precondition(nbh.is_valid());
+      mln_precondition(nbh.is_valid());
 
       mln_ch_value(I, D) dmap; // Distance map is aux data.
       initialize(dmap, input);
diff --git a/milena/mln/canvas/labeling.hh b/milena/mln/canvas/labeling.hh
index c8a9e5c..cdd0b10 100644
--- a/milena/mln/canvas/labeling.hh
+++ b/milena/mln/canvas/labeling.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -70,7 +70,7 @@ namespace mln
 	const N& nbh   = exact(nbh_);
 
 	mln_precondition(input.is_valid());
-	// mln_precondition(nbh.is_valid());
+	mln_precondition(nbh.is_valid());
 
 	(void) input;
 	(void) nbh;
diff --git a/milena/mln/convert/to_image.hh b/milena/mln/convert/to_image.hh
index e71aeda..9be01d3 100644
--- a/milena/mln/convert/to_image.hh
+++ b/milena/mln/convert/to_image.hh
@@ -108,7 +108,7 @@ namespace mln
     to_image(const Window<W>& win)
     {
       mln_is_simple_window(W)::check();
-      // mln_precondition(exact(win).is_valid());
+      mln_precondition(exact(win).is_valid());
       mln_image_from_grid(mln_site(W)::grid, bool) tmp;
       convert::from_to(win, tmp);
       return tmp;
@@ -120,7 +120,7 @@ namespace mln
     to_image(const Weighted_Window<W>& w_win)
     {
       mln_is_simple_window(W)::check();
-      // mln_precondition(exact(w_win).is_valid());
+      mln_precondition(exact(w_win).is_valid());
       mln_image_from_grid(mln_site(W)::grid, mln_weight(W)) tmp;
       convert::from_to(exact(w_win), tmp);
       return tmp;
@@ -131,7 +131,7 @@ namespace mln
     mln_image_from_grid(mln_site(N)::grid, bool)
     to_image(const Neighborhood<N>& nbh)
     {
-      // mln_precondition(exact(nbh).is_valid());
+      mln_precondition(exact(nbh).is_valid());
       return to_image(exact(nbh).win());
     }
 
diff --git a/milena/mln/core/concept/neighborhood.hh b/milena/mln/core/concept/neighborhood.hh
index f5df84a..5547865 100644
--- a/milena/mln/core/concept/neighborhood.hh
+++ b/milena/mln/core/concept/neighborhood.hh
@@ -152,7 +152,7 @@ namespace mln
     const I& ima = exact(ima_);
     const N& nbh = exact(nbh_);
     mln_precondition(ima.is_valid());
-    // mln_precondition(nbh.is_valid());
+    mln_precondition(nbh.is_valid());
 
     return offsets_wrt(ima, nbh.win());
   }
diff --git a/milena/mln/core/concept/window.hh b/milena/mln/core/concept/window.hh
index 3b4dfe5..64b05fe 100644
--- a/milena/mln/core/concept/window.hh
+++ b/milena/mln/core/concept/window.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -34,8 +34,6 @@
 ///
 /// \todo Operator== should test if the cmp is possible.
 ///
-/// \todo Add an is_valid() method.
-///
 /// \todo The is_centered() method could also exist when the window is
 /// not regular...
 
@@ -327,7 +325,7 @@ namespace mln
     const I& ima = exact(ima_);
     const W& win = exact(win_);
     mln_precondition(ima.is_valid());
-    // mln_precondition(win.is_valid());
+    mln_precondition(win.is_valid());
 
     util::array<int> arr;
     unsigned n = win.size();
@@ -357,7 +355,7 @@ namespace mln
 	const W& win = exact(win_);
 	I& ima = exact(ima_);
 
-	// mln_precondition(win.is_valid());
+	mln_precondition(win.is_valid());
 	mln_precondition(! ima.is_valid());
 
 	// Hack (below) to avoid circular dependency.
diff --git a/milena/mln/core/internal/neighborhood_base.hh b/milena/mln/core/internal/neighborhood_base.hh
index 35349fc..210408e 100644
--- a/milena/mln/core/internal/neighborhood_base.hh
+++ b/milena/mln/core/internal/neighborhood_base.hh
@@ -133,6 +133,9 @@ namespace mln
       /// Site associated type.
       typedef mln_site(W) site;
 
+      /// Return true by default.
+      bool is_valid() const;
+
     protected:
       neighborhood_base();
     };
@@ -151,6 +154,13 @@ namespace mln
     {
     }
 
+    template <typename W, typename E>
+    inline
+    bool
+    neighborhood_base<W,E>::is_valid() const
+    {
+      return true;
+    }
 
     // neighborhood_impl
 
diff --git a/milena/mln/core/internal/window_base.hh b/milena/mln/core/internal/window_base.hh
index 68f9f83..3ab8664 100644
--- a/milena/mln/core/internal/window_base.hh
+++ b/milena/mln/core/internal/window_base.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -28,10 +29,9 @@
 #ifndef MLN_CORE_INTERNAL_WINDOW_BASE_HH
 # define MLN_CORE_INTERNAL_WINDOW_BASE_HH
 
-/*! \file mln/core/internal/window_base.hh
- *
- * \brief Definition of a base class for window classes.
- */
+/// \file mln/core/internal/window_base.hh
+///
+/// Definition of a base class for window classes.
 
 # include <mln/core/concept/window.hh>
 
@@ -43,10 +43,10 @@ namespace mln
   {
 
 
-    /*! A base class for window classes.
-     *
-     * \p D is a dpsite type.
-     */
+    /// A base class for window classes.
+    ///
+    /// \p D is a dpsite type.
+    ///
     template <typename D, typename E>
     struct window_base : public Window<E>
     {
@@ -64,6 +64,9 @@ namespace mln
       // This method is used in the neighborhood window-adapter.
       bool is_neighbable_() const;
 
+      /// return true by default.
+      bool is_valid() const;
+
     protected:
       window_base();
     };
@@ -80,6 +83,14 @@ namespace mln
     template <typename D, typename E>
     inline
     bool
+    window_base<D,E>::is_valid() const
+    {
+      return true;
+    }
+
+    template <typename D, typename E>
+    inline
+    bool
     window_base<D,E>::is_neighbable_() const
     {
       return exact(this)->is_symmetric() && ! exact(this)->is_centered();
diff --git a/milena/mln/core/w_window.hh b/milena/mln/core/w_window.hh
index ac55e2a..adacb7e 100644
--- a/milena/mln/core/w_window.hh
+++ b/milena/mln/core/w_window.hh
@@ -348,7 +348,7 @@ namespace mln
 
 	I& ima = exact(ima_);
 	mln_precondition(! ima.is_valid());
-	// mln_precondition(w_win.is_valid());
+	mln_precondition(w_win.is_valid());
 
 	ima.init_(geom::bbox(w_win));
 	{
diff --git a/milena/mln/geom/delta.hh b/milena/mln/geom/delta.hh
index dd7dac4..68afa31 100644
--- a/milena/mln/geom/delta.hh
+++ b/milena/mln/geom/delta.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
 // (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
@@ -98,7 +98,7 @@ namespace mln
     template <typename W>
     unsigned delta(const Window<W>& win)
     {
-      // mln_precondition(exact(win).is_valid());
+      mln_precondition(exact(win).is_valid());
       return internal::delta_dispatch(mln_trait_window_support(W)(),
 				      mln_trait_window_definition(W)(),
 				      exact(win));
@@ -107,14 +107,14 @@ namespace mln
     template <typename W>
     unsigned delta(const Weighted_Window<W>& wwin)
     {
-      // mln_precondition(exact(wwin).is_valid());
+      mln_precondition(exact(wwin).is_valid());
       return delta(exact(wwin).win());
     }
 
     template <typename N>
     unsigned delta(const Neighborhood<N>& nbh)
     {
-      // mln_precondition(exact(nbh).is_valid());
+      mln_precondition(exact(nbh).is_valid());
       return delta(exact(nbh).win());
     }
 
diff --git a/milena/mln/labeling/background.hh b/milena/mln/labeling/background.hh
index 30187bd..14e48eb 100644
--- a/milena/mln/labeling/background.hh
+++ b/milena/mln/labeling/background.hh
@@ -77,7 +77,7 @@ namespace mln
       mlc_equal(mln_trait_image_kind(I),
 		mln::trait::image::kind::binary)::check();
       mln_precondition(exact(input).is_valid());
-      // mln_precondition(exact(nbh).is_valid());
+      mln_precondition(exact(nbh).is_valid());
 
       mln_ch_value(I, L) output = labeling::level(input, false, nbh, nlabels);
 
diff --git a/milena/mln/labeling/foreground.hh b/milena/mln/labeling/foreground.hh
index b5a28e4..b86a718 100644
--- a/milena/mln/labeling/foreground.hh
+++ b/milena/mln/labeling/foreground.hh
@@ -77,7 +77,7 @@ namespace mln
       mlc_equal(mln_trait_image_kind(I),
 		mln::trait::image::kind::binary)::check();
       mln_precondition(exact(input).is_valid());
-      // mln_precondition(exact(nbh).is_valid());
+      mln_precondition(exact(nbh).is_valid());
 
       mln_ch_value(I, L) output = labeling::level(input, true, nbh, nlabels);
 
diff --git a/milena/mln/labeling/level.hh b/milena/mln/labeling/level.hh
index 17850bc..563e9b9 100644
--- a/milena/mln/labeling/level.hh
+++ b/milena/mln/labeling/level.hh
@@ -79,7 +79,7 @@ namespace mln
 		  L& nlabels)
       {
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	(void) input;
 	(void) val;
diff --git a/milena/mln/level/median.hh b/milena/mln/level/median.hh
index 29eaa99..4a5c3cd 100644
--- a/milena/mln/level/median.hh
+++ b/milena/mln/level/median.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -79,7 +79,7 @@ namespace mln
       median_tests(const Image<I>& input, const Window<W>& win)
       {
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(win).is_valid());
+	mln_precondition(exact(win).is_valid());
 	(void) input;
 	(void) win;
       }
diff --git a/milena/mln/linear/convolve.hh b/milena/mln/linear/convolve.hh
index 1996f76..64779df 100644
--- a/milena/mln/linear/convolve.hh
+++ b/milena/mln/linear/convolve.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -75,7 +75,7 @@ namespace mln
 		     const Weighted_Window<W>& w_win)
       {
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(w_win).is_valid());
+	mln_precondition(exact(w_win).is_valid());
 	(void) input;
 	(void) w_win;
       }
diff --git a/milena/mln/morpho/elementary/closing.hh b/milena/mln/morpho/elementary/closing.hh
index fef94c5..eb1b72f 100644
--- a/milena/mln/morpho/elementary/closing.hh
+++ b/milena/mln/morpho/elementary/closing.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -28,10 +29,9 @@
 #ifndef MLN_MORPHO_ELEMENTARY_CLOSING_HH
 # define MLN_MORPHO_ELEMENTARY_CLOSING_HH
 
-/*! \file mln/morpho/elementary/closing.hh
- *
- * \brief Morphological elementary closing.
- */
+/// \file mln/morpho/elementary/closing.hh
+///
+/// Morphological elementary closing.
 
 # include <mln/morpho/elementary/erosion.hh>
 # include <mln/morpho/elementary/dilation.hh>
@@ -62,7 +62,7 @@ namespace mln
 	trace::entering("morpho::elementary::closing");
 
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	mln_concrete(I) output = erosion(dilation(input, nbh), nbh);
 
diff --git a/milena/mln/morpho/elementary/dilation.hh b/milena/mln/morpho/elementary/dilation.hh
index 8488100..9b169aa 100644
--- a/milena/mln/morpho/elementary/dilation.hh
+++ b/milena/mln/morpho/elementary/dilation.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -100,10 +101,10 @@ namespace mln
 	trace::entering("morpho::elementary::dilation");
 
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	mln_concrete(I) output = internal::dilation_dispatch(input, nbh);
-	
+
 	mln_postcondition(output >= input);
 	trace::exiting("morpho::elementary::dilation");
 	return output;
diff --git a/milena/mln/morpho/elementary/erosion.hh b/milena/mln/morpho/elementary/erosion.hh
index 765dabe..b51a552 100644
--- a/milena/mln/morpho/elementary/erosion.hh
+++ b/milena/mln/morpho/elementary/erosion.hh
@@ -100,10 +100,10 @@ namespace mln
 	trace::entering("morpho::elementary::erosion");
 
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	mln_concrete(I) output = internal::erosion_dispatch(input, nbh);
-	
+
 	mln_postcondition(output <= input);
 	trace::exiting("morpho::elementary::erosion");
 	return output;
diff --git a/milena/mln/morpho/elementary/gradient.hh b/milena/mln/morpho/elementary/gradient.hh
index 5c98801..9973afb 100644
--- a/milena/mln/morpho/elementary/gradient.hh
+++ b/milena/mln/morpho/elementary/gradient.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
 // (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
@@ -62,7 +62,7 @@ namespace mln
 	gradient_tests(const Image<I>& input, const Neighborhood<N>& nbh)
 	{
 	  mln_precondition(exact(input).is_valid());
-	  // mln_precondition(exact(nbh).is_valid());
+	  mln_precondition(exact(nbh).is_valid());
 	  (void) input;
 	  (void) nbh;
 	}
diff --git a/milena/mln/morpho/elementary/gradient_external.hh b/milena/mln/morpho/elementary/gradient_external.hh
index 6403845..27056db 100644
--- a/milena/mln/morpho/elementary/gradient_external.hh
+++ b/milena/mln/morpho/elementary/gradient_external.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -111,10 +112,10 @@ namespace mln
 	trace::entering("morpho::elementary::gradient_external");
 
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	mln_concrete(I) output = internal::gradient_external_dispatch(input, nbh);
-	
+
 	trace::exiting("morpho::elementary::gradient_external");
 	return output;
       }
diff --git a/milena/mln/morpho/elementary/gradient_internal.hh b/milena/mln/morpho/elementary/gradient_internal.hh
index 5bc3f3e..844daac 100644
--- a/milena/mln/morpho/elementary/gradient_internal.hh
+++ b/milena/mln/morpho/elementary/gradient_internal.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -111,10 +112,10 @@ namespace mln
 	trace::entering("morpho::elementary::gradient_internal");
 
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	mln_concrete(I) output = internal::gradient_internal_dispatch(input, nbh);
-	
+
 	mln_postcondition(output <= input);
 	trace::exiting("morpho::elementary::gradient_internal");
 	return output;
diff --git a/milena/mln/morpho/elementary/laplacian.hh b/milena/mln/morpho/elementary/laplacian.hh
index 87b0d92..974504c 100644
--- a/milena/mln/morpho/elementary/laplacian.hh
+++ b/milena/mln/morpho/elementary/laplacian.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -66,7 +67,7 @@ namespace mln
 	trace::entering("morpho::elementary::laplacian");
 
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	mln_trait_op_minus_twice(mln_concrete(I)) output;
 	output = gradient_external(input, nbh) - gradient_internal(input, nbh);
diff --git a/milena/mln/morpho/elementary/opening.hh b/milena/mln/morpho/elementary/opening.hh
index 9b19087..50e8df5 100644
--- a/milena/mln/morpho/elementary/opening.hh
+++ b/milena/mln/morpho/elementary/opening.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -28,10 +29,9 @@
 #ifndef MLN_MORPHO_ELEMENTARY_OPENING_HH
 # define MLN_MORPHO_ELEMENTARY_OPENING_HH
 
-/*! \file mln/morpho/elementary/opening.hh
- *
- * \brief Morphological elementary opening.
- */
+/// \file mln/morpho/elementary/opening.hh
+///
+/// Morphological elementary opening.
 
 # include <mln/morpho/elementary/erosion.hh>
 # include <mln/morpho/elementary/dilation.hh>
@@ -62,7 +62,7 @@ namespace mln
 	trace::entering("morpho::elementary::opening");
 
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	mln_concrete(I) output = dilation(erosion(input, nbh), nbh);
 
diff --git a/milena/mln/morpho/elementary/top_hat.hh b/milena/mln/morpho/elementary/top_hat.hh
index 4bce465..2f5423d 100644
--- a/milena/mln/morpho/elementary/top_hat.hh
+++ b/milena/mln/morpho/elementary/top_hat.hh
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
 // software; you can redistribute it and/or modify it under the terms
@@ -28,12 +29,11 @@
 #ifndef MLN_MORPHO_ELEMENTARY_TOP_HAT_HH
 # define MLN_MORPHO_ELEMENTARY_TOP_HAT_HH
 
-/*! \file mln/morpho/elementary/top_hat.hh
- *
- * \brief Morphological elementary top-hats.
- *
- * \todo Save memory.
- */
+/// \file mln/morpho/elementary/top_hat.hh
+///
+/// Morphological elementary top-hats.
+///
+/// \todo Save memory.
 
 # include <mln/morpho/elementary/opening.hh>
 # include <mln/morpho/elementary/closing.hh>
@@ -89,7 +89,7 @@ namespace mln
       {
 	trace::entering("morpho::elementary::top_hat_white");
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	mln_concrete(I) output = morpho::minus(input,
 					       opening(input, nbh));
@@ -107,7 +107,7 @@ namespace mln
       {
 	trace::entering("morpho::elementary::top_hat_black");
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	mln_concrete(I) output = morpho::minus(closing(input, nbh),
 					       input);
@@ -125,7 +125,7 @@ namespace mln
       {
 	trace::entering("morpho::elementary::top_hat_self_complementary");
 	mln_precondition(exact(input).is_valid());
-	// mln_precondition(exact(nbh).is_valid());
+	mln_precondition(exact(nbh).is_valid());
 
 	mln_concrete(I) output = morpho::minus(closing(input, nbh),
 					       opening(input, nbh));
diff --git a/milena/mln/morpho/general.hh b/milena/mln/morpho/general.hh
index 5ece056..f4590ea 100644
--- a/milena/mln/morpho/general.hh
+++ b/milena/mln/morpho/general.hh
@@ -82,7 +82,7 @@ namespace mln
 
 	mln_precondition(input.is_valid());
 	mln_precondition(! win.is_empty());
-	// mln_precondition(win.is_valid());
+	mln_precondition(win.is_valid());
 
 	(void) op;
 	(void) input;
diff --git a/milena/mln/morpho/tree/compute_parent.hh b/milena/mln/morpho/tree/compute_parent.hh
index 7cfc1d6..3c33e81 100644
--- a/milena/mln/morpho/tree/compute_parent.hh
+++ b/milena/mln/morpho/tree/compute_parent.hh
@@ -92,7 +92,7 @@ namespace mln
 	  const S& s   = exact(s_);
 
 	  mln_precondition(f.is_valid());
-	  // mln_precondition(nbh.is_valid());
+	  mln_precondition(nbh.is_valid());
 	  mln_precondition(s == f.domain());
 
 	  (void) f;
diff --git a/milena/mln/morpho/tree/max.hh b/milena/mln/morpho/tree/max.hh
index b904fff..24938f5 100644
--- a/milena/mln/morpho/tree/max.hh
+++ b/milena/mln/morpho/tree/max.hh
@@ -69,7 +69,7 @@ namespace mln
 	const N& nbh = exact(nbh_);
 
 	mln_precondition(f.is_valid());
-	// mln_precondition(nbh.is_valid());
+	mln_precondition(nbh.is_valid());
 
 	// For the max-tree, childhood maps "increasing level":
 	p_array<mln_psite(I)> s = level::sort_psites_increasing(f);
diff --git a/milena/mln/transform/distance_front.hh b/milena/mln/transform/distance_front.hh
index 4e9feb9..6054aab 100644
--- a/milena/mln/transform/distance_front.hh
+++ b/milena/mln/transform/distance_front.hh
@@ -61,8 +61,8 @@ namespace mln
       trace::entering("transform::distance_front");
 
       mln_precondition(exact(input).is_valid());
-      // mln_precondition(exact(nbh).is_valid());
-      // mln_precondition(exact(w_win).is_valid());
+      mln_precondition(exact(nbh).is_valid());
+      mln_precondition(exact(w_win).is_valid());
 
       mln_ch_value(I, D) output;
       internal::distance_functor<I> f;
diff --git a/milena/mln/transform/distance_geodesic.hh b/milena/mln/transform/distance_geodesic.hh
index e076309..eb4bfa6 100644
--- a/milena/mln/transform/distance_geodesic.hh
+++ b/milena/mln/transform/distance_geodesic.hh
@@ -59,7 +59,7 @@ namespace mln
       trace::entering("transform::distance_geodesic");
 
       mln_precondition(exact(input).is_valid());
-      // mln_precondition(exact(nbh).is_valid());
+      mln_precondition(exact(nbh).is_valid());
 
       mln_ch_value(I, D) output;
       internal::distance_functor<I> f;
diff --git a/milena/mln/transform/influence_zone_front.hh b/milena/mln/transform/influence_zone_front.hh
index 014f5d6..55e7138 100644
--- a/milena/mln/transform/influence_zone_front.hh
+++ b/milena/mln/transform/influence_zone_front.hh
@@ -65,8 +65,8 @@ namespace mln
       trace::entering("transform::influence_zone_front");
 
       mln_precondition(exact(input).is_valid());
-      // mln_precondition(exact(nbh).is_valid());
-      // mln_precondition(exact(w_win).is_valid());
+      mln_precondition(exact(nbh).is_valid());
+      mln_precondition(exact(w_win).is_valid());
 
       internal::influence_zone_functor<I> f;
       (void) mln::canvas::distance_front(input, nbh, w_win, max, f);
diff --git a/milena/mln/transform/influence_zone_geodesic.hh b/milena/mln/transform/influence_zone_geodesic.hh
index ca8e56b..7a92cff 100644
--- a/milena/mln/transform/influence_zone_geodesic.hh
+++ b/milena/mln/transform/influence_zone_geodesic.hh
@@ -66,7 +66,7 @@ namespace mln
       trace::entering("transform::influence_zone_geodesic");
 
       mln_precondition(exact(input).is_valid());
-      // mln_precondition(exact(nbh).is_valid());
+      mln_precondition(exact(nbh).is_valid());
 
       internal::influence_zone_functor<I> f;
       (void) mln::canvas::distance_geodesic(input, nbh, max, f);
diff --git a/milena/mln/win/sym.hh b/milena/mln/win/sym.hh
index 208f75a..cc0a680 100644
--- a/milena/mln/win/sym.hh
+++ b/milena/mln/win/sym.hh
@@ -62,7 +62,7 @@ namespace mln
     W sym(const Window<W>& win)
     {
       trace::entering("win::sym");
-      // mln_precondition(win.is_valid());
+      mln_precondition(exact(win).is_valid());
       W tmp = exact(win);
       tmp.sym();
       trace::exiting("win::sym");
@@ -74,7 +74,7 @@ namespace mln
     W sym(const Weighted_Window<W>& w_win)
     {
       trace::entering("win::sym");
-      // mln_precondition(win.is_valid());
+      mln_precondition(exact(w_win).is_valid());
       W tmp = exact(w_win);
       tmp.sym();
       trace::exiting("win::sym");
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        	* mln/accu/rms.hh: rename attributes and add a hook to the underlying
	values.
---
 milena/ChangeLog       |    7 +++++++
 milena/mln/accu/rms.hh |   26 +++++++++++++++++++-------
 2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 205f6d9..5debdb3 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,4 +1,11 @@
 2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
+  
+	Cleanup accu::rms.
+
+	* mln/accu/rms.hh: rename attributes and add a hook to the underlying
+	values.
+
+2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
 	Add debug::histo.
 
diff --git a/milena/mln/accu/rms.hh b/milena/mln/accu/rms.hh
index 339eabc..35709eb 100644
--- a/milena/mln/accu/rms.hh
+++ b/milena/mln/accu/rms.hh
@@ -66,13 +66,17 @@ namespace mln
       /// Get the value of the accumulator.
       V to_result() const;
 
+      /// Return the underlying value used to compute the result.
+      /// v = sum(t * t);
+      V hook_value_() const;
+
       /// Check whether this accu is able to return a result.
       /// Always true here.
       bool is_valid() const;
 
     protected:
 
-      V t_;
+      V v_;
       unsigned count_;
     };
 
@@ -107,7 +111,7 @@ namespace mln
     void
     rms<T,V>::init()
     {
-      t_ = literal::zero;
+      v_ = literal::zero;
       count_ = 0;
     }
 
@@ -116,7 +120,7 @@ namespace mln
     void
     rms<T,V>::take_as_init(const T& t)
     {
-      t_ += t * t;
+      v_ += t * t;
       ++count_;
     }
 
@@ -125,7 +129,7 @@ namespace mln
     void
     rms<T,V>::take(const T& t)
     {
-      t_ += t * t;
+      v_ += t * t;
       ++count_;
     }
 
@@ -134,7 +138,7 @@ namespace mln
     void
     rms<T,V>::take(const rms<T,V>& other)
     {
-      t_ += other.t_;
+      v_ += other.v_;
       count_ += other.count_;
     }
 
@@ -144,8 +148,16 @@ namespace mln
     rms<T,V>::to_result() const
     {
       if (count_ == 0)
-	return literal::zero;
-      return math::sqrt<V>(t_ / count_);
+	return V(0);
+      return math::sqrt<V>(v_ / count_);
+    }
+
+    template <typename T, typename V>
+    inline
+    V
+    rms<T,V>::hook_value_() const
+    {
+      return v_;
     }
 
     template <typename T, typename V>
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        	* mln/debug/histo.hh: new. Print a histogram into a plot data file.
	* mln/debug/all.hh: include this new header.
---
 milena/ChangeLog                      |    8 ++++
 milena/mln/debug/all.hh               |    1 +
 milena/mln/debug/{all.hh => histo.hh} |   63 ++++++++++++++++++++++----------
 3 files changed, 52 insertions(+), 20 deletions(-)
 copy milena/mln/debug/{all.hh => histo.hh} (54%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 1599b96..205f6d9 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,11 @@
+2009-02-05  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
+	Add debug::histo.
+
+	* mln/debug/histo.hh: new. Print a histogram into a plot data file.
+
+	* mln/debug/all.hh: include this new header.
+
 2009-02-04  Roland Levillain  <roland(a)lrde.epita.fr>
 
 	Fix the generation of milena/headers.mk.
diff --git a/milena/mln/debug/all.hh b/milena/mln/debug/all.hh
index c01d416..dd1fda8 100644
--- a/milena/mln/debug/all.hh
+++ b/milena/mln/debug/all.hh
@@ -50,6 +50,7 @@ namespace mln
 # include <mln/debug/colorize.hh>
 # include <mln/debug/format.hh>
 # include <mln/debug/draw_graph.hh>
+# include <mln/debug/histo.hh>
 # include <mln/debug/iota.hh>
 # include <mln/debug/println.hh>
 # include <mln/debug/println_with_border.hh>
diff --git a/milena/mln/debug/all.hh b/milena/mln/debug/histo.hh
similarity index 54%
copy from milena/mln/debug/all.hh
copy to milena/mln/debug/histo.hh
index c01d416..1b0bbeb 100644
--- a/milena/mln/debug/all.hh
+++ b/milena/mln/debug/histo.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2009 EPITA Research and Development Laboratory
 // (LRDE)
 //
 // This file is part of the Olena Library.  This library is free
@@ -26,36 +26,59 @@
 // reasons why the executable file might be covered by the GNU General
 // Public License.
 
-#ifndef MLN_DEBUG_ALL_HH
-# define MLN_DEBUG_ALL_HH
+#ifndef MLN_DEBUG_HISTO_HH
+# define MLN_DEBUG_HISTO_HH
 
-/// \file mln/debug/all.hh
+/// \file mln/debug/histo.hh
 ///
-/// File that includes all debug-related routines.
+/// save a histogram to a plot data file.
 
+# include <vector>
+# include <mln/core/image/image2d.hh>
+# include <mln/draw/line.hh>
 
 namespace mln
 {
 
-  /// Namespace of routines that help to debug.
   namespace debug
   {
-    /// Implementation namespace of debug namespace.
-    namespace impl {}
-  }
 
-}
 
+    void
+    histo_plot(const histo::array<unsigned>& h, const std::string& filename);
 
-# include <mln/debug/colorize.hh>
-# include <mln/debug/format.hh>
-# include <mln/debug/draw_graph.hh>
-# include <mln/debug/iota.hh>
-# include <mln/debug/println.hh>
-# include <mln/debug/println_with_border.hh>
-# include <mln/debug/put_word.hh>
-# include <mln/debug/quiet.hh>
-# include <mln/debug/slices_2d.hh>
+    void
+    histo_plot(const std::vector<unsigned>& h, const std::string& filename);
 
+# ifndef MLN_INCLUDE_ONLY
 
-#endif // ! MLN_DEBUG_ALL_HH
+    void
+    histo_plot(const histo::array<unsigned>& h, const std::string& filename)
+    {
+      mln_precondition(h.is_valid());
+      histo_plot(h.vect(), filename);
+    }
+
+    void
+    histo_plot(const std::vector<unsigned>& h, const std::string& filename)
+    {
+      std::ofstream file(filename.c_str());
+      if (! file)
+      {
+	std::cerr << "error: cannot open file '" << filename << "'!";
+	abort();
+      }
+
+      for (unsigned i = 0; i < h.size(); ++i)
+	file << i << ' ' << h[i] << std::endl;
+    }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::debug
+
+} // end of namespace mln
+
+
+#endif // ! MLN_DEBUG_HISTO_HH
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                          URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-02-05  Fabien Freling  <freling(a)lrde.epita.fr>
	Enable the fastest version of labeling.
	* fabien/labeling.hh: Fastest version enabled.
	* fabien/regional_maxima.cc: Launch 10 times the test.
---
 labeling.hh        |    2 +-
 regional_maxima.cc |    7 +++++--
 2 files changed, 6 insertions(+), 3 deletions(-)
Index: trunk/milena/sandbox/fabien/regional_maxima.cc
===================================================================
--- trunk/milena/sandbox/fabien/regional_maxima.cc	(revision 3292)
+++ trunk/milena/sandbox/fabien/regional_maxima.cc	(revision 3293)
@@ -46,9 +46,12 @@
   using namespace mln;
   using value::int_u8;
 
-  image2d<int_u8> lena = io::pgm::load<int_u8>(MLN_IMG_DIR "/tiny.pgm");
+  image2d<int_u8> lena = io::pgm::load<int_u8>(MLN_IMG_DIR "/lena.pgm");
 
   unsigned n;
-  debug::println(labeling::regional_maxima(lena, c4(), n));
+  for (int i = 0; i < 10; ++i)
+  {
+    labeling::regional_maxima(lena, c4(), n);
+  }
   mln_assertion(n == 25);
 }
Index: trunk/milena/sandbox/fabien/labeling.hh
===================================================================
--- trunk/milena/sandbox/fabien/labeling.hh	(revision 3292)
+++ trunk/milena/sandbox/fabien/labeling.hh	(revision 3293)
@@ -530,7 +530,7 @@
 	    &&
 	    mln_is_simple_neighborhood(N)::value
 	};
-	return labeling_sorted_dispatch(metal::false_(),
+	return labeling_sorted_dispatch(metal::bool_<test>(),
 	    input, nbh, nlabels,
 	    functor, increasing);
       }
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                          URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-02-05  Fabien Freling  <freling(a)lrde.epita.fr>
	Correct generic implementation labeling.
	* fabien/labeling.hh: Minor fixes, fastest version off.
	* fabien/regional_maxima.cc: Print output.
	* fabien/regional_maxima.hh: Correct generic impl.
---
 labeling.hh        |    6 +++---
 regional_maxima.cc |    3 ++-
 regional_maxima.hh |   16 ++++++++--------
 3 files changed, 13 insertions(+), 12 deletions(-)
Index: trunk/milena/sandbox/fabien/regional_maxima.cc
===================================================================
--- trunk/milena/sandbox/fabien/regional_maxima.cc	(revision 3291)
+++ trunk/milena/sandbox/fabien/regional_maxima.cc	(revision 3292)
@@ -38,6 +38,7 @@
 #include "regional_maxima.hh"
 
 #include <tests/data.hh>
+#include <mln/debug/println.hh>
 
 
 int main()
@@ -48,6 +49,6 @@
   image2d<int_u8> lena = io::pgm::load<int_u8>(MLN_IMG_DIR "/tiny.pgm");
 
   unsigned n;
-  labeling::regional_maxima(lena, c4(), n);
+  debug::println(labeling::regional_maxima(lena, c4(), n));
   mln_assertion(n == 25);
 }
Index: trunk/milena/sandbox/fabien/regional_maxima.hh
===================================================================
--- trunk/milena/sandbox/fabien/regional_maxima.hh	(revision 3291)
+++ trunk/milena/sandbox/fabien/regional_maxima.hh	(revision 3292)
@@ -84,15 +84,15 @@
 
 	void init()                              { data::fill(attr, true); }
 	bool handles(const P&) const             { return true; }
-	bool labels(const P& p) const            { return attr.element(p); }
-	bool equiv(const P& n, const P& p) const { return input.element(n) ==
-	    input.element(p); }
-	void do_no_union(const P& n, const P& p) { mln_invariant(input.element(n) >
-								 input.element(p));
-	  attr.element(p) = false; }
+	bool labels(const P& p) const            { return attr(p); }
+	bool equiv(const P& n, const P& p) const { return input(n) ==
+						   input(p); }
+	void do_no_union(const P& n, const P& p) { mln_invariant(input(n) >
+								 input(p));
+						   attr(p) = false; }
 	void init_attr(const P&)                 {}
-	void merge_attr(const P& r, const P& p)  { attr.element(p) = attr.element(p) &&
-	    attr.element(r); }
+	void merge_attr(const P& r, const P& p)  { attr(p) = attr(p) &&
+	    attr(r); }
 
 	// Fastest implementation
 
Index: trunk/milena/sandbox/fabien/labeling.hh
===================================================================
--- trunk/milena/sandbox/fabien/labeling.hh	(revision 3291)
+++ trunk/milena/sandbox/fabien/labeling.hh	(revision 3292)
@@ -154,7 +154,7 @@
 
 	  // First Pass.
 	  {
-	    mln_fwd_piter(S) p(f.s);
+	    mln_fwd_piter(S) p(s);
 	    mln_niter(N) n(nbh, p);
 	    for_all(p) if (f.handles(p))
 	      {
@@ -184,7 +184,7 @@
 
 	  // Second Pass.
 	  {
-	    mln_bkd_piter(S) p(f.s);
+	    mln_bkd_piter(S) p(s);
 	    for_all(p) if (f.handles(p))
 	      {
 		if (parent(p) == p) // if p is root
@@ -530,7 +530,7 @@
 	    &&
 	    mln_is_simple_neighborhood(N)::value
 	};
-	return labeling_sorted_dispatch(metal::bool_<test>(),
+	return labeling_sorted_dispatch(metal::false_(),
 	    input, nbh, nlabels,
 	    functor, increasing);
       }
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                          URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-02-05  Fabien Freling  <freling(a)lrde.epita.fr>
	Compile fastest versions of labeling.
	* fabien/labeling.hh: Compile fastest versions.
	* fabien/regional_maxima.cc: Simple test file.
	* fabien/regional_maxima.hh: Functor in fastest implementation.
---
 labeling.hh        |  293 ++++++++++++++++++++++++++---------------------------
 regional_maxima.cc |   53 +++++++++
 regional_maxima.hh |    8 -
 3 files changed, 204 insertions(+), 150 deletions(-)
Index: trunk/milena/sandbox/fabien/regional_maxima.cc
===================================================================
--- trunk/milena/sandbox/fabien/regional_maxima.cc	(revision 0)
+++ trunk/milena/sandbox/fabien/regional_maxima.cc	(revision 3291)
@@ -0,0 +1,53 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/*! \file tests/labeling/regional_maxima.cc
+ *
+ * \brief Test on mln::labeling::regional_maxima.
+ */
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/io/pgm/load.hh>
+
+#include "regional_maxima.hh"
+
+#include <tests/data.hh>
+
+
+int main()
+{
+  using namespace mln;
+  using value::int_u8;
+
+  image2d<int_u8> lena = io::pgm::load<int_u8>(MLN_IMG_DIR "/tiny.pgm");
+
+  unsigned n;
+  labeling::regional_maxima(lena, c4(), n);
+  mln_assertion(n == 25);
+}
Index: trunk/milena/sandbox/fabien/regional_maxima.hh
===================================================================
--- trunk/milena/sandbox/fabien/regional_maxima.hh	(revision 3290)
+++ trunk/milena/sandbox/fabien/regional_maxima.hh	(revision 3291)
@@ -35,7 +35,9 @@
 
 # include <mln/core/concept/image.hh>
 # include <mln/core/concept/neighborhood.hh>
-# include <mln/canvas/labeling.hh>
+
+# include "labeling.hh"
+
 # include <mln/data/fill.hh>
 # include <mln/level/sort_psites.hh>
 
@@ -102,7 +104,7 @@
 	void do_no_union_(unsigned n, unsigned p) { mln_invariant(input.element(n) >
 								  input.element(p));
 	  attr.element(p) = false; }
-	void init_attr_(const P&)                 {}
+	void init_attr_(unsigned)                 {}
 	void merge_attr_(unsigned r, unsigned p)  { attr.element(p) = attr.element(p) &&
 	    attr.element(r); }
 
@@ -110,7 +112,7 @@
 
 	mln_ch_value(I, bool) attr;
 
-	regional_maxima_functor(const I_& input, const N_& nbh)
+	regional_maxima_functor(const I& input)
 	  : input(input)
 	{
 	  initialize(attr, input);
Index: trunk/milena/sandbox/fabien/labeling.hh
===================================================================
--- trunk/milena/sandbox/fabien/labeling.hh	(revision 3290)
+++ trunk/milena/sandbox/fabien/labeling.hh	(revision 3291)
@@ -223,105 +223,104 @@
 	if (parent.element(x) == x)
 	  return x;
 	else
-	  return parent.element(x) = find_root(parent, parent.element(x));
+	  return parent.element(x) = find_root_fastest(parent, parent.element(x));
       }
 
-//       // FIXME: Use the same functer for the generic and the fastest versions 
 
-//       template <typename I, typename N, typename L,
-// 		typename F>
-//       mln_ch_value(I, L)
-// 	labeling_fastest_video(const Image<I>& input_, const Neighborhood<N>& nbh_,
-// 			       F& f, L& nlabels)
-//       {
-// 	trace::entering("canvas::impl::labeling");
-
-// 	// FIXME: Test?!
-
-// 	const I& input = exact(input_);
-// 	const N& nbh   = exact(nbh_);
-
-// 	// Local type.
-// 	typedef mln_psite(I) P;
-
-// 	// Auxiliary data.
-// 	mln_ch_value(I, bool) deja_vu;
-// 	mln_ch_value(I, P)    parent;
-
-// 	// Output.
-// 	mln_ch_value(I, L) output;
-// 	bool status;
-
-// 	// Initialization.
-// 	{
-// 	  initialize(deja_vu, input);
-// 	  mln::data::fill(deja_vu, false);
-
-// 	  initialize(parent, input);
-
-// 	  initialize(output, input);
-// 	  mln::data::fill(output, L(literal::zero));
-// 	  nlabels = 0;
-
-// 	  f.init(); // Client initialization.
-// 	}
-
-// 	// First Pass.
-// 	{
-// 	  mln_pixter(const S) p(f.s);
-// 	  mln_nixter(const S, N) n(p, nbh);
-// 	  for_all(p) if (f.handles(p))
-// 	    {
-// 	      // Make-Set.
-// 	      parent.element(p) = p;
-// 	      f.init_attr(p);
-
-// 	      for_all(n)
-// 		if (input.has(n) && deja_vu(n))
-// 		  {
-// 		    if (f.equiv(n, p))
-// 		      {
-// 			// Do-Union.
-// 			unsigned r = find_root_fastest(parent, n);
-// 			if (r != p)
-// 			  {
-// 			    parent.element(r) = p;
-// 			    f.merge_attr(r, p);
-// 			  }
-// 		      }
-// 		    else
-// 		      f.do_no_union(n, p);
-// 		    (p) = true;
-// 		  }
-// 	    }
-// 	}
-
-// 	// Second Pass.
-// 	{
-// 	  mln_bkd_pixter(S) p(f.s);
-// 	  for_all(p) if (f.handles(p))
-// 	    {
-// 	      if (parent.element(p) == p) // if p is root
-// 		{
-// 		  if (f.labels(p))
-// 		    {
-// 		      if (nlabels == mln_max(L))
-// 			{
-// 			  status = false;
-// 			  return output;
-// 			}
-// 		      output.element(p) = ++nlabels;
-// 		    }
-// 		}
-// 	      else
-// 		output.element(p) = output(parent.element(p));
-// 	    }
-// 	  status = true;
-// 	}
-
-// 	trace::exiting("canvas::impl::labeling");
-// 	return output;
-//       }
+      template <typename I, typename N, typename L,
+	       typename F>
+      mln_ch_value(I, L)
+      labeling_video_fastest(const Image<I>& input_, const Neighborhood<N>& nbh_,
+	  F& f, L& nlabels)
+      {
+	trace::entering("canvas::impl::labeling");
+
+	// FIXME: Test?!
+
+	const I& input = exact(input_);
+	const N& nbh   = exact(nbh_);
+
+	// Local type.
+	typedef mln_psite(I) P;
+
+	// Auxiliary data.
+	mln_ch_value(I, bool) deja_vu;
+	mln_ch_value(I, P)    parent;
+
+	// Output.
+	mln_ch_value(I, L) output;
+	bool status;
+
+	// Initialization.
+	{
+	  initialize(deja_vu, input);
+	  mln::data::fill(deja_vu, false);
+
+	  initialize(parent, input);
+
+	  initialize(output, input);
+	  mln::data::fill(output, L(literal::zero));
+	  nlabels = 0;
+
+	  f.init_(); // Client initialization.
+	}
+
+	// First Pass.
+	{
+	  mln_pixter(const I) p(input);
+	  mln_nixter(const I, N) n(p, nbh);
+	  for_all(p) if (f.handles_(p))
+	  {
+	    // Make-Set.
+	    parent.element(p) = p;
+	    f.init_attr(p);
+
+	    for_all(n)
+	      if (input.has(n) && deja_vu(n))
+	      {
+		if (f.equiv_(n, p))
+		{
+		  // Do-Union.
+		  unsigned r = find_root_fastest(parent, n);
+		  if (r != p)
+		  {
+		    parent.element(r) = p;
+		    f.merge_attr_(r, p);
+		  }
+		}
+		else
+		  f.do_no_union_(n, p);
+		(p) = true;
+	      }
+	  }
+	}
+
+	// Second Pass.
+	{
+	  mln_bkd_pixter(I) p(input);
+	  for_all(p) if (f.handles_(p))
+	  {
+	    if (parent.element(p) == p) // if p is root
+	    {
+	      if (f.labels_(p))
+	      {
+		if (nlabels == mln_max(L))
+		{
+		  status = false;
+		  return output;
+		}
+		output.element(p) = ++nlabels;
+	      }
+	    }
+	    else
+	      output.element(p) = output(parent.element(p));
+	  }
+	  status = true;
+	}
+
+	trace::exiting("canvas::impl::labeling");
+	return output;
+      }
 
 
 
@@ -345,7 +344,7 @@
 
 	// Auxiliary data.
 	mln_ch_value(I, bool) deja_vu;
-	mln_ch_value(I, P)    parent;
+	mln_ch_value(I, unsigned)    parent;
 
 	// Output.
 	mln_ch_value(I, L) output;
@@ -362,13 +361,13 @@
 	  mln::data::fill(output, L(literal::zero));
 	  nlabels = 0;
 
-	  f.init(); // Client initialization.
+	  f.init_(); // Client initialization.
 	}
 
-	util::array<int> dp = offsers_wrt(input, nbh);
+	util::array<int> dp = offsets_wrt(input, nbh);
 	const unsigned n_nbhs = dp.nelements();
 
-	const unsigned n_points = s.elements();
+	const unsigned n_points = s.nelements();
 
 	// First Pass.
 	{
@@ -376,31 +375,31 @@
 	  for (unsigned i = 0; i < n_points; ++i)
 	    {
 	      unsigned p = s[i];
-	      if (!f.handles(p))
+	      if (!f.handles_(p))
 		continue;
 
 	      // Make-Set.
 	      parent.element(p) = p;
-	      f.init_attr(p);
+	      f.init_attr_(p);
 
 	      for (unsigned j = 0; j < n_nbhs; ++j)
 		{
 		  unsigned n = p + dp[j];
-		  if (!deja_vu[n])
+		  if (!deja_vu.element(n))
 		    continue;
 
-		  if (f.equiv(n, p))
+		  if (f.equiv_(n, p))
 		    {
 		      // Do-Union.
 		      unsigned r = find_root_fastest(parent, n);
 		      if (input.element(r) != input.element(p))
 			{
 			  parent.element(r) = p;
-			  f.merge_attr(r, p);
+			  f.merge_attr_(r, p);
 			}
 		    }
 		  else
-		    f.do_no_union(n, p);
+		    f.do_no_union_(n, p);
 		}
 	      deja_vu.element(p) = true;
 
@@ -412,12 +411,12 @@
 	  for (int i = n_points - 1; i >=0; --i)
 	    {
 	      unsigned p = s[i];
-	      if (!f.handles(p))
+	      if (!f.handles_(p))
 		continue;
 
 	      if (parent.element(p) == p) // if p is root
 		{
-		  if (f.labels(p))
+		  if (f.labels_(p))
 		    {
 		      if (nlabels == mln_max(L))
 			{
@@ -428,7 +427,7 @@
 		    }
 		}
 	      else
-		output.element(p) = output(parent.element(p));
+		output.element(p) = output.element(parent.element(p));
 	    }
 	  status = true;
 	}
@@ -446,45 +445,45 @@
     namespace internal
     {
 
-//       // Video
+      // Video
 
-//       template <typename I, typename N, typename L,
-// 		typename F>
-//       inline
-//       mln_ch_value(I, L)
-// 	labeling_video(metal::false_, const Image<I>& input,
-// 		       const Neighborhood<N>& nbh, L& nlabels, F& functor)
-//       {
-// 	return impl::generic::labeling(input, nbh, input.domain(),
-// 				       nlabels, functor);
-//       }
-
-//       template <typename I, typename N, typename L,
-// 		typename F>
-//       inline
-//       mln_ch_value(I, L)
-// 	labeling_video(metal::true_, const Image<I>& input,
-// 		       const Neighborhood<N>& nbh, L& nlabels, F& functor)
-//       {
-// 	return impl::labeling_fastest_video(input, nbh, nlabels, functor);
-//       }
-
-//       template <typename I, typename N, typename L,
-// 		typename F>
-//       inline
-//       mln_ch_value(I, L)
-// 	labeling_video_dispatch(const Image<I>& input, const Neighborhood<N>& nbh,
-// 				L& nlabels, F& functor)
-//       {
-// 	enum {
-// 	  test = mlc_equal(mln_trait_image_speed(I),
-// 			   trait::image::speed::fastest)::value
-// 	  &&
-// 	  mln_is_simple_neighborhood(N)::value
-// 	};
-// 	return impl::generic::labeling_video(metal::bool_<test>(), input,
-// 					     nbh, nlabels, functor);
-//       }
+      template <typename I, typename N, typename L,
+		typename F>
+      inline
+      mln_ch_value(I, L)
+      labeling_video(metal::false_, const Image<I>& input,
+	  const Neighborhood<N>& nbh, L& nlabels, F& functor)
+      {
+	return impl::generic::labeling(input, nbh, input.domain(),
+	    nlabels, functor);
+      }
+
+      template <typename I, typename N, typename L,
+	        typename F>
+      inline
+      mln_ch_value(I, L)
+      labeling_video(metal::true_, const Image<I>& input,
+	  const Neighborhood<N>& nbh, L& nlabels, F& functor)
+      {
+	return impl::labeling_video_fastest(input, nbh, nlabels, functor);
+      }
+
+      template <typename I, typename N, typename L,
+	        typename F>
+      inline
+      mln_ch_value(I, L)
+      labeling_video_dispatch(const Image<I>& input, const Neighborhood<N>& nbh,
+	  L& nlabels, F& functor)
+      {
+	enum {
+	  test = mlc_equal(mln_trait_image_speed(I),
+	      trait::image::speed::fastest)::value
+	    &&
+	    mln_is_simple_neighborhood(N)::value
+	};
+	return impl::generic::labeling(metal::bool_<test>(), input,
+	    nbh, nlabels, functor);
+      }
 
 
       // Sorted dispatch.
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0