https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Géraud <thierry.geraud(a)lrde.epita.fr>
Add morpho elementary gradient and test.
* doc/tutorial/examples/sub_image.cc: Use an IP operator.
* mln/accu/pair.hh (first, second): Fix return type.
* mln/morpho/gradient_elementary.hh: New.
doc/tutorial/examples/sub_image.cc | 3
mln/accu/pair.hh | 8 +-
mln/morpho/gradient_elementary.hh | 125 +++++++++++++++++++++++++++++++++++++
3 files changed, 132 insertions(+), 4 deletions(-)
Index: doc/tutorial/examples/sub_image.cc
--- doc/tutorial/examples/sub_image.cc (revision 2084)
+++ doc/tutorial/examples/sub_image.cc (working copy)
@@ -1,9 +1,11 @@
# include <mln/core/image2d.hh>
+# include <mln/core/neighb2d.hh>
# include <mln/core/sub_image.hh>
# include <mln/debug/iota.hh>
# include <mln/debug/println.hh>
+# include <mln/morpho/gradient_elementary.hh>
int main()
@@ -17,6 +19,7 @@
sub_image<I, box2d> sub(ima, box2d(2,3));
debug::println(sub);
+ debug::println(morpho::gradient_elementary(sub, c4()));
trait::image::print(sub);
}
Index: mln/accu/pair.hh
--- mln/accu/pair.hh (revision 2084)
+++ mln/accu/pair.hh (working copy)
@@ -75,8 +75,8 @@
result to_result() const;
void get_result(result_1& r1, result_2& r2) const;
- result_1 first() const;
- result_2 second() const;
+ mln_result(A1) first() const;
+ mln_result(A2) second() const;
protected:
@@ -166,7 +166,7 @@
template <typename A1, typename A2, typename T>
inline
- result_1
+ mln_result(A1)
pair_<A1,A2,T>::first()const
{
return a1_.to_result();
@@ -174,7 +174,7 @@
template <typename A1, typename A2, typename T>
inline
- result_2
+ mln_result(A2)
pair_<A1,A2,T>::second() const
{
return a2_.to_result();
Index: mln/morpho/gradient_elementary.hh
--- mln/morpho/gradient_elementary.hh (revision 0)
+++ mln/morpho/gradient_elementary.hh (revision 0)
@@ -0,0 +1,125 @@
+// Copyright (C) 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.
+
+#ifndef MLN_MORPHO_GRADIENT_ELEMENTARY_HH
+# define MLN_MORPHO_GRADIENT_ELEMENTARY_HH
+
+/// \file mln/morpho/gradient_elementary.hh
+/// \brief Morphological elementary gradient.
+///
+/// \todo Write specific code.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/accu/min_max.hh>
+
+
+namespace mln
+{
+
+ namespace morpho
+ {
+
+ /// Morphological elementary gradient.
+ ///
+ /// \param[in] input The image to be dilated.
+ /// \param[in] nbh The neighborhood to consider.
+ ///
+ /// The structuring element is the neighborhood + the center site.
+ ///
+ /// \{
+ template <typename I, typename N>
+ mln_concrete(I)
+ gradient_elementary(const Image<I>& input, const Neighborhood<N>& nbh);
+ /// \}
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ gradient_elementary_(const mln::trait::image::kind::any&,
+ const I& input, const N& nbh)
+ {
+ trace::entering("morpho::impl::generic::gradient_elementary_");
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ accu::min_max_<mln_value(I)> m;
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ m.take_as_init(input(p));
+ for_all(n) if (input.has(n))
+ m.take(input(n));
+ output(p) = m.second() - m.first();
+ }
+
+ trace::exiting("morpho::impl::generic::gradient_elementary_");
+ return output;
+
+ }
+
+ } // end of namespace mln::internal::generic
+
+ } // end of namespace mln::internal
+
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ gradient_elementary(const Image<I>& input_, const Neighborhood<N>& nbh_)
+ {
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ trace::entering("morpho::gradient_elementary");
+ mln_precondition(input.has_data());
+ // FIXME: mln_precondition(! nbh.is_empty());
+
+ mln_concrete(I) output = impl::generic::gradient_elementary_(mln_trait_image_kind(I)(),
+ input, nbh);
+
+ trace::exiting("morpho::gradient_elementary");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_GRADIENT_ELEMENTARY_HH
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Misc. fixes in mln::p_array<P>.
* mln/core/p_array.hh: Update documentation.
Aesthetic changes.
(mln::p_array<P>::p_array ())
(mln::p_array<P>::p_array (const std::vector<P>&)):
Initialize mln::p_array<P>::bb_needs_update_ using the
initialization list of the ctor.
(mln::p_array<P>::clear): Don't forget to initialize
mln::p_array<P>::bb_.
p_array.hh | 35 +++++++++++++++++++----------------
1 file changed, 19 insertions(+), 16 deletions(-)
Index: mln/core/p_array.hh
--- mln/core/p_array.hh (revision 2078)
+++ mln/core/p_array.hh (working copy)
@@ -28,10 +28,8 @@
#ifndef MLN_CORE_P_ARRAY_HH
# define MLN_CORE_P_ARRAY_HH
-/*! \file mln/core/p_array.hh
- *
- * \brief Definition of a point set class based on std::vector.
- */
+/// \file mln/core/p_array.hh
+/// \brief Definition of a point set class based on std::vector.
# include <vector>
@@ -47,15 +45,17 @@
template <typename P> struct p_array_bkd_piter_;
- /*! \brief Point set class based on std::vector.
- *
- * This is a multi-set of points.
- *
- * \warning We have some troubles with point set comparison based on
- * a call to npoints(). FIXME: Explain!
- *
- * \todo Make it work with P being a Point_Site.
- */
+ /// \brief Point set class based on std::vector.
+ ///
+ /// This is a multi-set of points. The parameter \p P shall be a
+ /// Point type or a Point_Site.
+ ///
+ /// FIXME: If \p P is a Point_Site, but not a Point, the method
+ /// mln::p_array<P>::bbox will not compile (see below). (Will be
+ /// fixed with the merge with branch cleanup-2008.)
+ ///
+ /// \warning We have some troubles with point set comparison based on
+ /// a call to npoints(). FIXME: Explain!
template <typename P>
class p_array : public internal::point_set_base_< P, p_array<P> >
{
@@ -87,6 +87,8 @@
/// Give the number of points.
std::size_t npoints() const;
+ /* FIXME: Won't work if P is not (implicitly) convertible to
+ mln_point(P). */
/// Give the exact bounding box.
const box_<point>& bbox() const;
@@ -125,16 +127,16 @@
template <typename P>
inline
p_array<P>::p_array()
+ : bb_needs_update_(false)
{
- bb_needs_update_ = false;
}
template <typename P>
inline
p_array<P>::p_array(const std::vector<P>& vect)
- : vect_(vect)
+ : vect_(vect),
+ bb_needs_update_(true)
{
- bb_needs_update_ = true;
}
template <typename P>
@@ -223,6 +225,7 @@
p_array<P>::clear()
{
vect_.clear();
+ bb_.init();
bb_needs_update_ = false;
}
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Now, mln::p_set<P>'s and mln::p_array<P>'s implementations are much closer
one another.
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Make the computation of the bbox of an mln::p_set<P> lazy.
* mln/core/p_set.hh (mln::p_set<P>::point): New typedef.
Use it...
(mln::p_set<P>::bbox): ...in the declaration of this method.
(mln::p_set<P>::bb_): Make it mutable.
Change type from `accu::bbox<P>' to `accu::bbox<point>'.
(mln::p_set<P>::bb_needs_update_): New attribute.
(mln::p_set<P>::update_bb_): New method.
(p_set<P>::p_set): Adjust ctor.
(mln::p_set<P>::insert)
(mln::p_set<P>::remove)
(mln::p_set<P>::clear)
(mln::p_set<P>::bbox):
Adjust methods.
* tests/core/point_set_compatibility.cc: Exercise
p_set< graph_psite<point2d> >.
mln/core/p_set.hh | 66 ++++++++++++++++++++++++----------
tests/core/point_set_compatibility.cc | 35 ++++++++++++++----
2 files changed, 75 insertions(+), 26 deletions(-)
Index: mln/core/p_set.hh
--- mln/core/p_set.hh (revision 2077)
+++ mln/core/p_set.hh (working copy)
@@ -28,10 +28,9 @@
#ifndef MLN_CORE_P_SET_HH
# define MLN_CORE_P_SET_HH
-/*! \file mln/core/p_set.hh
- *
- * \brief Definition of a point set class based on std::set.
- */
+/// \file mln/core/p_set.hh
+/// \brief Definition of a point set class based on std::set, that can
+/// behave also as a vector.
# include <mln/core/internal/point_set_base.hh>
# include <mln/core/internal/set_of.hh>
@@ -42,13 +41,14 @@
namespace mln
{
- /*! \brief Point set class based on std::set.
- *
- * This is a mathematical set of points (not a multi-set). The
- * parameter \p P shall be a Point type.
- *
- * \todo Test if \p P being a Point_Site is ok.
- */
+ /// \brief Point set class based on std::set.
+ ///
+ /// This is a mathematical set of points (not a multi-set). The
+ /// parameter \p P shall be a Point type or a Point_Site.
+ ///
+ /// FIXME: If \p is a Point_Site, but not a Point, the method
+ /// mln::p_set<P>::bbox will not compile (see below). (Will be fixed
+ /// with the merge with branch cleanup-2008.)
template <typename P>
class p_set : public internal::point_set_base_< P, p_set<P> >,
private internal::set_of_<P>
@@ -56,6 +56,16 @@
typedef internal::set_of_<P> super_;
public:
+ /* FIXME: Should be removed as soon as branch cleanup-2008 is
+ merged with the trunk. */
+ typedef mln_point(P) point;
+
+ /* FIXME: mln::p_set uses the same iterators as mln::p_array,
+ because mln::p_set also have the interface of an array. We
+ might want to keep this, but we should change the name of the
+ iterator, either by using an alias (typedef), of by giving them
+ their own type (which could share code with
+ mln::p_array_{fwd,bkd}_piter_, of course). */
/// Forward Point_Iterator associated type.
typedef p_array_fwd_piter_<P> fwd_piter;
@@ -87,12 +97,16 @@
/// Clear this set.
void clear();
+ /* FIXME: Won't work if P is not (implicitly) convertible to
+ mln_point(P). */
/// Give the exact bounding box.
- const box_<mln_point(P)>& bbox() const;
+ const box_<point>& bbox() const;
protected:
+ mutable accu::bbox<point> bb_;
+ mutable bool bb_needs_update_;
- accu::bbox<P> bb_;
+ void update_bb_() const;
// FIXME: Add invariant bb_.is_valid() <=> npoints() != 0
};
@@ -102,11 +116,24 @@
template <typename P>
inline
p_set<P>::p_set()
+ : bb_needs_update_(false)
{
}
template <typename P>
inline
+ void
+ p_set<P>::update_bb_() const
+ {
+ bb_.init();
+ for (typename std::set<P>::const_iterator i = this->s_.begin();
+ i != this->s_.end(); ++i)
+ bb_.take(*i);
+ bb_needs_update_ = false;
+ }
+
+ template <typename P>
+ inline
bool
p_set<P>::has(const P& p) const
{
@@ -127,7 +154,8 @@
p_set<P>::insert(const P& p)
{
this->super_::insert(p);
- bb_.take(p);
+ if (! bb_needs_update_)
+ bb_needs_update_ = true;
return *this;
}
@@ -137,11 +165,8 @@
p_set<P>::remove(const P& p)
{
this->super_::remove(p);
- // Rebuild the bounding box.
- bb_.init();
- for (typename std::set<P>::const_iterator i = this->s_.begin();
- i != this->s_.end(); ++i)
- bb_.take(*i);
+ if (! bb_needs_update_)
+ bb_needs_update_ = true;
return *this;
}
@@ -161,6 +186,7 @@
{
this->super_::clear();
bb_.init();
+ bb_needs_update_ = false;
}
template <typename P>
@@ -169,6 +195,8 @@
p_set<P>::bbox() const
{
mln_precondition(npoints() != 0);
+ if (bb_needs_update_)
+ update_bb_();
return bb_.to_result();
}
Index: tests/core/point_set_compatibility.cc
--- tests/core/point_set_compatibility.cc (revision 2077)
+++ tests/core/point_set_compatibility.cc (working copy)
@@ -32,6 +32,7 @@
#include <mln/core/point2d.hh>
#include <mln/core/p_array.hh>
+#include <mln/core/p_set.hh>
#include <mln/core/graph_psite.hh>
#include <mln/core/p_graph_piter.hh>
@@ -69,21 +70,41 @@
// Graph point set.
+ typedef p_graph<point2d> pg_t;
p_graph<point2d> pg(g);
-
-
- // Array of graph point sites.
typedef graph_psite<point2d> gpsite_t;
- p_array<gpsite_t> pa;
+ {
+ // Array of graph point sites.
+ typedef p_array<gpsite_t> pa_t;
+ pa_t pa;
// Tests: copying all psites from PG to PA.
- p_graph_fwd_piter_<point2d> p(pg);
+ mln_piter_(pg_t) p(pg);
for_all (p)
pa.append (p);
// Test: create and use an iterator over PA.
- p_array_fwd_piter_<gpsite_t> p2(pa);
+ mln_piter_(pa_t) p2(pa);
for_all (p2)
- std::cout << p2 << std::endl;
+ std::cout << p2 << ' ';
+ std::cout << std::endl;
+ }
+
+ {
+ // Set of graph point sites.
+ typedef p_set<gpsite_t> ps_t;
+ ps_t ps;
+
+ // Tests: copying all psites from PG to PS.
+ mln_piter_(pg_t) p(pg);
+ for_all (p)
+ ps.insert(p);
+
+ // Test: create and use an iterator over PS.
+ mln_piter_(ps_t) p2(ps);
+ for_all (p2)
+ std::cout << p2 << ' ';
+ std::cout << std::endl;
+ }
}