2121: Add complex-based psite and pset.
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from 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. mln/core/complex_psite.hh | 249 ++++++++++++++++++++++++++++++++++++++++++++++ mln/core/face.hh | 17 ++- mln/core/p_complex.hh | 199 ++++++++++++++++++++++++++++++++++++ tests/core/Makefile.am | 2 tests/core/p_complex.cc | 95 +++++++++++++++++ 5 files changed, 556 insertions(+), 6 deletions(-) Index: mln/core/face.hh --- mln/core/face.hh (revision 2121) +++ mln/core/face.hh (working copy) @@ -150,7 +150,6 @@ /// 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 @@ 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 @@ complex<D>& face_handle<N, D>::cplx() const { - mln_assertion(cplx_); + mln_precondition(cplx_); return *cplx_; } @@ -321,7 +326,7 @@ 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 @@ 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 @@ 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 @@ { // Check consistency. if (!faces_.empty()) - mln_assertion(&faces_.front().cplx() == &f.cplx()); + mln_precondition(&faces_.front().cplx() == &f.cplx()); faces_.push_back(f); } Index: mln/core/complex_psite.hh --- mln/core/complex_psite.hh (revision 0) +++ mln/core/complex_psite.hh (revision 0) @@ -0,0 +1,249 @@ +// 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 Index: mln/core/p_complex.hh --- mln/core/p_complex.hh (revision 0) +++ mln/core/p_complex.hh (revision 0) @@ -0,0 +1,199 @@ +// 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 Index: tests/core/p_complex.cc --- tests/core/p_complex.cc (revision 0) +++ tests/core/p_complex.cc (revision 0) @@ -0,0 +1,95 @@ +// 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). + face_handle<0, 2> v0 = c.add_face(); + face_handle<0, 2> v1 = c.add_face(); + face_handle<0, 2> v2 = c.add_face(); + face_handle<0, 2> v3 = c.add_face(); + + // 1-faces (segments). + face_handle<1, 2> e0 = c.add_face(v0 + v1); + face_handle<1, 2> e1 = c.add_face(v0 + v2); + face_handle<1, 2> e2 = c.add_face(v1 + v2); + face_handle<1, 2> e3 = c.add_face(v0 + v3); + face_handle<1, 2> e4 = c.add_face(v2 + v3); + + // 2-faces (triangles). + face_handle<2, 2> t0 = c.add_face(e0 + e1 + e2); + face_handle<2, 2> t1 = c.add_face(e1 + e3 + e4); + + + /*----------------------. + | Complex-based psets. | + `----------------------*/ + + // Pset of 0-faces. + p_complex<point2d, 0, 2> pc0(c); + // Pset of 1-faces. + p_complex<point2d, 1, 2> pc1(c); + // Pset of 2-faces. + p_complex<point2d, 2, 2> pc2(c); +} Index: tests/core/Makefile.am --- tests/core/Makefile.am (revision 2121) +++ tests/core/Makefile.am (working copy) @@ -51,6 +51,7 @@ \ obased_rle_image \ \ + p_complex \ p_priority_queue \ p_priority_queue_fast \ p_priority_queue_fast_with_array \ @@ -138,6 +139,7 @@ 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
participants (1)
-
Roland Levillain