***SPAM*** L3 cleanup-2008 2070: Prefer delegation to impl inheritance for neighborhood.

https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Prefer delegation to impl inheritance for neighborhood. * doc/tutorial/examples/window.cc: Test make. * mln/core/internal/basic_window_impl.hh: Remove; its contents is now directly handled by... * mln/core/window.hh: ...this class. * mln/core/internal/neighborhood_impl_mixin.hh: Remove. * mln/core/internal/neighborhood_base.hh (is_centered, is_symmetric, sym): Remove; meaningless. * mln/core/pset_if_piter.hh: Use using and update. * mln/core/neighb2d.hh (neighb2d): Rely on neighborhood. Clean code. * mln/core/neighborhood.hh: New; use delegation to window. * mln/metal/math/sqrt.hh (mlc_sqrt_int): New. (sqrt_int_): Help compiler. (sqrt): Fix params. * mln/make/neighb2d.hh: New. * mln/make/window2d.hh: New overload. * mln/morpho/dilation_elementary.hh (todo): New. doc/tutorial/examples/window.cc | 11 + mln/core/internal/neighborhood_base.hh | 44 ----- mln/core/neighb2d.hh | 31 ++- mln/core/neighborhood.hh | 274 +++++++++++++++++++++++++++++++++ mln/core/pset_if_piter.hh | 18 +- mln/core/window.hh | 202 ++++++++++++++++++++++-- mln/make/neighb2d.hh | 67 +++++--- mln/make/window2d.hh | 42 +++-- mln/metal/math/sqrt.hh | 18 +- mln/morpho/dilation_elementary.hh | 2 10 files changed, 592 insertions(+), 117 deletions(-) Index: doc/tutorial/examples/window.cc --- doc/tutorial/examples/window.cc (revision 2069) +++ doc/tutorial/examples/window.cc (working copy) @@ -53,6 +53,17 @@ std::cout << win << std::endl; { + bool b[9] = { 1, 1, 0, + 1, 0, 0, + 0, 0, 0 }; + bool b2[3][3] = { { 1, 1, 0 }, + { 1, 0, 0 }, + { 0, 0, 0 } }; + mln_assertion(make::window2d(b) == make::window2d(b2)); + mln_assertion(make::window2d(b) == win); + } + + { mln_fwd_piter_(I) p(ima.domain()); for_all(p) picture(ima, win, p); Index: mln/core/window.hh --- mln/core/window.hh (revision 2069) +++ mln/core/window.hh (working copy) @@ -36,25 +36,33 @@ * point_, neighb_, etc. * * \todo Code other comparisons (< and <=). + * + * \todo Add static checks in insert methods. */ # include <mln/core/internal/window_base.hh> -# include <mln/core/internal/basic_window_impl.hh> # include <mln/metal/is_a.hh> +# include <mln/util/set.hh> +# include <mln/fun/i2v/all_to.hh> +# include <mln/norm/linfty.hh> namespace mln { + // Fwd decls. + template <typename V> class dpsites_fwd_piter; + template <typename V> class dpsites_bkd_piter; + + /*! \brief Generic window class. * * This type of window is just like a set of delta-points. The * parameter is \c D, type of delta-point. */ template <typename D> - class window : public internal::window_base< D, window<D> >, - public internal::basic_window_impl< D, window<D> > + class window : public internal::window_base< D, window<D> > { public: @@ -64,11 +72,6 @@ */ window(); - window(const util::set<D>& s) - { - this->dps_ = s; - } - /*! \brief Test if the window is centered. * * \return True if the delta-point 0 belongs to the window. @@ -82,6 +85,65 @@ /*! Apply a central symmetry to the target window. */ void sym(); + + + /*! \brief Site_Iterator type to browse the points of a basic window + * w.r.t. the ordering of delta-points. + */ + typedef dpsites_fwd_piter< window<D> > fwd_qiter; + + /*! \brief Site_Iterator type to browse the points of a basic window + * w.r.t. the reverse ordering of delta-points. + */ + typedef dpsites_bkd_piter< window<D> > bkd_qiter; + + /*! \brief Site_Iterator type to browse the points of a basic window + * whatever the ordering of delta-points. + */ + typedef fwd_qiter qiter; + + + /// Give the window size, i.e., the number of delta-sites. + unsigned size() const; + + /*! \brief Test if the window is empty (null size; no delta-point). + */ + bool is_empty() const; + + /*! \brief Give the maximum coordinate gap between the window + center and a window point. + */ + unsigned delta() const; + + // Give the \p i-th delta-point. + const D& dp(unsigned i) const; + + + + /// Insert a delta-point \p dp. + window<D>& insert(const D& dp); + + /// \{ Insertion of a delta-point with different numbers of + /// arguments (coordinates) w.r.t. the dimension. + window<D>& insert(const mln_coord(D)& dind); // For 1D. + + window<D>& insert(const mln_coord(D)& drow, + const mln_coord(D)& dcol); // For 2D. + + window<D>& insert(const mln_coord(D)& dsli, + const mln_coord(D)& drow, + const mln_coord(D)& dcol); // For 3D. + /// \} + + /// Give the vector of delta-points. + const std::vector<D>& std_vector() const; + + /// Hook to the set of D. + const util::set<D>& dps_hook_() const; + + private: + + util::set<D> dps_; }; @@ -114,7 +176,8 @@ template <typename D> inline - bool window<D>::is_symmetric() const + bool + window<D>::is_symmetric() const { window<D> cpy = *this; return cpy.sym() == *this; @@ -122,7 +185,8 @@ template <typename D> inline - bool window<D>::is_centered() const + bool + window<D>::is_centered() const { static const D origin = all_to(0); return this->dps_.has(origin); // FIXME: Use literal::origin. @@ -134,22 +198,127 @@ window<D>::sym() { window<D> tmp; - const unsigned n = this->ndpoints(); + const unsigned n = size(); for (unsigned i = 0; i < n; ++i) tmp.insert(- this->dp(i)); *this = tmp; } + + template <typename D> + inline + bool + window<D>::is_empty() const + { + return dps_.is_empty(); + } + template <typename D> - std::ostream& operator<<(std::ostream& ostr, const window<D>& win) + inline + unsigned + window<D>::delta() const + { + // FIXME: Is-it correct? + unsigned d = 0; + const unsigned n = size(); + for (unsigned i = 0; i < n; ++i) { - return ostr << win.dps_hook(); + unsigned dd = norm::linfty(dp(i).to_vec()); + if (dd > d) + d = dd; + } + return d; } template <typename D> - bool operator==(const window<D>& lhs, const window<D>& rhs) + inline + unsigned + window<D>::size() const { - return lhs.dps_hook() == rhs.dps_hook(); + return dps_.nelements(); + } + + template <typename D> + inline + const D& + window<D>::dp(unsigned i) const + { + mln_precondition(i < size()); + return dps_[i]; + } + + template <typename D> + inline + const std::vector<D>& + window<D>::std_vector() const + { + return dps_.vect(); + } + + template <typename D> + inline + window<D>& + window<D>::insert(const D& dp) + { + dps_.insert(dp); + return *this; + } + + template <typename D> + inline + window<D>& + window<D>::insert(const mln_coord(D)& dind) + { + mlc_bool(D::dim == 1)::check(); + D dp(dind); + return insert(dp); + } + + template <typename D> + inline + window<D>& + window<D>::insert(const mln_coord(D)& drow, + const mln_coord(D)& dcol) + { + mlc_bool(D::dim == 2)::check(); + D dp(drow, dcol); + return insert(dp); + } + + template <typename D> + inline + window<D>& + window<D>::insert(const mln_coord(D)& dsli, + const mln_coord(D)& drow, + const mln_coord(D)& dcol) + { + mlc_bool(D::dim == 3)::check(); + D dp(dsli, drow, dcol); + return insert(dp); + } + + template <typename D> + inline + const util::set<D>& + window<D>::dps_hook_() const + { + return dps_; + } + + // Operators. + + template <typename D> + std::ostream& + operator<<(std::ostream& ostr, const window<D>& win) + { + return ostr << win.dps_hook_(); + } + + template <typename D> + bool + operator==(const window<D>& lhs, const window<D>& rhs) + { + return lhs.dps_hook_() == rhs.dps_hook_(); } # endif // ! MLN_INCLUDE_ONLY @@ -157,4 +326,7 @@ } // end of namespace mln +# include <mln/core/dpsites_piter.hh> + + #endif // ! MLN_CORE_WINDOW_HH Index: mln/core/internal/neighborhood_base.hh --- mln/core/internal/neighborhood_base.hh (revision 2069) +++ mln/core/internal/neighborhood_base.hh (working copy) @@ -60,26 +60,6 @@ /// Site associated type. typedef mln_site(D) site; - - /*! \brief Test (as a window) if it is centered so (as a - * neighborhood) return false. - * - * \return Always false. - */ - bool is_centered() const; - - /*! \brief Test (as a window) if it is symmetric so (as a - * neighborhood) return true. - * - * \return Always true. - */ - bool is_symmetric() const; - - /*! Apply (as a window) a central symmetry so (as a - neighborhood) it is a no-op. - */ - void sym(); - protected: neighborhood_base(); }; @@ -93,30 +73,6 @@ { } - template <typename D, typename E> - inline - bool - neighborhood_base<D,E>::is_centered() const - { - return false; - } - - template <typename D, typename E> - inline - bool - neighborhood_base<D,E>::is_symmetric() const - { - return true; - } - - template <typename D, typename E> - inline - void - neighborhood_base<D,E>::sym() - { - // No-op. - } - # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::internal Index: mln/core/pset_if_piter.hh --- mln/core/pset_if_piter.hh (revision 2069) +++ mln/core/pset_if_piter.hh (working copy) @@ -68,6 +68,14 @@ /// The set site targeted by pi_. const S& pi_set_from_(const pset_if<S,F>& s) const; + + private: + typedef pset_if_piter_<Pi,S,F> self_; + typedef internal::piter_adaptor_<Pi, pset_if<S,F>, self_> super_; + + protected: + using super_::s_; + using super_::pi_; }; @@ -92,9 +100,9 @@ void pset_if_piter_<Pi,S,F>::start_() { - this->pi_.start(); - while (this->pi_.is_valid() && ! this->s_->pred(this->pi_)) - this->pi_.next(); + pi_.start(); + while (pi_.is_valid() && ! s_->pred(pi_)) + pi_.next(); } template <typename Pi, typename S, typename F> @@ -103,8 +111,8 @@ pset_if_piter_<Pi,S,F>::next_() { do - this->pi_.next(); - while (this->pi_.is_valid() && ! this->s_->pred(this->pi_)); + pi_.next(); + while (pi_.is_valid() && ! s_->pred(pi_)); } template <typename Pi, typename S, typename F> Index: mln/core/neighb2d.hh --- mln/core/neighb2d.hh (revision 2069) +++ mln/core/neighb2d.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -35,7 +35,7 @@ */ # include <cmath> -# include <mln/core/neighb.hh> +# include <mln/core/neighborhood.hh> # include <mln/core/dpoint2d.hh> @@ -45,9 +45,17 @@ /*! \brief Type alias for a neighborhood defined on the 2D square * grid with integer coordinates. */ - typedef neighb<dpoint2d> neighb2d; + typedef neighborhood<dpoint2d> neighb2d; + +} + + +# include <mln/make/neighb2d.hh> +namespace mln +{ + /*! \brief 4-connectivity neighborhood on the 2D grid. * * - o - @@ -104,8 +112,8 @@ static neighb2d it; if (flower) { - it.insert(make::dpoint2d(0, 1)); - it.insert(make::dpoint2d(1, 0)); + it.insert(0, 1) + .insert(1, 0); flower = false; } return it; @@ -118,10 +126,10 @@ static neighb2d it; if (flower) { - it.insert(make::dpoint2d(0, 1)); - it.insert(make::dpoint2d(1,-1)); - it.insert(make::dpoint2d(1, 0)); - it.insert(make::dpoint2d(1, 1)); + it.insert(0, 1) + .insert(1,-1) + .insert(1, 0) + .insert(1, 1); flower = false; } return it; @@ -134,7 +142,7 @@ static neighb2d it; if (flower) { - it.insert(make::dpoint2d(0, 1)); + it.insert(0, 1); flower = false; } return it; @@ -147,7 +155,7 @@ static neighb2d it; if (flower) { - it.insert(make::dpoint2d(1, 0)); + it.insert(1, 0); flower = false; } return it; @@ -158,4 +166,5 @@ } // end of namespace mln + #endif // ! MLN_CORE_NEIGHB2D_HH Index: mln/core/neighborhood.hh --- mln/core/neighborhood.hh (revision 0) +++ mln/core/neighborhood.hh (revision 0) @@ -0,0 +1,274 @@ +// Copyright (C) 2008 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +#ifndef MLN_CORE_NEIGHBORHOOD_HH +# define MLN_CORE_NEIGHBORHOOD_HH + +/*! \file mln/core/neighborhood.hh + * + * \brief Definition of the generic neighborhood class mln::neighborhood. + * + * \todo Make naming coherent: we have neighborhood (without '_') but + * point_, neighb_, etc. + * + * \todo Code other comparisons (< and <=). + * + * \todo Add static checks in insert methods. + */ + +# include <mln/core/internal/neighborhood_base.hh> +# include <mln/core/window.hh> +# include <mln/literal/zero.hh> + + +namespace mln +{ + + // Fwd decls. + template <typename V> class dpsites_fwd_piter; + template <typename V> class dpsites_bkd_piter; + + + /*! \brief Generic neighborhood class. + * + * This type of neighborhood is just like a set of delta-points. The + * parameter is \c D, type of delta-point. + */ + template <typename D> + class neighborhood : public internal::neighborhood_base< D, neighborhood<D> > + { + public: + + /*! \brief Constructor without argument. + * + * The constructed neighborhood is empty. + */ + neighborhood(); + + /*! \brief Constructor from a window. + * + * \pre The window has to be symmetrical and not centered. + */ + neighborhood(const mln::window<D>& win); + + /*! \brief Site_Iterator type to browse the points of a basic neighborhood + * w.r.t. the ordering of delta-points. + */ + typedef dpsites_fwd_piter< neighborhood<D> > fwd_niter; + + /*! \brief Site_Iterator type to browse the points of a basic neighborhood + * w.r.t. the reverse ordering of delta-points. + */ + typedef dpsites_bkd_piter< neighborhood<D> > bkd_niter; + + /*! \brief Site_Iterator type to browse the points of a basic neighborhood + * whatever the ordering of delta-points. + */ + typedef fwd_niter niter; + + + /// Give the neighborhood size, i.e., the number of delta-sites. + unsigned size() const; + + /*! \brief Give the maximum coordinate gap between the neighborhood + center and a neighborhood point. + */ + unsigned delta() const; + + + /// Insert a delta-point \p dp. + neighborhood<D>& insert(const D& dp); + + /// \{ Insertion of a delta-point with different numbers of + /// arguments (coordinates) w.r.t. the dimension. + neighborhood<D>& insert(const mln_coord(D)& dind); // For 1D. + + neighborhood<D>& insert(const mln_coord(D)& drow, + const mln_coord(D)& dcol); // For 2D. + + neighborhood<D>& insert(const mln_coord(D)& dsli, + const mln_coord(D)& drow, + const mln_coord(D)& dcol); // For 3D. + /// \} + + + + typedef window<D> window; + + mln::window<D> to_window() const + { + mln::window<D> tmp = win_; + D zero = literal::zero; + tmp.insert(zero); + return tmp; + } + + /// Give the vector of delta-points. + const std::vector<D>& std_vector() const; + + /// Hook to the set of D. + const util::set<D>& dps_hook_() const; + + private: + + mln::window<D> win_; + }; + + + // FIXME: Doc! + template <typename D> + std::ostream& operator<<(std::ostream& ostr, const neighborhood<D>& nbh); + + + + /*! \brief Equality comparison between neighborhoods \p lhs and \p rhs. + * + * \relates mln::neighborhood<D> + */ + template <typename D> + bool operator==(const neighborhood<D>& lhs, const neighborhood<D>& rhs); + + + +# ifndef MLN_INCLUDE_ONLY + + // neighborhood<D> + + template <typename D> + inline + neighborhood<D>::neighborhood() + { + // FIXME HERE: Was: mln::metal::is_a<D, Dpoint>::check(); + // mln::metal::is_a<D, Delta_Point_Site>::check(); + } + + template <typename D> + inline + neighborhood<D>::neighborhood(const mln::window<D>& win) + { + mln_precondition(win.is_symmetric() == true); + mln_precondition(win.is_centered() == false); + win_ = win; + } + + template <typename D> + inline + unsigned + neighborhood<D>::delta() const + { + mln_precondition(size() != 0); + return win_.delta(); + } + + template <typename D> + inline + unsigned + neighborhood<D>::size() const + { + return win_.size(); + } + + template <typename D> + inline + const std::vector<D>& + neighborhood<D>::std_vector() const + { + return win_.std_vector(); + } + + template <typename D> + inline + neighborhood<D>& + neighborhood<D>::insert(const D& dp) + { + win_.insert( dp); + win_.insert(-dp); + return *this; + } + + template <typename D> + inline + neighborhood<D>& + neighborhood<D>::insert(const mln_coord(D)& dind) + { + mlc_bool(D::dim == 1)::check(); + D dp(dind); + return insert(dp); + } + + template <typename D> + inline + neighborhood<D>& + neighborhood<D>::insert(const mln_coord(D)& drow, + const mln_coord(D)& dcol) + { + mlc_bool(D::dim == 2)::check(); + D dp(drow, dcol); + return insert(dp); + } + + template <typename D> + inline + neighborhood<D>& + neighborhood<D>::insert(const mln_coord(D)& dsli, + const mln_coord(D)& drow, + const mln_coord(D)& dcol) + { + mlc_bool(D::dim == 3)::check(); + D dp(dsli, drow, dcol); + return insert(dp); + } + + template <typename D> + inline + const util::set<D>& + neighborhood<D>::dps_hook_() const + { + return win_.dps_hook_(); + } + + // Operators. + + template <typename D> + std::ostream& operator<<(std::ostream& ostr, const neighborhood<D>& nbh) + { + return ostr << nbh.dps_hook_(); + } + + template <typename D> + bool operator==(const neighborhood<D>& lhs, const neighborhood<D>& rhs) + { + return lhs.dps_hook_() == rhs.dps_hook_(); + } + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + + + +#endif // ! MLN_CORE_NEIGHBORHOOD_HH Index: mln/metal/math/sqrt.hh --- mln/metal/math/sqrt.hh (revision 2069) +++ mln/metal/math/sqrt.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -37,6 +37,9 @@ # include <mln/metal/int.hh> +# define mlc_sqrt_int(N) mln::metal::math::sqrt_int<( N )>::value + + namespace mln { @@ -54,11 +57,12 @@ template <int n, int lo = 1, int hi = n> struct sqrt_int_ { - enum { mid = (lo + hi + 1) / 2 }; - - enum { value = n < mid * mid - ? sqrt_int_<n, lo, mid-1>::value - : sqrt_int_<n, mid, hi>::result }; + enum { + mid = (lo + hi + 1) / 2, + val_lo = sqrt_int_<n, lo, mid-1>::value, + val_hi = sqrt_int_<n, mid, hi>::value + }; + enum { value = n < mid * mid ? val_lo : val_hi }; }; template<int n, int m> @@ -92,7 +96,7 @@ // sqrt<N> - template <typename X, typename N> + template <typename N> struct sqrt; template <int n> Index: mln/make/neighb2d.hh --- mln/make/neighb2d.hh (revision 2069) +++ mln/make/neighb2d.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -25,17 +25,15 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_MAKE_WINDOW2D_HH -# define MLN_MAKE_WINDOW2D_HH +#ifndef MLN_MAKE_NEIGHB2D_HH +# define MLN_MAKE_NEIGHB2D_HH -/*! \file mln/make/window2d.hh +/*! \file mln/make/neighb2d.hh * - * \brief Routine to create an mln::window2d. + * \brief Routine to create an mln::neighb2d. */ -# include <cmath> -# include <mln/core/window2d.hh> -# include <mln/make/dpoint2d.hh> +# include <mln/make/window2d.hh> namespace mln @@ -44,32 +42,53 @@ namespace make { - /*! \brief Create an mln::window2d. + /*! \brief Create a mln::neighb2d. * * \param[in] values Array of Booleans. * - * \pre The array size, \c M, has to be a square of an odd integer. + * \pre The array size, \c S, has to be a square of an odd integer. * - * \return A 2D window. + * \return A 2D neighborhood. */ - template <unsigned M> - mln::window2d window2d(bool (&values)[M]); + template <unsigned S> + mln::neighb2d neighb2d(bool (&values)[S]); + + + /*! \brief Create a mln::neighb2d. + * + * \param[in] values Double-array of Booleans. + * + * \pre \c R and \c C, defining the array size, have to be odd. + * + * \return A 2D neighborhood. + */ + template <unsigned R, unsigned C> + mln::neighb2d neighb2d(bool (&values)[R][C]); # ifndef MLN_INCLUDE_ONLY - template <unsigned M> + template <unsigned S> + inline + mln::neighb2d + neighb2d(bool (&values)[S]) + { + enum { h = mlc_sqrt_int(S) / 2 }; + mlc_bool((2 * h + 1) * (2 * h + 1) == S)::check(); + mln::window2d win = make::window2d(values); + neighb2d tmp(win); + return tmp; + } + + template <unsigned R, unsigned C> inline - mln::window2d window2d(bool (&values)[M]) + mln::neighb2d + neighb2d(bool (&values)[R][C]) { - int h = unsigned(std::sqrt(float(M))) / 2; - assert((2 * h + 1) * (2 * h + 1) == M); - mln::window2d tmp; - unsigned i = 0; - for (int row = - h; row <= h; ++row) - for (int col = - h; col <= h; ++col) - if (values[i++]) - tmp.insert(make::dpoint2d(row, col)); + mlc_bool(R % 2 == 1)::check(); + mlc_bool(C % 2 == 1)::check(); + mln::window2d win = make::window2d(values); + neighb2d tmp(win); return tmp; } @@ -80,4 +99,4 @@ } // end of namespace mln -#endif // ! MLN_MAKE_WINDOW2D_HH +#endif // ! MLN_MAKE_NEIGHB2D_HH Index: mln/make/window2d.hh --- mln/make/window2d.hh (revision 2069) +++ mln/make/window2d.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -33,9 +33,8 @@ * \brief Routine to create an mln::window2d. */ -# include <cmath> # include <mln/core/window2d.hh> -# include <mln/make/dpoint2d.hh> +# include <mln/metal/math/sqrt.hh> namespace mln @@ -48,28 +47,49 @@ * * \param[in] values Array of Booleans. * - * \pre The array size, \c M, has to be a square of an odd integer. + * \pre The array size, \c S, has to be a square of an odd integer. * * \return A 2D window. */ - template <unsigned M> - mln::window2d window2d(bool (&values)[M]); + template <unsigned S> + mln::window2d window2d(bool (&values)[S]); + + + template <unsigned R, unsigned C> + mln::window2d window2d(bool (&values)[R][C]); # ifndef MLN_INCLUDE_ONLY - template <unsigned M> + template <unsigned S> inline - mln::window2d window2d(bool (&values)[M]) + mln::window2d + window2d(bool (&values)[S]) { - int h = unsigned(std::sqrt(float(M))) / 2; - assert((2 * h + 1) * (2 * h + 1) == M); + enum { h = mlc_sqrt_int(S) / 2 }; + mlc_bool((2 * h + 1) * (2 * h + 1) == S)::check(); mln::window2d tmp; unsigned i = 0; for (int row = - h; row <= h; ++row) for (int col = - h; col <= h; ++col) if (values[i++]) - tmp.insert(make::dpoint2d(row, col)); + tmp.insert(row, col); + return tmp; + } + + template <unsigned R, unsigned C> + inline + mln::window2d + window2d(bool (&values)[R][C]) + { + mlc_bool(R % 2 == 1)::check(); + mlc_bool(C % 2 == 1)::check(); + const int drow = int(R) / 2, dcol = int(C) / 2; + mln::window2d tmp; + for (int row = - drow; row <= drow; ++row) + for (int col = - dcol; col <= dcol; ++col) + if (values[row + drow][col + dcol]) + tmp.insert(row, col); return tmp; } Index: mln/morpho/dilation_elementary.hh --- mln/morpho/dilation_elementary.hh (revision 2069) +++ mln/morpho/dilation_elementary.hh (working copy) @@ -30,6 +30,8 @@ /// \file mln/morpho/dilation_elementary.hh /// \brief Morphological elementary dilation. +/// +/// \todo Write specific code. # include <mln/morpho/dilation.hh>
participants (1)
-
Thierry Geraud