Commit 9ff8258e authored by Roland Levillain's avatar Roland Levillain
Browse files

Add a backward iterator on complex-based images.

	* mln/core/p_complex_piter.hh (mln::p_complex_bkd_piter_<D, P>):
	(operator<<(std::ostream&, const p_complex_bkd_piter_<D, P>&)):
	New.
	(mln::p_complex_fwd_piter_<D, P>::next_): Reimplement to make it
	symmetric to mln::p_complex_bkd_piter_<D, P>::next_.
	* mln/core/p_complex.hh (mln::p_complex<D, P>::bkd_piter): Set
	typedef to p_complex_bkd_piter_<D, P>.
	* mln/core/p_complex_piter.hh: Test the backward iterator on
	complex_image.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@2148 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent 366a438f
2008-08-12 Roland Levillain <roland@lrde.epita.fr>
Add a backward iterator on complex-based images.
* mln/core/p_complex_piter.hh (mln::p_complex_bkd_piter_<D, P>):
(operator<<(std::ostream&, const p_complex_bkd_piter_<D, P>&)):
New.
(mln::p_complex_fwd_piter_<D, P>::next_): Reimplement to make it
symmetric to mln::p_complex_bkd_piter_<D, P>::next_.
* mln/core/p_complex.hh (mln::p_complex<D, P>::bkd_piter): Set
typedef to p_complex_bkd_piter_<D, P>.
* mln/core/p_complex_piter.hh: Test the backward iterator on
complex_image.
2008-08-12 Roland Levillain <roland@lrde.epita.fr>
Add a forward iterator on complex-based images.
......
......@@ -73,9 +73,10 @@ namespace mln
/// Point_Site associated type.
typedef complex_psite<D, P> psite;
// FIXME: Fake.
/// Forward Point_Iterator associated type.
typedef p_complex_fwd_piter_<D, P> fwd_piter;
typedef void bkd_piter;
/// Backward Point_Iterator associated type.
typedef p_complex_bkd_piter_<D, P> bkd_piter;
/// \brief Return The number of points (sites) of the set, i.e., the
/// number of \em faces.
......
......@@ -37,8 +37,12 @@
/// \file mln/core/p_complex_piter.hh
/// \brief Definition of point iterator on complex-based pset.
// Factor p_complex_fwd_piter_<D, P> and p_complex_bkd_piter_<D, P>
namespace mln
{
/* FIXME: Get rid of P? */
// Fwd decls.
template <unsigned D, typename P> class p_complex;
template <unsigned D, typename P> class complex_psite;
......@@ -48,8 +52,6 @@ namespace mln
| p_complex_fwd_piter_<D, P>. |
`-----------------------------*/
/* FIXME: Get rid of P? */
/// \brief Forward iterator on point sites of a mln::p_complex<D, P>.
template <unsigned D, typename P>
class p_complex_fwd_piter_
......@@ -143,14 +145,100 @@ namespace mln
| p_complex_bkd_piter_<D, P>. |
`-----------------------------*/
// FIXME: Define p_complex_bkd_piter_<D, P>.
/// \brief Backward iterator on point sites of a mln::p_complex<D, P>.
template <unsigned D, typename P>
class p_complex_bkd_piter_
: public internal::point_iterator_base_< P, p_complex_bkd_piter_<D, P> >
{
typedef p_complex_bkd_piter_<D, P> self_;
typedef internal::point_iterator_base_< P, self_ > super_;
public:
// Make definitions from super class available.
// FIXME: Is it still meaningful for a complex?
enum { dim = super_::dim };
typedef complex_psite<D, P> psite;
typedef P point;
typedef mln_coord(point) coord;
/// Construction and assignment.
/// \{
p_complex_bkd_piter_(const p_complex<D, P>& pc);
p_complex_bkd_piter_(const self_& rhs);
self_& operator= (const self_& rhs);
/// \}
/// 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 point.
void next_();
/// Update the internal data of the iterator.
void update_();
/// \}
/// Conversion and accessors.
/// \{
/// Reference to the corresponding point.
// FIXME: Don't use this method (dummy value).
const point& to_point () const;
/// Reference to the corresponding point site.
const psite& to_psite () const;
/// Convert the iterator into a line graph psite.
operator psite() const;
/// Read-only access to the \a i-th coordinate.
// FIXME: Don't use this operator (dummy value).
coord operator[](unsigned i) const;
/// \}
private:
/// The face handle this iterator is pointing to.
any_face_handle<D> face_;
/// The psite corresponding to this iterator.
psite psite_;
/// \brief The point associated to this psite.
// FIXME: Actually, this is a dummy value!
point p_;
/// \brief An invalid value for both the dimension and the id of
/// the face.
///
/// Use a function instead of a static constant, since `static'
/// variables needs to be compiled once, which requires a compiled
/// library to avoid duplicate symbols, which is something that
/// was not really planned in Milena. A function tagged `inlined'
/// can appear multiple times in a program, and solves this
/// problem. We rely on the compiler to inline this call.
///
/// Of course, we could have used UINT_MAX, but it is not very
/// C++.
unsigned invalid_unsigned_() const;
};
/* FIXME: This hand-made delegation is painful. We should rely on
the general mechanism provided by Point_Site. But then again, we
need to refine/adjust the interface of Point_Site w.r.t. the
mandatory conversions to points. */
template <unsigned D, typename P>
inline
std::ostream&
operator<<(std::ostream& ostr, const p_complex_bkd_piter_<D, P>& p);
# ifndef MLN_INCLUDE_ONLY
/*-----------------------------.
| p_line_graph_fwd_piter_<P>. |
| p_complex_fwd_piter_<D, P>. |
`-----------------------------*/
template <unsigned D, typename P>
......@@ -228,10 +316,11 @@ namespace mln
void
p_complex_fwd_piter_<D, P>::next_()
{
unsigned n = face_.n();
unsigned face_id = face_.face_id();
if (n <= D)
if (is_valid())
{
unsigned n = face_.n();
unsigned face_id = face_.face_id();
if (face_id + 1 < face_.cplx().nfaces(n))
/* FIXME: Provide accessor any_face_handle::n() returning
a mutable reference? This way, we could just write
......@@ -241,12 +330,16 @@ namespace mln
instead of the following. */
face_.set_face_id(face_id + 1);
else
{
// Start to iterate on the faces of the next dimension.
// FIXME: Same remark as above.
face_.set_n(n + 1);
face_.set_face_id(0u);
}
// Start to iterate on the faces of the next dimension if
// possible.
if (n <= D)
{
// FIXME: Same remark as above.
face_.set_n(n + 1);
face_.set_face_id(0u);
}
else
invalidate();
}
if (is_valid())
update_();
......@@ -331,7 +424,183 @@ namespace mln
| p_complex_bkd_piter_<D, P>. |
`-----------------------------*/
// FIXME: Implement p_complex_bkd_piter_<D, P>.
template <unsigned D, typename P>
inline
p_complex_bkd_piter_<D, P>::p_complex_bkd_piter_(const p_complex<D, P>& pc)
// Initialize psite_ and p_ a dummy values.
: psite_(),
p_()
{
face_.set_cplx(pc.cplx());
// Invalidate face_.
invalidate();
}
template <unsigned D, typename P>
inline
p_complex_bkd_piter_<D, P>::p_complex_bkd_piter_(const p_complex_bkd_piter_<D, P>& rhs)
: face_(rhs.face_),
psite_(rhs.psite_),
// Dummy value.
p_()
{
}
template <unsigned D, typename P>
inline
p_complex_bkd_piter_<D, P>&
p_complex_bkd_piter_<D, P>::operator=(const p_complex_bkd_piter_<D, P>& rhs)
{
if (&rhs == this)
return *this;
face_ = rhs.face_;
psite_ = rhs.psite_;
return *this;
}
template <unsigned D, typename P>
inline
mln_coord(P)
p_complex_bkd_piter_<D, P>::operator[](unsigned i) const
{
// Dummy value.
return p_[i];
}
template <unsigned D, typename P>
inline
bool
p_complex_bkd_piter_<D, P>::is_valid() const
{
return face_.is_valid();
}
template <unsigned D, typename P>
inline
void
p_complex_bkd_piter_<D, P>::invalidate()
{
face_.set_n(invalid_unsigned_());
face_.set_face_id(invalid_unsigned_());
}
template <unsigned D, typename P>
inline
void
p_complex_bkd_piter_<D, P>::start()
{
face_.set_n(D);
face_.set_face_id(face_.cplx().template nfaces<D>() - 1);
update_();
}
template <unsigned D, typename P>
inline
void
p_complex_bkd_piter_<D, P>::next_()
{
if (is_valid())
{
unsigned n = face_.n();
unsigned face_id = face_.face_id();
if (face_id > 0)
/* FIXME: Provide accessor any_face_handle::n() returning
a mutable reference? This way, we could just write
++face_.face_id();
instead of the following. */
face_.set_face_id(face_id - 1);
else
// Start to iterate on the faces of the previous dimension
// if it exists.
if (n > 0)
{
// FIXME: Same remark as above.
face_.set_n(n - 1);
face_.set_face_id(face_.cplx().nfaces(n - 1) - 1);
}
else
invalidate();
}
if (is_valid())
update_();
}
template <unsigned D, typename P>
inline
void
p_complex_bkd_piter_<D, P>::update_()
{
// Update psite_.
psite_ = complex_psite<D, P>(face_);
}
template <unsigned D, typename P>
inline
const P&
p_complex_bkd_piter_<D, P>::to_point() const
{
// Dummy value.
return p_;
}
template <unsigned D, typename P>
inline
const complex_psite<D, P>&
p_complex_bkd_piter_<D, P>::to_psite() const
{
/* We don't check whether the iterator is valid before returning
the value using
mln_precondition(is_valid());
since this method may be called *before* the iterator is
actually initialized. This is the case for instance when this
point iterator (say, P) is used to initialize another iterator
on window or neighborhood (say, Q); most of the time, for_all()
is responsible for the initialization of P, but it takes place
*after* the creation of Q. */
return psite_;
}
template <unsigned D, typename P>
inline
p_complex_bkd_piter_<D, P>::operator complex_psite<D, P>() const
{
mln_precondition(is_valid());
return psite_;
}
template <unsigned D, typename P>
unsigned
p_complex_bkd_piter_<D, P>::invalid_unsigned_() const
{
return std::numeric_limits<unsigned>::max();
}
template <unsigned D, typename P>
inline
std::ostream&
operator<<(std::ostream& ostr, const p_complex_bkd_piter_<D, P>& p)
{
/* FIXME: We should use p.to_psite() here, but as it lacks the
precondition the conversion operator has, so we use the latter.
We should
- rename `to_psite' as `to_psite_';
- write a new `to_psite' routine checking the validity of the
iterator;
- have the conversion operator to psite use this new `to_psite'
routine;
- adjust former clients of `to_psite'
This is a general remark that applies to all point/psite
iterators of Milena. */
return ostr << static_cast< complex_psite<D, P> >(p);
}
# endif // ! MLN_INCLUDE_ONLY
......
......@@ -194,18 +194,34 @@ int main()
| Complex-based image iterators. |
`--------------------------------*/
mln_piter_(ima_t) p(ima.domain());
for_all(p)
std::cout << "ima(" << p << ") = " << ima(p) << std::endl;
mln_fwd_piter_(ima_t) fp(ima.domain());
for_all(fp)
std::cout << "ima(" << fp << ") = " << ima(fp) << std::endl;
std::cout << std::endl;
/* FIXME: Implement windows (and neighborhoods) for complex-images.
mln_bkd_piter_(ima_t) bp(ima.domain());
for_all(bp)
std::cout << "ima(" << bp << ") = " << ima(bp) << std::endl;
/* FIXME: Implement other psite iterators, for instance:
- iterators on N-faces with N fixed in [0, D] (using p_faces
and faces_psite?)
- iterators on N-faces with N in a subset of [0, D];
- etc. */
/* FIXME: Implement windows (and neighborhoods) and corresponding
iterators for complex-based images.
For a given (fixed) dimension N and a psite P on a N-face,
implement windows returning
- the set of (N-1)-faces adjacent to P;
- the set of (N+1)-faces adjacent to P;
- the set of (N-1)-faces adjacent to P (using p_faces and
faces_psite?);
- the set of (N+1)-faces adjacent to P (using p_faces and
faces_psite?);
- the set of N-faces sharing a (N-1)-face with P;
- the set of N-faces sharing a (N-1)-face or (N-2)-face (by
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment