let circulators return smart handles

This commit is contained in:
Max Lyon
2019-09-27 09:29:27 +02:00
parent 253c9b6afa
commit b62d846f32
4 changed files with 1034 additions and 589 deletions

View File

@@ -40,9 +40,8 @@
* ========================================================================= */ * ========================================================================= */
#pragma once
#ifndef OPENMESH_CIRCULATORS_HH
#define OPENMESH_CIRCULATORS_HH
//============================================================================= //=============================================================================
// //
// Vertex and Face circulators for PolyMesh/TriMesh // Vertex and Face circulators for PolyMesh/TriMesh
@@ -54,6 +53,7 @@
//== INCLUDES ================================================================= //== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h> #include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Mesh/SmartHandles.hh>
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <iterator> #include <iterator>
@@ -248,19 +248,25 @@ class GenericCirculatorBaseT {
int lap_counter_; int lap_counter_;
}; };
template<class Mesh, class CenterEntityHandle, class ValueHandle, //template<class Mesh, class CenterEntityHandle, class ValueHandle,
ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true > // ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true >
class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> { template <typename GenericCirculatorT_TraitsT, bool CW = true>
class GenericCirculatorT : protected GenericCirculatorBaseT<typename GenericCirculatorT_TraitsT::Mesh> {
public: public:
using Mesh = typename GenericCirculatorT_TraitsT::Mesh;
using value_type = typename GenericCirculatorT_TraitsT::ValueHandle;
using CenterEntityHandle = typename GenericCirculatorT_TraitsT::CenterEntityHandle;
using smart_value_type = decltype(make_smart(std::declval<value_type>(), std::declval<Mesh>()));
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef ValueHandle value_type;
typedef const value_type& reference; typedef const value_type& reference;
typedef const value_type* pointer; typedef const smart_value_type* pointer;
typedef std::bidirectional_iterator_tag iterator_category; typedef std::bidirectional_iterator_tag iterator_category;
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr; typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref; typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
typedef GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, ValueHandle, CW> GenericCirculator_ValueHandleFns; typedef GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, value_type, CW> GenericCirculator_ValueHandleFns;
public: public:
GenericCirculatorT() {} GenericCirculatorT() {}
@@ -276,8 +282,8 @@ class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
} }
GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {} GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
friend class GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>; friend class GenericCirculatorT<GenericCirculatorT_TraitsT,!CW>;
explicit GenericCirculatorT( const GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>& rhs ) explicit GenericCirculatorT( const GenericCirculatorT<GenericCirculatorT_TraitsT,!CW>& rhs )
:GenericCirculatorBaseT<Mesh>(rhs){} :GenericCirculatorBaseT<Mesh>(rhs){}
GenericCirculatorT& operator++() { GenericCirculatorT& operator++() {
@@ -308,16 +314,16 @@ class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
} }
/// Standard dereferencing operator. /// Standard dereferencing operator.
value_type operator*() const { smart_value_type operator*() const {
// We can't use this due to a GCC6 compiler bug // We can't use this due to a GCC6 compiler bug
const GenericCirculatorBaseT<Mesh>* self = this; const GenericCirculatorBaseT<Mesh>* self = this;
#ifndef NDEBUG #ifndef NDEBUG
assert(this->heh_.is_valid()); assert(this->heh_.is_valid());
value_type res = (self->*Handle2Value)(); value_type res = GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_);
assert(res.is_valid()); assert(res.is_valid());
return res; return res;
#else #else
return (self->*Handle2Value)(); return make_smart(GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
#endif #endif
} }
@@ -357,7 +363,7 @@ class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
} }
private: private:
mutable value_type pointer_deref_value; mutable smart_value_type pointer_deref_value;
}; };
////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -420,19 +426,22 @@ class GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, typ
} }
}; };
template<class Mesh, class CenterEntityHandle, class ValueHandle, template <typename GenericCirculatorT_DEPRECATED_TraitsT>
ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const> class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh> {
class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
public: public:
using Mesh = typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh;
using CenterEntityHandle = typename GenericCirculatorT_DEPRECATED_TraitsT::CenterEntityHandle;
using value_type = typename GenericCirculatorT_DEPRECATED_TraitsT::ValueHandle;
using smart_value_type = decltype (make_smart(std::declval<value_type>(), std::declval<Mesh>()));
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef ValueHandle value_type;
typedef const value_type& reference; typedef const value_type& reference;
typedef const value_type* pointer; typedef const smart_value_type* pointer;
typedef std::bidirectional_iterator_tag iterator_category; typedef std::bidirectional_iterator_tag iterator_category;
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr; typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref; typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
typedef GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, ValueHandle> GenericCirculator_ValueHandleFns; typedef GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, value_type> GenericCirculator_ValueHandleFns;
public: public:
GenericCirculatorT_DEPRECATED() {} GenericCirculatorT_DEPRECATED() {}
@@ -494,16 +503,16 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
} }
/// Standard dereferencing operator. /// Standard dereferencing operator.
value_type operator*() const { smart_value_type operator*() const {
// We can't use this due to a GCC6 compiler bug // We can't use this due to a GCC6 compiler bug
const GenericCirculatorBaseT<Mesh>* self = this; const GenericCirculatorBaseT<Mesh>* self = this;
#ifndef NDEBUG #ifndef NDEBUG
assert(this->heh_.is_valid()); assert(this->heh_.is_valid());
value_type res = (self->*Handle2Value)(); value_type res = (self->GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_);
assert(res.is_valid()); assert(res.is_valid());
return res; return res;
#else #else
return (self->*Handle2Value)(); return make_smart(GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
#endif #endif
} }
@@ -584,10 +593,9 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
} }
private: private:
mutable value_type pointer_deref_value; mutable smart_value_type pointer_deref_value;
}; };
} // namespace Iterators } // namespace Iterators
} // namespace OpenMesh } // namespace OpenMesh
#endif

View File

@@ -623,141 +623,6 @@ void PolyConnectivity::delete_face(FaceHandle _fh, bool _delete_isolated_vertice
adjust_outgoing_halfedge(*v_it); adjust_outgoing_halfedge(*v_it);
} }
//-----------------------------------------------------------------------------
PolyConnectivity::VertexIter PolyConnectivity::vertices_begin()
{
return VertexIter(*this, VertexHandle(0));
}
//-----------------------------------------------------------------------------
PolyConnectivity::ConstVertexIter PolyConnectivity::vertices_begin() const
{
return ConstVertexIter(*this, VertexHandle(0));
}
//-----------------------------------------------------------------------------
PolyConnectivity::VertexIter PolyConnectivity::vertices_end()
{
return VertexIter(*this, VertexHandle( int(n_vertices() ) ));
}
//-----------------------------------------------------------------------------
PolyConnectivity::ConstVertexIter PolyConnectivity::vertices_end() const
{
return ConstVertexIter(*this, VertexHandle( int(n_vertices()) ));
}
//-----------------------------------------------------------------------------
PolyConnectivity::HalfedgeIter PolyConnectivity::halfedges_begin()
{
return HalfedgeIter(*this, HalfedgeHandle(0));
}
//-----------------------------------------------------------------------------
PolyConnectivity::ConstHalfedgeIter PolyConnectivity::halfedges_begin() const
{
return ConstHalfedgeIter(*this, HalfedgeHandle(0));
}
//-----------------------------------------------------------------------------
PolyConnectivity::HalfedgeIter PolyConnectivity::halfedges_end()
{
return HalfedgeIter(*this, HalfedgeHandle(int(n_halfedges())));
}
//-----------------------------------------------------------------------------
PolyConnectivity::ConstHalfedgeIter PolyConnectivity::halfedges_end() const
{
return ConstHalfedgeIter(*this, HalfedgeHandle(int(n_halfedges())));
}
//-----------------------------------------------------------------------------
PolyConnectivity::EdgeIter PolyConnectivity::edges_begin()
{
return EdgeIter(*this, EdgeHandle(0));
}
//-----------------------------------------------------------------------------
PolyConnectivity::ConstEdgeIter PolyConnectivity::edges_begin() const
{
return ConstEdgeIter(*this, EdgeHandle(0));
}
//-----------------------------------------------------------------------------
PolyConnectivity::EdgeIter PolyConnectivity::edges_end()
{
return EdgeIter(*this, EdgeHandle(int(n_edges())));
}
//-----------------------------------------------------------------------------
PolyConnectivity::ConstEdgeIter PolyConnectivity::edges_end() const
{
return ConstEdgeIter(*this, EdgeHandle(int(n_edges())));
}
//-----------------------------------------------------------------------------
PolyConnectivity::FaceIter PolyConnectivity::faces_begin()
{
return FaceIter(*this, FaceHandle(0));
}
//-----------------------------------------------------------------------------
PolyConnectivity::ConstFaceIter PolyConnectivity::faces_begin() const
{
return ConstFaceIter(*this, FaceHandle(0));
}
//-----------------------------------------------------------------------------
PolyConnectivity::FaceIter PolyConnectivity::faces_end()
{
return FaceIter(*this, FaceHandle(int(n_faces())));
}
//-----------------------------------------------------------------------------
PolyConnectivity::ConstFaceIter PolyConnectivity::faces_end() const
{
return ConstFaceIter(*this, FaceHandle(int(n_faces())));
}
PolyConnectivity::VertexIter PolyConnectivity::vertices_sbegin()
{
return VertexIter(*this, VertexHandle(0), true);
}
PolyConnectivity::ConstVertexIter PolyConnectivity::vertices_sbegin() const
{
return ConstVertexIter(*this, VertexHandle(0), true);
}
PolyConnectivity::HalfedgeIter PolyConnectivity::halfedges_sbegin()
{
return HalfedgeIter(*this, HalfedgeHandle(0), true);
}
PolyConnectivity::ConstHalfedgeIter PolyConnectivity::halfedges_sbegin() const
{
return ConstHalfedgeIter(*this, HalfedgeHandle(0), true);
}
PolyConnectivity::EdgeIter PolyConnectivity::edges_sbegin()
{
return EdgeIter(*this, EdgeHandle(0), true);
}
PolyConnectivity::ConstEdgeIter PolyConnectivity::edges_sbegin() const
{
return ConstEdgeIter(*this, EdgeHandle(0), true);
}
PolyConnectivity::FaceIter PolyConnectivity::faces_sbegin()
{
return FaceIter(*this, FaceHandle(0), true);
}
PolyConnectivity::ConstFaceIter PolyConnectivity::faces_sbegin() const
{
return ConstFaceIter(*this, FaceHandle(0), true);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void PolyConnectivity::collapse(HalfedgeHandle _hh) void PolyConnectivity::collapse(HalfedgeHandle _hh)

File diff suppressed because it is too large Load Diff

View File

@@ -284,6 +284,103 @@ TEST_F(OpenMeshSmartHandles, SimpleRanges)
} }
} }
/* Test if ranges yield the same elements when using smart handles
*/
TEST_F(OpenMeshSmartHandles, RangesOfRanges)
{
for (auto vh : mesh_.vertices())
{
{
std::vector<OpenMesh::VertexHandle> handles0;
std::vector<OpenMesh::VertexHandle> handles1;
for (auto h : mesh_.vv_range(vh))
for (auto h2 : mesh_.vv_range(h))
handles0.push_back(h2);
for (auto h : vh.vertices())
for (auto h2 : h.vertices())
handles1.push_back(h2);
EXPECT_EQ(handles0, handles1) << "vertex range of vertex range does not match";
}
{
std::vector<OpenMesh::HalfedgeHandle> handles0;
std::vector<OpenMesh::HalfedgeHandle> handles1;
for (auto h : mesh_.vv_range(vh))
for (auto h2 : mesh_.voh_range(h))
handles0.push_back(h2);
for (auto h : vh.vertices())
for (auto h2 : h.outgoing_halfedges())
handles1.push_back(h2);
EXPECT_EQ(handles0, handles1) << "outgoing halfedge range of vertex range does not match";
}
{
std::vector<OpenMesh::HalfedgeHandle> handles0;
std::vector<OpenMesh::HalfedgeHandle> handles1;
for (auto h : mesh_.vv_range(vh))
for (auto h2 : mesh_.vih_range(h))
handles0.push_back(h2);
for (auto h : vh.vertices())
for (auto h2 : h.incoming_halfedges())
handles1.push_back(h2);
EXPECT_EQ(handles0, handles1) << "incoming halfedge range of vertex range does not match";
}
{
std::vector<OpenMesh::EdgeHandle> handles0;
std::vector<OpenMesh::EdgeHandle> handles1;
for (auto h : mesh_.vv_range(vh))
for (auto h2 : mesh_.ve_range(h))
handles0.push_back(h2);
for (auto h : vh.vertices())
for (auto h2 : h.edges())
handles1.push_back(h2);
EXPECT_EQ(handles0, handles1) << "edge range of vertex range does not match";
}
{
std::vector<OpenMesh::FaceHandle> handles0;
std::vector<OpenMesh::FaceHandle> handles1;
for (auto h : mesh_.vv_range(vh))
for (auto h2 : mesh_.vf_range(h))
handles0.push_back(h2);
for (auto h : vh.vertices())
for (auto h2 : h.faces())
handles1.push_back(h2);
EXPECT_EQ(handles0, handles1) << "face range of vertex range does not match";
}
{
std::vector<OpenMesh::VertexHandle> handles0;
std::vector<OpenMesh::VertexHandle> handles1;
for (auto h : mesh_.vf_range(vh))
for (auto h2 : mesh_.fv_range(h))
handles0.push_back(h2);
for (auto h : vh.faces())
for (auto h2 : h.vertices())
handles1.push_back(h2);
EXPECT_EQ(handles0, handles1) << "vertex range of face range does not match";
}
{
std::vector<OpenMesh::HalfedgeHandle> handles0;
std::vector<OpenMesh::HalfedgeHandle> handles1;
for (auto h : mesh_.vf_range(vh))
for (auto h2 : mesh_.fh_range(h))
handles0.push_back(h2);
for (auto h : vh.faces())
for (auto h2 : h.halfedges())
handles1.push_back(h2);
EXPECT_EQ(handles0, handles1) << "vertex range of face range does not match";
}
{
std::vector<OpenMesh::FaceHandle> handles0;
std::vector<OpenMesh::FaceHandle> handles1;
for (auto h : mesh_.vf_range(vh))
for (auto h2 : mesh_.ff_range(h))
handles0.push_back(h2);
for (auto h : vh.faces())
for (auto h2 : h.faces())
handles1.push_back(h2);
EXPECT_EQ(handles0, handles1) << "vertex range of face range does not match";
}
}
}
/* Test a chain of navigation on a cube /* Test a chain of navigation on a cube
*/ */