Commit b62d846f authored by Max Lyon's avatar Max Lyon
Browse files

let circulators return smart handles

parent 253c9b6a
......@@ -40,9 +40,8 @@
* ========================================================================= */
#pragma once
#ifndef OPENMESH_CIRCULATORS_HH
#define OPENMESH_CIRCULATORS_HH
//=============================================================================
//
// Vertex and Face circulators for PolyMesh/TriMesh
......@@ -54,6 +53,7 @@
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Mesh/SmartHandles.hh>
#include <cassert>
#include <cstddef>
#include <iterator>
......@@ -248,19 +248,25 @@ class GenericCirculatorBaseT {
int lap_counter_;
};
template<class Mesh, class CenterEntityHandle, class ValueHandle,
ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true >
class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
//template<class Mesh, class CenterEntityHandle, class ValueHandle,
// ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true >
template <typename GenericCirculatorT_TraitsT, bool CW = true>
class GenericCirculatorT : protected GenericCirculatorBaseT<typename GenericCirculatorT_TraitsT::Mesh> {
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 ValueHandle value_type;
typedef const value_type& reference;
typedef const value_type* pointer;
typedef const smart_value_type* pointer;
typedef std::bidirectional_iterator_tag iterator_category;
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
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:
GenericCirculatorT() {}
......@@ -276,8 +282,8 @@ class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
}
GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
friend class GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>;
explicit GenericCirculatorT( const GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>& rhs )
friend class GenericCirculatorT<GenericCirculatorT_TraitsT,!CW>;
explicit GenericCirculatorT( const GenericCirculatorT<GenericCirculatorT_TraitsT,!CW>& rhs )
:GenericCirculatorBaseT<Mesh>(rhs){}
GenericCirculatorT& operator++() {
......@@ -308,16 +314,16 @@ class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
}
/// Standard dereferencing operator.
value_type operator*() const {
smart_value_type operator*() const {
// We can't use this due to a GCC6 compiler bug
const GenericCirculatorBaseT<Mesh>* self = this;
#ifndef NDEBUG
assert(this->heh_.is_valid());
value_type res = (self->*Handle2Value)();
value_type res = GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_);
assert(res.is_valid());
return res;
#else
return (self->*Handle2Value)();
return make_smart(GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
#endif
}
......@@ -357,7 +363,7 @@ class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
}
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,
ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const>
class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
template <typename GenericCirculatorT_DEPRECATED_TraitsT>
class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh> {
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 ValueHandle value_type;
typedef const value_type& reference;
typedef const value_type* pointer;
typedef const smart_value_type* pointer;
typedef std::bidirectional_iterator_tag iterator_category;
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
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:
GenericCirculatorT_DEPRECATED() {}
......@@ -494,16 +503,16 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
}
/// Standard dereferencing operator.
value_type operator*() const {
smart_value_type operator*() const {
// We can't use this due to a GCC6 compiler bug
const GenericCirculatorBaseT<Mesh>* self = this;
#ifndef NDEBUG
assert(this->heh_.is_valid());
value_type res = (self->*Handle2Value)();
value_type res = (self->GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_);
assert(res.is_valid());
return res;
#else
return (self->*Handle2Value)();
return make_smart(GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
#endif
}
......@@ -584,10 +593,9 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
}
private:
mutable value_type pointer_deref_value;
mutable smart_value_type pointer_deref_value;
};
} // namespace Iterators
} // namespace OpenMesh
#endif
......@@ -623,141 +623,6 @@ void PolyConnectivity::delete_face(FaceHandle _fh, bool _delete_isolated_vertice
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)
......
This diff is collapsed.
......@@ -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
*/
......
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