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
01 Oct '08
* mln/topo/internal/complex_relative_iterator_base.hh
(complex_relative_iterator_base<F, E>::to_face):
Remove.
(complex_relative_iterator_base<F, E>::operator face):
Turn into...
(complex_relative_iterator_base<F, E>::operator const face&):
..this.
Return a const reference to the held face instead of a copy, so
that its address can be safely taken.
Remove the precondition, as invalid iterators are allowed to give
access to the face they hold.
---
milena/ChangeLog | 16 ++++++++++++++++
.../internal/complex_relative_iterator_base.hh | 15 ++-------------
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index cf00b66..5107bb1 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,21 @@
2008-10-01 Roland Levillain <roland(a)lrde.epita.fr>
+ Overhaul conversions of complex_relative_iterator_base<F, E>.
+
+ * mln/topo/internal/complex_relative_iterator_base.hh
+ (complex_relative_iterator_base<F, E>::to_face):
+ Remove.
+ (complex_relative_iterator_base<F, E>::operator face):
+ Turn into...
+ (complex_relative_iterator_base<F, E>::operator const face&):
+ ..this.
+ Return a const reference to the held face instead of a copy, so
+ that its address can be safely taken.
+ Remove the precondition, as invalid iterators are allowed to give
+ access to the face they hold.
+
+2008-10-01 Roland Levillain <roland(a)lrde.epita.fr>
+
Delegate pretty-printing of complex_psite<D> to topo::face<D>.
* mln/core/site_set/complex_psite.hh
diff --git a/milena/mln/topo/internal/complex_relative_iterator_base.hh b/milena/mln/topo/internal/complex_relative_iterator_base.hh
index 599727a..43a38ae 100644
--- a/milena/mln/topo/internal/complex_relative_iterator_base.hh
+++ b/milena/mln/topo/internal/complex_relative_iterator_base.hh
@@ -110,10 +110,8 @@ namespace mln
/// Conversion and accessors.
/// \{
- /// Reference to the corresponding face handle.
- const face& to_face () const;
/// Convert the iterator into an face handle.
- operator face() const;
+ operator const face&() const;
/// \}
protected:
@@ -297,20 +295,11 @@ namespace mln
template <typename F, typename E>
inline
- const F&
- complex_relative_iterator_base<F, E>::to_face() const
+ complex_relative_iterator_base<F, E>::operator const F&() const
{
return f_;
}
- template <typename F, typename E>
- inline
- complex_relative_iterator_base<F, E>::operator F() const
- {
- mln_precondition(exact(this)->is_valid());
- return f_;
- }
-
template <typename F, typename E>
inline
--
1.6.0.1
1
0
01 Oct '08
* mln/core/site_set/complex_psite.hh
(operator<<(std::ostream&, const complex_psite<D, P>&)): Here.
---
milena/ChangeLog | 7 +++++++
milena/mln/core/site_set/complex_psite.hh | 2 +-
2 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 641ceda..cf00b66 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,12 @@
2008-10-01 Roland Levillain <roland(a)lrde.epita.fr>
+ Delegate pretty-printing of complex_psite<D> to topo::face<D>.
+
+ * mln/core/site_set/complex_psite.hh
+ (operator<<(std::ostream&, const complex_psite<D, P>&)): Here.
+
+2008-10-01 Roland Levillain <roland(a)lrde.epita.fr>
+
Fix mln::topo::complex_psite<D, P> conversion to topo::face<D>.
* mln/core/site_set/complex_psite.hh
diff --git a/milena/mln/core/site_set/complex_psite.hh b/milena/mln/core/site_set/complex_psite.hh
index fdff939..1fe3ccc 100644
--- a/milena/mln/core/site_set/complex_psite.hh
+++ b/milena/mln/core/site_set/complex_psite.hh
@@ -363,7 +363,7 @@ namespace mln
std::ostream&
operator<<(std::ostream& ostr, const complex_psite<D, P>& p)
{
- return ostr << "(dim = " << p.n() << ", id = " << p.face_id() << ')';
+ return ostr << p.face();
}
# endif // ! MLN_INCLUDE_ONLY
--
1.6.0.1
1
0
2454: Fix mln::topo::complex_psite<D, P> conversion to topo::face<D>.
by Roland Levillain 01 Oct '08
by Roland Levillain 01 Oct '08
01 Oct '08
* mln/core/site_set/complex_psite.hh
(mln::topo::complex_psite<D, P>): Return a const reference to the
held face instead of a copy, so that its address can be safely
taken.
---
milena/ChangeLog | 9 +++++++++
milena/mln/core/site_set/complex_psite.hh | 4 ++--
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index e6ca427..641ceda 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,14 @@
2008-10-01 Roland Levillain <roland(a)lrde.epita.fr>
+ Fix mln::topo::complex_psite<D, P> conversion to topo::face<D>.
+
+ * mln/core/site_set/complex_psite.hh
+ (mln::topo::complex_psite<D, P>): Return a const reference to the
+ held face instead of a copy, so that its address can be safely
+ taken.
+
+2008-10-01 Roland Levillain <roland(a)lrde.epita.fr>
+
Fix comparison operators on topo::face<D> and topo::n_face<N, D>.
* mln/topo/face.hh
diff --git a/milena/mln/core/site_set/complex_psite.hh b/milena/mln/core/site_set/complex_psite.hh
index 02ab19e..fdff939 100644
--- a/milena/mln/core/site_set/complex_psite.hh
+++ b/milena/mln/core/site_set/complex_psite.hh
@@ -107,7 +107,7 @@ namespace mln
/// Face handle manipulators.
/// \{
/// Return the face handle of this point site.
- topo::face<D> face() const;
+ const topo::face<D>& face() const;
/// Return the dimension of the face of this psite.
unsigned n() const;
@@ -289,7 +289,7 @@ namespace mln
template <unsigned D, typename P>
inline
- topo::face<D>
+ const topo::face<D>&
complex_psite<D, P>::face() const
{
return face_;
--
1.6.0.1
1
0
2453: Fix comparison operators on topo::face<D> and topo::n_face<N, D>.
by Roland Levillain 01 Oct '08
by Roland Levillain 01 Oct '08
01 Oct '08
* mln/topo/face.hh
(operator==(const face<D>&, const face<D>&))
(operator< (const face<D>&, const face<D>&)):
* mln/topo/n_face.hh
(operator==(const n_face<N, D>&, const n_face<N, D>&))
(operator< (const n_face<N, D>&, const n_face<N, D>&)):
Fix preconditions.
Fix and catch up with the current interface of mln::topo::face<D>.
---
milena/ChangeLog | 13 +++++++++++++
milena/mln/topo/face.hh | 12 +++++-------
milena/mln/topo/n_face.hh | 8 ++++----
3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 5cefbda..e6ca427 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,18 @@
2008-10-01 Roland Levillain <roland(a)lrde.epita.fr>
+ Fix comparison operators on topo::face<D> and topo::n_face<N, D>.
+
+ * mln/topo/face.hh
+ (operator==(const face<D>&, const face<D>&))
+ (operator< (const face<D>&, const face<D>&)):
+ * mln/topo/n_face.hh
+ (operator==(const n_face<N, D>&, const n_face<N, D>&))
+ (operator< (const n_face<N, D>&, const n_face<N, D>&)):
+ Fix preconditions.
+ Fix and catch up with the current interface of mln::topo::face<D>.
+
+2008-10-01 Roland Levillain <roland(a)lrde.epita.fr>
+
Fix exact type of mln::internal::p_complex_piter_base_
* mln/core/internal/p_complex_piter_base.hh
diff --git a/milena/mln/topo/face.hh b/milena/mln/topo/face.hh
index 00d6049..686c50a 100644
--- a/milena/mln/topo/face.hh
+++ b/milena/mln/topo/face.hh
@@ -380,10 +380,8 @@ namespace mln
operator==(const face<D>& lhs, const face<D>& rhs)
{
// Ensure LHS and RHS belong to the same complex.
- mln_precondition(&lhs.face.cplx() == &rhs.face.cplx());
- return
- lhs.face().n() == rhs.face().n() &&
- lhs.face().id() == rhs.face().id();
+ mln_precondition(lhs.cplx() == rhs.cplx());
+ return lhs.n() == rhs.n() && lhs.face_id() == rhs.face_id();
}
template <unsigned D>
@@ -392,10 +390,10 @@ namespace mln
operator< (const face<D>& lhs, const face<D>& rhs)
{
// Ensure LHS and RHS belong to the same complex.
- mln_precondition(&lhs.face.cplx() == &rhs.face.cplx());
+ mln_precondition(lhs.cplx() == rhs.cplx());
// Ensure LHS and RHS have the same dimension.
- mln_precondition(lhs.face().n() == rhs.face().n());
- return lhs.face().id() < rhs.face().id();
+ mln_precondition(lhs.n() == rhs.n());
+ return lhs.face_id() < rhs.face_id();
}
diff --git a/milena/mln/topo/n_face.hh b/milena/mln/topo/n_face.hh
index fddf568..343f7b0 100644
--- a/milena/mln/topo/n_face.hh
+++ b/milena/mln/topo/n_face.hh
@@ -239,8 +239,8 @@ namespace mln
operator==(const n_face<N, D>& lhs, const n_face<N, D>& rhs)
{
// Ensure LHS and RHS belong to the same complex.
- mln_precondition(&lhs.face.cplx() == &rhs.face.cplx());
- return lhs.face().id() == rhs.face().id();
+ mln_precondition(lhs.cplx() == rhs.cplx());
+ return lhs.face_id() == rhs.face_id();
}
template <unsigned N, unsigned D>
@@ -249,8 +249,8 @@ namespace mln
operator< (const n_face<N, D>& lhs, const n_face<N, D>& rhs)
{
// Ensure LHS and RHS belong to the same complex.
- mln_precondition(&lhs.face.cplx() == &rhs.face.cplx());
- return lhs.face().id() < rhs.face().id();
+ mln_precondition(lhs.cplx() == rhs.cplx());
+ return lhs.face_id() < rhs.face_id();
}
--
1.6.0.1
1
0
01 Oct '08
* mln/core/internal/p_complex_piter_base.hh
(mln::internal::p_complex_piter_base_<I, S, P, E>): Fix the type
of the base class w.r.t. the exact type.
(mln::internal::p_complex_piter_base_<I, S, P, E>::super_):
Adjust.
---
milena/ChangeLog | 10 ++++++++++
milena/mln/core/internal/p_complex_piter_base.hh | 7 +++----
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index c32bd1d..5cefbda 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,13 @@
+2008-10-01 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Fix exact type of mln::internal::p_complex_piter_base_
+
+ * mln/core/internal/p_complex_piter_base.hh
+ (mln::internal::p_complex_piter_base_<I, S, P, E>): Fix the type
+ of the base class w.r.t. the exact type.
+ (mln::internal::p_complex_piter_base_<I, S, P, E>::super_):
+ Adjust.
+
2008-09-30 Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
Add interpolation function. Revamp lazy_image.
diff --git a/milena/mln/core/internal/p_complex_piter_base.hh b/milena/mln/core/internal/p_complex_piter_base.hh
index d906011..edd73b5 100644
--- a/milena/mln/core/internal/p_complex_piter_base.hh
+++ b/milena/mln/core/internal/p_complex_piter_base.hh
@@ -59,11 +59,10 @@ namespace mln
/// \arg \p E The type exact type of the iterator.
template <typename I, typename S, typename P, typename E>
class p_complex_piter_base_
- : public internal::site_set_iterator_base< S,
- p_complex_piter_base_<I, S, P, E> >
+ : public internal::site_set_iterator_base< S, E >
{
- typedef p_complex_piter_base_<I, S, P, E> self_;
- typedef internal::site_set_iterator_base< S, self_ > super_;
+ typedef p_complex_piter_base_< I, S, P, E > self_;
+ typedef internal::site_set_iterator_base< S, E > super_;
/// The type of the underlying complex iterator.
typedef I iter;
--
1.6.0.1
1
0
30 Sep '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
Add interpolation function. Revamp lazy_image.
* mln/core/image/lazy_image.hh: Fix traits, Add init_.
* mln/fun/x2x/all.hh: Upgrade.
* mln/fun/x2x/geom: New.
* mln/fun/x2x/composed.hh: Move and update ...
* mln/fun/x2x/geom/composed.hh: ... here.
* mln/fun/x2x/translation.hh: Move and update ...
* mln/fun/x2x/geom/translation.hh: ... here.
* mln/fun/x2x/rotation.hh: Move and update ...
* mln/fun/x2x/geom/rotation.hh: ... here.
* mln/fun/x2x/interpol: New.
* mln/fun/x2x/interpol/bilinear.hh: New interpolation.
* mln/fun/x2x/interpol/linear.hh: New interpolation.
* mln/draw/plot.hh: Fix doxygen.
core/image/lazy_image.hh | 32 ++--
draw/plot.hh | 5
fun/x2x/all.hh | 9 -
fun/x2x/geom/composed.hh | 285 +++++++++++++++++++++++++++++++++++++++++++
fun/x2x/geom/rotation.hh | 243 ++++++++++++++++++++++++++++++++++++
fun/x2x/geom/translation.hh | 152 ++++++++++++++++++++++
fun/x2x/interpol/bilinear.hh | 139 ++++++++++++++++++++
fun/x2x/interpol/linear.hh | 124 ++++++++++++++++++
fun/x2x/interpol/test.cc | 14 ++
9 files changed, 982 insertions(+), 21 deletions(-)
Index: mln/core/image/lazy_image.hh
--- mln/core/image/lazy_image.hh (revision 2450)
+++ mln/core/image/lazy_image.hh (working copy)
@@ -37,7 +37,6 @@
# include <mln/core/internal/image_identity.hh>
# include <mln/core/alias/box2d.hh>
-# include <mln/core/line_piter.hh>
namespace mln
@@ -69,19 +68,11 @@
{
template <typename I, typename F, typename B>
- struct image_< lazy_image<I,F,B> > : default_image_morpher_< I, mln_value(I),
+ struct image_< lazy_image<I,F,B> > : default_image_morpher< I, mln_value(I),
lazy_image<I,F,B> >
{
typedef trait::image::category::domain_morpher category;
-
- typedef mln_trait_image_access(I) access;
- typedef mln_trait_image_space(I) space;
- typedef mln_trait_image_size(I) size;
- typedef mln_trait_image_support(I) support;
- typedef mln_trait_image_border(I) border;
- typedef mln_trait_image_io_from_(I) io;
- typedef mln_trait_image_data_from_(I) data;
-
+ typedef trait::image::value_io::read_only value_io;
};
} // end of namespace mln::trait
@@ -100,15 +91,13 @@
*/
template <typename I, typename F, typename B>
struct lazy_image :
- public mln::internal::image_identity_< mln_ch_value(I, mln_result(F)),
+ public mln::internal::image_identity< mln_ch_value(I, mln_result(F)),
mln_pset(I), lazy_image<I, F,B> >
{
- typedef mln::internal::image_identity_< mln_ch_value(I, mln_result(F)),
+ typedef mln::internal::image_identity< mln_ch_value(I, mln_result(F)),
mln_pset(I),
lazy_image<I, F,B> > super_;
- typedef line_piter_<mln_psite(I)> line_piter;
-
/// Return type of read access.
typedef mln_result(F) rvalue;
@@ -122,8 +111,14 @@
using super_::has_data;
/// Constructors.
+ lazy_image();
+
+ /// Constructors.
lazy_image(const F& fun, const B& box);
+ /// Initialize an empty image.
+ void init_(const F& fun, const B& box);
+
/// Return domain of lazyd_image.
const box2d& domain() const;
@@ -164,6 +159,13 @@
template <typename I, typename F, typename B>
inline
+ void lazy_image<I,F,B>::init_(const F& fun, const B& box)
+ {
+ this->data_ = new internal::data< lazy_image<I,F,B> >(fun, box);
+ }
+
+ template <typename I, typename F, typename B>
+ inline
bool lazy_image<I,F,B>::has(const mln_psite(I)& p) const
{
return this->data_->ima_.has(p);
Index: mln/draw/plot.hh
--- mln/draw/plot.hh (revision 2450)
+++ mln/draw/plot.hh (working copy)
@@ -46,8 +46,7 @@
namespace draw
{
- /*! Plot a point at level \p v in image \p ima between the points
- * \p beg and \p end.
+ /*! Plot a point at level \p v in image \p ima
*
* \param[in,out] ima The image to be drawn.
* \param[in] p The point to be plotted.
@@ -68,7 +67,7 @@
template <typename I>
inline
void plot(Image<I>& ima,
- const mln_point(I)& p,
+ const mln_psite(I)& p,
const mln_value(I)& v)
{
mln_precondition(exact(ima).has_data());
Index: mln/fun/x2x/all.hh
--- mln/fun/x2x/all.hh (revision 2450)
+++ mln/fun/x2x/all.hh (working copy)
@@ -54,9 +54,12 @@
}
-# include <mln/fun/x2x/composed.hh>
-# include <mln/fun/x2x/rotation.hh>
-# include <mln/fun/x2x/translation.hh>
+# include <mln/fun/x2x/geom/composed.hh>
+# include <mln/fun/x2x/geom/rotation.hh>
+# include <mln/fun/x2x/geom/translation.hh>
+
+# include <mln/fun/x2x/interpol/linear.hh>
+# include <mln/fun/x2x/interpol/bilinear.hh>
Index: mln/fun/x2x/geom/composed.hh
--- mln/fun/x2x/geom/composed.hh (revision 0)
+++ mln/fun/x2x/geom/composed.hh (revision 0)
@@ -0,0 +1,285 @@
+// Copyright (C) 2007 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_FUN_X2X_GEOM_COMPOSED_HH
+# define MLN_FUN_X2X_GEOM_COMPOSED_HH
+
+/*! \file mln/fun/x2x/composed.hh
+ *
+ * \brief Definition of a composed transformation.
+ */
+
+# include <mln/core/concept/function.hh>
+# include <mln/fun/internal/x2x_linear_impl.hh>
+# include <mln/algebra/vec.hh>
+# include <mln/metal/is.hh>
+# include <mln/metal/bexpr.hh>
+# include <mln/algebra/h_mat.hh>
+
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace x2x
+ {
+
+ namespace geom
+ {
+
+ // Fwd decl.
+ template <typename F, typename G>
+ struct composed;
+
+ namespace internal
+ {
+ template <typename F, typename G, 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 >,
+ public Bijection_x2x<E>
+ {
+ typedef fun::internal::x2x_linear_impl_<typename F::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);
+
+ 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);
+
+ /// Type of the inverse function.
+ typedef composed<mln_invert(G),mln_invert(F)> invert;
+ /// Return the inverse function.
+ invert inv() const;
+
+ protected:
+
+ F f_;
+ G 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 >,
+ public Function_x2x<E>
+ {
+ typedef fun::internal::x2x_linear_impl_<typename F::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);
+
+ 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);
+
+ protected:
+
+ F f_;
+ G g_;
+ };
+
+ } // end of namespace mln::fun::x2x::geom::internal
+
+
+ /*! \brief Represent a composition of two transformations.
+ *
+ */
+ template <typename F, typename G>
+ 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)>
+ >::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)
+ {
+ }
+ };
+
+ } // end of namespace mln::fun::x2x::geom
+
+ } // end of namespace mln::fun::x2x
+
+ } // 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::geom::composed<F,G> compose(F f, G g);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace fun
+ {
+
+ namespace x2x
+ {
+
+ namespace geom
+ {
+
+ namespace internal
+ {
+
+ // Implementation of the bijective version.
+
+ template <typename F, typename G, typename E>
+ inline
+ helper_composed_<F,G,E,true>::helper_composed_()
+ {
+ }
+
+ template <typename F, typename G, typename E>
+ inline
+ helper_composed_<F,G,E,true>::helper_composed_(const F& f, const G& g)
+ :f_(f),
+ g_(g)
+ {
+ this->m_ = f_.mat() * g_.mat();
+ }
+
+ template <typename F, typename G, typename E>
+ inline
+ typename helper_composed_<F,G,E,true>::invert
+ helper_composed_<F,G,E,true>::inv() const
+ {
+ return compose(g_.inv(), f_.inv());
+ }
+
+ template <typename F, typename G, typename E>
+ inline
+ void
+ helper_composed_<F,G,E,true>::set_first(const F& f)
+ {
+ this->f_ = f;
+ this->m_ = this->f_.mat() * this->g_.mat();
+ }
+
+ template <typename F, typename G, typename E>
+ inline
+ void
+ helper_composed_<F,G,E,true>::set_second(const G& 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>
+ inline
+ helper_composed_<F,G,E,false>::helper_composed_()
+ {
+ }
+
+ template <typename F, typename G, typename E>
+ inline
+ helper_composed_<F,G,E,false>::helper_composed_(const F& f, const G& g)
+ :f_(f),
+ g_(g)
+ {
+ this->m_ = f_.mat() * g_.mat();
+ }
+
+ template <typename F, typename G, typename E>
+ inline
+ void
+ helper_composed_<F,G,E,false>::set_first(const F& f)
+ {
+ this->f_ = f;
+ this->m_ = this->f_.mat() * this->g_.mat();
+ }
+
+ template <typename F, typename G, typename E>
+ inline
+ void
+ helper_composed_<F,G,E,false>::set_second(const G& g)
+ {
+ this->g_ = g;
+ this->m_ = this->f_.mat() * this->g_.mat();
+ }
+
+ } // end of namespace mln::fun::x2x::geom::internal
+
+ } // end of namespace mln::fun::x2x::geom
+
+ } // end of namespace mln::fun::x2x
+
+ } // end of namespace mln::fun
+
+ template <typename F, typename G>
+ inline
+ fun::x2x::geom::composed<F,G> compose(F f, G g)
+ {
+ trace::entering("fun::x2x::compose");
+ fun::x2x::geom::composed<F,G> comp(f, g);
+ trace::exiting("fun::x2x::compose");
+ return comp;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_X2X_GEOM_COMPOSED_HH
Index: mln/fun/x2x/geom/translation.hh
--- mln/fun/x2x/geom/translation.hh (revision 0)
+++ mln/fun/x2x/geom/translation.hh (revision 0)
@@ -0,0 +1,152 @@
+// Copyright (C) 2007 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_FUN_X2X_TRANSLATION_HH
+# define MLN_FUN_X2X_TRANSLATION_HH
+
+/*! \file mln/fun/x2x/translation.hh
+ *
+ * \brief Define a translation function.
+ */
+
+# include <mln/core/concept/function.hh>
+# include <mln/fun/internal/x2x_linear_impl.hh>
+# include <mln/algebra/vec.hh>
+# include <mln/algebra/h_mat.hh>
+# include <mln/fun/i2v/all.hh>
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace x2x
+ {
+
+ namespace geom
+ {
+
+ /*! \brief Represent a translation function.
+ *
+ */
+ template <unsigned n, typename C>
+ struct translation
+ : fun::internal::x2x_linear_impl_< algebra::vec<n,C>, translation<n,C> >
+ , public Bijection_x2x< translation<n,C> >
+ {
+ typedef fun::internal::x2x_linear_impl_< algebra::vec<n,C>, translation<n,C> > super_;
+
+ /// Type of the inverse function.
+ typedef translation<n,C> invert;
+ /// Return the inverse function.
+ invert inv() const;
+
+ /// Constructor without argument.
+ translation();
+ /// Constructor with the translation vector.
+ translation(const algebra::vec<n,C>& t);
+
+ using super_::operator();
+ /// Perform the translation of the given vector
+ algebra::vec<n,C> operator()(const algebra::vec<n,C>& v) const;
+
+ /// Set a net translation vector.
+ void set_t(const algebra::vec<n,C>& t);
+
+ protected:
+ void update();
+
+ algebra::vec<n,C> t_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <unsigned n, typename C>
+ inline
+ translation<n,C>::translation()
+ {
+ }
+
+ template <unsigned n, typename C>
+ inline
+ translation<n,C>::translation(const algebra::vec<n,C>& t)
+ :t_(t)
+ {
+ this->update();
+ }
+
+ template <unsigned n, typename C>
+ inline
+ algebra::vec<n,C>
+ translation<n,C>::operator()(const algebra::vec<n,C>& v) const
+ {
+ return v + t_;
+ }
+
+ template <unsigned n, typename C>
+ inline
+ translation<n,C>
+ translation<n,C>::inv() const
+ {
+ typename translation::invert res(-t_);
+
+ return res;
+ }
+
+ template <unsigned n, typename C>
+ inline
+ void
+ translation<n,C>::set_t(const algebra::vec<n,C>& t)
+ {
+ this->t_ = t;
+ this->update();
+ }
+
+ template <unsigned n, typename C>
+ inline
+ void
+ translation<n,C>::update()
+ {
+ this->m_ = algebra::h_mat<n,C>::Id;
+ for (unsigned i = 0; i < n; ++i)
+ this->m_(i,n) = this->t_[i];
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::x2x::geom
+
+ } // end of namespace mln::fun::x2x
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_X2X_TRANSLATION_HH
Index: mln/fun/x2x/geom/rotation.hh
--- mln/fun/x2x/geom/rotation.hh (revision 0)
+++ mln/fun/x2x/geom/rotation.hh (revision 0)
@@ -0,0 +1,243 @@
+// Copyright (C) 2007 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_FUN_X2X_ROTATION_HH
+# define MLN_FUN_X2X_ROTATION_HH
+
+/*! \file mln/fun/x2x/rotation.hh
+ *
+ * \brief Define a rotation function.
+ */
+
+# include <mln/core/concept/function.hh>
+# include <mln/fun/internal/x2x_linear_impl.hh>
+# include <mln/algebra/vec.hh>
+# include <mln/algebra/mat.hh>
+# include <cmath>
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace x2x
+ {
+
+ namespace geom
+ {
+
+ namespace internal
+ {
+ template < unsigned n, typename C >
+ algebra::h_mat<n, C>
+ get_rot_h_mat(const float alpha_, const algebra::vec<3,C>& axis_)
+ {
+ assert(!"get_h_mat : n not implemented");
+ }
+
+ template <typename C >
+ algebra::h_mat<3, C>
+ get_rot_h_mat(const float alpha_, const algebra::vec<3,C>& axis_)
+ {
+ algebra::h_mat<3, C> m_;
+
+ const float cos_a = cos(alpha_);
+ const float sin_a = sin(alpha_);
+ const float u = axis_[0];
+ const float v = axis_[1];
+ const float w = axis_[2];
+ const float u2 = u * u;
+ const float v2 = v * v;
+ const float w2 = w * w;
+ const float uvw2 = u2 + v2 + w2;
+
+ m_(0,0) = (u2 + (v2 + w2) * cos_a) / uvw2;
+ m_(0,1) = (u*v * (1 - cos_a) - u * std::sqrt(uvw2) * sin_a) / uvw2;
+ m_(0,2) = (u*w * (1 - cos_a) + v * std::sqrt(uvw2) * sin_a) / uvw2;
+ m_(0,3) = 0;
+
+ m_(1,0) = (u*v * (1 - cos_a) + w * std::sqrt(uvw2) * sin_a) / uvw2;
+ m_(1,1) = (v2 + (u2 + w2) * cos_a) / uvw2;
+ m_(1,2) = (v*w * (1 - cos_a) - u * std::sqrt(uvw2) * sin_a) / uvw2;
+ m_(1,3) = 0;
+
+ m_(2,0) = (u*w * (1 - cos_a) - v * std::sqrt(uvw2) * sin_a) / uvw2;
+ m_(2,1) = (v*w * (1 - cos_a) + u * std::sqrt(uvw2) * sin_a) / uvw2;
+ m_(2,1) = (u2 + (u2 + v2) * cos_a) / uvw2;
+ m_(2,3) = 0;
+
+ m_(2,0) = 0;
+ m_(2,1) = 0;
+ m_(2,1) = 0;
+ m_(2,3) = 1;
+
+ return m_;
+ }
+
+ template <typename C >
+ algebra::h_mat<2, C>
+ get_rot_h_mat(const float alpha_, const algebra::vec<2,C>&)
+ {
+ algebra::h_mat<2, C> m_;
+
+ const float cos_a = cos(alpha_);
+ const float sin_a = sin(alpha_);
+
+ m_(0,0) = cos_a; m_(0,1) = -sin_a; m_(0,2) = 0;
+
+ m_(1,0) = sin_a; m_(1,1) = cos_a; m_(1,2) = 0;
+
+ m_(2,0) = 0; m_(2,1) = 0; m_(2,2) = 1;
+
+ return m_;
+ }
+ }
+
+
+ /*! \brief Represent a rotation function.
+ *
+ */
+ template <unsigned n, typename C>
+ struct rotation
+ : fun::internal::x2x_linear_impl_< algebra::vec<n,C>, rotation<n,C> >
+ , public Bijection_x2x< rotation<n,C> >
+ {
+ typedef fun::internal::x2x_linear_impl_< algebra::vec<n,C>, rotation<n,C> > super_;
+
+ /// Type of the inverse function.
+ typedef rotation<n,C> invert;
+ /// Return the invere function.
+ invert inv() const;
+
+ /// Constructor without argument.
+ rotation();
+ /// Constructor with grade alpha and a facultative direction (rotation axis).
+ rotation(float alpha, const algebra::vec<n,float>& axis);
+
+ using super_::operator();
+ /// Perform the rotation of the given vector.
+ algebra::vec<n,C> operator()(const algebra::vec<n,C>& v) const;
+
+ /// Set a new grade alpha.
+ void set_alpha(float alpha);
+ /// Set a new rotation axis.
+ void set_dir(unsigned dir);
+
+ protected:
+ void update();
+
+ float alpha_;
+ algebra::vec <n,float> axis_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <unsigned n, typename C>
+ inline
+ rotation<n,C>::rotation()
+ {
+ }
+
+ template <unsigned n, typename C>
+ inline
+ rotation<n,C>::rotation(float alpha, const algebra::vec<n,float>& axis)
+ :alpha_(alpha),
+ axis_(axis)
+ {
+ this->m_ = algebra::h_mat<n,C>::Id;
+ update();
+ }
+
+ template <unsigned n, typename C>
+ inline
+ algebra::vec<n,C>
+ rotation<n,C>::operator()(const algebra::vec<n,C>& v) const
+ {
+ algebra::mat<n+1,1,C> hmg;
+ algebra::mat<n+1,1,C> tmp;
+ algebra::vec<n,C> res;
+
+ for (unsigned i = 0; i < n; ++i)
+ hmg(i,0) = v[i];
+ hmg(n,0) = 1;
+ tmp = this->m_ * hmg;
+ mln_assertion(tmp(n,0) == 1);
+ for (unsigned i = 0; i < n; ++i)
+ res[i] = tmp(i,0);
+ return res;
+ }
+
+ template <unsigned n, typename C>
+ inline
+ rotation<n,C>
+ rotation<n,C>::inv() const
+ {
+ typename rotation::invert res(-alpha_, axis_);
+ return res;
+ }
+
+ template <unsigned n, typename C>
+ inline
+ void
+ rotation<n,C>::set_alpha(float alpha)
+ {
+ alpha_ = alpha;
+ update();
+ }
+
+ template <unsigned n, typename C>
+ inline
+ void
+ rotation<n,C>::set_dir(unsigned dir)
+ {
+ update();
+ }
+
+ // Homogenous matrix for a rotation of a point (x,y,z)
+ // about the vector (u,v,w) by the angle alpha
+ template <unsigned n, typename C>
+ inline
+ void
+ rotation<n,C>::update()
+ {
+ this->m_ = internal::get_rot_h_mat(alpha_, axis_);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::x2x::geom
+
+ } // end of namespace mln::fun::x2x
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_X2X_ROTATION_HH
Index: mln/fun/x2x/interpol/bilinear.hh
--- mln/fun/x2x/interpol/bilinear.hh (revision 0)
+++ mln/fun/x2x/interpol/bilinear.hh (revision 0)
@@ -0,0 +1,139 @@
+// 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_FUN_X2X_INTERPOL_BILINEAR_HH
+# define MLN_FUN_X2X_INTERPOL_BILINEAR_HH
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/concept/function.hh>
+# include <mln/fun/internal/selector.hh>
+
+/*! \file mln/fun/x2x/interpol/bilinear.hh
+ *
+ * \brief Define a bilinear interpolation of values from an underlying image
+ */
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace x2x
+ {
+
+ namespace interpol
+ {
+
+
+ /*! \brief Represent a bilinear interolation of values from an underlying image
+ *
+ */
+ template < typename I >
+ struct bilinear
+ : public fun::internal::selector_<const algebra::vec<3,float>,
+ // 3,float is a dummy parameter (real is n,T)
+ mln_value(I), bilinear<I> >::ret
+ {
+ typedef mln_value(I) result;
+
+ bilinear(const I& ima);
+
+ template <unsigned n, typename T>
+ mln_value(I)
+ operator()(const algebra::vec<n,T>& v) const;
+
+ const I& ima;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ bilinear<I>::bilinear(const I& ima) : ima(ima)
+ {
+ mlc_bool(I::psite::dim == 2)::check();
+ }
+
+ template <typename I>
+ template <unsigned n, typename T>
+ mln_value(I)
+ bilinear<I>::operator()(const algebra::vec<n,T>& v) const
+ {
+ typedef mln_sum(mln_value(I)) vsum;
+
+ // q12----r2----q22
+ // | | |
+ // | x |
+ // | | |
+ // q11----r1----q21
+
+ // looking for img(P(x,y))
+ double x = v[0];
+ double y = v[1];
+
+ double x1 = std::floor(v[0]);
+ double x2 = std::floor(v[0]) + 1;
+ double y1 = std::floor(v[1]);
+ double y2 = std::floor(v[1]) + 1;
+
+ //if (not ima.has(point2d(x1, y1))) return mln_value(I)();
+ vsum q11 = ima(point2d(x1, y1));
+ vsum q12 = ima(point2d(x1, y2));
+ vsum q21 = ima(point2d(x2, y1));
+ vsum q22 = ima(point2d(x2, y2));
+
+ double x2_x1 = x2 - x1;
+ double y2_y1 = y2 - y1;
+
+ // linear interpolation #1
+ vsum img_r1 = q11 * (x2 - x) / (x2_x1) +
+ q21 * (x - x1) / (x2_x1);
+
+ // linear interpolation #2
+ vsum img_r2 = q12 * (x2 - x) / (x2_x1) + q22 * (x - x1) / (x2_x1);
+
+ // interpolating in y direction
+ vsum res = (img_r1 * (y2 - y) / (y2_y1)
+ + img_r2 * (y - y1) / (y2_y1));
+
+ return convert::to<mln_value(I)>(res);
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::x2x::interpol
+
+ } // end of namespace mln::fun::x2x
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_X2X_INTERPOL_BILINEAR_HH
Index: mln/fun/x2x/interpol/test.cc
--- mln/fun/x2x/interpol/test.cc (revision 0)
+++ mln/fun/x2x/interpol/test.cc (revision 0)
@@ -0,0 +1,14 @@
+#include "bilinear.hh"
+#include "linear.hh"
+
+int main()
+{
+ typedef mln::image2d<int> I;
+ typedef mln::image1d<int> II;
+
+ I ima2d;
+ II ima1d;
+
+ mln::fun::x2x::interpol::bilinear<I> interp(ima2d);
+ mln::fun::x2x::interpol::linear<II> interp3(ima1d);
+}
Index: mln/fun/x2x/interpol/linear.hh
--- mln/fun/x2x/interpol/linear.hh (revision 0)
+++ mln/fun/x2x/interpol/linear.hh (revision 0)
@@ -0,0 +1,124 @@
+// 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_FUN_X2X_INTERPOL_LINEAR_HH
+# define MLN_FUN_X2X_INTERPOL_LINEAR_HH
+
+/*! \file mln/fun/x2x/interpol/linear.hh
+ *
+ * \brief Define a linear interpolation of values from an underlying image
+ */
+
+# include <mln/core/image/image1d.hh>
+# include <mln/core/concept/function.hh>
+# include <mln/fun/internal/selector.hh>
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace x2x
+ {
+
+ namespace interpol
+ {
+
+
+ /*! \brief Represent a linear interolation of values from an underlying image
+ *
+ */
+ template < typename I >
+ struct linear
+ : public fun::internal::selector_<const algebra::vec<1,float>,
+ // float is a dummy parameter (real is C)
+ mln_value(I), linear<I> >::ret
+ {
+ typedef mln_value(I) result;
+
+ /// Constructor with the underlying image
+ linear(const I& ima);
+
+ /// Return the interpolated value in the underlying image
+ /// at the given 'point' v.
+ template <typename C>
+ mln_value(I)
+ operator()(const algebra::vec<1,C>& v) const;
+
+ /// Underlying image
+ const I& ima;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ linear<I>::linear(const I& ima) : ima(ima)
+ {
+ mlc_bool(I::psite::dim == 1)::check();
+ }
+
+ template <typename I>
+ template <typename C>
+ mln_value(I)
+ linear<I>::operator()(const algebra::vec<1,C>& v) const
+ {
+ typedef mln_sum(mln_value(I)) vsum;
+
+ // looking for img(x);
+ double x = v[0];
+
+ // p1
+ double xa = mln_point(I)::coord(v[0]);
+ vsum ya = ima(point1d(xa));
+
+ // x makes sens in img
+ if (x == xa)
+ return ima(xa);
+
+ // p2
+ double xb = mln_point(I)::coord(v[0] + 1);
+ vsum yb = ima(point1d(xb));
+
+ // Taylor-young
+ return convert::to<mln_value(I)>
+ (ya + (x - xa) * (yb - ya) / (xb - xa));
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::x2x::interpol
+
+ } // end of namespace mln::fun::x2x
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_X2X_INTERPOL_HH
Index: mln/util/array.hh
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
Index: ChangeLog
from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
Sandbox: continue to revamp registration.
* jardonnet/test/registration.cc: Make use of lazy_image.
* jardonnet/registration/final_qk.hh: Remove use of size_t.
* jardonnet/registration/cloud.hh,
* jardonnet/registration/save.hh,
* jardonnet/registration/update_qk.hh,
* jardonnet/registration/registration.hh: Replace quat7 by generique T.
* jardonnet/registration/tools.hh,
* jardonnet/registration/quat7.hh,
* jardonnet/registration/rotation.hh: Remove Whitespace.
* jardonnet/virtual/access.hh: Minor fix.
registration/cloud.hh | 12 ++++++------
registration/final_qk.hh | 18 +++++++++---------
registration/quat7.hh | 2 +-
registration/registration.hh | 11 ++++-------
registration/rotation.hh | 1 +
registration/save.hh | 6 +++---
registration/tools.hh | 6 +++---
registration/update_qk.hh | 15 +++++++++------
test/registration.cc | 6 +++---
9 files changed, 39 insertions(+), 38 deletions(-)
Index: jardonnet/test/registration.cc
--- jardonnet/test/registration.cc (revision 2447)
+++ jardonnet/test/registration.cc (working copy)
@@ -5,8 +5,9 @@
#include <mln/io/ppm/save.hh>
#include <mln/convert/to_p_array.hh>
#include <mln/norm/l2.hh>
+#include <mln/core/image/lazy_image.hh>
-#include <sandbox/jardonnet/registration/icp.hh>
+#include <sandbox/jardonnet/registration/registration.hh>
#include <sandbox/jardonnet/registration/tools.hh>
#include <sandbox/jardonnet/registration/final_qk.hh>
#include <mln/geom/bbox.hh>
@@ -52,8 +53,7 @@
closest_point<mln_psite_(image2db)> fun(x, working_box);
// * Use real lazy image
- //lazy_image< closest_point<mln_psite_(image2db)> > map(fun);
- p_array<point2d> map;
+ lazy_image<image2d<bool>, closest_point<mln_psite_(image2db)>, box2d > map(fun, fun.domain());
quat7<2> qk ;//= registration::icp(c, map, q, e, x);
#ifndef NDEBUG
Index: jardonnet/virtual/access.hh
Index: jardonnet/registration/final_qk.hh
--- jardonnet/registration/final_qk.hh (revision 2447)
+++ jardonnet/registration/final_qk.hh (working copy)
@@ -17,7 +17,7 @@
std::vector<float> length(c.nsites());
mean = 0;
- for (size_t i = 0; i < c.nsites(); i++)
+ for (unsigned i = 0; i < c.nsites(); i++)
{
float f = norm::l2(convert::to< algebra::vec<P::dim,int> > (c[i] - map(c[i])));
length[i] = f;
@@ -27,7 +27,7 @@
//standar variation
stddev = 0;
- for (size_t i = 0; i < c.nsites(); i++)
+ for (unsigned i = 0; i < c.nsites(); i++)
stddev += (length[i] - mean) * (length[i] - mean);
stddev /= c.nsites();
stddev = math::sqrt(stddev);
@@ -42,12 +42,12 @@
float nstddev)
{
p_array<P> newc;
- algebra::vec<3,float> mu_newc(literal::zero);
+ algebra::vec<P::dim,float> mu_newc(literal::zero);
- for (size_t i = 0; i < c.nsites(); ++i)
+ for (unsigned i = 0; i < c.nsites(); ++i)
{
- algebra::vec<3,float> ci = c[i];
- algebra::vec<3,float> xki = map(c[i]);
+ algebra::vec<P::dim,float> ci = c[i];
+ algebra::vec<P::dim,float> xki = map(c[i]);
if (norm::l2(ci - xki) < nstddev)
{
@@ -74,11 +74,11 @@
float nstddev)
{
//mu_Xk = center map(Ck)
- algebra::vec<3,float> mu_Xk(literal::zero);
- algebra::vec<3,float> mu_C(literal::zero);
+ algebra::vec<P::dim,float> mu_Xk(literal::zero);
+ algebra::vec<P::dim,float> mu_C(literal::zero);
float nb_point = 0;
- for (size_t i = 0; i < c.nsites(); ++i)
+ for (unsigned i = 0; i < c.nsites(); ++i)
{
algebra::vec<P::dim,float> xki = map(c[i]);
algebra::vec<P::dim,float> ci = c[i];
Index: jardonnet/registration/save.hh
--- jardonnet/registration/save.hh (revision 2447)
+++ jardonnet/registration/save.hh (working copy)
@@ -9,7 +9,7 @@
# include <mln/core/alias/window2d.hh>
# include <string>
-# include "quat7.hh"
+//# include "quat7.hh"
# include "tools.hh"
# include "power_it.hh"
# include "center.hh"
@@ -38,8 +38,8 @@
namespace registration
{
- template<typename P, typename M>
- void save_(const quat7<3>& qk,
+ template<typename P, typename M, typename T>
+ void save_(const T& qk,
const p_array<P>& c,
const p_array<P>& x,
const M& map,
Index: jardonnet/registration/rotation.hh
--- jardonnet/registration/rotation.hh (revision 2447)
+++ jardonnet/registration/rotation.hh (working copy)
@@ -26,6 +26,7 @@
return (q * algebra::quat(0. ,p) * q.inv()).v();
}
+
//FIXME : check if correct with n != 3
template <unsigned n>
bool check_rotation(const algebra::mat<n,n,float>& mat,
Index: jardonnet/registration/tools.hh
--- jardonnet/registration/tools.hh (revision 2447)
+++ jardonnet/registration/tools.hh (working copy)
@@ -6,7 +6,7 @@
# include <mln/algebra/mat.hh>
# include <mln/core/site_set/p_array.hh>
-# include "quat7.hh"
+//# include "quat7.hh"
namespace mln
@@ -110,7 +110,7 @@
#endif
};
-
+ /*
// FIXME: Should be a morpher ?
// we could acces domain of a lazy map, iterator etc...
template < typename F >
@@ -147,7 +147,7 @@
mutable image3d<bool> is_known;
const F& fun;
};
-
+ */
// Box
Index: jardonnet/registration/quat7.hh
--- jardonnet/registration/quat7.hh (revision 2447)
+++ jardonnet/registration/quat7.hh (working copy)
@@ -127,7 +127,7 @@
const algebra::vec<P::dim,float>& mu_C,
const p_array<P>& Ck,
const M& map,
- size_t c_length)
+ unsigned c_length)
{
//mu_Xk = center map(Ck)
algebra::vec<P::dim,float> mu_Xk(literal::zero);
Index: jardonnet/registration/cloud.hh
--- jardonnet/registration/cloud.hh (revision 2447)
+++ jardonnet/registration/cloud.hh (working copy)
@@ -11,7 +11,7 @@
# include <mln/core/site_set/p_array.hh>
# include <mln/norm/l2.hh>
-#include "quat7.hh"
+//#include "quat7.hh"
namespace mln
{
@@ -64,9 +64,9 @@
return tmp;
}
- template <typename P, typename M>
+ template <typename P, typename M, typename T>
float rms(const p_array<P>& a1,
- quat7<P::dim>& qk,
+ const T& qk,
const M& map,
const size_t length)
{
@@ -82,12 +82,12 @@
return f / length;
}
- template <typename P, typename M>
+ template <typename P, typename M, typename T>
float rms(const p_array<P>& a1,
M& map,
const size_t length,
- quat7<P::dim>& q1,
- quat7<P::dim>& q2)
+ const T& q1,
+ const T& q2) // FIXME : transformation T can be diff ?
{
assert(length <= a1.nsites());
Index: jardonnet/registration/registration.hh
--- jardonnet/registration/registration.hh (revision 2447)
+++ jardonnet/registration/registration.hh (working copy)
@@ -37,7 +37,6 @@
# include <string>
# include <cmath>
-# include <mln/algebra/quat.hh>
# include <mln/algebra/vec.hh>
# include <mln/make/w_window.hh>
# include <mln/make/w_window3d.hh>
@@ -48,11 +47,9 @@
# include <mln/level/fill.hh>
# include <mln/io/ppm/save.hh>
-
# include "tools.hh"
# include "cloud.hh"
-# include "quat7.hh"
# include "update_qk.hh"
# include "chamfer.hh"
@@ -83,18 +80,18 @@
namespace impl
{
- template <typename P, typename M>
+ template <typename P, typename M, typename T>
inline
void
registration_(const p_array<P>& C,
const M& map,
- quat7<P::dim>& qk,
+ const T& qk,
const unsigned c_length,
const float epsilon = 1e-3)
{
trace::entering("registration::impl::registration_");
- buffer<4,quat7<P::dim> > buf_qk;
+ buffer<4,T> buf_qk;
buffer<3,float> buf_dk;
float d_k = 10000;
@@ -140,7 +137,7 @@
// FIXME: Make it works in 3d *AND* 2d
template <typename P, typename M>
inline
- quat7<P::dim>
+ quat7<P::dim> // what is it suposed to return tr(rot()), rot(tr()) or something else ...
registration(p_array<P>& cloud,
const M& map,
const p_array<P>& x)
Index: jardonnet/registration/update_qk.hh
--- jardonnet/registration/update_qk.hh (revision 2447)
+++ jardonnet/registration/update_qk.hh (working copy)
@@ -2,12 +2,14 @@
# define MLN_UPDATE_QK_HH
#include "interpolation.hh"
-#include "quat7.hh"
+//#include "quat7.hh"
namespace mln
{
- float arc(quat7<3> dqk, quat7<3> dqk_1)
+ // FIXME: T different ?
+ template <typename T>
+ float arc(const T& dqk, const T& dqk_1)
{
float res = 0.0;
for (int i = 0; i < 7; i++)
@@ -17,12 +19,13 @@
}
- quat7<3> update_qk(const quat7<3> qk[4],
+ template <typename T>
+ T update_qk(const T qk[4],
const float dk[3])
{
- quat7<3> dqk_2 = qk[2] - qk[3];
- quat7<3> dqk_1 = qk[1] - qk[2];
- quat7<3> dqk = qk[0] - qk[1];
+ T dqk_2 = qk[2] - qk[3];
+ T dqk_1 = qk[1] - qk[2];
+ T dqk = qk[0] - qk[1];
float tetak_1 = arc(dqk_1, dqk_2);
float tetak = arc(dqk, dqk_1);
1
0
---
milena/mln/util/internal/graph_edge.hh | 4 +-
milena/mln/util/internal/graph_edge_impl.hh | 89 +++++++++++++++++++++++++
milena/mln/util/internal/graph_vertex.hh | 4 +-
milena/mln/util/internal/graph_vertex_impl.hh | 89 +++++++++++++++++++++++++
4 files changed, 184 insertions(+), 2 deletions(-)
create mode 100644 milena/mln/util/internal/graph_edge_impl.hh
create mode 100644 milena/mln/util/internal/graph_vertex_impl.hh
diff --git a/milena/mln/util/internal/graph_edge.hh b/milena/mln/util/internal/graph_edge.hh
index 78a00c2..24bb716 100644
--- a/milena/mln/util/internal/graph_edge.hh
+++ b/milena/mln/util/internal/graph_edge.hh
@@ -28,6 +28,8 @@
#ifndef MLN_UTIL_INTERNAL_GRAPH_EDGE_HH
# define MLN_UTIL_INTERNAL_GRAPH_EDGE_HH
+# include <mln/util/internal/graph_edge_impl.hh>
+
/*! \file mln/util/internal/graph_edge.hh
* \brief Definition of a graph edge.
*/
@@ -44,7 +46,7 @@ namespace mln
/// \brief Edge of a graph \p G.
template <typename G>
- class edge
+ class edge : public internal::edge_impl_<G>
{
typedef mlc_const(G) graph_t;
diff --git a/milena/mln/util/internal/graph_edge_impl.hh b/milena/mln/util/internal/graph_edge_impl.hh
new file mode 100644
index 0000000..2ed90c5
--- /dev/null
+++ b/milena/mln/util/internal/graph_edge_impl.hh
@@ -0,0 +1,89 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_INTERNAL_EDGE_IMPL_HH
+# define MLN_CORE_INTERNAL_EDGE_IMPL_HH
+
+/*! \file mln/core/internal/edge_impl.hh
+ *
+ * \brief Define a couple of implementation classes to provide methods
+ * to classes of generalized edges.
+ */
+
+# include <mln/core/internal/force_exact.hh>
+
+
+namespace mln
+{
+
+ namespace util
+ {
+
+ namespace internal
+ {
+
+ /// Implementation class to equip generalized edge classes.
+ template <typename G>
+ class edge_impl_
+ {
+ protected:
+ edge_impl_();
+ };
+
+ } // end of namespace internal
+
+ } // end of namespace util
+
+} // end of namespace mln
+
+#ifndef MLN_INCLUDE_ONLY
+
+namespace mln
+{
+
+ namespace util
+ {
+
+ namespace internal
+ {
+
+ template <typename G>
+ inline
+ edge_impl_<G>::edge_impl_()
+ {
+ }
+
+ } // end of namespace internal
+
+ } // end of namespace util
+
+} // end of namespace mln
+
+#endif // ! MLN_INCLUDE_ONLY
+
+
+#endif // ! MLN_CORE_INTERNAL_EDGE_IMPL_HH
diff --git a/milena/mln/util/internal/graph_vertex.hh b/milena/mln/util/internal/graph_vertex.hh
index c40bf0f..fc4ff2b 100644
--- a/milena/mln/util/internal/graph_vertex.hh
+++ b/milena/mln/util/internal/graph_vertex.hh
@@ -28,6 +28,8 @@
#ifndef MLN_UTIL_INTERNAL_GRAPH_VERTEX_HH
# define MLN_UTIL_INTERNAL_GRAPH_VERTEX_HH
+# include <mln/util/internal/graph_vertex_impl.hh>
+
/// \file mln/util/internal/graph_vertex.hh
/// \brief Implementation of a graph vertex.
@@ -39,7 +41,7 @@ namespace mln
/// \brief Vertex of a graph \p G.
template<typename G>
- class vertex
+ class vertex : public internal::vertex_impl_<G>
{
typedef mlc_const(G) graph_t;
diff --git a/milena/mln/util/internal/graph_vertex_impl.hh b/milena/mln/util/internal/graph_vertex_impl.hh
new file mode 100644
index 0000000..863cf25
--- /dev/null
+++ b/milena/mln/util/internal/graph_vertex_impl.hh
@@ -0,0 +1,89 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_INTERNAL_VERTEX_IMPL_HH
+# define MLN_CORE_INTERNAL_VERTEX_IMPL_HH
+
+/*! \file mln/core/internal/vertex_impl.hh
+ *
+ * \brief Define a couple of implementation classes to provide methods
+ * to classes of generalized vertexs.
+ */
+
+# include <mln/core/internal/force_exact.hh>
+
+
+namespace mln
+{
+
+ namespace util
+ {
+
+ namespace internal
+ {
+
+ /// Implementation class to equip generalized vertex classes.
+ template <typename G>
+ class vertex_impl_
+ {
+ protected:
+ vertex_impl_();
+ };
+
+ } // end of namespace internal
+
+ } // end of namespace util
+
+} // end of namespace mln
+
+#ifndef MLN_INCLUDE_ONLY
+
+namespace mln
+{
+
+ namespace util
+ {
+
+ namespace internal
+ {
+
+ template <typename G>
+ inline
+ vertex_impl_<G>::vertex_impl_()
+ {
+ }
+
+ } // end of namespace internal
+
+ } // end of namespace util
+
+} // end of namespace mln
+
+#endif // ! MLN_INCLUDE_ONLY
+
+
+#endif // ! MLN_CORE_INTERNAL_VERTEX_IMPL_HH
--
1.5.6.5
1
0
2448: Add a new util::graph implementation. The graph does not store data anymore.
by Guillaume Lazzara 30 Sep '08
by Guillaume Lazzara 30 Sep '08
30 Sep '08
---
milena/mln/core/concept/graph.hh | 150 ++++
milena/mln/core/internal/graph_iter_base.hh | 135 ++++
milena/mln/core/macros.hh | 53 ++
milena/mln/util/graph.hh | 284 ++------
milena/mln/util/internal/graph_base.hh | 742 +++++++-------------
milena/mln/util/internal/graph_edge.hh | 378 ++++++++++
milena/mln/util/internal/graph_edge_iter.hh | 273 +++++++
.../mln/util/internal/graph_edge_nbh_edge_iter.hh | 335 +++++++++
milena/mln/util/internal/graph_vertex.hh | 361 ++++++++++
milena/mln/util/internal/graph_vertex_iter.hh | 266 +++++++
.../util/internal/graph_vertex_nbh_edge_iter.hh | 323 +++++++++
.../util/internal/graph_vertex_nbh_vertex_iter.hh | 320 +++++++++
milena/tests/util/graph.cc | 107 +++-
13 files changed, 3013 insertions(+), 714 deletions(-)
create mode 100644 milena/mln/core/concept/graph.hh
create mode 100644 milena/mln/core/internal/graph_iter_base.hh
create mode 100644 milena/mln/util/internal/graph_edge.hh
create mode 100644 milena/mln/util/internal/graph_edge_iter.hh
create mode 100644 milena/mln/util/internal/graph_edge_nbh_edge_iter.hh
create mode 100644 milena/mln/util/internal/graph_vertex.hh
create mode 100644 milena/mln/util/internal/graph_vertex_iter.hh
create mode 100644 milena/mln/util/internal/graph_vertex_nbh_edge_iter.hh
create mode 100644 milena/mln/util/internal/graph_vertex_nbh_vertex_iter.hh
diff --git a/milena/mln/core/concept/graph.hh b/milena/mln/core/concept/graph.hh
new file mode 100644
index 0000000..36d94c9
--- /dev/null
+++ b/milena/mln/core/concept/graph.hh
@@ -0,0 +1,150 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_CONCEPT_GRAPH_HH
+# define MLN_CORE_CONCEPT_GRAPH_HH
+
+/*! \file mln/core/concept/graph.hh
+ * \brief Definition of the concept of mln::Graph.
+ */
+
+namespace mln
+{
+
+
+ // Fwd decl.
+ template <typename E> struct Graph;
+
+ // Graph category flag type.
+ template <>
+ struct Graph<void>
+ {
+ typedef Object<void> super;
+ };
+
+ /*! \brief Base class for implementation of graph classes.
+ *
+ * \see mln::doc::Graph for a complete documentation of this class
+ * contents.
+ */
+ template <typename E>
+ struct Graph : public Object<E>
+ {
+ typedef Graph<void> category;
+
+ /*
+ // provided by internal::image_base:
+
+ typedef pset;
+ typedef site;
+ typedef psite;
+
+ typedef fwd_piter;
+ typedef bkd_piter;
+
+ // Misc.
+ void *graph_id() const;
+ template<typename G2>
+ bool is_subgraph_of(const G2& gr) const;
+
+ // Vertex and edges oriented.
+ unsigned v_other(unsigned id_e, unsigned id_v) const;
+
+ // Vertex oriented.
+ size_t v_nmax() const;
+ bool has_v(unsigned id_v) const;
+ size_t v_nmax_nbh_edges(unsigned id_v) const;
+ unsigned v_ith_nbh_edge(unsigned id_v, unsigned i) const;
+
+ // Edge oriented.
+ size_t e_nmax() const;
+ bool has_e(unsigned id_e) const;
+ unsigned v1(unsigned id_e) const;
+ unsigned v2(unsigned id_e) const;
+ size_t e_nmax_nbh_edges(unsigned id_e) const;
+ unsigned e_ith_nbh_edge(unsigned id_e, unsigned i) const;
+
+ */
+
+ protected:
+ Graph();
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename E>
+ inline
+ Graph<E>::Graph()
+ {
+ // provided by internal::graph_base:
+
+ //typedef mln_psite(E) psite;
+
+ //typedef mln_fwd_piter(E) fwd_piter;
+ //typedef mln_bkd_piter(E) bkd_piter;
+
+ // Check methods
+ const void * const(E::*m1)() const = & E::graph_id;
+ m1 = 0;
+ unsigned (E::*m2)(unsigned id_e, unsigned id_v) const = & E::v_other;
+ m2 = 0;
+ unsigned (E::*m3)() = & E::add_vertex;
+ m3 = 0;
+ size_t (E::*m4)() const = & E::v_nmax;
+ m4 = 0;
+ bool (E::*m5)(unsigned id_v) const = & E::has_v;
+ m5 = 0;
+ size_t (E::*m6)(unsigned id_v) const = & E::v_nmax_nbh_edges;
+ m6 = 0;
+ unsigned (E::*m7)(unsigned id_v, unsigned i) const = & E::v_ith_nbh_edge;
+ m7 = 0;
+ size_t (E::*m8)() const = & E::e_nmax;
+ m8 = 0;
+ bool (E::*m9)(unsigned id_e) const = & E::has_e;
+ m9 = 0;
+ unsigned (E::*m10)(unsigned id_e) const = & E::v1;
+ m10 = 0;
+ unsigned (E::*m11)(unsigned id_e) const = & E::v2;
+ m11 = 0;
+ size_t (E::*m12)(unsigned id_e) const = & E::e_nmax_nbh_edges;
+ m12 = 0;
+ unsigned (E::*m13)(unsigned id_e, unsigned i) const = & E::e_ith_nbh_edge;
+ m13 = 0;
+
+ //FIXME: enable this test. Currently does not work because this is
+ // a templated method.
+ //bool (E::*m14)(...) = & E::is_subgraph_of;
+ //m14 = 0;
+}
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+#endif // ! MLN_CORE_CONCEPT_GRAPH_HH
+
diff --git a/milena/mln/core/internal/graph_iter_base.hh b/milena/mln/core/internal/graph_iter_base.hh
new file mode 100644
index 0000000..2d7297c
--- /dev/null
+++ b/milena/mln/core/internal/graph_iter_base.hh
@@ -0,0 +1,135 @@
+// 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_CORE_INTERNAL_GRAPH_ITER_BASE_HH
+# define MLN_CORE_INTERNAL_GRAPH_ITER_BASE_HH
+
+# include <mln/core/concept/iterator.hh>
+# include <mln/core/concept/proxy.hh>
+
+/// \file mln/core/internal/graph_iter_base.hh
+/// \brief Base class for graph iterators.
+
+namespace mln
+{
+
+ namespace internal
+ {
+
+ /// Base class for graph iterators
+ /// \p G graph type.
+ /// \p S the type of the data pointed by the iterator.
+ /// For instance : edge, vertex....
+ template<typename G, typename S>
+ class graph_iterator_base
+ : public Iterator< graph_iterator_base<G> >,
+ public internal::proxy_impl< const S&, graph_iterator_base<G> >
+ {
+ public:
+ /// Constructors.
+ /// \{
+ graph_iterator_base();
+ graph_iterator_base(const G& g);
+ /// \}
+
+ /// Iterator interface.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next_();
+
+ /// Return current index
+ unsigned index() const;
+ /// \}
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const S& subj_();
+ /// \}
+
+ protected:
+ const G *g_;
+ unsigned i_;
+ };
+
+
+ template<typename G, typename S>
+ class graph_fwd_iterator_base
+ : public Iterator< graph_fwd_iterator_base<G> >,
+ public internal::proxy_impl< const S&, graph_fwd_iterator_base<G> >
+ {
+ public:
+ /// Construction and assignment.
+ /// \{
+ graph_fwd_iterator_base();
+ graph_fwd_iterator_base(const G& g);
+ /// \}
+
+ /// Manipulation.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+ /// \}
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next_();
+
+ /// Return current index
+ unsigned index() const;
+
+ /// Proxy.
+ /// \{
+ /// Proxy Subject type
+ typedef const mln_vertex(G)& q_subject;
+
+ /// Proxy subject
+ q_subject subj_();
+ /// \}
+
+ protected:
+ const G *g_;
+ unsigned i_;
+ };
+
+ } // End of namespace mln::internal.
+
+} // End of namespace mln.
+
+#endif // !MLN_CORE_INTERNAL_GRAPH_ITER_BASE_HH
diff --git a/milena/mln/core/macros.hh b/milena/mln/core/macros.hh
index 3b0b88c..3dc9036 100644
--- a/milena/mln/core/macros.hh
+++ b/milena/mln/core/macros.hh
@@ -418,5 +418,58 @@
# define mln_nixter(I, N) mln_fwd_nixter(I, N)
# define mln_nixter_(I, N) mln_fwd_nixter_(I, N)
+/// Shortcuts to access the vertex iterator type associated to a graph G.
+/// \{
+# define mln_vertex_iter(G) typename G::vertex_iter
+# define mln_vertex_iter_(G) G::vertex_iter
+# define mln_vertex_fwd_iter(G) typename G::vertex_fwd_iter
+# define mln_vertex_fwd_iter_(G) G::vertex_fwd_iter
+# define mln_vertex_bkd_iter(G) typename G::vertex_bkd_iter
+# define mln_vertex_bkd_iter_(G) G::vertex_bkd_iter
+/// \}
+
+/// Shortcuts to access the edge iterator type associated to a graph G.
+/// \{
+# define mln_edge_iter(G) typename G::edge_iter
+# define mln_edge_iter_(G) G::edge_iter
+# define mln_edge_fwd_iter(G) typename G::edge_fwd_iter
+# define mln_edge_fwd_iter_(G) G::edge_fwd_iter
+# define mln_edge_bkd_iter(G) typename G::edge_bkd_iter
+# define mln_edge_bkd_iter_(G) G::edge_bkd_iter
+/// \}
+
+/// Shortcuts to access the vertex centered edge neighbors iterator type
+/// associated to a graph G.
+/// \{
+# define mln_vertex_nbh_vertex_iter(G) typename G::vertex_nbh_vertex_iter
+# define mln_vertex_nbh_vertex_iter_(G) G::vertex_nbh_vertex_iter
+# define mln_vertex_nbh_vertex_fwd_iter(G) typename G::vertex_nbh_vertex_fwd_iter
+# define mln_vertex_nbh_vertex_fwd_iter_(G) G::vertex_nbh_vertex_fwd_iter
+# define mln_vertex_nbh_vertex_bkd_iter(G) typename G::vertex_nbh_vertex_bkd_iter
+# define mln_vertex_nbh_vertex_bkd_iter_(G) G::vertex_nbh_vertex_bkd_iter
+/// \}
+
+/// Shortcuts to access the vertex centered edge neighbors iterator type
+/// associated to a graph G.
+/// \{
+# define mln_vertex_nbh_edge_iter(G) typename G::vertex_nbh_edge_iter
+# define mln_vertex_nbh_edge_iter_(G) G::vertex_nbh_edge_iter
+# define mln_vertex_nbh_edge_fwd_iter(G) typename G::vertex_nbh_edge_fwd_iter
+# define mln_vertex_nbh_edge_fwd_iter_(G) G::vertex_nbh_edge_fwd_iter
+# define mln_vertex_nbh_edge_bkd_iter(G) typename G::vertex_nbh_edge_bkd_iter
+# define mln_vertex_nbh_edge_bkd_iter_(G) G::vertex_nbh_edge_bkd_iter
+/// \}
+
+/// Shortcuts to access the edge centered edge neighbors iterator type
+/// associated to a graph G.
+/// \{
+# define mln_edge_nbh_edge_iter(G) typename G::edge_nbh_edge_iter
+# define mln_edge_nbh_edge_iter_(G) G::edge_nbh_edge_iter
+# define mln_edge_nbh_edge_fwd_iter(G) typename G::edge_nbh_edge_fwd_iter
+# define mln_edge_nbh_edge_fwd_iter_(G) G::edge_nbh_edge_fwd_iter
+# define mln_edge_nbh_edge_bkd_iter(G) typename G::edge_nbh_edge_bkd_iter
+# define mln_edge_nbh_edge_bkd_iter_(G) G::edge_nbh_edge_bkd_iter
+/// \}
#endif // ! MLN_CORE_MACROS_HH
+
diff --git a/milena/mln/util/graph.hh b/milena/mln/util/graph.hh
index 0273bd8..ba148d3 100644
--- a/milena/mln/util/graph.hh
+++ b/milena/mln/util/graph.hh
@@ -32,281 +32,97 @@
/// \brief Definitions of undirected graphs.
# include <mln/util/internal/graph_base.hh>
+# include <mln/util/internal/graph_vertex_iter.hh>
+# include <mln/util/internal/graph_edge_iter.hh>
+# include <mln/util/internal/graph_vertex_nbh_vertex_iter.hh>
+# include <mln/util/internal/graph_vertex_nbh_edge_iter.hh>
+# include <mln/util/internal/graph_edge_nbh_edge_iter.hh>
namespace mln
{
namespace util
{
- /*-----------.
- | Fwd decl. |
- `-----------*/
/// \brief Undirected graph.
- template<typename V = void, typename E = void>
- class graph;
-
- /*--------------------.
- | graph<void, void>. |
- `--------------------*/
-
- /// Specialization for undirected graphs with no data on vertices nor
- /// on edges.
- template <>
- class graph<void, void> : public internal::graph_base<void, void>
+ class graph : public internal::graph_base<graph>
{
public:
/// The super class.
- typedef internal::graph_base<void, void> super;
-
- /// \brief Add a vertex.
- ///
- /// \return The id of the new vertex.
- vertex_id add_vertex();
- /// \brief Add an edge between vertices with ids \p v1 and \p v2.
- ///
- /// \return The id of the new edge if it does not exist yet;
- /// otherwise, return <tt>mln_max(edge_id)</tt>.
- edge_id add_edge(vertex_id v1, vertex_id v2);
- };
-
- /*-----------------.
- | graph<V, void>. |
- `-----------------*/
+ typedef internal::graph_base<graph> super;
- /// Specialization for undirected graphs with data on vertices.
- template <typename V>
- class graph<V, void> : public internal::graph_base<V, void>
- {
- public:
- /// The super class.
- typedef internal::graph_base<V, void> super;
-
- /// \brief Add a vertex.
- ///
- /// \return The id of the new vertex.
- vertex_id add_vertex(const V& data);
- /// \brief Add an edge between vertices with ids \p v1 and \p v2.
- ///
- /// \return The id of the new edge if it does not exist yet;
- /// otherwise, return <tt>mln_max(edge_id)</tt>.
- edge_id add_edge(vertex_id v1, vertex_id v2);
+ /// Iterator types
+ /// \{
- /// Return the data associated to vertex with id \a v.
+ /// Vertex iterators
/// \{
- V& vertex_data(vertex_id v);
- const V& vertex_data(vertex_id v) const;
+ typedef mln::internal::vertex_fwd_iterator<graph> vertex_fwd_iter;
+ typedef mln::internal::vertex_bkd_iterator<graph> vertex_bkd_iter;
+ typedef vertex_fwd_iter vertex_iter;
/// \}
- };
- /*--------------.
- | graph<V, E>. |
- `--------------*/
-
- /// Specialization for undirected graphs with data on vertices and
- /// edges.
- template <typename V, typename E>
- class graph : public internal::graph_base<V, E>
- {
- public:
- /// The super class.
- typedef internal::graph_base<V, E> super;
-
- /// \brief Add a vertex.
- ///
- /// \return The id of the new vertex.
- vertex_id add_vertex(const V& data);
- /// \brief Add an edge between vertices with ids \p v1 and \p v2.
- ///
- /// \return The id of the new edge if it does not exist yet;
- /// otherwise, return <tt>mln_max(edge_id)</tt>.
- edge_id add_edge(vertex_id v1, vertex_id v2, const E& data);
-
- /// Return the data associated to vertex with id \a v.
+ /// Vertex centered edge iterators
/// \{
- V& vertex_data(vertex_id v);
- const V& vertex_data(vertex_id v) const;
+ typedef mln::internal::vertex_nbh_edge_fwd_iterator<graph> vertex_nbh_edge_fwd_iter;
+ typedef mln::internal::vertex_nbh_edge_bkd_iterator<graph> vertex_nbh_edge_bkd_iter;
+ typedef vertex_nbh_edge_fwd_iter vertex_nbh_edge_iter;
/// \}
- /// Return the data associated to the edge with id \a e.
+ /// Vertex centered vertex iterators
/// \{
- E& edge_data(edge_id e);
- const E& edge_data(edge_id e) const;
+ typedef mln::internal::vertex_nbh_vertex_fwd_iterator<graph> vertex_nbh_vertex_fwd_iter;
+ typedef mln::internal::vertex_nbh_vertex_bkd_iterator<graph> vertex_nbh_vertex_bkd_iter;
+ typedef vertex_nbh_vertex_fwd_iter vertex_nbh_vertex_iter;
/// \}
- /// Return the data associated to the edge between vertices with
- /// ids \a v1 and \a v2.
+ /// Edge iterators
/// \{
- E& edge_data(vertex_id v1, vertex_id v2);
- const E& edge_data(vertex_id v1, vertex_id v2) const;
+ typedef mln::internal::edge_fwd_iterator<graph> edge_fwd_iter;
+ typedef mln::internal::edge_bkd_iterator<graph> edge_bkd_iter;
+ typedef edge_fwd_iter edge_iter;
/// \}
- };
-
-
-
-# ifndef MLN_INCLUDE_ONLY
-
- /*--------------------.
- | graph<void, void>. |
- `--------------------*/
-
- /* Note that definition of members from fully specialized
- template classes are not preceded by `template<>'. */
- inline
- vertex_id
- graph<void, void>::add_vertex()
- {
- return super::add_vertex_(new util::vertex<void>);
- }
-
- /* Note that ddefinition of members from fully specialized
- template classes are not preceded by `template<>'. */
- inline
- edge_id
- graph<void, void>::add_edge(vertex_id v1, vertex_id v2)
- {
- mln_assertion(v1 < this->nvertices());
- mln_assertion(v2 < this->nvertices());
- return super::add_edge_(new util::edge<void>(v1, v2));
- }
-
- /*-----------------.
- | graph<V, void>. |
- `-----------------*/
- template<typename V>
- inline
- vertex_id
- graph<V, void>::add_vertex(const V& data)
- {
- return super::add_vertex_(new util::vertex<V>(data));
- }
-
- template<typename V>
- inline
- edge_id
- graph<V, void>::add_edge(vertex_id v1, vertex_id v2)
- {
- mln_assertion(v1 < this->nvertices());
- mln_assertion(v2 < this->nvertices());
- return super::add_edge_(new util::edge<void>(v1, v2));
- }
-
- template <class V>
- inline
- V&
- graph<V, void>::vertex_data(vertex_id v)
- {
- mln_assertion(v < this->nvertices());
- return this->vertices_[v]->data;
- }
+ /// Edge centered edge iterators.
+ /// \{
+ typedef mln::internal::edge_nbh_edge_fwd_iterator<graph> edge_nbh_edge_fwd_iter;
+ typedef mln::internal::edge_nbh_edge_bkd_iterator<graph> edge_nbh_edge_bkd_iter;
+ typedef edge_nbh_edge_fwd_iter edge_nbh_edge_iter;
+ /// \}
- template<typename V>
- inline
- const V&
- graph<V, void>::vertex_data(vertex_id v) const
- {
- mln_assertion(v < this->nvertices());
- return this->vertices_[v]->data;
- }
+ /// \}
+ /// Return whether this graph is a subgraph
+ /// Return always false here.
+ template <typename G2>
+ bool is_subgraph_of(const G2& g);
+ };
- /*--------------.
- | graph<V, E>. |
- `--------------*/
+ } // end of namespace mln::util
- template<typename V, typename E>
- inline
- vertex_id
- graph<V, E>::add_vertex(const V& data)
- {
- return super::add_vertex_(new util::vertex<V>(data));
- }
+} // end of namespace mln
- template<typename V, typename E>
- inline
- edge_id
- graph<V, E>::add_edge(vertex_id v1, vertex_id v2, const E& data)
- {
- mln_assertion(v1 < this->nvertices());
- mln_assertion(v2 < this->nvertices());
- return super::add_edge_(new util::edge<E>(v1, v2, data));
- }
- template<typename V, typename E>
- inline
- V&
- graph<V, E>::vertex_data(vertex_id v)
- {
- mln_assertion(v < this->nvertices());
- return this->vertices_[v]->data;
- }
+# ifndef MLN_INCLUDE_ONLY
- template<typename V, typename E>
- inline
- const V&
- graph<V, E>::vertex_data(vertex_id v) const
- {
- mln_assertion(v < this->nvertices());
- return this->vertices_[v]->data;
- }
+namespace mln
+{
- template<typename V, typename E>
- inline
- E&
- graph<V, E>::edge_data(edge_id e)
- {
- mln_assertion(e < this->nedges());
- return this->edges_[e]->data;
- }
+ namespace util
+ {
- template<typename V, typename E>
+ template <typename G2>
inline
- const E&
- graph<V, E>::edge_data(edge_id e) const
+ bool
+ graph::is_subgraph_of(const G2& g)
{
- mln_assertion(e < this->nedges());
- return this->edges_[e]->data;
+ return false;
}
- template<typename V, typename E>
- inline
- E&
- graph<V, E>::edge_data(vertex_id v1, vertex_id v2)
- {
- mln_assertion(v1 < this->nvertices());
- mln_assertion(v2 < this->nvertices());
- ord_pair<vertex_id> vertex_pair (v1, v2);
- std::vector<edge_id>& edges_ids = this->vertices_[v1]->edges;
- for (std::vector<edge_id>::iterator e = edges_ids.begin();
- e != edges_ids.end(); ++e)
- if (this->edges_[*e] == vertex_pair)
- return this->edges_[*e]->data;
- // If no edge between V1 and V2 was found, abort.
- abort();
- }
+ } // end of namespace mln::util
- template<typename V, typename E>
- inline
- const E&
- graph<V, E>::edge_data(vertex_id v1, vertex_id v2) const
- {
- mln_assertion(v1 < this->nvertices());
- mln_assertion(v2 < this->nvertices());
- ord_pair<vertex_id> vertex_pair (v1, v2);
- const std::vector<edge_id>& edges_ids = this->vertices_[v1]->edges;
- for (std::vector<edge_id>::const_iterator e = edges_ids.begin();
- e != edges_ids.end(); ++e)
- if (this->edges_[*e] == vertex_pair)
- return this->edges_[*e]->data;
- // If no edge between V1 and V2 was found, abort.
- abort();
- }
+} // end of namespace mln
# endif // ! MLN_INCLUDE_ONLY
- } // end of namespace mln::util
-
-} // end of namespace mln
#endif // ! MLN_UTIL_GRAPH_HH
diff --git a/milena/mln/util/internal/graph_base.hh b/milena/mln/util/internal/graph_base.hh
index d6fb437..17143c5 100644
--- a/milena/mln/util/internal/graph_base.hh
+++ b/milena/mln/util/internal/graph_base.hh
@@ -39,14 +39,15 @@
# include <set>
# include <ostream>
-// For gen_id.
-# include <mln/value/builtin/all.hh>
-
# include <mln/core/concept/object.hh>
+# include <mln/core/concept/graph.hh>
+# include <mln/core/concept/proxy.hh>
# include <mln/util/ord_pair.hh>
# include <mln/value/builtin/integers.hh>
+# include <mln/util/internal/graph_edge.hh>
+# include <mln/util/internal/graph_vertex.hh>
namespace mln
{
@@ -54,391 +55,151 @@ namespace mln
namespace util
{
- /*--------------.
- | Identifiers. |
- `--------------*/
-
- /// \brief Generic identifier/handler.
- ///
- /// Inspired by Vaucansons's handlers for automata.
- ///
- /// https://svn.lrde.epita.fr/svn/vaucanson/trunk/include/vaucanson/automata/co…
- /// https://svn.lrde.epita.fr/svn/vaucanson/trunk/include/vaucanson/automata/co…
- ///
- /// \todo We /might/ want to integrate this into Milena's value system.
- ///
- /// \todo Move this class elsewhere?
-
- template <typename Tag, typename Equiv>
- class gen_id : public Object< gen_id < Tag, Equiv > >
- {
- typedef gen_id<Tag, Equiv> self_t;
-
- public:
- typedef Equiv equiv;
-
- gen_id();
- gen_id(const Equiv& e);
- self_t& operator=(const Equiv& e);
-
- const equiv& to_equiv() const;
- equiv& to_equiv();
- operator const equiv() const;
- operator equiv();
-
- private:
- equiv e_;
- };
-
-
- /// Compare two identifiers.
- /// \{
- template <typename Tag, typename Equiv>
- bool
- operator==(const gen_id<Tag, Equiv>& i, const gen_id<Tag, Equiv>& j);
-
- template <typename Tag, typename Equiv>
- bool
- operator==(const Equiv& i, const gen_id<Tag, Equiv>& j);
-
- template <typename Tag, typename Equiv>
- bool
- operator==(const gen_id<Tag, Equiv>& i, const Equiv j);
-
-
- template <typename Tag, typename Equiv>
- bool
- ord_strict(const gen_id<Tag, Equiv>& i, const gen_id<Tag, Equiv>& j);
-
- template <typename Tag, typename Equiv>
- bool
- ord_weak(const gen_id<Tag, Equiv>& i, const gen_id<Tag, Equiv>& j);
- /// \}
-
-
- /// Tags.
- /// \{
- struct vertex_tag;
- struct edge_tag;
- /// \}
-
-
- /// \brief The type used to identify vertices.
- ///
- /// Used internally as a key to manipulate vertices.
- typedef gen_id<vertex_tag, unsigned> vertex_id;
-
- /// \brief The type used to identify edges.
- ///
- /// Used internally as a key to manipulate edges.
- typedef gen_id<edge_tag, unsigned> edge_id;
-
-
- /*---------.
- | Vertex. |
- `---------*/
-
- /// \brief Vertex of a graph, holding a value of type \p T.
- template<typename T>
- struct vertex
- {
- vertex(T data)
- : data(data)
- {}
-
- T data;
- std::vector<edge_id> edges;
- };
-
- /// \brief Specialization of mln::util::vertex for vertices with no
- /// associated value.
- template <>
- struct vertex<void>
- {
- std::vector<edge_id> edges;
- };
-
-
- /*-------.
- | Edge. |
- `-------*/
-
- /// \brief Edge of a graph, holding a value of type \p T.
- template<typename T>
- struct edge
- {
- edge(vertex_id v1, vertex_id v2)
- : pair_vertex_(v1, v2)
- {}
-
- /// Return the lowest vertex id adjacent to this edge.
- vertex_id v1() const { return pair_vertex_.first(); }
- /// Return the highest vertex id adjacent to this edge.
- vertex_id v2() const { return pair_vertex_.second(); }
-
- T data;
- ord_pair<vertex_id> pair_vertex_;
- };
-
- /// \brief Specialization of mln::util::vertex for edges with no
- /// associated value.
- template <>
- struct edge<void>
- {
- edge(vertex_id v1, vertex_id v2)
- : pair_vertex_(v1, v2)
- {}
-
- /// Return the lowest vertex id adjacent to this edge.
- vertex_id v1() const { return pair_vertex_.first(); }
- /// Return the highest vertex id adjacent to this edge.
- vertex_id v2() const { return pair_vertex_.second(); }
-
- ord_pair<vertex_id> pair_vertex_;
- };
-
- // FIXME: Document this. In particular, we should state that edges are
- // only compared w.r.t. their adjacent vertices, not the data they
- // possibly hold!
- template <typename E>
- bool
- operator==(const edge<E>& lhs, const edge<E>& rhs);
-
- template <typename E>
- bool
- operator< (const edge<E>& lhs, const edge<E>& rhs);
-
-
/*-------------.
| Graph base. |
`-------------*/
namespace internal
{
- // FIXME: This should be no longer useful once vertices and edges
- // are handled without pointers and dynamic allocation.
- template <typename T>
- struct less_ptr
- {
- bool
- operator()(const T& a, const T& b)
- {
- mln_assertion(a);
- mln_assertion(b);
- return (*a < *b);
- }
- };
-
-
/// \brief Base class for undirected graphs.
- template<typename V, typename E>
- class graph_base
+ template<typename E>
+ class graph_base : public Graph<E>
{
- typedef graph_base<V, E> self_t;
-
- public:
- /* FIXME: Do we really want handle vertices and edges through
- pointers? In my (Roland) opinion, this is just a drawback,
- here. */
+ /// The type of a vertex.
+ typedef util::vertex<E> vertex_t;
+ /// Internal vertex data type
+ typedef std::vector<unsigned> vertex_data_t;
/// The type of the set of vertices.
- typedef std::vector< util::vertex<V>* > vertices_t;
+ typedef std::vector<vertex_data_t> vertices_t;
+
+ /// The type of an edge.
+ typedef util::edge<E> edge_t;
+ /// Internal edge data type.
+ typedef ord_pair<unsigned> edge_data_t;
/// The type of the set of edges.
- typedef std::vector< util::edge<E>* > edges_t;
+ typedef std::vector<edge_data_t> edges_t;
/// A set to test the presence of a given edge.
- typedef std::set< util::edge<E>*,
- less_ptr< util::edge<E>* > > edges_set_t;
+ typedef std::set<edge_data_t> edges_set_t;
- /// Construction, assignments and destruction.
+ public:
+ /// Misc. methods
/// \{
- graph_base();
- graph_base(const self_t& rhs);
- self_t& operator=(const self_t& rhs);
- ~graph_base();
+ /// Returns the graph id, the "this" pointer.
+ const void * const graph_id() const;
/// \}
- /// Return the vertex whose id is \a v.
+ /// Vertex and edge oriented methods.
/// \{
- util::vertex<V>& vertex(vertex_id v);
- const util::vertex<V>& vertex(vertex_id v) const;
+ /// Returns the other adjacent vertex id of a given edge id \p id_e.
+ unsigned v_other(unsigned id_e, unsigned id_v) const;
/// \}
- /// Return the edge whose id is \a e.
- /// \{
- util::edge<E>& edge(edge_id e);
- const util::edge<E>& edge(edge_id e) const;
- /// \}
- /// Return the whole vertices of the graph.
+ /// Vertex oriented.
+ /// \{
+
+ /// Shortcuts factoring the insertion of vertices and edges.
/// \{
- vertices_t& vertices();
- const vertices_t& vertices() const;
- /// \}
+ /// \brief Add a vertex.
+ ///
+ /// \return The id of the new vertex.
+ unsigned add_vertex();
- /// Return the whole edges of the graph.
+ /// Return the vertex whose id is \a v.
/// \{
- edges_t& edges();
- const edges_t& edges() const;
+ vertex_t vertex(unsigned id_v) const;
/// \}
/// \brief Return the number of vertices in the graph.
- size_t nvertices() const;
- /// \brief Return the number of edges in the graph.
- size_t nedges() const;
+ size_t v_nmax() const;
- // FIXME: We might want to externalize this in routine of
- // namespace mln::debug.
- /** \brief Print on \p ostr the graph.
+ /// Check whether a vertex id \p id_v is valid in the graph.
+ bool has_v(unsigned id_v) const;
- \param[in] ostr The output stream. */
- void print_debug(std::ostream& ostr) const;
+ /// Return the number of adjacent edges of vertex \p id_v.
+ size_t v_nmax_nbh_edges(unsigned id_v) const;
- protected:
- /// Shortcuts factoring the insertion of vertices and edges.
+ /// Returns the \p i th edge adjacent to the vertex \p id_v.
+ unsigned v_ith_nbh_edge(unsigned id_v, unsigned i) const;
+
+ /// Return the number of adjacent vertices of vertex \p id_v.
+ size_t v_nmax_nbh_vertices(unsigned id_v) const;
+
+ /// Returns the \p i th vertex adjacent to the vertex \p id_v.
+ unsigned v_ith_nbh_vertex(unsigned id_v, unsigned i) const;
+
+ /// \}
+
+
+ /// Edge oriented.
/// \{
- /// \brief Add a vertex.
- ///
- /// \return The id of the new vertex.
- vertex_id add_vertex_(util::vertex<V>* vertex);
/// \brief Add an edge.
///
/// \return The id of the new edge if it does not exist yet;
- /// otherwise, return <tt>mln_max(edge_id)</tt>.
- edge_id add_edge_(util::edge<E>* edge);
+ /// otherwise, return <tt>mln_max(unsigned)</tt>.
+ unsigned add_edge(unsigned id_v1, unsigned id_v2);
/// \}
- protected:
- /// The vertices.
- vertices_t vertices_;
- /// The edges.
- edges_t edges_;
- /// An index of the set of edges, for fast-access purpose.
- edges_set_t edges_set_;
- };
-
- } // end of namespace mln::util::internal
-
-
-
-# ifndef MLN_INCLUDE_ONLY
+ /// Return the edge whose id is \a e.
+ /// \{
+ const edge_t& edge(unsigned e) const;
+ /// \}
- /*--------------.
- | Identifiers. |
- `--------------*/
+ /// \brief Return the number of edges in the graph.
+ size_t e_nmax() const;
- template <typename Tag, typename Equiv>
- inline
- gen_id<Tag, Equiv>::gen_id()
- {
- }
+ /// Return whether \p id_e is in the graph.
+ bool has_e(unsigned id_e) const;
- template <typename Tag, typename Equiv>
- inline
- gen_id<Tag, Equiv>::gen_id(const Equiv& e)
- : e_ (e)
- {
- }
+ /// Return the first vertex associated to the edge \p id_e.
+ unsigned v1(unsigned id_e) const;
- template <typename Tag, typename Equiv>
- inline
- gen_id<Tag, Equiv>&
- gen_id<Tag, Equiv>::operator=(const Equiv& e)
- {
- e_ = e;
- return *this;
- }
-
- template <typename Tag, typename Equiv>
- inline
- const Equiv&
- gen_id<Tag, Equiv>::to_equiv() const
- {
- return e_;
- }
+ /// Return the second vertex associated to edge \p id_e
+ unsigned v2(unsigned id_e) const;
- template <typename Tag, typename Equiv>
- inline
- Equiv&
- gen_id<Tag, Equiv>::to_equiv()
- {
- return e_;
- }
+ /// Return the number max of adjacent edge, given an edge \p id_e.
+ size_t e_nmax_nbh_edges(unsigned id_e) const;
- template <typename Tag, typename Equiv>
- inline
- gen_id<Tag, Equiv>::operator const Equiv() const
- {
- return to_equiv();
- }
+ /// Return the \p i th edge adjacent to the edge \p id_e.
+ unsigned e_ith_nbh_edge(unsigned id_e, unsigned i) const;
- template <typename Tag, typename Equiv>
- inline
- gen_id<Tag, Equiv>::operator Equiv()
- {
- return to_equiv();
- }
+ /// \}
+ // FIXME: We might want to externalize this in routine of
+ // namespace mln::debug.
+ /** \brief Print on \p ostr the graph.
- template <typename Tag, typename Equiv>
- inline
- bool
- operator==(const gen_id<Tag, Equiv>& i, const gen_id<Tag, Equiv>& j)
- {
- return i.to_equiv() == j.to_equiv();
- }
+ \param[in] ostr The output stream. */
+ void print_debug(std::ostream& ostr) const;
- template <typename Tag, typename Equiv>
- inline
- bool
- operator==(const Equiv& i, const gen_id<Tag, Equiv>& j)
- {
- return i == j.to_equiv();
- }
- template <typename Tag, typename Equiv>
- inline
- bool
- operator==(const gen_id<Tag, Equiv>& i, const Equiv j)
- {
- return i.to_equiv() == j;
- }
+ protected:
- template <typename Tag, typename Equiv>
- inline
- bool
- ord_strict (const gen_id<Tag, Equiv>& i, const gen_id<Tag, Equiv>& j)
- {
- return i.to_equiv() < j.to_equiv();
- }
+ /// The vertices.
+ vertices_t vertices_;
+ /// The edges.
+ edges_t edges_;
+ /// An index of the set of edges, for fast-access purpose.
+ edges_set_t edges_set_;
- template <typename Tag, typename Equiv>
- inline
- bool
- ord_weak (const gen_id<Tag, Equiv>& i, const gen_id<Tag, Equiv>& j)
- {
- return i.to_equiv() <= j.to_equiv();
- }
+ /// Construction, assignments and destruction.
+ /// \{
+ graph_base<E>();
+ //graph_base<E>(const self_t& rhs);
+ //self_t& operator=(const self_t& rhs);
+ //~graph_base<E>();
+ /// \}
+ };
- /*---------------------.
- | Operators on edges. |
- `---------------------*/
+ } // end of namespace mln::util::internal
+ } // End of namespace mln::util
- template <typename E>
- inline
- bool
- operator==(const edge<E>& lhs, const edge<E>& rhs)
- {
- return lhs.pair_vertex_ == rhs.pair_vertex_;
- }
+# ifndef MLN_INCLUDE_ONLY
- template <typename E>
- inline
- bool
- operator< (const edge<E>& lhs, const edge<E>& rhs)
- {
- return lhs.pair_vertex_ < rhs.pair_vertex_;
- }
+ namespace util
+ {
namespace internal
{
@@ -447,194 +208,145 @@ namespace mln
| Construction, assignments and destruction. |
`--------------------------------------------*/
- template<typename V, typename E>
+ template<typename E>
inline
- graph_base<V, E>::graph_base()
+ graph_base<E>::graph_base()
: vertices_(), edges_(), edges_set_()
{
}
- template<typename V, typename E>
- inline
- graph_base<V, E>::graph_base(const graph_base<V, E>& rhs)
- : vertices_(), edges_(), edges_set_()
- {
- vertices_.reserve(rhs.vertices_.size());
- edges_.reserve(rhs.edges_.size());
- for (typename vertices_t::const_iterator v = rhs.vertices_.begin();
- v != rhs.vertices_.end(); ++v)
- vertices_.push_back(new util::vertex<V>(**v));
- for (typename edges_t::const_iterator e = rhs.edges_.begin();
- e != rhs.edges_.end(); ++e)
- edges_.push_back(new util::edge<E>(**e));
- std::copy(edges_.begin(), edges_.end(),
- std::insert_iterator<edges_set_t>(edges_set_,
- edges_set_.begin()));
- }
+ /*-------------.
+ | Misc methods |
+ `-------------*/
- template<typename V, typename E>
+ template<typename E>
inline
- graph_base<V, E>&
- graph_base<V, E>::operator=(const graph_base<V, E>& rhs)
+ const void * const
+ graph_base<E>::graph_id() const
{
- if (this != &rhs)
- {
- /// Free previous vertices and edges.
- for (typename vertices_t::iterator v = vertices_.begin();
- v != vertices_.end(); ++v)
- delete *v;
- for (typename edges_t::iterator e = edges_.begin();
- e != edges_.end(); ++e)
- delete *e;
- edges_set_.clear();
- /// Assign values from RHS.
- vertices_.reserve(rhs.vertices_.size());
- edges_.reserve(rhs.edges_.size());
- for (typename vertices_t::const_iterator v = rhs.vertices_.begin();
- v != rhs.vertices_.end(); ++v)
- vertices_.push_back(new util::vertex<V>(**v));
- for (typename edges_t::const_iterator e = rhs.edges_.begin();
- e != rhs.edges_.end(); ++e)
- edges_.push_back(new util::edge<E>(**e));
- std::copy(edges_.begin(), edges_.end(),
- std::insert_iterator<edges_set_t>(edges_set_,
- edges_set_.begin()));
- }
- return *this;
+ return this;
}
- template<typename V, typename E>
+ /*-------------------------.
+ | Vertex and edges related |
+ `-------------------------*/
+
+ template<typename E>
inline
- graph_base<V, E>::~graph_base()
+ unsigned
+ graph_base<E>::v_other(unsigned id_e, unsigned id_v) const
{
- for (typename vertices_t::iterator v = vertices_.begin();
- v != vertices_.end(); ++v)
- delete *v;
- for (typename edges_t::iterator e = edges_.begin(); e != edges_.end();
- ++e)
- delete *e;
- edges_set_.clear();
+ mln_precondition(has_e(id_e));
+ mln_precondition(has_v(id_v));
+ mln_precondition(edges_[id_e].first() == id_v
+ || edges_[id_e].second() == id_v);
+
+ const edge_data_t& e = edges_[id_e];
+ if (e.first() == id_v)
+ return e.second();
+ return e.first();
}
- /*------------.
- | Accessors. |
- `------------*/
+ /*---------------.
+ | Vertex related |
+ `---------------*/
- template<typename V, typename E>
+ template<typename E>
inline
- util::vertex<V>&
- graph_base<V, E>::vertex(vertex_id v)
+ unsigned
+ graph_base<E>::add_vertex()
{
- mln_assertion(v < this->nvertices());
- return *vertices_[v];
- }
+ /* FIXME: This is not thread-proof (these two lines should
+ form an atomic section). */
+ vertices_.resize(vertices_.size() + 1);
- template<typename V, typename E>
- inline
- const util::vertex<V>&
- graph_base<V, E>::vertex(vertex_id v) const
- {
- mln_assertion(v < this->nvertices());
- return *vertices_[v];
+ return vertices_.size() - 1;
}
- template<typename V, typename E>
+ template<typename E>
inline
- util::edge<E>&
- graph_base<V, E>::edge(edge_id e)
+ typename graph_base<E>::vertex_t
+ graph_base<E>::vertex(unsigned id_v) const
{
- mln_assertion(e < this->nedges());
- return *edges_[e];
- }
+ mln_assertion(has_v(id_v));
- template<typename V, typename E>
- inline
- const util::edge<E>&
- graph_base<V, E>::edge(edge_id e) const
- {
- mln_assertion(e < this->nedges());
- return *edges_[e];
+ return vertex_t(this, id_v);
}
- template<typename V, typename E>
+ template<typename E>
inline
- typename graph_base<V, E>::vertices_t&
- graph_base<V, E>::vertices()
+ size_t
+ graph_base<E>::v_nmax() const
{
- return vertices_;
+ return vertices_.size();
}
- template<typename V, typename E>
+ template<typename E>
inline
- const typename graph_base<V, E>::vertices_t&
- graph_base<V, E>::vertices() const
+ bool
+ graph_base<E>::has_v(unsigned id_v) const
{
- return vertices_;
+ return id_v < vertices_.size();
}
- template<typename V, typename E>
+ template<typename E>
inline
- typename graph_base<V, E>::edges_t&
- graph_base<V, E>::edges()
+ size_t
+ graph_base<E>::v_nmax_nbh_edges(unsigned id_v) const
{
- return edges_;
+ mln_precondition(has_v(id_v));
+
+ return vertices_[id_v].size();
}
- template<typename V, typename E>
+ template<typename E>
inline
- const typename graph_base<V, E>::edges_t&
- graph_base<V, E>::edges() const
+ unsigned
+ graph_base<E>::v_ith_nbh_edge(unsigned id_v, unsigned i) const
{
- return edges_;
+ mln_precondition(has_v(id_v));
+ if (i >= v_nmax_nbh_edges(id_v))
+ return v_nmax();
+
+ return vertices_[id_v][i];
}
- template<typename V, typename E>
+ template<typename E>
inline
size_t
- graph_base<V, E>::nvertices() const
+ graph_base<E>::v_nmax_nbh_vertices(unsigned id_v) const
{
- return vertices_.size();
+ mln_precondition(has_v(id_v));
+ return v_nmax_nbh_edges(id_v);
}
- template<typename V, typename E>
+ template<typename E>
inline
- size_t
- graph_base<V, E>::nedges() const
+ unsigned
+ graph_base<E>::v_ith_nbh_vertex(unsigned id_v, unsigned i) const
{
- return edges_.size();
+ mln_precondition(has_v(id_v));
+
+ unsigned id_e = v_ith_nbh_edge(id_v, i);
+ return v_other(id_e, id_v);
}
- /*---------------.
- | Manipulators. |
- `---------------*/
- template<typename V, typename E>
- inline
- vertex_id
- graph_base<V, E>::add_vertex_(util::vertex<V>* vertex)
- {
- /* FIXME: This is not thread-proof (these two lines should
- form an atomic section). */
- vertices_.push_back (vertex);
- return vertices_.size() - 1;
- }
+ /*--------------.
+ | Edges related |
+ `---------------*/
- template<typename V, typename E>
+ template<typename E>
inline
- edge_id
- graph_base<V, E>::add_edge_(util::edge<E>* edge)
+ unsigned
+ graph_base<E>::add_edge(unsigned id_v1, unsigned id_v2)
{
// Does this edge already exist in the graph?
+ edge_data_t edge(id_v1, id_v2);
if (edges_set_.find(edge) != edges_set_.end ())
{
- // Remove the previously allocated data for EDGE.
- delete edge;
- edge = 0;
// Return the erroneous value.
- /* FIXME: We have to explicitly extract the numerical
- equivalent type here, because mln::util::gen_id<T, E>
- is not compatible with Milena's value system (yet). */
- return mln_max(edge_id::equiv);
+ return mln_max(unsigned);
}
else
{
@@ -642,49 +354,121 @@ namespace mln
/* FIXME: This is not thread-proof (these two lines should
form an atomic section). */
edges_.push_back(edge);
- edge_id id = edges_.size() - 1;
+ unsigned id = edges_.size() - 1;
// Update the set of edges.
edges_set_.insert(edge);
- vertices_[edge->v1()]->edges.push_back(id);
- vertices_[edge->v2()]->edges.push_back(id);
+ vertices_[edge.first()].push_back(id);
+ vertices_[edge.second()].push_back(id);
return id;
}
}
+ template<typename E>
+ inline
+ const typename graph_base<E>::edge_t&
+ graph_base<E>::edge(unsigned e) const
+ {
+ mln_assertion(e < this->nedges());
+ return edge_t(this, edges_[e].first(), edges_[e].second());
+ }
+
+ template<typename E>
+ inline
+ size_t
+ graph_base<E>::e_nmax() const
+ {
+ return edges_.size();
+ }
+
+ template<typename E>
+ inline
+ bool
+ graph_base<E>::has_e(unsigned id_e) const
+ {
+ return id_e < edges_.size();
+ }
+
+ template<typename E>
+ inline
+ unsigned
+ graph_base<E>::v1(unsigned id_e) const
+ {
+ mln_precondition(has_e(id_e));
+ return edges_[id_e].first();
+ }
+
+ template<typename E>
+ inline
+ unsigned
+ graph_base<E>::v2(unsigned id_e) const
+ {
+ mln_precondition(has_e(id_e));
+ return edges_[id_e].second();
+ }
+
+ template<typename E>
+ inline
+ size_t
+ graph_base<E>::e_nmax_nbh_edges(unsigned id_e) const
+ {
+ mln_precondition(has_e(id_e));
+ return v_nmax_nbh_edges(v1(id_e)) + v_nmax_nbh_edges(v2(id_e));
+ }
+
+ template<typename E>
+ inline
+ unsigned
+ graph_base<E>::e_ith_nbh_edge(unsigned id_e, unsigned i) const
+ {
+ mln_precondition(has_e(id_e));
+ if (i >= e_nmax_nbh_edges(id_e))
+ return e_nmax();
+
+ unsigned v1_nmax = v_nmax_nbh_edges(v1(id_e));
+ if (i < v1_nmax)
+ return v_ith_nbh_edge(v1(id_e), i);
+ return v_ith_nbh_edge(v2(id_e), i - v1_nmax);
+ }
+
/*--------.
| Debug. |
`--------*/
- template<typename V, typename E>
+ template<typename E>
inline
void
- graph_base<V, E>::print_debug (std::ostream& ostr) const
+ graph_base<E>::print_debug (std::ostream& ostr) const
{
ostr << "graph: " << std::endl;
for (unsigned v = 0; v < vertices_.size(); ++v)
{
ostr << "vertex: " << v << std::endl << " -- adjacent vertices: ";
- /* FIXME: We shouldn't manipulate std::vector<edge_id>
- directly, but use a typedef instead. */
- for (typename std::vector<util::edge_id>::const_iterator e =
- vertices_[v]->edges.begin(); e != vertices_[v]->edges.end();
+ for (vertex_data_t::const_iterator e =
+ vertices_[v].begin(); e != vertices_[v].end();
++e)
- if (v == edges_[*e]->v1())
- ostr << edges_[*e]->v2() << " ";
+ if (v == edges_[*e].first())
+ ostr << edges_[*e].second() << " ";
else
- ostr << edges_[*e]->v1() << " ";
+ ostr << edges_[*e].first() << " ";
ostr << std::endl;
}
ostr << std::endl;
+
+ ostr << "edges:" << std::endl;
+ unsigned ei = 0;
+ for (edges_t::const_iterator e = edges_.begin(); e != edges_.end();
+ ++e, ++ei)
+ ostr << "edge " << ei << ": (" << e->first() << ", " << e->second() << " )" << std::endl;
}
} // end of namespace mln::util::internal
+ } // end of namespace mln::util
+
# endif // ! MLN_INCLUDE_ONLY
- } // end of namespace mln::util
} // end of namespace mln
diff --git a/milena/mln/util/internal/graph_edge.hh b/milena/mln/util/internal/graph_edge.hh
new file mode 100644
index 0000000..78a00c2
--- /dev/null
+++ b/milena/mln/util/internal/graph_edge.hh
@@ -0,0 +1,378 @@
+// 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.
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_UTIL_INTERNAL_GRAPH_EDGE_HH
+# define MLN_UTIL_INTERNAL_GRAPH_EDGE_HH
+
+/*! \file mln/util/internal/graph_edge.hh
+ * \brief Definition of a graph edge.
+ */
+
+namespace mln
+{
+
+ namespace util
+ {
+
+ /*-------.
+ | Edge. |
+ `-------*/
+
+ /// \brief Edge of a graph \p G.
+ template <typename G>
+ class edge
+ {
+ typedef mlc_const(G) graph_t;
+
+ public:
+ /// Constructors
+ /// \{
+ edge();
+ explicit edge(graph_t *g);
+ edge(graph_t *g, unsigned id);
+ /// \}
+
+
+
+ /// Misc.
+ /// \{
+ /// Return the edge id.
+ unsigned id() const;
+
+ /// Set \att id_ with \p id;
+ void update_id(unsigned id);
+
+ /// Return pointer of the graph holding this edge.
+ const graph_t * const g() const;
+ /// \}
+
+
+
+ /// Vertex and edges oriented.
+ /// \{
+ /// Return the vertex id of this edge which is different from \p id_v.
+ unsigned v_other(unsigned id_v) const;
+ /// \}
+
+
+ /// Edge oriented.
+ /// \{
+ bool is_valid() const;
+
+ /// Return the lowest vertex id adjacent to this edge.
+ unsigned v1() const;
+
+ /// Return the highest vertex id adjacent to this edge.
+ unsigned v2() const;
+
+ /// Return the number max of adjacent edges.
+ size_t nmax_nbh_edges() const;
+
+ /// Return the \p i th adjacent edge.
+ unsigned ith_nbh_edge(unsigned i) const;
+ /// \}
+
+ private:
+ graph_t * const g_;
+ unsigned id_;
+ };
+
+ template <typename G>
+ bool
+ operator==(const util::edge<G>& lhs, const util::edge<G>& rhs);
+
+ template <typename G>
+ bool
+ operator< (const util::edge<G>& lhs, const util::edge<G>& rhs);
+
+ } // End of namespace mln::util
+
+
+ /// subject_impl specialization (Proxy)
+ /// \{
+ namespace internal
+ {
+
+ template <typename G, typename E>
+ struct subject_impl< const util::edge<G>, E >
+ {
+ unsigned id() const;
+ const mlc_const(G) * const g() const;
+ unsigned v_other(unsigned id_v) const;
+ bool is_valid() const;
+ unsigned v1() const;
+ unsigned v2() const;
+ size_t nmax_nbh_edges() const;
+ unsigned ith_nbh_edge(unsigned i) const;
+
+
+ private:
+ const E& exact_() const;
+ };
+
+ template <typename G, typename E>
+ struct subject_impl< util::edge<G>, E > :
+ subject_impl< const util::edge<G>, E >
+ {
+ void update_id(unsigned id);
+
+ private:
+ E& exact_();
+ };
+
+ } // end of namespace mln::internal
+ /// \}
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ /*---------------------.
+ | Operators on edges. |
+ `---------------------*/
+
+ namespace util
+ {
+
+ template <typename G>
+ inline
+ edge<G>::edge()
+ : g_(0), id_(0)
+ {
+ }
+
+ template <typename G>
+ inline
+ edge<G>::edge(graph_t *g)
+ : g_(g), id_(g->e_nmax())
+ {
+ }
+
+ template <typename G>
+ inline
+ edge<G>::edge(graph_t *g, unsigned id)
+ : g_(g), id_(id)
+ {
+ mln_precondition(g->has_e(id));
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ edge<G>::id() const
+ {
+ return id_;
+ }
+
+ template <typename G>
+ inline
+ void
+ edge<G>::update_id(unsigned id)
+ {
+ id_ = id;
+ }
+
+ template <typename G>
+ inline
+ const typename edge<G>::graph_t * const
+ edge<G>::g() const
+ {
+ return g_;
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ edge<G>::v_other(unsigned id_v) const
+ {
+ mln_precondition(v1() == id_v || v2() == id_v);
+ return g_->v_other(id_, id_v);
+ }
+
+ template <typename G>
+ inline
+ bool
+ edge<G>::is_valid() const
+ {
+ return g_ != 0 && g_->has_e(id_);
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ edge<G>::v1() const
+ {
+ mln_precondition(g_->has_e(id_));
+ return g_->v1(id_);
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ edge<G>::v2() const
+ {
+ mln_precondition(g_->has_e(id_));
+ return g_->v2(id_);
+ }
+
+ template <typename G>
+ inline
+ size_t
+ edge<G>::nmax_nbh_edges() const
+ {
+ mln_precondition(g_->has_e(id_));
+ return g_->e_nmax_nbh_edges(id_);
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ edge<G>::ith_nbh_edge(unsigned i) const
+ {
+ mln_precondition(g_->has_e(id_));
+ return g_->e_ith_nbh_edge(id_, i);
+ }
+
+
+
+ template <typename G>
+ inline
+ bool
+ operator==(const util::edge<G>& lhs, const util::edge<G>& rhs)
+ {
+ return lhs.pair_vertex_ == rhs.pair_vertex_;
+ }
+
+ template <typename G>
+ inline
+ bool
+ operator< (const util::edge<G>& lhs, const util::edge<G>& rhs)
+ {
+ return lhs.pair_vertex_ < rhs.pair_vertex_;
+ }
+
+ } // end of namespace mln::util
+
+ namespace internal
+ {
+
+ /*----------------------------------`
+ | subject_impl< const util::edge<G> |
+ \----------------------------------*/
+
+ template <typename G, typename E>
+ inline
+ const E&
+ subject_impl< const util::edge<G>, E >::exact_() const
+ {
+ return internal::force_exact<const E>(*this);
+ }
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::edge<G>, E >::id() const
+ {
+ return exact_().get_subject().id();
+ }
+
+ template <typename G, typename E>
+ inline
+ const mlc_const(G) * const
+ subject_impl< const util::edge<G>, E >::g() const
+ {
+ return exact_().get_subject().g();
+ }
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::edge<G>, E >::v_other(unsigned id_v) const
+ {
+ return exact_().get_subject().v_other(id_v);
+ }
+
+ template <typename G, typename E>
+ inline
+ bool
+ subject_impl< const util::edge<G>, E >::is_valid() const
+ {
+ return exact_().get_subject().is_valid();
+ }
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::edge<G>, E >::v1() const
+ {
+ return exact_().get_subject().v1();
+ }
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::edge<G>, E >::v2() const
+ {
+ return exact_().get_subject().v2();
+ }
+
+ template <typename G, typename E>
+ inline
+ size_t
+ subject_impl< const util::edge<G>, E >::nmax_nbh_edges() const
+ {
+ return exact_().get_subject().nmax_nbh_edges();
+ }
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::edge<G>, E >::ith_nbh_edge(unsigned i) const
+ {
+ return exact_().get_subject().ith_nbh_edge(i);
+ }
+
+
+ /*----------------------------------`
+ | subject_impl< util::edge<G> |
+ \----------------------------------*/
+
+ template <typename G, typename E>
+ inline
+ void
+ subject_impl< util::edge<G>, E >::update_id(unsigned id)
+ {
+ return exact_().get_subject().update_id(id);
+ }
+
+ } // End of namespace mln::internal
+
+# endif // !MLN_INCLUDE_ONLY
+
+} // End of namespace mln
+
+#endif // !MLN_UTIL_INTERNAL_GRAPH_EDGE_HH
+
diff --git a/milena/mln/util/internal/graph_edge_iter.hh b/milena/mln/util/internal/graph_edge_iter.hh
new file mode 100644
index 0000000..9bcf9ff
--- /dev/null
+++ b/milena/mln/util/internal/graph_edge_iter.hh
@@ -0,0 +1,273 @@
+// 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_UTIL_INTERNAL_GRAPH_EDGE_ITER_HH
+# define MLN_UTIL_INTERNAL_GRAPH_EDGE_ITER_HH
+
+# include <mln/core/concept/iterator.hh>
+# include <mln/core/concept/proxy.hh>
+# include <mln/util/internal/graph_edge.hh>
+
+/// \file mln/util/internal/graph_edge_iter.hh
+/// \brief Implementation for graph edge iterators.
+
+namespace mln
+{
+
+ namespace internal
+ {
+
+ /// Forward edge iterator.
+ template <typename G>
+ class edge_fwd_iterator
+ : public Proxy< edge_fwd_iterator<G> >,
+ public internal::proxy_impl< const util::edge<G>&, edge_fwd_iterator<G> >
+ {
+ public:
+ /// Constructors.
+ /// \{
+ edge_fwd_iterator();
+ edge_fwd_iterator(const G& g);
+ /// \}
+
+ /// Iterator interface
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next();
+
+ /// Return current index
+ unsigned index() const;
+ /// \}
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const util::edge<G>& subj_();
+ /// \}
+
+ protected:
+ util::edge<G> e_;
+ };
+
+ template <typename G>
+ class edge_bkd_iterator
+ : public Proxy< edge_bkd_iterator<G> >,
+ public proxy_impl< const util::edge<G>&, edge_bkd_iterator<G> >
+ {
+ public:
+ /// Constructors.
+ /// \{
+ edge_bkd_iterator();
+ edge_bkd_iterator(const G& g);
+ /// \}
+
+ /// Iterator interface.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next();
+
+ /// Return current index
+ unsigned index() const;
+ /// \}
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const util::edge<G>& subj_();
+ /// \}
+
+ protected:
+ util::edge<G> e_;
+ };
+
+ } // End of namespace mln::internal
+
+} // End of namespace mln
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+namespace mln
+{
+
+ namespace internal
+ {
+
+ template <typename G>
+ inline
+ edge_fwd_iterator<G>::edge_fwd_iterator()
+ {
+ }
+
+ template <typename G>
+ inline
+ edge_fwd_iterator<G>::edge_fwd_iterator(const G& g)
+ : e_(util::edge<G>(&g))
+ {
+ invalidate();
+ }
+
+ template <typename G>
+ inline
+ bool
+ edge_fwd_iterator<G>::is_valid() const
+ {
+ return e_.is_valid();
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_fwd_iterator<G>::invalidate()
+ {
+ e_.update_id(e_.g()->e_nmax());
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_fwd_iterator<G>::start()
+ {
+ e_.update_id(0);
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_fwd_iterator<G>::next()
+ {
+ e_.update_id(e_.id() + 1);
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ edge_fwd_iterator<G>::index() const
+ {
+ return e_.id();
+ }
+
+ template <typename G>
+ inline
+ const util::edge<G>&
+ edge_fwd_iterator<G>::subj_()
+ {
+ return e_;
+ }
+
+
+
+ /*------------------`
+ | edge_bkd_iterator |
+ \------------------*/
+
+ template <typename G>
+ inline
+ edge_bkd_iterator<G>::edge_bkd_iterator()
+ {
+ }
+
+ template <typename G>
+ inline
+ edge_bkd_iterator<G>::edge_bkd_iterator(const G& g)
+ : e_(util::edge<G>(&g))
+ {
+ invalidate();
+ }
+
+ template <typename G>
+ inline
+ bool
+ edge_bkd_iterator<G>::is_valid() const
+ {
+ return e_.is_valid();
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_bkd_iterator<G>::invalidate()
+ {
+ e_.update_id(e_.g()->e_nmax());
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_bkd_iterator<G>::start()
+ {
+ e_.update_id(e_.g()->e_nmax() - 1);
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_bkd_iterator<G>::next()
+ {
+ e_.update_id(e_.id() - 1);
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ edge_bkd_iterator<G>::index() const
+ {
+ return e_.id();
+ }
+
+ template <typename G>
+ inline
+ const util::edge<G>&
+ edge_bkd_iterator<G>::subj_()
+ {
+ return e_;
+ }
+
+ } // End of namespace mln::internal
+
+} // End of namespace mln
+
+# endif // !MLN_INCLUDE_ONLY
+
+#endif // !MLN_UTIL_INTERNAL_GRAPH_EDGE_ITER_HH
+
diff --git a/milena/mln/util/internal/graph_edge_nbh_edge_iter.hh b/milena/mln/util/internal/graph_edge_nbh_edge_iter.hh
new file mode 100644
index 0000000..084ad23
--- /dev/null
+++ b/milena/mln/util/internal/graph_edge_nbh_edge_iter.hh
@@ -0,0 +1,335 @@
+// 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_UTIL_INTERNAL_GRAPH_EDGE_NBH_EDGE_ITER_HH
+# define MLN_UTIL_INTERNAL_GRAPH_EDGE_NBH_EDGE_ITER_HH
+
+# include <mln/core/concept/proxy.hh>
+
+/// \file mln/util/internal/graph_edge_nbh_edge_iter.hh
+/// \brief Implementation for graph edge iterators centered to an edge.
+
+namespace mln
+{
+
+ namespace internal
+ {
+
+ template <typename G>
+ class edge_nbh_edge_fwd_iterator
+ : public Proxy< edge_nbh_edge_fwd_iterator<G> >,
+ public internal::proxy_impl< const util::edge<G>&, edge_nbh_edge_fwd_iterator<G> >
+ {
+ public:
+ /// Construction and assignment.
+ /// \{
+ template <typename C>
+ edge_nbh_edge_fwd_iterator(const C& c);
+ /// \}
+
+ /// Iterator interface.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next();
+
+ /// Return current index
+ unsigned index() const;
+ /// \}
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const util::edge<G>& subj_();
+ /// \}
+
+ protected:
+ void update_();
+
+ template <typename C>
+ void center_at(const C& c);
+
+
+ const util::edge<G>* c_; //Center
+ util::edge<G> e_;
+ unsigned i_;
+ };
+
+ template <typename G>
+ class edge_nbh_edge_bkd_iterator
+ : public Proxy< edge_nbh_edge_bkd_iterator<G> >,
+ public proxy_impl< const util::edge<G>&, edge_nbh_edge_bkd_iterator<G> >
+ {
+ public:
+ /// Construction and assignment.
+ /// \{
+ template <typename C>
+ edge_nbh_edge_bkd_iterator(const C& e);
+ /// \}
+
+ /// Iterator interface.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next();
+
+ /// Return current index
+ unsigned index() const;
+ /// \}
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const util::edge<G>& subj_();
+ /// \}
+
+ protected:
+ void update_();
+
+ template <typename C>
+ void center_at(const C& c);
+
+ const util::edge<G>* c_; //Center
+ util::edge<G> e_;
+ unsigned i_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename G>
+ template <typename C>
+ inline
+ edge_nbh_edge_fwd_iterator<G>::edge_nbh_edge_fwd_iterator(const C& c)
+ : e_(c.g()), i_(0)
+ {
+ //FIXME: Check if typeof(e.g()) == G
+ center_at(c);
+ }
+
+ template <typename G>
+ inline
+ bool
+ edge_nbh_edge_fwd_iterator<G>::is_valid() const
+ {
+ return i_ < c_->nmax_nbh_edges();
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_nbh_edge_fwd_iterator<G>::invalidate()
+ {
+ i_ = e_.g()->e_nmax();
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_nbh_edge_fwd_iterator<G>::start()
+ {
+ i_ = 0;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_nbh_edge_fwd_iterator<G>::next()
+ {
+ ++i_;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ edge_nbh_edge_fwd_iterator<G>::index() const
+ {
+ return i_;
+ }
+
+ template <typename G>
+ inline
+ const util::edge<G>&
+ edge_nbh_edge_fwd_iterator<G>::subj_()
+ {
+ return e_;
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_nbh_edge_fwd_iterator<G>::update_()
+ {
+ mln_precondition(is_valid());
+ mln_precondition(c_->is_valid());
+
+ // We shall encounter vertices which are part of the
+ // current edge.
+ // We do not want them to be part of the edge neighbors.
+ unsigned e_id = c_->ith_nbh_edge(i_);
+ while (e_id == c_->id())
+ e_id = c_->ith_nbh_edge(++i_);
+
+ e_.update_id(e_id);
+ }
+
+ template <typename G>
+ template <typename E>
+ inline
+ void
+ edge_nbh_edge_fwd_iterator<G>::center_at(const E& c)
+ {
+ internal::get_adr(c_, c);
+ mln_precondition(c_ != 0);
+
+ invalidate();
+ }
+
+
+
+ /*---------------------------`
+ | edge_nbh_edge_bkd_iterator |
+ \---------------------------*/
+
+ template <typename G>
+ template <typename C>
+ inline
+ edge_nbh_edge_bkd_iterator<G>::edge_nbh_edge_bkd_iterator(const C& c)
+ : e_(c.g()), i_(0)
+ {
+ //FIXME: Check if typeof(e.g()) == G
+ center_at(c);
+ }
+
+ template <typename G>
+ inline
+ bool
+ edge_nbh_edge_bkd_iterator<G>::is_valid() const
+ {
+ return i_ < c_->nmax_nbh_edges();
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_nbh_edge_bkd_iterator<G>::invalidate()
+ {
+ i_ = e_.g()->e_nmax();
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_nbh_edge_bkd_iterator<G>::start()
+ {
+ i_ = c_->nmax_nbh_edges() - 1;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_nbh_edge_bkd_iterator<G>::next()
+ {
+ --i_;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ edge_nbh_edge_bkd_iterator<G>::index() const
+ {
+ return i_;
+ }
+
+ template <typename G>
+ inline
+ const util::edge<G>&
+ edge_nbh_edge_bkd_iterator<G>::subj_()
+ {
+ return e_;
+ }
+
+ template <typename G>
+ inline
+ void
+ edge_nbh_edge_bkd_iterator<G>::update_()
+ {
+ mln_precondition(is_valid());
+ mln_precondition(c_->is_valid());
+
+ // We shall encounter vertices which are part of the
+ // current edge.
+ // We do not want them to be part of the edge neighbors.
+ unsigned e_id = c_->ith_nbh_edge(i_);
+ while (e_id == c_->id())
+ e_id = c_->ith_nbh_edge(--i_);
+
+ e_.update_id(e_id);
+ }
+
+ template <typename G>
+ template <typename E>
+ inline
+ void
+ edge_nbh_edge_bkd_iterator<G>::center_at(const E& c)
+ {
+ internal::get_adr(c_, c);
+ mln_precondition(c_ != 0);
+
+ invalidate();
+ }
+# endif // !MLN_INCLUDE_ONLY
+
+ } // End of namespace mln::internal
+
+} // End of namespace mln
+
+
+#endif // !MLN_UTIL_INTERNAL_GRAPH_EDGE_NBH_EDGE_ITER_HH
+
diff --git a/milena/mln/util/internal/graph_vertex.hh b/milena/mln/util/internal/graph_vertex.hh
new file mode 100644
index 0000000..c40bf0f
--- /dev/null
+++ b/milena/mln/util/internal/graph_vertex.hh
@@ -0,0 +1,361 @@
+// 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.
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_UTIL_INTERNAL_GRAPH_VERTEX_HH
+# define MLN_UTIL_INTERNAL_GRAPH_VERTEX_HH
+
+/// \file mln/util/internal/graph_vertex.hh
+/// \brief Implementation of a graph vertex.
+
+namespace mln
+{
+
+ namespace util
+ {
+
+ /// \brief Vertex of a graph \p G.
+ template<typename G>
+ class vertex
+ {
+ typedef mlc_const(G) graph_t;
+
+ public:
+
+ /// Constructors.
+ /// \{
+ vertex();
+ explicit vertex(graph_t *g);
+ vertex(graph_t *g, unsigned id);
+ /// \}
+
+ /// Check whether the vertex is still part of the graph.
+ bool is_valid() const;
+
+ unsigned other(unsigned id_e) const;
+
+ /// Returns the ith edge starting from this vertex.
+ unsigned ith_nbh_edge(unsigned i) const;
+
+ /// Returns the number max of edges starting from this vertex.
+ /// If g_ is a sub graph of another graph, nmax will be retrived from
+ /// the initial graph.
+ unsigned nmax_nbh_edges() const;
+
+ /// Returns the ith vertex adjacent to this vertex.
+ unsigned ith_nbh_vertex(unsigned i) const;
+
+ /// Returns the number max of vertices adjacent to this vertex.
+ unsigned nmax_nbh_vertices() const;
+
+ /// Change the parent graph of that vertex.
+ void change_graph(const G& g);
+
+ /// Update vertex id.
+ void update_id(unsigned id);
+
+ /// Returns the graph pointer this vertex belongs to.
+ const graph_t * const g() const;
+
+ /// Returns vertex id.
+ unsigned id() const;
+
+ private:
+ graph_t * const g_;
+ unsigned id_;
+ };
+
+ } // End of namespace mln::util
+
+
+/// subject_impl specialization (Proxy)
+/// \{
+ namespace internal
+ {
+ template <typename G, typename E>
+ struct subject_impl< const util::vertex<G>, E >
+ {
+ bool is_valid() const;
+ const mlc_const(G) * const g() const;
+ unsigned id() const;
+
+ unsigned other(unsigned id_e) const;
+ unsigned ith_nbh_edge(unsigned i) const;
+ unsigned nmax_nbh_edges() const;
+ unsigned ith_nbh_vertex(unsigned i) const;
+ unsigned nmax_nbh_vertices() const;
+
+ private:
+ const E& exact_() const;
+ };
+
+ template <typename G, typename E>
+ struct subject_impl< util::vertex<G>, E > :
+ subject_impl< const util::vertex<G>, E >
+ {
+ void change_graph(const G& g);
+ void update_id(unsigned id);
+
+ private:
+ E& exact_();
+ };
+
+ } // end of namespace mln::internal
+
+} // End of namespace mln
+/// \}
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+namespace mln
+{
+
+ namespace util
+ {
+
+ template <typename G>
+ inline
+ vertex<G>::vertex()
+ : g_(0), id_(0)
+ {
+ }
+
+ template <typename G>
+ inline
+ vertex<G>::vertex(graph_t *g)
+ : g_(g), id_(g_->v_nmax())
+ {
+ }
+
+ template<typename G>
+ inline
+ vertex<G>::vertex(graph_t *g, unsigned id)
+ : g_(g), id_(id)
+ {
+ mln_precondition(g_->has_v(id));
+ }
+
+ template<typename G>
+ inline
+ bool
+ vertex<G>::is_valid() const
+ {
+ return g_ != 0 && g_->has_v(id_);
+ }
+
+ template<typename G>
+ inline
+ unsigned
+ vertex<G>::other(unsigned id_e) const
+ {
+ mln_precondition(g_->has_v(id_));
+ mln_precondition(g_->has_e(id_e));
+ mln_precondition(g_->v1(id_e) == id_ || g_->v2(id_e) == id_);
+ return g_->v_other(id_e, id_);
+ }
+
+ template<typename G>
+ inline
+ unsigned
+ vertex<G>::ith_nbh_edge(unsigned i) const
+ {
+ mln_precondition(g_->has_v(id_));
+ return g_->v_ith_nbh_edge(id_, i);
+ }
+
+ template<typename G>
+ inline
+ unsigned
+ vertex<G>::nmax_nbh_edges() const
+ {
+ mln_precondition(g_->has_v(id_));
+ return g_->v_nmax_nbh_edges(id_);
+ }
+
+ template<typename G>
+ inline
+ unsigned
+ vertex<G>::ith_nbh_vertex(unsigned i) const
+ {
+ mln_precondition(g_->has_v(id_));
+ return g_->v_ith_nbh_vertex(id_, i);
+ }
+
+ template<typename G>
+ inline
+ unsigned
+ vertex<G>::nmax_nbh_vertices() const
+ {
+ mln_precondition(g_->has_v(id_));
+ return g_->v_nmax_nbh_vertices(id_);
+ }
+
+ template<typename G>
+ inline
+ void
+ vertex<G>::change_graph(const G& g)
+ {
+ mln_precondition(g_->has_v(id_));
+ g_ = &g;
+ }
+
+ template<typename G>
+ inline
+ void
+ vertex<G>::update_id(unsigned id)
+ {
+ id_ = id;
+ }
+
+ template<typename G>
+ inline
+ const typename vertex<G>::graph_t * const
+ vertex<G>::g() const
+ {
+ return g_;
+ }
+
+ template<typename G>
+ inline
+ unsigned
+ vertex<G>::id() const
+ {
+ return id_;
+ }
+
+ } // end of namespace mln::util
+
+ namespace internal
+ {
+
+ template <typename G, typename E>
+ inline
+ const E&
+ subject_impl< const util::vertex<G>, E >::exact_() const
+ {
+ return internal::force_exact<const E>(*this);
+ }
+
+ template <typename G, typename E>
+ inline
+ bool
+ subject_impl< const util::vertex<G>, E >::is_valid() const
+ {
+ return exact_().get_subject().is_valid();
+ }
+
+ template <typename G, typename E>
+ inline
+ const mlc_const(G)* const
+ subject_impl< const util::vertex<G>, E >::g() const
+ {
+ return exact_().get_subject().g();
+ }
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::vertex<G>, E >::id() const
+ {
+ return exact_().get_subject().id();
+ };
+
+
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::vertex<G>, E >::other(unsigned id_e) const
+ {
+ return exact_().get_subject().other(id_e);
+ }
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::vertex<G>, E >::ith_nbh_edge(unsigned i) const
+ {
+ return exact_().get_subject().ith_nbh_edge(i);
+ }
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::vertex<G>, E >::nmax_nbh_edges() const
+ {
+ return exact_().get_subject().nmax_nbh_edges();
+ }
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::vertex<G>, E >::ith_nbh_vertex(unsigned i) const
+ {
+ return exact_().get_subject().ith_nbh_vertex(i);
+ }
+
+ template <typename G, typename E>
+ inline
+ unsigned
+ subject_impl< const util::vertex<G>, E >::nmax_nbh_vertices() const
+ {
+ return exact_().get_subject().nmax_nbh_vertices();
+ }
+
+ template <typename G, typename E>
+ inline
+ E&
+ subject_impl< util::vertex<G>, E >::exact_()
+ {
+ return internal::force_exact<E>(*this);
+ }
+
+ template <typename G, typename E>
+ inline
+ void
+ subject_impl< util::vertex<G>, E >::change_graph(const G& g)
+ {
+ exact_().get_subject().change_graph(g);
+ }
+
+ template <typename G, typename E>
+ inline
+ void
+ subject_impl< util::vertex<G>, E >::update_id(unsigned id)
+ {
+ exact_().get_subject().update_id(id);
+ };
+
+ } // end of namespace mln::internal
+
+} // End of namespace mln
+
+# endif // !MLN_INCLUDE_ONLY
+
+
+#endif // !MLN_UTIL_INTERNAL_GRAPH_VERTEX_HH
+
diff --git a/milena/mln/util/internal/graph_vertex_iter.hh b/milena/mln/util/internal/graph_vertex_iter.hh
new file mode 100644
index 0000000..9d2f3df
--- /dev/null
+++ b/milena/mln/util/internal/graph_vertex_iter.hh
@@ -0,0 +1,266 @@
+// 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_UTIL_INTERNAL_GRAPH_VERTEX_ITER_HH
+# define MLN_UTIL_INTERNAL_GRAPH_VERTEX_ITER_HH
+
+# include <mln/metal/const.hh>
+# include <mln/core/concept/iterator.hh>
+# include <mln/core/concept/proxy.hh>
+# include <mln/util/internal/graph_base.hh>
+
+/// \file mln/util/internal/graph_vertex_iter.hh
+/// \brief Implementation for graph vertex iterators.
+
+namespace mln
+{
+
+ namespace internal
+ {
+
+ template<typename G>
+ class vertex_fwd_iterator
+ : public Proxy< vertex_fwd_iterator<G> >,
+ public proxy_impl< const util::vertex<G>&, vertex_fwd_iterator<G> >
+ {
+ public:
+ /// Constructors.
+ /// \{
+ vertex_fwd_iterator();
+ vertex_fwd_iterator(const G& g);
+ /// \}
+
+ /// Iterator interface.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next();
+
+ /// Return current index
+ unsigned index() const;
+ /// \}
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const util::vertex<G>& subj_();
+ /// \}
+
+ protected:
+ util::vertex<G> v_;
+ };
+
+ template<typename G>
+ class vertex_bkd_iterator
+ : public Proxy< vertex_bkd_iterator<G> >,
+ public proxy_impl< const util::vertex<G>&, vertex_fwd_iterator<G> >
+ {
+ public:
+ /// Constructors.
+ /// \{
+ vertex_bkd_iterator();
+ vertex_bkd_iterator(const G& g);
+ /// \}
+
+ /// Iterator interface.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next();
+
+ /// Return current index
+ unsigned index() const;
+ /// \}
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const util::vertex<G>& subj_();
+ /// \}
+
+ protected:
+ util::vertex<G> v_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ /*--------------------`
+ | vertex_fwd_iterator |
+ \--------------------*/
+
+ template<typename G>
+ inline
+ vertex_fwd_iterator<G>::vertex_fwd_iterator()
+ {
+ }
+
+ template<typename G>
+ inline
+ vertex_fwd_iterator<G>::vertex_fwd_iterator(const G& g)
+ : v_(util::vertex<G>(&g))
+ {
+ invalidate();
+ }
+
+ template<typename G>
+ inline
+ bool
+ vertex_fwd_iterator<G>::is_valid() const
+ {
+ return v_.is_valid();
+ }
+
+ template<typename G>
+ inline
+ void
+ vertex_fwd_iterator<G>::invalidate()
+ {
+ v_.update_id(v_.g()->v_nmax());
+ }
+
+ template<typename G>
+ inline
+ void
+ vertex_fwd_iterator<G>::start()
+ {
+ v_.update_id(0);
+ }
+
+ template<typename G>
+ inline
+ void
+ vertex_fwd_iterator<G>::next()
+ {
+ v_.update_id(v_.id() + 1);
+ }
+
+ template<typename G>
+ inline
+ unsigned
+ vertex_fwd_iterator<G>::index() const
+ {
+ return v_.id();
+ }
+
+ template<typename G>
+ inline
+ const util::vertex<G>&
+ vertex_fwd_iterator<G>::subj_()
+ {
+ return v_;
+ }
+
+
+ /*--------------------`
+ | vertex_bkd_iterator |
+ \--------------------*/
+
+ template<typename G>
+ inline
+ vertex_bkd_iterator<G>::vertex_bkd_iterator()
+ {
+ }
+
+ template<typename G>
+ inline
+ vertex_bkd_iterator<G>::vertex_bkd_iterator(const G& g)
+ : v_(util::vertex<G>(&g))
+ {
+ invalidate();
+ }
+
+ template<typename G>
+ inline
+ bool
+ vertex_bkd_iterator<G>::is_valid() const
+ {
+ return v_.is_valid();
+ }
+
+ template<typename G>
+ inline
+ void
+ vertex_bkd_iterator<G>::invalidate()
+ {
+ v_.update_id(v_.g()->v_nmax());
+ }
+
+ template<typename G>
+ inline
+ void
+ vertex_bkd_iterator<G>::start()
+ {
+ v_.update_id(v_.g()->v_nmax() - 1);
+ }
+
+ template<typename G>
+ inline
+ void
+ vertex_bkd_iterator<G>::next()
+ {
+ v_.update_id(v_.id() - 1);
+ }
+
+ template<typename G>
+ inline
+ unsigned
+ vertex_bkd_iterator<G>::index() const
+ {
+ return v_.id();
+ }
+
+ template<typename G>
+ inline
+ const util::vertex<G>&
+ vertex_bkd_iterator<G>::subj_()
+ {
+ return v_;
+ }
+# endif // !MLN_INCLUDE_ONLY
+
+ } // End of namespace mln::internal
+
+} // End of namespace mln
+
+
+#endif // !MLN_UTIL_INTERNAL_GRAPH_VERTEX_ITER_HH
+
diff --git a/milena/mln/util/internal/graph_vertex_nbh_edge_iter.hh b/milena/mln/util/internal/graph_vertex_nbh_edge_iter.hh
new file mode 100644
index 0000000..4edc652
--- /dev/null
+++ b/milena/mln/util/internal/graph_vertex_nbh_edge_iter.hh
@@ -0,0 +1,323 @@
+// 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_UTIL_INTERNAL_GRAPH_VERTEX_NBH_EDGE_ITER_HH
+# define MLN_UTIL_INTERNAL_GRAPH_VERTEX_NBH_EDGE_ITER_HH
+
+# include <mln/core/concept/proxy.hh>
+
+/// \file mln/util/internal/graph_vertex_nbh_edge_iter.hh
+/// \brief Implementation for graph edge iterators centered to a vertex.
+
+namespace mln
+{
+
+ namespace internal
+ {
+
+ template <typename G>
+ class vertex_nbh_edge_fwd_iterator
+ : public Proxy< vertex_nbh_edge_fwd_iterator<G> >,
+ public internal::proxy_impl< const util::edge<G>&, vertex_nbh_edge_fwd_iterator<G> >
+ {
+ public:
+ /// Construction and assignment.
+ /// \{
+ template <typename C>
+ vertex_nbh_edge_fwd_iterator(const C& c);
+ /// \}
+
+ /// Iterator interface.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next();
+
+ /// Return current index
+ unsigned index() const;
+ /// \}
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const util::edge<G>& subj_();
+ /// \}
+
+ protected:
+ void update_();
+
+ template <typename C>
+ void center_at(const C& c);
+
+ const util::vertex<G>* c_; // Center
+ util::edge<G> e_;
+ unsigned i_;
+ };
+
+ template <typename G>
+ class vertex_nbh_edge_bkd_iterator
+ : public Proxy< vertex_nbh_edge_bkd_iterator<G> >,
+ public proxy_impl< const util::edge<G>&, vertex_nbh_edge_bkd_iterator<G> >
+ {
+ public:
+ /// Constructors.
+ /// \{
+ template <typename C>
+ vertex_nbh_edge_bkd_iterator(const C& c);
+ /// \}
+
+ /// Iterator interface.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next();
+
+ /// Return current index
+ unsigned index() const;
+ /// \}
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const util::edge<G>& subj_();
+ /// \}
+
+ protected:
+ void update_();
+
+ template <typename C>
+ void center_at(const C& c);
+
+ const util::vertex<G>* c_; //Center
+ util::edge<G> e_;
+ unsigned i_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename G>
+ template <typename C>
+ inline
+ vertex_nbh_edge_fwd_iterator<G>::vertex_nbh_edge_fwd_iterator(const C& c)
+ : e_(c.g()), i_(0)
+ {
+ //FIXME: Check if typeof(v.g()) == G
+ center_at(c);
+ }
+
+ template <typename G>
+ inline
+ bool
+ vertex_nbh_edge_fwd_iterator<G>::is_valid() const
+ {
+ return i_ < c_->nmax_nbh_edges();
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_edge_fwd_iterator<G>::invalidate()
+ {
+ i_ = e_.g()->e_nmax();
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_edge_fwd_iterator<G>::start()
+ {
+ i_ = 0;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_edge_fwd_iterator<G>::next()
+ {
+ ++i_;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ vertex_nbh_edge_fwd_iterator<G>::index() const
+ {
+ return i_;
+ }
+
+ template <typename G>
+ inline
+ const util::edge<G>&
+ vertex_nbh_edge_fwd_iterator<G>::subj_()
+ {
+ return e_;
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_edge_fwd_iterator<G>::update_()
+ {
+ mln_precondition(is_valid());
+ mln_precondition(c_->is_valid());
+ e_.update_id(c_->ith_nbh_edge(i_));
+ }
+
+ template <typename G>
+ template <typename C>
+ inline
+ void
+ vertex_nbh_edge_fwd_iterator<G>::center_at(const C& c)
+ {
+ internal::get_adr(c_, c);
+ mln_precondition(c_ != 0);
+
+ invalidate();
+ }
+
+
+
+
+ /*-----------------------------`
+ | vertex_nbh_edge_bkd_iterator |
+ \-----------------------------*/
+
+
+ template <typename G>
+ template <typename C>
+ inline
+ vertex_nbh_edge_bkd_iterator<G>::vertex_nbh_edge_bkd_iterator(const C& c)
+ : e_(c.g()), i_(0)
+ {
+ //FIXME: Check if typeof(v.g()) == G
+ center_at(c);
+ }
+
+ template <typename G>
+ inline
+ bool
+ vertex_nbh_edge_bkd_iterator<G>::is_valid() const
+ {
+ return i_ < c_->nmax_nbh_edges();
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_edge_bkd_iterator<G>::invalidate()
+ {
+ e_.update_id(e_.g()->e_nmax());
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_edge_bkd_iterator<G>::start()
+ {
+ i_ = c_->nmax_nbh_edges() - 1;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_edge_bkd_iterator<G>::next()
+ {
+ --i_;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ vertex_nbh_edge_bkd_iterator<G>::index() const
+ {
+ return i_;
+ }
+
+ template <typename G>
+ inline
+ const util::edge<G>&
+ vertex_nbh_edge_bkd_iterator<G>::subj_()
+ {
+ return e_;
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_edge_bkd_iterator<G>::update_()
+ {
+ mln_precondition(is_valid());
+ mln_precondition(c_->is_valid());
+ e_.update_id(c_->ith_nbh_edge(i_));
+ }
+
+ template <typename G>
+ template <typename C>
+ inline
+ void
+ vertex_nbh_edge_bkd_iterator<G>::center_at(const C& c)
+ {
+ internal::get_adr(c_, c);
+ mln_precondition(c_ != 0);
+
+ invalidate();
+ }
+
+
+
+# endif // !MLN_INCLUDE_ONLY
+
+ } // End of namespace mln::internal
+
+} // End of namespace mln
+
+
+#endif // !MLN_UTIL_INTERNAL_GRAPH_NBH_EDGE_ITER_HH
+
diff --git a/milena/mln/util/internal/graph_vertex_nbh_vertex_iter.hh b/milena/mln/util/internal/graph_vertex_nbh_vertex_iter.hh
new file mode 100644
index 0000000..d51bc29
--- /dev/null
+++ b/milena/mln/util/internal/graph_vertex_nbh_vertex_iter.hh
@@ -0,0 +1,320 @@
+// 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_UTIL_INTERNAL_GRAPH_VERTEX_NBH_VERTEX_ITER_HH
+# define MLN_UTIL_INTERNAL_GRAPH_VERTEX_NBH_VERTEX_ITER_HH
+
+# include <mln/core/concept/proxy.hh>
+
+/// \file mln/util/internal/graph_vertex_nbh_vertex_iter.hh
+/// \brief Implementation for graph vertex iterators centered to a vertex.
+
+namespace mln
+{
+
+ namespace internal
+ {
+
+ template <typename G>
+ class vertex_nbh_vertex_fwd_iterator
+ : public Proxy< vertex_nbh_vertex_fwd_iterator<G> >,
+ public internal::proxy_impl< const util::vertex<G>&, vertex_nbh_vertex_fwd_iterator<G> >
+ {
+ public:
+ /// Construction and assignment.
+ /// \{
+ template <typename C>
+ vertex_nbh_vertex_fwd_iterator(const C& c);
+ /// \}
+
+ /// Manipulation.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+ /// \}
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next();
+
+ /// Return current index
+ unsigned index() const;
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const util::vertex<G>& subj_();
+ /// \}
+
+ protected:
+ void update_();
+
+ template <typename C>
+ void center_at(const C& c);
+
+ const util::vertex<G>* c_;
+ util::vertex<G> v_;
+ unsigned i_;
+ };
+
+ template <typename G>
+ class vertex_nbh_vertex_bkd_iterator
+ : public Proxy< vertex_nbh_vertex_bkd_iterator<G> >,
+ public proxy_impl< const util::vertex<G>&, vertex_nbh_vertex_fwd_iterator<G> >
+ {
+ public:
+ /// Constructors.
+ /// \{
+ template <typename C>
+ vertex_nbh_vertex_bkd_iterator(const C& v);
+ /// \}
+
+ /// Manipulation.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next value.
+ void next();
+
+ /// Return current index
+ unsigned index() const;
+ /// \}
+
+ /// Proxy.
+ /// \{
+ /// Proxy subject
+ const util::vertex<G>& subj_();
+ /// \}
+
+ protected:
+ void update_();
+
+ template <typename C>
+ void center_at(const C& c);
+
+ const util::vertex<G>* c_; //Center
+ util::vertex<G> v_;
+ unsigned i_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename G>
+ template <typename C>
+ inline
+ vertex_nbh_vertex_fwd_iterator<G>::vertex_nbh_vertex_fwd_iterator(const C& c)
+ : v_(c.g()), i_(0)
+ {
+ //FIXME: Check if typeof(v.g()) == G
+ center_at(c);
+ }
+
+ template <typename G>
+ inline
+ bool
+ vertex_nbh_vertex_fwd_iterator<G>::is_valid() const
+ {
+ return i_ < c_->nmax_nbh_vertices();
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_vertex_fwd_iterator<G>::invalidate()
+ {
+ i_ = v_.g()->v_nmax();
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_vertex_fwd_iterator<G>::start()
+ {
+ i_ = 0;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_vertex_fwd_iterator<G>::next()
+ {
+ ++i_;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ vertex_nbh_vertex_fwd_iterator<G>::index() const
+ {
+ return i_;
+ }
+
+ template <typename G>
+ inline
+ const util::vertex<G>&
+ vertex_nbh_vertex_fwd_iterator<G>::subj_()
+ {
+ return v_;
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_vertex_fwd_iterator<G>::update_()
+ {
+ mln_precondition(is_valid());
+ mln_precondition(c_->is_valid());
+ v_.update_id(c_->ith_nbh_vertex(i_));
+ }
+
+ template <typename G>
+ template <typename C>
+ inline
+ void
+ vertex_nbh_vertex_fwd_iterator<G>::center_at(const C& c)
+ {
+ internal::get_adr(c_, c);
+ mln_precondition(c_ != 0);
+
+ invalidate();
+ }
+
+
+ /*-------------------------------`
+ | vertex_nbh_vertex_bkd_iterator |
+ \-------------------------------*/
+
+
+ template <typename G>
+ template <typename C>
+ inline
+ vertex_nbh_vertex_bkd_iterator<G>::vertex_nbh_vertex_bkd_iterator(const C& c)
+ : v_(c.g()), i_(0)
+ {
+ //FIXME: Check if typeof(v.g()) == G
+ center_at(c);
+ }
+
+ template <typename G>
+ inline
+ bool
+ vertex_nbh_vertex_bkd_iterator<G>::is_valid() const
+ {
+ return i_ < c_->nmax_nbh_vertices();
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_vertex_bkd_iterator<G>::invalidate()
+ {
+ v_.update_id(v_.g()->e_nmax());
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_vertex_bkd_iterator<G>::start()
+ {
+ i_ = c_->nmax_nbh_edges() - 1;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_vertex_bkd_iterator<G>::next()
+ {
+ --i_;
+ if (is_valid())
+ update_();
+ }
+
+ template <typename G>
+ inline
+ unsigned
+ vertex_nbh_vertex_bkd_iterator<G>::index() const
+ {
+ return i_;
+ }
+
+ template <typename G>
+ inline
+ const util::vertex<G>&
+ vertex_nbh_vertex_bkd_iterator<G>::subj_()
+ {
+ return v_;
+ }
+
+ template <typename G>
+ inline
+ void
+ vertex_nbh_vertex_bkd_iterator<G>::update_()
+ {
+ mln_precondition(is_valid());
+ mln_precondition(c_->is_valid());
+ v_.update_id(c_->ith_nbh_vertex(i_));
+ }
+
+ template <typename G>
+ template <typename C>
+ inline
+ void
+ vertex_nbh_vertex_bkd_iterator<G>::center_at(const C& c)
+ {
+ internal::get_adr(c_, c);
+ mln_precondition(c_ != 0);
+
+ invalidate();
+ }
+
+# endif // !MLN_INCLUDE_ONLY
+
+ } // End of namespace mln::internal
+
+} // End of namespace mln
+
+
+#endif // !MLN_UTIL_INTERNAL_GRAPH_VERTEX_NBH_VERTEX_ITER_HH
+
diff --git a/milena/tests/util/graph.cc b/milena/tests/util/graph.cc
index d20b02d..60a609a 100644
--- a/milena/tests/util/graph.cc
+++ b/milena/tests/util/graph.cc
@@ -35,7 +35,7 @@ int main ()
{
using namespace mln;
- util::graph<void> g;
+ util::graph g;
g.add_vertex (); // 0
g.add_vertex (); // 1
@@ -51,4 +51,109 @@ int main ()
g.add_edge (1, 0);
g.add_edge (5, 3);
g.add_edge (2, 1);
+
+
+ // Vertex iter and edge iter
+ {
+ unsigned i = 0;
+ mln_vertex_fwd_iter_(util::graph) v(g);
+ for_all(v)
+ mln_assertion(i++ == v.index());
+ mln_assertion(i != 0);
+
+ i = 0;
+ mln_edge_fwd_iter_(util::graph) e(g);
+ for_all(e)
+ mln_assertion(i++ == e.index());
+ mln_assertion(i != 0);
+ }
+ {
+ unsigned i = g.v_nmax() - 1;
+ mln_vertex_bkd_iter_(util::graph) v(g);
+ for_all(v)
+ mln_assertion(i-- == v.index());
+ mln_assertion(i != g.v_nmax() - 1);
+
+ i = g.e_nmax() - 1;
+ mln_edge_bkd_iter_(util::graph) e(g);
+ for_all(e)
+ mln_assertion(i-- == e.index());
+ mln_assertion(i != g.e_nmax() - 1);
+ }
+
+ // vertex iter + Edge nbh iter
+ {
+ mln_vertex_fwd_iter_(util::graph) v(g);
+ mln_vertex_nbh_edge_fwd_iter_(util::graph) n(v);
+ for_all(v)
+ {
+ unsigned i = 0;
+ for_all(n)
+ mln_assertion(i++ == n.index());
+ mln_assertion(i != 0);
+ }
+ }
+ {
+ mln_vertex_bkd_iter_(util::graph) v(g);
+ mln_vertex_nbh_edge_bkd_iter_(util::graph) e(v);
+ for_all(v)
+ {
+ unsigned i = v.nmax_nbh_edges();
+ for_all(e)
+ mln_assertion(--i == e.index());
+ mln_assertion((v.nmax_nbh_edges() == 0 && i == 0) || i != v.nmax_nbh_edges());
+ }
+ }
+
+ {
+ mln_edge_fwd_iter_(util::graph) e(g);
+ mln_edge_nbh_edge_fwd_iter_(util::graph) n(e);
+ for_all(e)
+ {
+ unsigned i = 0;
+ for_all(n)
+ ++i;
+ // we check i == e.nmax_nbh_edges() - 2 since e is it's own neighboor and the
+ // iterator skip it.
+ mln_assertion((i == 0 && e.nmax_nbh_edges() < 2) || i == e.nmax_nbh_edges() - 2);
+ }
+ }
+ {
+ mln_edge_bkd_iter_(util::graph) e(g);
+ mln_edge_nbh_edge_bkd_iter_(util::graph) n(e);
+ for_all(e)
+ {
+ //std::cout << "== e.id() = " << e.id() << std::endl;
+ unsigned i = e.nmax_nbh_edges();
+ for_all(n)
+ --i;
+ // we check i == e.nmax_nbh_edges() - 2 since e is it's own neighboor and the
+ // iterator skip it.
+ mln_assertion((i == e.nmax_nbh_edges() && e.nmax_nbh_edges() < 2) || i == 2);
+
+ }
+ }
+
+ {
+ mln_vertex_fwd_iter_(util::graph) v(g);
+ mln_vertex_nbh_vertex_fwd_iter_(util::graph) n(v);
+ for_all(v)
+ {
+ unsigned i = 0;
+ for_all(n)
+ ++i;
+ mln_assertion(i == v.nmax_nbh_vertices());
+ }
+ }
+ {
+ mln_vertex_bkd_iter_(util::graph) v(g);
+ mln_vertex_nbh_vertex_bkd_iter_(util::graph) n(v);
+ for_all(v)
+ {
+ unsigned i = v.nmax_nbh_vertices();
+ for_all(n)
+ --i;
+ mln_assertion(i == 0);
+ }
+ }
}
--
1.5.6.5
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add traits for windows and factor code.
* mln/trait/windows.hh: New.
* mln/trait/window: New.
* mln/trait/window/props.hh: New.
* mln/trait/window/print.hh: New.
* mln/core/macros.hh (mln_regular): New.
* mln/core/neighb.hh (operator<<): New.
* mln/core/concept/weighted_window.hh (include): Update.
* mln/core/concept/neighborhood.hh: Likewise.
* mln/core/concept/window.hh: Likewise.
(window_size_check, window_support_check): New.
(window_definition_check): New.
(operator<<): New.
* mln/core/concept/object.hh: New metal include.
* mln/core/internal/dpsites_impl.hh: Rename as...
* mln/core/internal/classical_window_base.hh: ...this.
(is_centered, is_symmetric, sym): New.
(delta): Rely on...
(delta_): ...this new method.
(print, print_): New.
* mln/geom/shift.hh: Revamp.
* mln/core/window.hh,
* mln/win/cube3d.hh,
* mln/win/line.hh,
* mln/win/rectangle2d.hh,
* mln/win/diag2d.hh,
* mln/win/backdiag2d.hh,
* mln/win/multiple.hh,
* mln/win/cuboid3d.hh,
* mln/win/octagon2d.hh,
* mln/win/disk2d.hh: Update and factor code.
core/concept/neighborhood.hh | 1
core/concept/object.hh | 1
core/concept/weighted_window.hh | 1
core/concept/window.hh | 154 ++++++++++++++++++++++++++++++++-
core/internal/classical_window_base.hh | 136 +++++++++++++++++++++--------
core/macros.hh | 6 +
core/neighb.hh | 7 +
core/window.hh | 43 ++++++---
geom/shift.hh | 53 +++++++++--
trait/window/print.hh | 119 +++++++++++++++++++++++++
trait/window/props.hh | 136 +++++++++++++++++++++++++++++
trait/windows.hh | 113 ++++++++++++++++++++++++
win/backdiag2d.hh | 64 ++-----------
win/cube3d.hh | 64 ++-----------
win/cuboid3d.hh | 69 ++------------
win/diag2d.hh | 64 ++-----------
win/disk2d.hh | 66 ++------------
win/line.hh | 87 ++++++------------
win/multiple.hh | 96 +++++++++++++++-----
win/octagon2d.hh | 64 ++-----------
win/rectangle2d.hh | 68 ++------------
21 files changed, 893 insertions(+), 519 deletions(-)
Index: mln/trait/windows.hh
--- mln/trait/windows.hh (revision 0)
+++ mln/trait/windows.hh (revision 0)
@@ -0,0 +1,113 @@
+// 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_TRAIT_WINDOWS_HH
+# define MLN_TRAIT_WINDOWS_HH
+
+/*! \file mln/trait/windows.hh
+ *
+ * \brief Some base trait types for windows.
+ */
+
+# include <mln/trait/undef.hh>
+# include <mln/trait/window/props.hh>
+
+
+/// Shortcut to the window property about the 'size' method presence.
+# define mln_trait_window_size(W) typename mln::trait::window_< W >::size
+
+/// Shortcut to the window property about the 'support' it is designed for.
+# define mln_trait_window_support(W) typename mln::trait::window_< W >::support
+
+/// Shortcut to the window property about its definition.
+# define mln_trait_window_definition(W) typename mln::trait::window_< W >::definition
+
+
+# define mln_internal_add_classical_window_trait(W) \
+ \
+ namespace win { struct W; } \
+ \
+ namespace trait \
+ { \
+ \
+ template <> \
+ struct window_< win::W > : classical_window_ \
+ { \
+ }; \
+ \
+ } \
+ \
+ struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_u_m_n
+
+
+namespace mln
+{
+
+ namespace trait
+ {
+
+ /// Pack of 'undefined' type values for properties of windows.
+ template <typename W>
+ struct undefined_window_
+ {
+ typedef undef size; // Fixed or unknown.
+ typedef undef support; // Regular or irregular.
+ typedef undef definition; // Unique, n_ary, or varying.
+ };
+
+
+ /*! \brief The trait pack structure for properties of windows.
+ *
+ * This structure is specialized for every concrete class of site
+ * set so that properties are properly defined.
+ *
+ * \see mln::doc::Window for the documentation of the "window"
+ * concept.
+ */
+ template <typename W>
+ struct window_ : undefined_window_<W>
+ {
+ };
+
+
+ // \internal Trait for classical windows.
+ struct classical_window_
+ {
+ typedef mln::trait::window::size::fixed size;
+ typedef mln::trait::window::support::regular support;
+ typedef mln::trait::window::definition::unique definition;
+ };
+
+ } // end of namespace mln::trait
+
+} // end of namespace mln
+
+
+# include <mln/trait/window/print.hh>
+
+
+#endif // ! MLN_TRAIT_WINDOWS_HH
Index: mln/trait/window/props.hh
--- mln/trait/window/props.hh (revision 0)
+++ mln/trait/window/props.hh (revision 0)
@@ -0,0 +1,136 @@
+// 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_TRAIT_WINDOW_PROPS_HH
+# define MLN_TRAIT_WINDOW_PROPS_HH
+
+/*! \file mln/trait/window/props.hh
+ *
+ * \brief Properties of window classes.
+ *
+ * \todo Precise the differences (?) between dynamic, growing, and
+ * free...
+ */
+
+# include <string>
+# include <mln/trait/undef.hh>
+
+
+
+// Properties of windows.
+// ========================
+
+// size: /any/
+// |
+// + -- fixed
+// |
+// + -- unknown
+
+// support: /any/
+// |
+// + -- regular
+// |
+// + -- irregular
+
+// definition: /any/
+// |
+// + -- unique
+// |
+// + -- /multiple/
+// |
+// + -- n_ary
+// |
+// + -- varying
+
+
+namespace mln
+{
+
+ namespace trait
+ {
+
+ namespace window
+ {
+
+
+ /// Window property about the 'size' method presence.
+ struct size
+ {
+ /// Base class for the window 'size' property.
+ struct any { protected: any() {} };
+
+ /// Property that states that the size is fixed.
+ struct fixed : any { std::string name() const { return "size::fixed"; } };
+
+ /// Property that states that the size is not fixed so unknown.
+ struct unknown : any { std::string name() const { return "size::unknown"; } };
+ };
+
+
+ /// Window property about the 'support' it is designed for.
+ struct support
+ {
+ /// Base class for the window 'support' property.
+ struct any { protected: any() {} };
+
+ /// Property that states that the window is designed for a regular support.
+ struct regular : any { std::string name() const { return "support::regular"; } };
+
+ /// Property that states that the window is not designed for a regular support.
+ struct irregular : any { std::string name() const { return "support::irregular"; } };
+ };
+
+
+ /// Window property about how the window is defined.
+ struct definition
+ {
+ /// Base class for the window 'definition' property.
+ struct any { protected: any() {} };
+
+ /// Property that states that the definition is unique.
+ struct unique : any { std::string name() const { return "definition::unique"; } };
+
+ /// Abstract property that states that the definition is multiple.
+ struct multiple : any { protected: multiple() {} };
+
+ /// Property that states that this window has n definitions.
+ struct n_ary : multiple { std::string name() const { return "definition::n_ary"; } };
+
+ /// Property that states that this window has a varying definition.
+ struct varying : multiple { std::string name() const { return "definition::varying"; } };
+ };
+
+
+ } // end of namespace mln::trait::window
+
+ } // end of namespace mln::trait
+
+
+} // end of namespace mln
+
+
+#endif // ! MLN_TRAIT_WINDOW_PROPS_HH
Index: mln/trait/window/print.hh
--- mln/trait/window/print.hh (revision 0)
+++ mln/trait/window/print.hh (revision 0)
@@ -0,0 +1,119 @@
+// 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_TRAIT_WINDOW_PRINT_HH
+# define MLN_TRAIT_WINDOW_PRINT_HH
+
+/*! \file mln/trait/window/print.hh
+ *
+ * \brief Print the collection of traits for a window type.
+ */
+
+# include <iostream>
+
+# include <mln/trait/windows.hh>
+# include <mln/metal/is_a.hh>
+# include <mln/metal/bexpr.hh>
+
+
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <typename E> struct Window;
+ template <typename E> struct Weighted_Window;
+ template <typename E> struct Neighborhood;
+
+
+ namespace trait
+ {
+
+ namespace window
+ {
+
+ template <typename T>
+ void print(std::ostream& ostr = std::cout);
+
+ template <typename T>
+ void print(const Neighborhood<T>& nbh, std::ostream& ostr = std::cout);
+
+ template <typename T>
+ void print(const Window<T>& win, std::ostream& ostr = std::cout);
+
+ template <typename T>
+ void print(const Weighted_Window<T>& w_win, std::ostream& ostr = std::cout);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename T>
+ inline
+ void print(std::ostream& ostr)
+ {
+ metal::or_< mlc_is_a(T, Neighborhood),
+ metal::or_< mlc_is_a(T, Window),
+ mlc_is_a(T, Weighted_Window) >
+ >::check();
+ typedef mln::trait::window_<T> the;
+ ostr << "{ "
+ << typename the::size() .name() << ", "
+ << typename the::support() .name() << ", "
+ << typename the::definition() .name() << " }" << std::endl;
+ }
+
+ template <typename T>
+ inline
+ void print(const Neighborhood<T>&, std::ostream& ostr)
+ {
+ print<T>(ostr);
+ }
+
+ template <typename T>
+ inline
+ void print(const Window<T>&, std::ostream& ostr)
+ {
+ print<T>(ostr);
+ }
+
+ template <typename T>
+ inline
+ void print(const Weighted_Window<T>&, std::ostream& ostr)
+ {
+ print<T>(ostr);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::trait::window
+
+ } // end of namespace mln::trait
+
+} // end of namespace mln
+
+
+#endif // ! MLN_TRAIT_WINDOW_PRINT_HH
Index: mln/core/macros.hh
--- mln/core/macros.hh (revision 2446)
+++ mln/core/macros.hh (working copy)
@@ -299,6 +299,12 @@
# define mln_r_element_(T) T::r_element
/// \}
+/// Shortcuts to access the regular type associated to T.
+/// \{
+# define mln_regular(T) typename T::regular
+# define mln_regular_(T) T::regular
+/// \}
+
/// Shortcuts to access the result type associated to T.
/// \{
# define mln_result(T) typename T::result
Index: mln/core/neighb.hh
--- mln/core/neighb.hh (revision 2446)
+++ mln/core/neighb.hh (working copy)
@@ -105,6 +105,13 @@
};
+ template <typename W>
+ inline
+ std::ostream& operator<<(std::ostream&ostr, const neighb<W>& nbh)
+ {
+ return ostr << nbh.win();
+ }
+
namespace convert
{
Index: mln/core/concept/weighted_window.hh
--- mln/core/concept/weighted_window.hh (revision 2446)
+++ mln/core/concept/weighted_window.hh (working copy)
@@ -35,6 +35,7 @@
# include <mln/core/concept/object.hh>
# include <mln/core/concept/iterator.hh>
+# include <mln/trait/windows.hh>
namespace mln
Index: mln/core/concept/object.hh
--- mln/core/concept/object.hh (revision 2446)
+++ mln/core/concept/object.hh (working copy)
@@ -43,6 +43,7 @@
# include <mln/trace/all.hh>
# include <mln/metal/is_a.hh>
# include <mln/metal/is.hh>
+# include <mln/metal/is_not.hh>
# include <mln/metal/ret.hh>
Index: mln/core/concept/neighborhood.hh
--- mln/core/concept/neighborhood.hh (revision 2446)
+++ mln/core/concept/neighborhood.hh (working copy)
@@ -33,6 +33,7 @@
*/
# include <mln/core/concept/object.hh>
+# include <mln/trait/windows.hh>
namespace mln
Index: mln/core/concept/window.hh
--- mln/core/concept/window.hh (revision 2446)
+++ mln/core/concept/window.hh (working copy)
@@ -32,10 +32,13 @@
* \brief Definition of the concept of mln::Window.
*
* \todo Operator== should test if the cmp is possible.
+ *
+ * \todo Activate run_extra() below.
*/
# include <mln/core/concept/object.hh>
# include <mln/core/concept/iterator.hh>
+# include <mln/trait/windows.hh>
# include <mln/core/site_set/p_array.hh>
@@ -82,20 +85,124 @@
bool operator==(const Window<Wl>& lhs, const Window<Wr>& rhs);
+ template <typename W>
+ std::ostream& operator<<(std::ostream& ostr, const Window<W>& win);
+
+
# ifndef MLN_INCLUDE_ONLY
+ namespace internal
+ {
+
+ // size: fixed or unknown.
+
+ template <typename trait_size, typename E>
+ struct window_size_check
+ {
+ static void run() { /* No requirement. */ }
+ };
+
+ template <typename E>
+ struct window_size_check< mln::trait::window::size::fixed, E >
+ {
+ static void run()
+ {
+ unsigned (E::*m)() const = & E::size;
+ m = 0;
+ }
+ };
+
+ // support: regular or irregular.
+
+ template <typename trait_support, typename E>
+ struct window_support_check
+ {
+ static void run() { /* No requirement. */ }
+ };
+
+ template <typename E>
+ struct window_support_check< mln::trait::window::support::regular, E >
+ {
+ static void run_extra()
+ {
+ bool (E::*m1)() const = &E::is_centered;
+ m1 = 0;
+ bool (E::*m2)() const = &E::is_symmetric;
+ m2 = 0;
+ void (E::*m3)() = &E::sym;
+ m3 = 0;
+ unsigned (E::*m4)() const = &E::delta;
+ m4 = 0;
+ }
+ static void run(mln::trait::window::definition::unique)
+ {
+ typedef mln_dpsite(E) D;
+ const D& (E::*m)(unsigned) const = &E::dp;
+ m = 0;
+ run_extra();
+ }
+ static void run(mln::trait::window::definition::n_ary)
+ {
+ // run_extra();
+ }
+ static void run(mln::trait::window::definition::varying)
+ {
+ /* No requirement. */
+ }
+ static void run()
+ {
+ run(mln_trait_window_definition(E)());
+ }
+ };
+
+ // definition: unique, n_ary, or varying.
+
+ template <typename trait_definition, typename E>
+ struct window_definition_check
+ {
+ static void run() { /* No requirement. */ }
+ };
+
+ template <typename E>
+ struct window_definition_check< mln::trait::window::definition::multiple, E >
+ {
+ static void run()
+ {
+ typedef mln_element(E) W;
+ void (E::*m1)(unsigned, const W&) = &E::set_window;
+ m1 = 0;
+ const W& (E::*m2)(unsigned) const = &E::window;
+ m2 = 0;
+ unsigned (E::*m3)() const = &E::nwindows;
+ m3 = 0;
+ }
+ };
+
+ } // end of namespace mln::internal
+
+
template <typename E>
inline
Window<E>::Window()
{
+ // Check properties.
+ mlc_not_equal( mln_trait_window_size(E), mln::trait::undef )::check();
+ mlc_not_equal( mln_trait_window_support(E), mln::trait::undef )::check();
+ mlc_not_equal( mln_trait_window_definition(E), mln::trait::undef )::check();
+
+ // Check associated types.
typedef mln_site(E) site;
typedef mln_psite(E) psite;
typedef mln_dpsite(E) dpsite;
-
typedef mln_qiter(E) qiter;
typedef mln_fwd_qiter(E) fwd_qiter;
typedef mln_bkd_qiter(E) bkd_qiter;
+
+ // Check methods depending upon properties.
+ internal::window_size_check < mln_trait_window_size(E), E >::run();
+ internal::window_support_check < mln_trait_window_support(E), E >::run();
+ internal::window_definition_check< mln_trait_window_definition(E), E >::run();
}
template <typename Wl, typename Wr>
@@ -105,6 +212,51 @@
return exact(lhs).std_vector() == exact(rhs).std_vector();
}
+
+ // Operator <<.
+
+ namespace internal
+ {
+
+ template <typename W>
+ inline
+ void print(trait::window::definition::unique,
+ std::ostream& ostr, const W& win) // FIXME: Add Window<W> to win?
+ {
+ win.print(ostr);
+ }
+
+ template <typename W>
+ inline
+ void print(trait::window::definition::multiple,
+ std::ostream& ostr, const W& win) // FIXME: Add Window<W> to win?
+ {
+ ostr << "[";
+ const unsigned nw = win.nwindows();
+ for (unsigned w = 0; w < nw; ++w)
+ {
+ ostr << " #" << w << ':';
+ win.window(w).print(ostr);
+ }
+ ostr << " ]";
+ }
+
+ } // end of namespace mln
+
+ template <typename W>
+ inline
+ std::ostream& operator<<(std::ostream& ostr, const Window<W>& win)
+ {
+ mlc_is(mln_trait_window_support(W),
+ trait::window::support::regular)::check();
+ mlc_is_not(mln_trait_window_definition(W),
+ trait::window::definition::varying)::check();
+ // FIXME: test on is_empty?
+ internal::print(mln_trait_window_definition(W)(),
+ ostr, exact(win));
+ return ostr;
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln
Index: mln/core/window.hh
--- mln/core/window.hh (revision 2446)
+++ mln/core/window.hh (working copy)
@@ -53,11 +53,28 @@
namespace mln
{
- // Fwd decls.
+ // Forward declarations.
+ template <typename D> class window;
template <typename V> class dpsites_fwd_piter;
template <typename V> class dpsites_bkd_piter;
+
+ namespace trait
+ {
+
+ template <typename D>
+ struct window_< mln::window<D> >
+ {
+ typedef trait::window::size::fixed size;
+ typedef trait::window::support::regular support;
+ typedef trait::window::definition::unique definition;
+ };
+
+ } // end of namespace trait
+
+
+
/*! \brief Generic window class.
*
* This type of window is just like a set of delta-points. The
@@ -68,6 +85,10 @@
{
public:
+ /// Regular window associated type.
+ typedef window<D> regular;
+
+
/*! \brief Constructor without argument.
*
* The constructed window is empty.
@@ -154,17 +175,15 @@
/// Hook to the set of D.
const util::set<D>& dps_hook_() const;
+ /// Print the window definition into \p ostr.
+ void print(std::ostream& ostr) const;
+
private:
util::set<D> dps_;
};
- // FIXME: Doc!
- template <typename D>
- std::ostream& operator<<(std::ostream& ostr, const window<D>& win);
-
-
/*! \brief Equality comparison between windows \p lhs and \p rhs.
*
@@ -347,15 +366,17 @@
return dps_;
}
- // Operators.
-
template <typename D>
- std::ostream&
- operator<<(std::ostream& ostr, const window<D>& win)
+ inline
+ void
+ window<D>::print(std::ostream& ostr) const
{
- return ostr << win.dps_hook_();
+ ostr << dps_;
}
+
+ // Operators.
+
template <typename D>
bool
operator==(const window<D>& lhs, const window<D>& rhs)
Index: mln/core/internal/classical_window_base.hh
--- mln/core/internal/classical_window_base.hh (revision 2440)
+++ mln/core/internal/classical_window_base.hh (working copy)
@@ -25,16 +25,17 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_CORE_INTERNAL_DPSITES_IMPL_HH
-# define MLN_CORE_INTERNAL_DPSITES_IMPL_HH
+#ifndef MLN_CORE_INTERNAL_CLASSICAL_WINDOW_BASE_HH
+# define MLN_CORE_INTERNAL_CLASSICAL_WINDOW_BASE_HH
-/*! \file mln/core/internal/dpsites_impl.hh
+/*! \file mln/core/internal/classical_window_base.hh
*
* \brief Definition of a base class for classes based on a set of dpoints.
*
- * \todo Rename as dpsites_impl.
- *
* \todo Remove the .vect() method.
+ *
+ * \todo Add a test that overridden delta_() and win.delta() give the
+ * same result.
*/
# include <mln/core/window.hh>
@@ -52,10 +53,15 @@
*
*/
template <typename D, typename E>
- class dpsites_impl
+ class classical_window_base : public window_base<D, E>
{
public:
+
+ /// Regular window associated type.
+ typedef window<D> regular;
+
+
/// Forward site iterator associated type.
typedef dpsites_fwd_piter<E> fwd_qiter;
@@ -66,41 +72,50 @@
typedef fwd_qiter qiter;
- /*! \brief Test if the window is centered.
- *
- * \return True if the delta-point 0 belongs to the window.
- */
- bool is_centered() const;
+ /// Give the number of delta-points.
+ unsigned size() const;
- /*! \brief Test if the window is empty (null size; no delta-point).
- */
+ /// 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.
- */
+
+ /// Test if the window is centered; return true.
+ bool is_centered() const;
+
+ /// Test if the window is symmetric; return true.
+ bool is_symmetric() const;
+
+ /// Apply a central symmetry to the target window; a no-op here.
+ void sym();
+
+
+ /// Give the maximum coordinate gap between the window center
+ /// and a window point.
unsigned delta() const;
- /// Give the number of delta-points.
- unsigned size() const;
/// Test if the delta-point \p dp belongs to the window.
bool has(const D& dp) const;
- // Give the \p i-th delta-point.
+ /// Give the \p i-th delta-point.
const D& dp(unsigned i) const;
- // Give the vector of delta-points.
+ /// Give the vector of delta-points.
const std::vector<D>& vect() const;
- // Give the vector of delta-points.
+ /// Give the vector of delta-points.
const std::vector<D>& std_vector() const;
+ /// Print into \p ostr the window definition.
+ void print(std::ostream& ostr) const;
+
protected:
- dpsites_impl();
+ classical_window_base();
void insert(const D& d);
+ unsigned delta_() const; // Default implementation based on win_.
+ void print_(std::ostream& ostr) const; // Default implementation based on win_.
mln::window<D> win_;
};
@@ -111,43 +126,76 @@
template <typename D, typename E>
inline
- dpsites_impl<D,E>::dpsites_impl()
+ classical_window_base<D,E>::classical_window_base()
{
}
template <typename D, typename E>
inline
- bool dpsites_impl<D,E>::is_centered() const
+ unsigned
+ classical_window_base<D,E>::size() const
{
- return win_.is_centered();
+ return win_.size();
}
template <typename D, typename E>
inline
- bool dpsites_impl<D,E>::is_empty() const
+ bool
+ classical_window_base<D,E>::is_empty() const
{
return win_.is_empty();
}
template <typename D, typename E>
inline
- unsigned dpsites_impl<D,E>::delta() const
+ bool
+ classical_window_base<D,E>::is_centered() const
{
- return win_.delta();
+ mln_invariant(win_.is_centered());
+ return true;
+ }
+
+ template <typename D, typename E>
+ inline
+ bool
+ classical_window_base<D,E>::is_symmetric() const
+ {
+ mln_invariant(win_.is_symmetric());
+ return true;
+ }
+
+ template <typename D, typename E>
+ inline
+ void
+ classical_window_base<D,E>::sym()
+ {
+ mln_invariant(win_.is_symmetric());
+ // No-op.
}
template <typename D, typename E>
inline
unsigned
- dpsites_impl<D,E>::size() const
+ classical_window_base<D,E>::delta() const
{
- return win_.size();
+ // void *v = (void*)(& classical_window_base<D,E>::delta_);
+ // void *w = (void*)(& E::delta_);
+ // std::cout << v << ' ' << w << std::endl;
+ return exact(this)->delta_();
+ }
+
+ template <typename D, typename E>
+ inline
+ unsigned
+ classical_window_base<D,E>::delta_() const
+ {
+ return win_.delta();
}
template <typename D, typename E>
inline
const D&
- dpsites_impl<D,E>::dp(unsigned i) const
+ classical_window_base<D,E>::dp(unsigned i) const
{
mln_precondition(i < size());
return win_.dp(i);
@@ -156,7 +204,7 @@
template <typename D, typename E>
inline
const std::vector<D>&
- dpsites_impl<D,E>::std_vector() const
+ classical_window_base<D,E>::std_vector() const
{
return win_.std_vector();
}
@@ -164,7 +212,7 @@
template <typename D, typename E>
inline
const std::vector<D>&
- dpsites_impl<D,E>::vect() const
+ classical_window_base<D,E>::vect() const
{
return std_vector();
}
@@ -172,7 +220,7 @@
template <typename D, typename E>
inline
bool
- dpsites_impl<D,E>::has(const D& dp) const
+ classical_window_base<D,E>::has(const D& dp) const
{
return win_.has(dp);
}
@@ -180,11 +228,27 @@
template <typename D, typename E>
inline
void
- dpsites_impl<D,E>::insert(const D& d)
+ classical_window_base<D,E>::insert(const D& d)
{
win_.insert(d);
}
+ template <typename D, typename E>
+ inline
+ void
+ classical_window_base<D,E>::print(std::ostream& ostr) const
+ {
+ exact(this)->print_(ostr);
+ }
+
+ template <typename D, typename E>
+ inline
+ void
+ classical_window_base<D,E>::print_(std::ostream& ostr) const
+ {
+ ostr << win_;
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace internal
@@ -192,4 +256,4 @@
} // end of namespace mln
-#endif // ! MLN_CORE_INTERNAL_DPSITES_IMPL_HH
+#endif // ! MLN_CORE_INTERNAL_CLASSICAL_WINDOW_BASE_HH
Index: mln/geom/shift.hh
--- mln/geom/shift.hh (revision 2446)
+++ mln/geom/shift.hh (working copy)
@@ -45,27 +45,66 @@
/// Shift a window \p win with a delta-point \p dp.
template <typename W>
- window<mln_dpsite(W)>
+ mln_regular(W)
shift(const Window<W>& win, const mln_dpsite(W)& dp);
# ifndef MLN_INCLUDE_ONLY
+ namespace impl
+ {
+
template <typename W>
inline
- window<mln_dpsite(W)>
- shift(const Window<W>& win_, const mln_dpsite(W)& dp)
+ mln_regular(W)
+ shift_(trait::window::definition::unique,
+ const W& win, const mln_dpsite(W)& dp)
{
- mlc_is_a(mln_site(W), Gpoint)::check();
- const W& win = exact(win_);
-
- window<mln_dpsite(W)> tmp;
+ mlc_is(mln_trait_window_size(W),
+ trait::window::size::fixed)::check();
+ mln_regular(W) tmp;
unsigned n = win.size();
for (unsigned i = 0; i < n; ++i)
tmp.insert(win.dp(i) + dp);
return tmp;
}
+ template <typename W>
+ inline
+ mln_regular(W)
+ shift_(trait::window::definition::multiple,
+ const W& win, const mln_dpsite(W)& dp)
+ {
+ mln_regular(W) tmp(win.function());
+ const unsigned nw = win.nwindows();
+ for (unsigned w = 0; w < nw; ++w)
+ tmp.set_window(w, geom::shift(win.window(w), dp));
+ return tmp;
+ }
+
+ } // end of namespace mln::geom::impl
+
+
+ // Facade.
+ template <typename W>
+ inline
+ mln_regular(W)
+ shift(const Window<W>& win, const mln_dpsite(W)& dp)
+ {
+ trace::entering("geom::shift");
+
+ mlc_is(mln_trait_window_support(W),
+ trait::window::support::regular)::check();
+ mlc_is_not(mln_trait_window_definition(W),
+ trait::window::definition::varying)::check();
+
+ mln_regular(W) tmp = impl::shift_(mln_trait_window_definition(W)(),
+ exact(win), dp);
+
+ trace::exiting("geom::shift");
+ return tmp;
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::geom
Index: mln/win/cube3d.hh
--- mln/win/cube3d.hh (revision 2446)
+++ mln/win/cube3d.hh (working copy)
@@ -33,14 +33,16 @@
* \brief Definition of the mln::win::cube3d window.
*/
-# include <mln/core/internal/window_base.hh>
-# include <mln/core/internal/dpsites_impl.hh>
+# include <mln/core/internal/classical_window_base.hh>
# include <mln/core/alias/dpoint3d.hh>
namespace mln
{
+ mln_internal_add_classical_window_trait(cube3d);
+
+
namespace win
{
@@ -63,8 +65,7 @@
* o o o \n
* is defined with length = 3.
*/
- struct cube3d : public internal::window_base< dpoint3d, cube3d >,
- public internal::dpsites_impl< dpoint3d, cube3d >
+ struct cube3d : public internal::classical_window_base< dpoint3d, cube3d >
{
/*! \brief Constructor.
*
@@ -74,18 +75,6 @@
*/
cube3d(unsigned length);
- /*! \brief Test if the window is centered.
- *
- * \return True.
- */
- bool is_centered() const;
-
- /*! \brief Test if the window is symmetric.
- *
- * \return true.
- */
- bool is_symmetric() const;
-
/*! \brief Give the cube length, that is, its height.
*/
unsigned length() const;
@@ -93,29 +82,15 @@
/*! \brief Give the maximum coordinate gap between the window
* center and a window point.
*/
- unsigned delta() const;
+ unsigned delta_() const;
- /// Apply a central symmetry to the target window.
- cube3d& sym();
+ void print_(std::ostream& ostr) const;
protected:
unsigned length_;
};
- /*! \brief Print a cube3d window \p win into the output
- * stream \p ostr.
- *
- * \param[in,out] ostr An output stream.
- * \param[in] win A cube3d window.
- *
- * \return The modified output stream \p ostr.
- *
- * \relates mln::win::cube3d
- */
- std::ostream& operator<<(std::ostream& ostr, const cube3d& win);
-
-
# ifndef MLN_INCLUDE_ONLY
@@ -132,40 +107,21 @@
}
inline
- bool cube3d::is_centered() const
- {
- return true;
- }
-
- inline
- bool cube3d::is_symmetric() const
- {
- return true;
- }
-
- inline
unsigned cube3d::length() const
{
return length_;
}
inline
- unsigned cube3d::delta() const
+ unsigned cube3d::delta_() const
{
return length_ / 2;
}
inline
- cube3d& cube3d::sym()
- {
- return *this;
- }
-
- inline
- std::ostream& operator<<(std::ostream& ostr, const cube3d& win)
+ void cube3d::print_(std::ostream& ostr) const
{
- ostr << "[cube3d: length=" << win.length() << ']';
- return ostr;
+ ostr << "[cube3d: length=" << length_ << ']';
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/win/line.hh
--- mln/win/line.hh (revision 2446)
+++ mln/win/line.hh (working copy)
@@ -33,14 +33,29 @@
* \brief Definition of the mln::win::line window.
*/
-# include <mln/core/internal/window_base.hh>
-# include <mln/core/internal/dpsites_impl.hh>
+# include <mln/core/internal/classical_window_base.hh>
# include <mln/core/dpoint.hh>
namespace mln
{
+ // Forward declaration.
+ namespace win { template <typename M, unsigned i, typename C> struct line; }
+
+
+ namespace trait
+ {
+
+ template <typename M, unsigned i, typename C>
+ struct window_< mln::win::line<M,i,C> > : classical_window_
+ {
+ };
+
+ } // end of namespace trait
+
+
+
namespace win
{
@@ -56,8 +71,7 @@
* \see mln::win::hline2d for an exemple of his use.
*/
template <typename M, unsigned i, typename C>
- struct line : public internal::window_base< dpoint<M, C>, line<M,i,C> >,
- public internal::dpsites_impl< dpoint<M, C>, line<M,i,C> >
+ struct line : public internal::classical_window_base< dpoint<M, C>, line<M,i,C> >
{
/*! \brief Constructor.
*
@@ -67,49 +81,24 @@
*/
line(unsigned length);
- /*! \brief Test if the window is centered.
- *
- * \return True.
- */
- bool is_centered() const;
-
- /*! \brief Test if the window is symmetric.
- *
- * \return true.
- */
- bool is_symmetric() const;
-
- /*! \brief Give the hline length, that is, its width.
- */
+ /// Give the line length.
unsigned length() const;
+ /// Give the line size, that is, its length.
+ unsigned size() const;
+
/*! \brief Give the maximum coordinate gap between the window
* center and a window point.
*/
- unsigned delta() const;
+ unsigned delta_() const;
- /// Apply a central symmetry to the target window.
- line<M,i,C>& sym();
+ void print_(std::ostream& ostr) const;
protected:
unsigned length_;
};
- /*! \brief Print an line window \p win into the output
- * stream \p ostr.
- *
- * \param[in,out] ostr An output stream.
- * \param[in] win An line window.
- *
- * \return The modified output stream \p ostr.
- *
- * \relates mln::win::line
- */
- template <typename M, unsigned i, typename C>
- std::ostream& operator<<(std::ostream& ostr, const line<M,i,C>& win);
-
-
# ifndef MLN_INCLUDE_ONLY
@@ -133,20 +122,6 @@
template <typename M, unsigned i, typename C>
inline
- bool line<M,i,C>::is_centered() const
- {
- return true;
- }
-
- template <typename M, unsigned i, typename C>
- inline
- bool line<M,i,C>::is_symmetric() const
- {
- return true;
- }
-
- template <typename M, unsigned i, typename C>
- inline
unsigned line<M,i,C>::length() const
{
return length_;
@@ -154,24 +129,24 @@
template <typename M, unsigned i, typename C>
inline
- unsigned line<M,i,C>::delta() const
+ unsigned line<M,i,C>::size() const
{
- return length_ / 2;
+ return length_;
}
template <typename M, unsigned i, typename C>
inline
- line<M,i,C>& line<M,i,C>::sym()
+ unsigned line<M,i,C>::delta_() const
{
- return *this;
+ return length_ / 2;
}
template <typename M, unsigned i, typename C>
inline
- std::ostream& operator<<(std::ostream& ostr, const line<M,i,C>& win)
+ void
+ line<M,i,C>::print_(std::ostream& ostr) const
{
- ostr << "[line: length=" << win.length() << ']';
- return ostr;
+ ostr << "[line: length=" << length_ << ']';
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/win/rectangle2d.hh
--- mln/win/rectangle2d.hh (revision 2446)
+++ mln/win/rectangle2d.hh (working copy)
@@ -35,8 +35,7 @@
* \todo Reactivate includes at EOF.
*/
-# include <mln/core/internal/window_base.hh>
-# include <mln/core/internal/dpsites_impl.hh>
+# include <mln/core/internal/classical_window_base.hh>
# include <mln/core/alias/dpoint2d.hh>
# include <mln/core/def/coord.hh>
@@ -44,6 +43,9 @@
namespace mln
{
+ mln_internal_add_classical_window_trait(rectangle2d);
+
+
namespace win
{
@@ -58,8 +60,7 @@
* o o o o o \n
* is defined with height = 3 and width = 5.
*/
- struct rectangle2d : public internal::window_base< dpoint2d, rectangle2d >,
- public internal::dpsites_impl< dpoint2d, rectangle2d >
+ struct rectangle2d : public internal::classical_window_base< dpoint2d, rectangle2d >
{
/*! \brief Constructor.
*
@@ -71,18 +72,6 @@
rectangle2d(unsigned height, unsigned width);
- /*! \brief Test if the window is centered.
- *
- * \return True.
- */
- bool is_centered() const;
-
- /*! \brief Test if the window is symmetric.
- *
- * \return true.
- */
- bool is_symmetric() const;
-
/// Give the rectangle height.
unsigned height() const;
@@ -95,34 +84,20 @@
/*! \brief Give the maximum coordinate gap between the window
* center and a window point.
*/
- unsigned delta() const;
-
- /// Apply a central symmetry to the target window; a no-op here.
- void sym();
+ unsigned delta_() const;
/// Give the std vector of delta-points.
const std::vector<dpoint2d>& std_vector() const;
+ void print_(std::ostream& ostr) const;
+
protected:
unsigned height_, width_;
};
- /*! \brief Print a rectangle window \p win into the output stream \p
- * ostr.
- *
- * \param[in,out] ostr An output stream.
- * \param[in] win A rectangle window.
- *
- * \return The modified output stream \p ostr.
- *
- * \relates mln::win::rectangle2d
- */
- std::ostream& operator<<(std::ostream& ostr, const rectangle2d& win);
-
-
# ifndef MLN_INCLUDE_ONLY
@@ -141,18 +116,6 @@
}
inline
- bool rectangle2d::is_centered() const
- {
- return true;
- }
-
- inline
- bool rectangle2d::is_symmetric() const
- {
- return true;
- }
-
- inline
unsigned rectangle2d::height() const
{
return height_;
@@ -171,19 +134,12 @@
}
inline
- unsigned rectangle2d::delta() const
+ unsigned rectangle2d::delta_() const
{
return width_ > height_ ? width_ / 2 : height_ / 2;
}
inline
- void
- rectangle2d::sym()
- {
- // No-op.
- }
-
- inline
const std::vector<dpoint2d>&
rectangle2d::std_vector() const
{
@@ -191,10 +147,10 @@
}
inline
- std::ostream& operator<<(std::ostream& ostr, const rectangle2d& win)
+ void
+ rectangle2d::print_(std::ostream& ostr) const
{
- ostr << "[rectangle2d: width=" << win.width() << ", height=" << win.height() << ']';
- return ostr;
+ ostr << "[rectangle2d: width=" << width_ << ", height=" << height_ << ']';
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/win/diag2d.hh
--- mln/win/diag2d.hh (revision 2446)
+++ mln/win/diag2d.hh (working copy)
@@ -33,14 +33,16 @@
* \brief Definition of the mln::win::diag2d window.
*/
-# include <mln/core/internal/window_base.hh>
-# include <mln/core/internal/dpsites_impl.hh>
+# include <mln/core/internal/classical_window_base.hh>
# include <mln/core/alias/dpoint2d.hh>
namespace mln
{
+ mln_internal_add_classical_window_trait(diag2d);
+
+
namespace win
{
@@ -57,8 +59,7 @@
* o \n
* is defined with length = 5.
*/
- struct diag2d : public internal::window_base< dpoint2d, diag2d >,
- public internal::dpsites_impl< dpoint2d, diag2d >
+ struct diag2d : public internal::classical_window_base< dpoint2d, diag2d >
{
/*! \brief Constructor.
*
@@ -68,18 +69,6 @@
*/
diag2d(unsigned length);
- /*! \brief Test if the window is centered.
- *
- * \return True.
- */
- bool is_centered() const;
-
- /*! \brief Test if the window is symmetric.
- *
- * \return true.
- */
- bool is_symmetric() const;
-
/*! \brief Give the diagonal length, that is, its width.
*/
unsigned length() const;
@@ -87,29 +76,15 @@
/*! \brief Give the maximum coordinate gap between the window
* center and a window point.
*/
- unsigned delta() const;
+ unsigned delta_() const;
- /// Apply a central symmetry to the target window.
- diag2d& sym();
+ void print_(std::ostream& ostr) const;
protected:
unsigned length_;
};
- /*! \brief Print an diagonal line window \p win into the output
- * stream \p ostr.
- *
- * \param[in,out] ostr An output stream.
- * \param[in] win A diagonal line window.
- *
- * \return The modified output stream \p ostr.
- *
- * \relates mln::win::diag2d
- */
- std::ostream& operator<<(std::ostream& ostr, const diag2d& win);
-
-
# ifndef MLN_INCLUDE_ONLY
@@ -124,40 +99,21 @@
}
inline
- bool diag2d::is_centered() const
- {
- return true;
- }
-
- inline
- bool diag2d::is_symmetric() const
- {
- return true;
- }
-
- inline
unsigned diag2d::length() const
{
return length_;
}
inline
- unsigned diag2d::delta() const
+ unsigned diag2d::delta_() const
{
return length_ / 2;
}
inline
- diag2d& diag2d::sym()
- {
- return *this;
- }
-
- inline
- std::ostream& operator<<(std::ostream& ostr, const diag2d& win)
+ void diag2d::print_(std::ostream& ostr) const
{
- ostr << "[diag 2d: length=" << win.length() << ']';
- return ostr;
+ ostr << "[diag 2d: length=" << length_ << ']';
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/win/backdiag2d.hh
--- mln/win/backdiag2d.hh (revision 2446)
+++ mln/win/backdiag2d.hh (working copy)
@@ -33,14 +33,16 @@
* \brief Definition of the mln::win::backdiag2d window.
*/
-# include <mln/core/internal/window_base.hh>
-# include <mln/core/internal/dpsites_impl.hh>
+# include <mln/core/internal/classical_window_base.hh>
# include <mln/core/alias/dpoint2d.hh>
namespace mln
{
+ mln_internal_add_classical_window_trait(backdiag2d);
+
+
namespace win
{
@@ -57,8 +59,7 @@
* o \n
* is defined with length = 5.
*/
- struct backdiag2d : public internal::window_base< dpoint2d, backdiag2d >,
- public internal::dpsites_impl< dpoint2d, backdiag2d >
+ struct backdiag2d : public internal::classical_window_base< dpoint2d, backdiag2d >
{
/*! \brief Constructor.
*
@@ -68,18 +69,6 @@
*/
backdiag2d(unsigned length);
- /*! \brief Test if the window is centered.
- *
- * \return True.
- */
- bool is_centered() const;
-
- /*! \brief Test if the window is symmetric.
- *
- * \return true.
- */
- bool is_symmetric() const;
-
/*! \brief Give the diagonal length, that is, its width.
*/
unsigned length() const;
@@ -87,29 +76,15 @@
/*! \brief Give the maximum coordinate gap between the window
* center and a window point.
*/
- unsigned delta() const;
+ unsigned delta_() const;
- /// Apply a central symmetry to the target window.
- backdiag2d& sym();
+ void print_(std::ostream& ostr) const;
protected:
unsigned length_;
};
- /*! \brief Print an diagonal line window \p win into the output
- * stream \p ostr.
- *
- * \param[in,out] ostr An output stream.
- * \param[in] win A diagonal line window.
- *
- * \return The modified output stream \p ostr.
- *
- * \relates mln::win::backdiag2d
- */
- std::ostream& operator<<(std::ostream& ostr, const backdiag2d& win);
-
-
# ifndef MLN_INCLUDE_ONLY
@@ -124,40 +99,21 @@
}
inline
- bool backdiag2d::is_centered() const
- {
- return true;
- }
-
- inline
- bool backdiag2d::is_symmetric() const
- {
- return true;
- }
-
- inline
unsigned backdiag2d::length() const
{
return length_;
}
inline
- unsigned backdiag2d::delta() const
+ unsigned backdiag2d::delta_() const
{
return length_ / 2;
}
inline
- backdiag2d& backdiag2d::sym()
- {
- return *this;
- }
-
- inline
- std::ostream& operator<<(std::ostream& ostr, const backdiag2d& win)
+ void backdiag2d::print_(std::ostream& ostr) const
{
- ostr << "[diag 2d: length=" << win.length() << ']';
- return ostr;
+ ostr << "[backdiag 2d: length=" << length_ << ']';
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/win/multiple.hh
--- mln/win/multiple.hh (revision 2446)
+++ mln/win/multiple.hh (working copy)
@@ -42,13 +42,33 @@
namespace mln
{
+ // Forward declarations.
namespace win
{
-
- // Forward declaration.
+ template <typename W, typename F> class multiple;
template <typename W, typename F> class multiple_qiter;
+ }
+
+ namespace trait
+ {
+
+ template <typename W, typename F>
+ struct window_< win::multiple<W,F> >
+ {
+ typedef trait::window::size::fixed size;
+ typedef trait::window::support::regular support;
+ typedef trait::window::definition::n_ary definition;
+ };
+
+ } // end of namespace trait
+
+
+
+ namespace win
+ {
+
template <typename W, typename F>
class multiple : public internal::window_base< mln_dpsite(W), multiple<W,F> >
{
@@ -58,10 +78,14 @@
typedef mln_psite(W) psite;
typedef mln_site(W) site;
+ typedef multiple< window<dpsite>, F > regular;
+
typedef multiple_qiter<W,F> fwd_qiter;
typedef multiple_qiter<W,F> bkd_qiter;
typedef multiple_qiter<W,F> qiter;
+ typedef W element;
+
multiple();
multiple(const F& f);
@@ -72,9 +96,13 @@
const W& window(unsigned i) const;
+ unsigned nwindows() const;
+
+ const F& function() const;
+
unsigned size() const;
- unsigned size_around(const mln_psite(W)& p) const;
+// unsigned size_around(const mln_psite(W)& p) const;
const mln_dpsite(W)& ith_dp_around(unsigned i, const mln_psite(W)& p) const;
@@ -86,11 +114,9 @@
util::array<W> win_;
F f_;
- unsigned size_;
};
-
template <typename W, typename F>
class multiple_qiter
: public internal::site_relative_iterator_base< multiple<W,F>,
@@ -120,7 +146,8 @@
private:
unsigned i_;
- unsigned n_() const;
+ unsigned size_;
+// unsigned n_() const;
};
@@ -148,7 +175,7 @@
bool
multiple<W,F>::is_empty() const
{
- return size_ == 0;
+ return win_.is_empty();
}
template <typename W, typename F>
@@ -157,6 +184,8 @@
multiple<W,F>::set_window(unsigned i, const W& win)
{
mln_precondition(i == win_.nelements());
+ if (i >= 1)
+ mln_precondition(win.size() == win_[0].size());
win_.append(win);
}
@@ -172,9 +201,25 @@
template <typename W, typename F>
inline
unsigned
+ multiple<W,F>::nwindows() const
+ {
+ return win_.nelements();
+ }
+
+ template <typename W, typename F>
+ inline
+ const F&
+ multiple<W,F>::function() const
+ {
+ return f_;
+ }
+
+ template <typename W, typename F>
+ inline
+ unsigned
multiple<W,F>::size() const
{
- mln_precondition(win_.nelements() >= 1);
+ mln_precondition(win_.nelements() >= 2); // Multiple cannot be just 1 element.
unsigned s = win_[0].size();
for (unsigned i = 1; i < win_.nelements(); ++i)
mln_precondition(win_[i].size() == s);
@@ -205,14 +250,14 @@
return true;
}
- template <typename W, typename F>
- inline
- unsigned
- multiple<W,F>::size_around(const mln_psite(W)& p) const
- {
- mln_precondition(f_(p) < win_.nelements());
- return win_[f_(p)].size();
- }
+// template <typename W, typename F>
+// inline
+// unsigned
+// multiple<W,F>::size_around(const mln_psite(W)& p) const
+// {
+// mln_precondition(f_(p) < win_.nelements());
+// return win_[f_(p)].size();
+// }
template <typename W, typename F>
inline
@@ -242,6 +287,7 @@
// We have to first change the center so that 'invalidate' can
// work when changing the target.
this->change_target(w);
+ size_ = w.size(); // FIXME: In a local change_target!
}
template <typename W, typename F>
@@ -249,7 +295,7 @@
bool
multiple_qiter<W,F>::is_valid_() const
{
- return i_ < n_();
+ return i_ < size_;
}
template <typename W, typename F>
@@ -257,7 +303,7 @@
void
multiple_qiter<W,F>::invalidate_()
{
- i_ = n_();
+ i_ = size_;
}
template <typename W, typename F>
@@ -284,13 +330,13 @@
return *this->c_ + this->s_->ith_dp_around(i_, *this->c_);
}
- template <typename W, typename F>
- inline
- unsigned
- multiple_qiter<W,F>::n_() const
- {
- return this->s_->size_around(*this->c_);
- }
+// template <typename W, typename F>
+// inline
+// unsigned
+// multiple_qiter<W,F>::size_() const
+// {
+// return this->s_->size_around(*this->c_);
+// }
# endif // ! MLN_INCLUDE_ONLY
Index: mln/win/cuboid3d.hh
--- mln/win/cuboid3d.hh (revision 2446)
+++ mln/win/cuboid3d.hh (working copy)
@@ -31,14 +31,16 @@
/// \file mln/win/cuboid3d.hh
/// \brief Definition of the mln::win::cuboid3d window.
-# include <mln/core/internal/window_base.hh>
-# include <mln/core/internal/dpsites_impl.hh>
+# include <mln/core/internal/classical_window_base.hh>
# include <mln/core/alias/dpoint3d.hh>
namespace mln
{
+ mln_internal_add_classical_window_trait(cuboid3d);
+
+
namespace win
{
@@ -73,8 +75,7 @@
Reference:
http://en.wikipedia.org/wiki/Cuboid
*/
- struct cuboid3d : public internal::window_base< dpoint3d, cuboid3d >,
- public internal::dpsites_impl< dpoint3d, cuboid3d >
+ struct cuboid3d : public internal::classical_window_base< dpoint3d, cuboid3d >
{
/// \brief Constructor.
///
@@ -86,16 +87,6 @@
cuboid3d(unsigned depth, unsigned height, unsigned width);
- /// Properties of the window.
- /// \{
- /// \brief Test if the window is centered.
- /// \return \c true (always).
- bool is_centered() const;
- /// \brief Test if the window is symmetric.
- /// \return \c true (always).
- bool is_symmetric() const;
- /// \}
-
/// Accessors.
/// \{
/// \brief Return the depth of the cuboid.
@@ -111,10 +102,9 @@
/// \brief Give the maximum coordinate gap between the center of
/// the window and a point of the window.
- unsigned delta() const;
+ unsigned delta_() const;
- /// Apply a central symmetry to the target window.
- cuboid3d& sym();
+ void print_(std::ostream& ostr) const;
protected:
/// The depth of the cuboid (expressed as a number of slices).
@@ -126,17 +116,6 @@
};
- /// \brief Print a cuboid window \a win into the output stream \a ostr.
- ///
- /// \param[in,out] ostr An output stream.
- /// \param[in] win A cuboid window.
- ///
- /// \return The modified output stream \a ostr.
- ///
- /// \relates mln::win::cuboid3d
- std::ostream& operator<<(std::ostream& ostr, const cuboid3d& win);
-
-
# ifndef MLN_INCLUDE_ONLY
@@ -157,20 +136,6 @@
}
inline
- bool
- cuboid3d::is_centered() const
- {
- return true;
- }
-
- inline
- bool
- cuboid3d::is_symmetric() const
- {
- return true;
- }
-
- inline
unsigned
cuboid3d::depth() const
{
@@ -200,7 +165,7 @@
inline
unsigned
- cuboid3d::delta() const
+ cuboid3d::delta_() const
{
if (depth_ > height_)
if (depth_ > width_)
@@ -219,20 +184,12 @@
}
inline
- cuboid3d&
- cuboid3d::sym()
- {
- return *this;
- }
-
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const cuboid3d& win)
+ void
+ cuboid3d::print_(std::ostream& ostr) const
{
- ostr << "[cuboid3d: width=" << win.depth()
- << ", depth=" << win.width()
- << ", height=" << win.height() << ']';
- return ostr;
+ ostr << "[cuboid3d: width=" << depth_
+ << ", depth=" << width_
+ << ", height=" << height_ << ']';
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/win/octagon2d.hh
--- mln/win/octagon2d.hh (revision 2446)
+++ mln/win/octagon2d.hh (working copy)
@@ -33,14 +33,16 @@
* \brief Definition of the mln::win::octagon2d window.
*/
-# include <mln/core/internal/window_base.hh>
-# include <mln/core/internal/dpsites_impl.hh>
+# include <mln/core/internal/classical_window_base.hh>
# include <mln/core/alias/dpoint2d.hh>
namespace mln
{
+ mln_internal_add_classical_window_trait(octagon2d);
+
+
namespace win
{
@@ -61,8 +63,7 @@
* o o o \n
* is defined with L = 7 (l = 1).
*/
- struct octagon2d : public internal::window_base< dpoint2d, octagon2d >,
- public internal::dpsites_impl< dpoint2d, octagon2d >
+ struct octagon2d : public internal::classical_window_base< dpoint2d, octagon2d >
{
/*! \brief Constructor.
*
@@ -72,18 +73,6 @@
*/
octagon2d(unsigned length);
- /*! \brief Test if the window is centered.
- *
- * \return True.
- */
- bool is_centered() const;
-
- /*! \brief Test if the window is symmetric.
- *
- * \return true.
- */
- bool is_symmetric() const;
-
/*! \brief Give the octagon length, that is, its width.
*/
unsigned length() const;
@@ -91,33 +80,19 @@
/*! \brief Give the maximum coordinate gap between the window
* center and a window point.
*/
- unsigned delta() const;
+ unsigned delta_() const;
/*! \brief Give the area.
*/
unsigned area() const;
- /// Apply a central symmetry to the target window.
- octagon2d& sym();
+ void print_(std::ostream& ostr) const;
protected:
unsigned length_;
};
- /*! \brief Print an octagon window \p win into the output
- * stream \p ostr.
- *
- * \param[in,out] ostr An output stream.
- * \param[in] win An octagon window.
- *
- * \return The modified output stream \p ostr.
- *
- * \relates mln::win::octagon2d
- */
- std::ostream& operator<<(std::ostream& ostr, const octagon2d& win);
-
-
# ifndef MLN_INCLUDE_ONLY
@@ -153,25 +128,13 @@
}
inline
- bool octagon2d::is_centered() const
- {
- return true;
- }
-
- inline
- bool octagon2d::is_symmetric() const
- {
- return true;
- }
-
- inline
unsigned octagon2d::length() const
{
return length_;
}
inline
- unsigned octagon2d::delta() const
+ unsigned octagon2d::delta_() const
{
return length_ / 2;
}
@@ -184,16 +147,9 @@
}
inline
- octagon2d& octagon2d::sym()
- {
- return *this;
- }
-
- inline
- std::ostream& operator<<(std::ostream& ostr, const octagon2d& win)
+ void octagon2d::print_(std::ostream& ostr) const
{
- ostr << "[octagon2d: length=" << win.length() << ']';
- return ostr;
+ ostr << "[octagon2d: length=" << length_ << ']';
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/win/disk2d.hh
--- mln/win/disk2d.hh (revision 2446)
+++ mln/win/disk2d.hh (working copy)
@@ -33,14 +33,16 @@
* \brief Definition of the mln::win::disk2d window.
*/
-# include <mln/core/internal/window_base.hh>
-# include <mln/core/internal/dpsites_impl.hh>
+# include <mln/core/internal/classical_window_base.hh>
# include <mln/core/alias/dpoint2d.hh>
namespace mln
{
+ mln_internal_add_classical_window_trait(disk2d);
+
+
namespace win
{
@@ -49,8 +51,7 @@
* An disk2d is centered and symmetric.
*
*/
- struct disk2d : public internal::window_base< dpoint2d, disk2d >,
- public internal::dpsites_impl< dpoint2d, disk2d >
+ struct disk2d : public internal::classical_window_base< dpoint2d, disk2d >
{
/*! \brief Constructor.
*
@@ -59,48 +60,22 @@
*/
disk2d(unsigned length);
- /*! \brief Test if the window is centered.
- *
- * \return True.
- */
- bool is_centered() const;
-
- /*! \brief Test if the window is symmetric.
- *
- * \return true.
- */
- bool is_symmetric() const;
-
- /*! \brief Give the disk length, that is, its width.
+ /*! \brief Give the disk diameter.
*/
unsigned length() const;
/*! \brief Give the maximum coordinate gap between the window
* center and a window point.
*/
- unsigned delta() const;
+ unsigned delta_() const;
- /// Apply a central symmetry to the target window.
- disk2d& sym();
+ void print_(std::ostream& ostr) const;
protected:
unsigned length_;
};
- /*! \brief Print an disk window \p win into the output
- * stream \p ostr.
- *
- * \param[in,out] ostr An output stream.
- * \param[in] win A disk window.
- *
- * \return The modified output stream \p ostr.
- *
- * \relates mln::win::disk2d
- */
- std::ostream& operator<<(std::ostream& ostr, const disk2d& win);
-
-
# ifndef MLN_INCLUDE_ONLY
@@ -118,40 +93,21 @@
}
inline
- bool disk2d::is_centered() const
- {
- return true;
- }
-
- inline
- bool disk2d::is_symmetric() const
- {
- return true;
- }
-
- inline
unsigned disk2d::length() const
{
return length_;
}
inline
- unsigned disk2d::delta() const
+ unsigned disk2d::delta_() const
{
return length_ / 2;
}
inline
- disk2d& disk2d::sym()
- {
- return *this;
- }
-
- inline
- std::ostream& operator<<(std::ostream& ostr, const disk2d& win)
+ void disk2d::print_(std::ostream& ostr) const
{
- ostr << "[disk2d: length=" << win.length() << ']';
- return ostr;
+ ostr << "[disk2d: length=" << length_ << ']';
}
# endif // ! MLN_INCLUDE_ONLY
1
0