Commit 3ddba94e authored by Roland Levillain's avatar Roland Levillain
Browse files

Add complex-based psite and pset.

	* mln/core/complex_psite.hh, mln/core/p_complex.hh: New.
	* mln/core/face.hh: s/mln_assertion/mln_precondition/.
	(mln::face_handle<N, D>::face_handle): Statically ensure N is
	compatible with D in ctors.
	* tests/core/p_complex.cc: New test.
	* tests/core/Makefile.am (check_PROGRAMS): Add p_complex.
	(p_complex_SOURCES): New.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@2122 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent d1433673
2008-08-06 Roland Levillain <roland@lrde.epita.fr>
Add complex-based psite and pset.
* mln/core/complex_psite.hh, mln/core/p_complex.hh: New.
* mln/core/face.hh: s/mln_assertion/mln_precondition/.
(mln::face_handle<N, D>::face_handle): Statically ensure N is
compatible with D in ctors.
* tests/core/p_complex.cc: New test.
* tests/core/Makefile.am (check_PROGRAMS): Add p_complex.
(p_complex_SOURCES): New.
2008-08-06 Roland Levillain <roland@lrde.epita.fr>
Check more preconditions in mln::complex<D>.
......
// 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_CORE_COMPLEX_PSITE_HH
# define MLN_CORE_COMPLEX_PSITE_HH
/// \file mln/core/complex_psite.hh
/// \brief Definition of a complex-based point site.
# include <mln/core/concept/point_site.hh>
# include <mln/core/complex.hh>
namespace mln
{
/* FIXME: Write also a complex_psite where N is dynamic, and can be
changed? */
/* FIXME: Currently, P and N are free variables; we might want to
relate them, e.g., have P::dim == N. Or even get rid of P. */
/// \brief Point site associated to a mln::complex_image.
///
/// \arg \p P The type of point associated to this psite.
/// \arg \p N The dimension of the face associated to this psite.
/// \arg \p D The dimention of the complex this psite belongs to.
template <typename P, unsigned N, unsigned D>
class complex_psite : public Point_Site< complex_psite<P, N, D> >
{
typedef complex_psite<P, N, D> self_;
typedef Point_Site<self_> super_;
public:
typedef mln_mesh(P) mesh;
enum { dim = P::dim };
typedef P point;
typedef mln_dpoint(P) dpoint;
typedef mln_coord(P) coord;
/// Construction and assignment.
/// \{
complex_psite();
complex_psite(const face_handle<N, D>& face);
complex_psite(const self_& rhs);
self_& operator= (const self_& rhs);
/// \}
/// Access to psite.
const self_& to_psite() const;
/* FIXME: Should be removed as soon as ``point sets'' become
``site sets''. */
/// Access to point.
/// \{
const point& to_point() const;
coord operator[](unsigned face) const;
/// \}
/// Return the face handle of this point site.
face_handle<N, D> face() const;
/// Return the complex on which this site is built.
const complex<D>& cplx() const;
/// Is this psite valid?
bool is_valid() const;
private:
/// The handle of the face this psite is pointing towards.
face_handle<N, D> face_;
// FIXME: Actually, this is a dummy value!
point p_;
};
/// Comparison of two instances of mln::complex_psite.
/// \{
/* FIXME: Shouldn't those comparisons be part of a much general
mechanism? */
/// \brief Is \a lhs equal to \a rhs?
///
/// \pre Arguments \a lhs and \a rhs must belong to the same
/// mln::complex.
template <typename P, unsigned N, unsigned D>
bool
operator==(const complex_psite<P, N, D>& lhs,
const complex_psite<P, N, D>& rhs);
/// \brief Is \a lhs ``less'' than \a rhs?
///
/// This comparison is required by algorithms sorting psites.
///
/// \pre Arguments \a lhs and \a rhs must belong to the same
/// mln::complex.
template <typename P, unsigned N, unsigned D>
bool
operator< (const complex_psite<P, N, D>& lhs,
const complex_psite<P, N, D>& rhs);
/// \}
# ifndef MLN_INCLUDE_ONLY
template <typename P, unsigned N, unsigned D>
inline
complex_psite<P, N, D>::complex_psite()
: super_(),
// Dummy initializations.
face_(), p_()
{
// Ensure N is compatible with D.
metal::bool_< N <= D >::check();
}
template <typename P, unsigned N, unsigned D>
inline
complex_psite<P, N, D>::complex_psite(const face_handle<N, D>& face)
: super_(),
face_(face), p_()
{
// Ensure N is compatible with D.
metal::bool_< N <= D >::check();
}
template <typename P, unsigned N, unsigned D>
inline
complex_psite<P, N, D>::complex_psite(const complex_psite<P, N, D>& rhs)
: super_(rhs),
face_(rhs.face_), p_()
{
// Ensure N is compatible with D.
metal::bool_< N <= D >::check();
}
template <typename P, unsigned N, unsigned D>
inline
complex_psite<P, N, D>&
complex_psite<P, N, D>::operator= (const complex_psite<P, N, D>& rhs)
{
if (&rhs == this)
return *this;
face_ = rhs.face_;
return *this;
}
template <typename P, unsigned N, unsigned D>
inline
bool
complex_psite<P, N, D>::is_valid() const
{
return face.is_valid();
}
template <typename P, unsigned N, unsigned D>
inline
const complex_psite<P, N, D>&
complex_psite<P, N, D>::to_psite() const
{
return *this;
}
template <typename P, unsigned N, unsigned D>
inline
const P&
complex_psite<P, N, D>::to_point() const
{
// FIXME: Dummy value.
return p_;
}
template <typename P, unsigned N, unsigned D>
inline
mln_coord(P)
complex_psite<P, N, D>::operator[](unsigned i) const
{
mln_precondition(is_valid());
return to_point()[i];
}
template <typename P, unsigned N, unsigned D>
inline
face_handle<N, D>
complex_psite<P, N, D>::face() const
{
return face_;
}
template <typename P, unsigned N, unsigned D>
inline
const complex<D>&
complex_psite<P, N, D>::cplx() const
{
return face_.cplx();
}
/*--------------.
| Comparisons. |
`--------------*/
template <typename P, unsigned N, unsigned D>
bool
operator==(const complex_psite<P, N, D>& lhs,
const complex_psite<P, N, D>& rhs)
{
mln_precondition(&lhs.cplx() == &rhs.cplx());
return lhs.face() == rhs.face();
}
template <typename P, unsigned N, unsigned D>
bool
operator< (const complex_psite<P, N, D>& lhs,
const complex_psite<P, N, D>& rhs)
{
mln_precondition(&lhs.cplx() == &rhs.cplx());
return lhs.face() < rhs.face();
}
# endif // ! MLN_INCLUDE_ONLY
} // end of mln
#endif // MLN_CORE_COMPLEX_PSITE_HH
......@@ -150,7 +150,6 @@ namespace mln
/// Accessors.
/// \{
/// Return the complex the face belongs to.
// FIXME: Rename to complex()?
complex<D>& cplx() const;
/// Return the id of the face.
unsigned face_id() const;
......@@ -269,18 +268,24 @@ namespace mln
face_handle<N, D>::face_handle()
: cplx_(0), face_id_(UINT_MAX)
{
// Ensure N is compatible with D.
metal::bool_< N <= D >::check();
}
template <unsigned N, unsigned D>
face_handle<N, D>::face_handle(complex<D>& c, unsigned face_id)
: cplx_(&c), face_id_(face_id)
{
// Ensure N is compatible with D.
metal::bool_< N <= D >::check();
}
template <unsigned N, unsigned D>
face_handle<N, D>::face_handle(const face_handle<N, D>& rhs)
: cplx_(rhs.cplx_), face_id_(rhs.face_id_)
{
// Ensure N is compatible with D.
metal::bool_< N <= D >::check();
}
template <unsigned N, unsigned D>
......@@ -306,7 +311,7 @@ namespace mln
complex<D>&
face_handle<N, D>::cplx() const
{
mln_assertion(cplx_);
mln_precondition(cplx_);
return *cplx_;
}
......@@ -321,7 +326,7 @@ namespace mln
face<N, D>&
face_handle<N, D>::to_face() const
{
mln_assertion(is_valid());
mln_precondition(is_valid());
return cplx_->template face_<N>(face_id_);
}
......@@ -337,7 +342,7 @@ namespace mln
bool
operator==(const face_handle<N, D>& lhs, const face_handle<N, D>& rhs)
{
mln_assertion(&lhs.face.cplx() == &rhs.face.cplx());
mln_precondition(&lhs.face.cplx() == &rhs.face.cplx());
return lhs.face().id() == rhs.face().id();
}
......@@ -345,7 +350,7 @@ namespace mln
bool
operator< (const face_handle<N, D>& lhs, const face_handle<N, D>& rhs)
{
mln_assertion(&lhs.face.cplx() == &rhs.face.cplx());
mln_precondition(&lhs.face.cplx() == &rhs.face.cplx());
return lhs.face().id() < rhs.face().id();
}
......@@ -360,7 +365,7 @@ namespace mln
{
// Check consistency.
if (!faces_.empty())
mln_assertion(&faces_.front().cplx() == &f.cplx());
mln_precondition(&faces_.front().cplx() == &f.cplx());
faces_.push_back(f);
}
......
// 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_CORE_P_COMPLEX_HH
# define MLN_CORE_P_COMPLEX_HH
/// \file mln/core/p_complex.hh
/// \brief Definition of a point set based on a complex.
# include <mln/core/internal/point_set_base.hh>
# include <mln/accu/bbox.hh>
# include <mln/util/tracked_ptr.hh>
# include <mln/core/complex.hh>
# include <mln/core/complex_psite.hh>
namespace mln
{
/// A complex psite set based on a complex of dimension \p D (a \p
/// D-complex).
template<typename P, unsigned N, unsigned D>
struct p_complex
: public internal::point_set_base_< complex_psite<P, N, D>,
p_complex<P, N, D> >
{
/// \brief Construct a complex psite set from a complex.
///
/// \param gr The complex upon which the complex psite set is built.
///
/// \a gr is \em copied internally, so that the complex psite set is
/// still valid after the initial complex has been removed.
p_complex (const complex<D>& cplx);
/// Point_Site associated type.
typedef complex_psite<P, N, D> psite;
// FIXME: Fake.
typedef void fwd_piter;
typedef void bkd_piter;
/// \brief Return The number of points (sites) of the set, i.e., the
/// number of \em faces.
///
/// Required by the mln::Point_Set concept.
std::size_t npoints() const;
/// Return The number of faces in the complex.
std::size_t nfaces() const;
/// Give the exact bounding box.
const box_<P>& bbox() const;
bool has(const psite& p) const;
/// Return the complex associated to the p_complex domain.
const complex<D>& cplx() const;
private:
/// The complex on which this pset is built.
util::tracked_ptr< complex<D> > cplx_;
// FIXME: Remove as soon as bbox become optional.
box_<P> bb_;
};
/// \brief Comparison between two mln::p_complex's.
///
/// Two mln::p_complex's are considered equal if they share the
/// same complex.
template <typename P, unsigned N, unsigned D>
bool
operator==(const p_complex<P, N, D>& lhs, const p_complex<P, N, D>& rhs);
/// \brief Inclusion of a mln::p_complex in another one.
///
/// This inclusion relation is very strict for the moment, since our
/// infrastrure for complexs is simple: a mln::p_complex is included
/// in another one if their are equal.
///
/// \todo Refine this later, when we are able to express subcomplex
/// relations.
template <typename P, unsigned N, unsigned D>
bool
operator<=(const p_complex<P, N, D>& lhs, const p_complex<P, N, D>& rhs);
# ifndef MLN_INCLUDE_ONLY
template <typename P, unsigned N, unsigned D>
inline
p_complex<P, N, D>::p_complex(const complex<D>& cplx)
// Create a deep, managed copy of CPLX.
: cplx_(new complex<D>(cplx))
{
// Ensure N is compatible with D.
metal::bool_< N <= D >::check();
// FIXME: Dummy initialization.
accu::bbox<P> a;
for (unsigned i = 0; i < npoints(); ++i)
a.take(P());
bb_ = a.to_result();
}
template <typename P, unsigned N, unsigned D>
inline
std::size_t
p_complex<P, N, D>::npoints() const
{
return nfaces();
}
template <typename P, unsigned N, unsigned D>
inline
std::size_t
p_complex<P, N, D>::nfaces() const
{
return this->cplx_->template nfaces<N>();
}
template <typename P, unsigned N, unsigned D>
inline
const box_<P>&
p_complex<P, N, D>::bbox() const
{
// FIXME: Dummy value.
return bb_;
}
template <typename P, unsigned N, unsigned D>
inline
bool
p_complex<P, N, D>::has(const psite& p) const
{
return
// Check whether P's complex is compatible with this pset's complex.
&p.cplx() == &cplx() &&
// Check whether the complex has the face associated to P.
p.face().is_valid();
}
template <typename P, unsigned N, unsigned D>
const complex<D>&
p_complex<P, N, D>::cplx() const
{
mln_precondition(cplx_);
return *cplx_.ptr_;
}
template <typename P, unsigned N, unsigned D>
bool
operator==(const p_complex<P, N, D>& lhs, const p_complex<P, N, D>& rhs)
{
return lhs.cplx_.ptr_ == rhs.cplx_.ptr_;
}
template <typename P, unsigned N, unsigned D>
bool
operator<=(const p_complex<P, N, D>& lhs, const p_complex<P, N, D>& rhs)
{
return lhs == rhs;
}
# endif // ! MLN_INCLUDE_ONLY
} // end of mln
#endif // MLN_CORE_P_COMPLEX_HH
......@@ -51,6 +51,7 @@ check_PROGRAMS = \
\
obased_rle_image \
\
p_complex \
p_priority_queue \
p_priority_queue_fast \
p_priority_queue_fast_with_array \
......@@ -138,6 +139,7 @@ neighb_SOURCES = neighb.cc
obased_rle_image_SOURCES = obased_rle_image.cc
p_complex_SOURCES = p_complex.cc
p_priority_queue_SOURCES = p_priority_queue.cc
p_priority_queue_fast_SOURCES = p_priority_queue_fast.cc
p_priority_queue_fast_with_array_SOURCES = p_priority_queue_fast.cc
......
// 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.
/// \file tests/core/p_complex.cc
/// \brief Test of mln::p_complex.
#include <iostream>
#include <mln/core/p_complex.hh>
#include <mln/core/point2d.hh>
// FIXME: Extend this test and rename it as complex_image.cc.
int main()
{
using namespace mln;
/*----------.
| Complex. |
`----------*/
/* A 2-d (simplicial) complex and its adjacency graph.
v0 e3 v3
o-----------o v0----e3----v3
/ \ ,-----. / / \ | /
/ . \ \ t2/ / / \ t2 /
e0 / / \ e1\ / / e4 e0. ,e1 `e4
/ /t1 \ \ ' / / t1 \ /
/ `-----' \ / / | \ /
o-----------o v1----e2----v2
v1 e2 v2
v = vertex
e = edge
t = triangle
*/
complex<2> c;
// 0-faces (points).