Merge branch 'master' into CustomProperties

This commit is contained in:
Max Lyon
2021-03-15 09:53:00 +01:00
17 changed files with 990 additions and 294 deletions

View File

@@ -854,6 +854,8 @@ Sources:
trigger_openmesh-python-rebuild: trigger_openmesh-python-rebuild:
stage: deploy stage: deploy
only:
- master
script: script:
- "curl -X POST -F token=b63ed804ada51d7d1ffe5d6ea0dfa2 -F ref=track-OM-master https://www.graphics.rwth-aachen.de:9000/api/v4/projects/1024/trigger/pipeline" - "curl -X POST -F token=b63ed804ada51d7d1ffe5d6ea0dfa2 -F ref=track-OM-master https://www.graphics.rwth-aachen.de:9000/api/v4/projects/1024/trigger/pipeline"

View File

@@ -37,6 +37,8 @@ Sources:
trigger_openmesh-python-rebuild: trigger_openmesh-python-rebuild:
stage: deploy stage: deploy
only:
- master
script: script:
- "curl -X POST -F token=b63ed804ada51d7d1ffe5d6ea0dfa2 -F ref=track-OM-master https://www.graphics.rwth-aachen.de:9000/api/v4/projects/1024/trigger/pipeline" - "curl -X POST -F token=b63ed804ada51d7d1ffe5d6ea0dfa2 -F ref=track-OM-master https://www.graphics.rwth-aachen.de:9000/api/v4/projects/1024/trigger/pipeline"

View File

@@ -12,6 +12,7 @@
<b>Breaking Changes</b> <b>Breaking Changes</b>
<ul> <ul>
<li>Dropped 32-bit Windows continuous integration and artifact builds (This does not mean that OpenMesh will not build and work on 32-bit, but we don't explicitly test and guarantee it anymore).</li> <li>Dropped 32-bit Windows continuous integration and artifact builds (This does not mean that OpenMesh will not build and work on 32-bit, but we don't explicitly test and guarantee it anymore).</li>
<li>Changed CCW begin/end/range to start on last element of CW counterpart. May break your code if you depend on CCW begin to start at a specific element.</li>
</ul> </ul>
<b>Core</b> <b>Core</b>
@@ -21,6 +22,8 @@
<li>Smart handles now give read access to status fields (feature(), selected(), deleted(), tagged(), tagged2(), hidden(), locked()</li> <li>Smart handles now give read access to status fields (feature(), selected(), deleted(), tagged(), tagged2(), hidden(), locked()</li>
<li>Add predicates that can be used as smart range filters. There are default predicates to test the status fields and whether an elements is boundary. Predicates can be composed via operators ||, && and !</li> <li>Add predicates that can be used as smart range filters. There are default predicates to test the status fields and whether an elements is boundary. Predicates can be composed via operators ||, && and !</li>
<li>Add make_predicate to create a predicate from anything containing a bool operator(T), e.g. a PropertyManager, a lambda, or a function pointer.</li> <li>Add make_predicate to create a predicate from anything containing a bool operator(T), e.g. a PropertyManager, a lambda, or a function pointer.</li>
<li>Added CW and CCW ranges.</li>
<li>Vertex incoming/outgoing halfedge circulators can be started for a given halfedge.</li>
</ul> </ul>
<b>IO</b> <b>IO</b>

View File

@@ -60,6 +60,9 @@
//== NAMESPACES =============================================================== //== NAMESPACES ===============================================================
namespace OpenMesh { namespace OpenMesh {
template <typename> class CirculatorRange;
namespace Iterators { namespace Iterators {
template<class Mesh, class CenterEntityHandle, bool CW> template<class Mesh, class CenterEntityHandle, bool CW>
@@ -153,7 +156,21 @@ class GenericCirculator_ValueHandleFnsT {
inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) { inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
return ( heh.is_valid() && (lap_counter == 0 ) ); return ( heh.is_valid() && (lap_counter == 0 ) );
} }
inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {}; inline static void init(const Mesh* mesh, typename Mesh::HalfedgeHandle& heh, typename Mesh::HalfedgeHandle& start, int& lap_counter, bool adjust_for_ccw)
{
if (!CW) // TODO: constexpr if
{
if (adjust_for_ccw)
{
// increment current heh and start so that cw and ccw version dont start with the same element but ranges are actually reversed
int lc = lap_counter;
increment(mesh, heh, start, lap_counter);
start = heh;
lap_counter = lc;
}
}
}
inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter); GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter);
} }
@@ -170,7 +187,19 @@ class GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, typename Mesh:
inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) { inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
return ( heh.is_valid() && (lap_counter == 0)); return ( heh.is_valid() && (lap_counter == 0));
} }
inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter, bool adjust_for_ccw)
{
if (!CW) // TODO: constexpr if
{
if (adjust_for_ccw)
{
// increment current heh and start so that cw and ccw version dont start with the same element but ranges are actually reversed
int lc = lap_counter;
increment(mesh, heh, start, lap_counter);
start = heh;
lap_counter = lc;
}
}
if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 ) if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
increment(mesh, heh, start, lap_counter); increment(mesh, heh, start, lap_counter);
}; };
@@ -192,6 +221,8 @@ class GenericCirculatorBaseT {
typedef const Mesh* mesh_ptr; typedef const Mesh* mesh_ptr;
typedef const Mesh& mesh_ref; typedef const Mesh& mesh_ref;
template <typename> friend class OpenMesh::CirculatorRange;
public: public:
GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {} GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {}
@@ -267,17 +298,21 @@ class GenericCirculatorT : protected GenericCirculatorBaseT<typename GenericCirc
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref; typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
typedef GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, value_type, CW> GenericCirculator_ValueHandleFns; typedef GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, value_type, CW> GenericCirculator_ValueHandleFns;
template <typename> friend class OpenMesh::CirculatorRange;
public: public:
GenericCirculatorT() {} GenericCirculatorT() {}
GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) : GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) { GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end)
{
GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_); bool adjust_for_ccw = true;
GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_, adjust_for_ccw);
} }
GenericCirculatorT(mesh_ref mesh, typename Mesh::HalfedgeHandle heh, bool end = false) : GenericCirculatorT(mesh_ref mesh, typename Mesh::HalfedgeHandle heh, bool end = false) :
GenericCirculatorBaseT<Mesh>(mesh, heh, end) { GenericCirculatorBaseT<Mesh>(mesh, heh, end)
{
GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_); bool adjust_for_ccw = false; // if iterator is initialized with specific heh, we want to start there
GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_, adjust_for_ccw);
} }
GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {} GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
@@ -440,6 +475,8 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<typename
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref; typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
typedef GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, value_type> GenericCirculator_ValueHandleFns; typedef GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, value_type> GenericCirculator_ValueHandleFns;
template <typename> friend class OpenMesh::CirculatorRange;
public: public:
GenericCirculatorT_DEPRECATED() {} GenericCirculatorT_DEPRECATED() {}
GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) : GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) :

View File

@@ -98,8 +98,10 @@ struct CirculatorRangeTraitT
using ITER_TYPE = ITER_T; using ITER_TYPE = ITER_T;
using CENTER_ENTITY_TYPE = CENTER_ENTITY_T; using CENTER_ENTITY_TYPE = CENTER_ENTITY_T;
using TO_ENTITYE_TYPE = TO_ENTITY_T; using TO_ENTITYE_TYPE = TO_ENTITY_T;
static ITER_TYPE begin(const CONTAINER_TYPE& _container, CENTER_ENTITY_TYPE _ce) { return (_container.*begin_fn)(_ce); } static ITER_TYPE begin(const CONTAINER_TYPE& _container, CENTER_ENTITY_TYPE _ce) { return (_container.*begin_fn)(_ce); }
static ITER_TYPE end(const CONTAINER_TYPE& _container, CENTER_ENTITY_TYPE _ce) { return (_container.*end_fn)(_ce); } static ITER_TYPE begin(const CONTAINER_TYPE& _container, HalfedgeHandle _heh, int) { return ITER_TYPE(_container, _heh); }
static ITER_TYPE end(const CONTAINER_TYPE& _container, CENTER_ENTITY_TYPE _ce) { return (_container.*end_fn)(_ce); }
static ITER_TYPE end(const CONTAINER_TYPE& _container, HalfedgeHandle _heh, int) { return ITER_TYPE(_container, _heh, true); }
}; };
struct SmartVertexHandle; struct SmartVertexHandle;
@@ -1167,76 +1169,38 @@ public:
typename ElementRange<HandleType>::Range all_elements() const; typename ElementRange<HandleType>::Range all_elements() const;
typedef CirculatorRange<CirculatorRangeTraitT< typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexVertexIter , VertexHandle , VertexHandle , &PolyConnectivity::cvv_begin , &PolyConnectivity::cvv_end >> ConstVertexVertexRange;
PolyConnectivity, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexIHalfedgeIter , VertexHandle , HalfedgeHandle, &PolyConnectivity::cvih_begin , &PolyConnectivity::cvih_end >> ConstVertexIHalfedgeRange;
ConstVertexVertexCWIter, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexOHalfedgeIter , VertexHandle , HalfedgeHandle, &PolyConnectivity::cvoh_begin , &PolyConnectivity::cvoh_end >> ConstVertexOHalfedgeRange;
VertexHandle, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexEdgeIter , VertexHandle , EdgeHandle , &PolyConnectivity::cve_begin , &PolyConnectivity::cve_end >> ConstVertexEdgeRange;
VertexHandle, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexFaceIter , VertexHandle , FaceHandle , &PolyConnectivity::cvf_begin , &PolyConnectivity::cvf_end >> ConstVertexFaceRange;
&PolyConnectivity::cvv_cwbegin, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceVertexIter , FaceHandle , VertexHandle , &PolyConnectivity::cfv_begin , &PolyConnectivity::cfv_end >> ConstFaceVertexRange;
&PolyConnectivity::cvv_cwend>> ConstVertexVertexRange; typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceHalfedgeIter , FaceHandle , HalfedgeHandle, &PolyConnectivity::cfh_begin , &PolyConnectivity::cfh_end >> ConstFaceHalfedgeRange;
typedef CirculatorRange<CirculatorRangeTraitT< typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceEdgeIter , FaceHandle , EdgeHandle , &PolyConnectivity::cfe_begin , &PolyConnectivity::cfe_end >> ConstFaceEdgeRange;
PolyConnectivity, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceFaceIter , FaceHandle , FaceHandle , &PolyConnectivity::cff_begin , &PolyConnectivity::cff_end >> ConstFaceFaceRange;
ConstVertexIHalfedgeIter, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstHalfedgeLoopIter , HalfedgeHandle, HalfedgeHandle, &PolyConnectivity::chl_begin , &PolyConnectivity::chl_end >> ConstHalfedgeLoopRange;
VertexHandle,
HalfedgeHandle, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexVertexCWIter , VertexHandle , VertexHandle , &PolyConnectivity::cvv_cwbegin , &PolyConnectivity::cvv_cwend >> ConstVertexVertexCWRange;
&PolyConnectivity::cvih_begin, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexIHalfedgeCWIter , VertexHandle , HalfedgeHandle, &PolyConnectivity::cvih_cwbegin , &PolyConnectivity::cvih_cwend >> ConstVertexIHalfedgeCWRange;
&PolyConnectivity::cvih_end>> ConstVertexIHalfedgeRange; typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexOHalfedgeCWIter , VertexHandle , HalfedgeHandle, &PolyConnectivity::cvoh_cwbegin , &PolyConnectivity::cvoh_cwend >> ConstVertexOHalfedgeCWRange;
typedef CirculatorRange<CirculatorRangeTraitT< typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexEdgeCWIter , VertexHandle , EdgeHandle , &PolyConnectivity::cve_cwbegin , &PolyConnectivity::cve_cwend >> ConstVertexEdgeCWRange;
PolyConnectivity, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexFaceCWIter , VertexHandle , FaceHandle , &PolyConnectivity::cvf_cwbegin , &PolyConnectivity::cvf_cwend >> ConstVertexFaceCWRange;
ConstVertexOHalfedgeIter, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceVertexCWIter , FaceHandle , VertexHandle , &PolyConnectivity::cfv_cwbegin , &PolyConnectivity::cfv_cwend >> ConstFaceVertexCWRange;
VertexHandle, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceHalfedgeCWIter , FaceHandle , HalfedgeHandle, &PolyConnectivity::cfh_cwbegin , &PolyConnectivity::cfh_cwend >> ConstFaceHalfedgeCWRange;
HalfedgeHandle, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceEdgeCWIter , FaceHandle , EdgeHandle , &PolyConnectivity::cfe_cwbegin , &PolyConnectivity::cfe_cwend >> ConstFaceEdgeCWRange;
&PolyConnectivity::cvoh_begin, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceFaceCWIter , FaceHandle , FaceHandle , &PolyConnectivity::cff_cwbegin , &PolyConnectivity::cff_cwend >> ConstFaceFaceCWRange;
&PolyConnectivity::cvoh_end>> ConstVertexOHalfedgeRange; typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstHalfedgeLoopCWIter , HalfedgeHandle, HalfedgeHandle, &PolyConnectivity::chl_cwbegin , &PolyConnectivity::chl_cwend >> ConstHalfedgeLoopCWRange;
typedef CirculatorRange<CirculatorRangeTraitT<
PolyConnectivity, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexVertexCCWIter , VertexHandle , VertexHandle , &PolyConnectivity::cvv_ccwbegin , &PolyConnectivity::cvv_ccwend >> ConstVertexVertexCCWRange;
ConstVertexEdgeIter, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexIHalfedgeCCWIter, VertexHandle , HalfedgeHandle, &PolyConnectivity::cvih_ccwbegin , &PolyConnectivity::cvih_ccwend >> ConstVertexIHalfedgeCCWRange;
VertexHandle, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexOHalfedgeCCWIter, VertexHandle , HalfedgeHandle, &PolyConnectivity::cvoh_ccwbegin , &PolyConnectivity::cvoh_ccwend >> ConstVertexOHalfedgeCCWRange;
EdgeHandle, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexEdgeCCWIter , VertexHandle , EdgeHandle , &PolyConnectivity::cve_ccwbegin , &PolyConnectivity::cve_ccwend >> ConstVertexEdgeCCWRange;
&PolyConnectivity::cve_begin, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstVertexFaceCCWIter , VertexHandle , FaceHandle , &PolyConnectivity::cvf_ccwbegin , &PolyConnectivity::cvf_ccwend >> ConstVertexFaceCCWRange;
&PolyConnectivity::cve_end>> ConstVertexEdgeRange; typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceVertexCCWIter , FaceHandle , VertexHandle , &PolyConnectivity::cfv_ccwbegin , &PolyConnectivity::cfv_ccwend >> ConstFaceVertexCCWRange;
typedef CirculatorRange<CirculatorRangeTraitT< typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceHalfedgeCCWIter , FaceHandle , HalfedgeHandle, &PolyConnectivity::cfh_ccwbegin , &PolyConnectivity::cfh_ccwend >> ConstFaceHalfedgeCCWRange;
PolyConnectivity, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceEdgeCCWIter , FaceHandle , EdgeHandle , &PolyConnectivity::cfe_ccwbegin , &PolyConnectivity::cfe_ccwend >> ConstFaceEdgeCCWRange;
ConstVertexFaceIter, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstFaceFaceCCWIter , FaceHandle , FaceHandle , &PolyConnectivity::cff_ccwbegin , &PolyConnectivity::cff_ccwend >> ConstFaceFaceCCWRange;
VertexHandle, typedef CirculatorRange<CirculatorRangeTraitT<PolyConnectivity, ConstHalfedgeLoopCCWIter , HalfedgeHandle, HalfedgeHandle, &PolyConnectivity::chl_ccwbegin , &PolyConnectivity::chl_ccwend >> ConstHalfedgeLoopCCWRange;
FaceHandle,
&PolyConnectivity::cvf_begin,
&PolyConnectivity::cvf_end>> ConstVertexFaceRange;
typedef CirculatorRange<CirculatorRangeTraitT<
PolyConnectivity,
ConstFaceVertexIter,
FaceHandle,
VertexHandle,
&PolyConnectivity::cfv_begin,
&PolyConnectivity::cfv_end>> ConstFaceVertexRange;
typedef CirculatorRange<CirculatorRangeTraitT<
PolyConnectivity,
ConstFaceHalfedgeIter,
FaceHandle,
HalfedgeHandle,
&PolyConnectivity::cfh_begin,
&PolyConnectivity::cfh_end>> ConstFaceHalfedgeRange;
typedef CirculatorRange<CirculatorRangeTraitT<
PolyConnectivity,
ConstFaceEdgeIter,
FaceHandle,
EdgeHandle,
&PolyConnectivity::cfe_begin,
&PolyConnectivity::cfe_end>> ConstFaceEdgeRange;
typedef CirculatorRange<CirculatorRangeTraitT<
PolyConnectivity,
ConstFaceFaceIter,
FaceHandle,
FaceHandle,
&PolyConnectivity::cff_begin,
&PolyConnectivity::cff_end>> ConstFaceFaceRange;
typedef CirculatorRange<CirculatorRangeTraitT<
PolyConnectivity,
ConstHalfedgeLoopIter,
HalfedgeHandle,
HalfedgeHandle,
&PolyConnectivity::chl_begin,
&PolyConnectivity::chl_end>> ConstHalfedgeLoopRange;
/** /**
* @return The vertices adjacent to the specified vertex * @return The vertices adjacent to the specified vertex
@@ -1250,12 +1214,26 @@ public:
*/ */
ConstVertexIHalfedgeRange vih_range(VertexHandle _vh) const; ConstVertexIHalfedgeRange vih_range(VertexHandle _vh) const;
/**
* @return The incoming halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
* Like vih_range(VertexHandle _heh.to()) but starts iteration at _heh
*/
ConstVertexIHalfedgeRange vih_range(HalfedgeHandle _heh) const;
/** /**
* @return The outgoing halfedges incident to the specified vertex * @return The outgoing halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops. * as a range object suitable for C++11 range based for loops.
*/ */
ConstVertexOHalfedgeRange voh_range(VertexHandle _vh) const; ConstVertexOHalfedgeRange voh_range(VertexHandle _vh) const;
/**
* @return The outgoing halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
* Like voh_range(VertexHandle _heh.from()) but starts iteration at _heh
*/
ConstVertexOHalfedgeRange voh_range(HalfedgeHandle _heh) const;
/** /**
* @return The edges incident to the specified vertex * @return The edges incident to the specified vertex
* as a range object suitable for C++11 range based for loops. * as a range object suitable for C++11 range based for loops.
@@ -1298,6 +1276,156 @@ public:
*/ */
ConstHalfedgeLoopRange hl_range(HalfedgeHandle _heh) const; ConstHalfedgeLoopRange hl_range(HalfedgeHandle _heh) const;
/**
* @return The vertices adjacent to the specified vertex
* as a range object suitable for C++11 range based for loops.
*/
ConstVertexVertexCWRange vv_cw_range(VertexHandle _vh) const;
/**
* @return The incoming halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
*/
ConstVertexIHalfedgeCWRange vih_cw_range(VertexHandle _vh) const;
/**
* @return The incoming halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
* Like vih_cw_range(VertexHandle _heh.to()) but starts iteration at _heh
*/
ConstVertexIHalfedgeCWRange vih_cw_range(HalfedgeHandle _heh) const;
/**
* @return The outgoing halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
*/
ConstVertexOHalfedgeCWRange voh_cw_range(VertexHandle _vh) const;
/**
* @return The outgoing halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
* Like voh_cw_range(VertexHandle _heh.from()) but starts iteration at _heh
*/
ConstVertexOHalfedgeCWRange voh_cw_range(HalfedgeHandle _heh) const;
/**
* @return The edges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
*/
ConstVertexEdgeCWRange ve_cw_range(VertexHandle _vh) const ;
/**
* @return The faces incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
*/
ConstVertexFaceCWRange vf_cw_range(VertexHandle _vh) const;
/**
* @return The vertices incident to the specified face
* as a range object suitable for C++11 range based for loops.
*/
ConstFaceVertexCWRange fv_cw_range(FaceHandle _fh) const;
/**
* @return The halfedges incident to the specified face
* as a range object suitable for C++11 range based for loops.
*/
ConstFaceHalfedgeCWRange fh_cw_range(FaceHandle _fh) const;
/**
* @return The edges incident to the specified face
* as a range object suitable for C++11 range based for loops.
*/
ConstFaceEdgeCWRange fe_cw_range(FaceHandle _fh) const;
/**
* @return The faces adjacent to the specified face
* as a range object suitable for C++11 range based for loops.
*/
ConstFaceFaceCWRange ff_cw_range(FaceHandle _fh) const;
/**
* @return The halfedges in the face
* as a range object suitable for C++11 range based for loops.
*/
ConstHalfedgeLoopCWRange hl_cw_range(HalfedgeHandle _heh) const;
/**
* @return The vertices adjacent to the specified vertex
* as a range object suitable for C++11 range based for loops.
*/
ConstVertexVertexCCWRange vv_ccw_range(VertexHandle _vh) const;
/**
* @return The incoming halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
*/
ConstVertexIHalfedgeCCWRange vih_ccw_range(VertexHandle _vh) const;
/**
* @return The incoming halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
* Like vih_ccw_range(VertexHandle _heh.to()) but starts iteration at _heh
*/
ConstVertexIHalfedgeCCWRange vih_ccw_range(HalfedgeHandle _heh) const;
/**
* @return The outgoing halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
*/
ConstVertexOHalfedgeCCWRange voh_ccw_range(VertexHandle _vh) const;
/**
* @return The outgoing halfedges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
* Like voh_ccw_range(VertexHandle _heh.from()) but starts iteration at _heh
*/
ConstVertexOHalfedgeCCWRange voh_ccw_range(HalfedgeHandle _heh) const;
/**
* @return The edges incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
*/
ConstVertexEdgeCCWRange ve_ccw_range(VertexHandle _vh) const ;
/**
* @return The faces incident to the specified vertex
* as a range object suitable for C++11 range based for loops.
*/
ConstVertexFaceCCWRange vf_ccw_range(VertexHandle _vh) const;
/**
* @return The vertices incident to the specified face
* as a range object suitable for C++11 range based for loops.
*/
ConstFaceVertexCCWRange fv_ccw_range(FaceHandle _fh) const;
/**
* @return The halfedges incident to the specified face
* as a range object suitable for C++11 range based for loops.
*/
ConstFaceHalfedgeCCWRange fh_ccw_range(FaceHandle _fh) const;
/**
* @return The edges incident to the specified face
* as a range object suitable for C++11 range based for loops.
*/
ConstFaceEdgeCCWRange fe_ccw_range(FaceHandle _fh) const;
/**
* @return The faces adjacent to the specified face
* as a range object suitable for C++11 range based for loops.
*/
ConstFaceFaceCCWRange ff_ccw_range(FaceHandle _fh) const;
/**
* @return The halfedges in the face
* as a range object suitable for C++11 range based for loops.
*/
ConstHalfedgeLoopCCWRange hl_ccw_range(HalfedgeHandle _heh) const;
//@} //@}
//=========================================================================== //===========================================================================

View File

@@ -43,6 +43,7 @@
#error Do not include this directly, include instead PolyConnectivity.hh #error Do not include this directly, include instead PolyConnectivity.hh
#endif // OPENMESH_POLYCONNECTIVITY_INTERFACE_INCLUDE #endif // OPENMESH_POLYCONNECTIVITY_INTERFACE_INCLUDE
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh> // To help some IDEs
#include <OpenMesh/Core/Mesh/IteratorsT.hh> #include <OpenMesh/Core/Mesh/IteratorsT.hh>
#include <OpenMesh/Core/Mesh/CirculatorsT.hh> #include <OpenMesh/Core/Mesh/CirculatorsT.hh>
@@ -99,13 +100,23 @@ class CirculatorRange : public SmartRangeT<CirculatorRange<CirculatorRangeTraitT
CirculatorRange( CirculatorRange(
const CONTAINER_TYPE &container, const CONTAINER_TYPE &container,
CENTER_ENTITY_TYPE center) : CENTER_ENTITY_TYPE center) :
container_(container), center_(center) {} container_(container), heh_()
ITER_TYPE begin() const { return CirculatorRangeTraitT::begin(container_, center_); } {
ITER_TYPE end() const { return CirculatorRangeTraitT::end(container_, center_); } auto it = CirculatorRangeTraitT::begin(container_, center);
heh_ = it.heh_;
}
CirculatorRange(
const CONTAINER_TYPE &container,
HalfedgeHandle heh, int) :
container_(container), heh_(heh) {}
ITER_TYPE begin() const { return CirculatorRangeTraitT::begin(container_, heh_, 1); }
ITER_TYPE end() const { return CirculatorRangeTraitT::end(container_, heh_, 1); }
private: private:
const CONTAINER_TYPE &container_; const CONTAINER_TYPE &container_;
CENTER_ENTITY_TYPE center_; HalfedgeHandle heh_;
}; };
@@ -136,10 +147,18 @@ inline PolyConnectivity::ConstVertexIHalfedgeRange PolyConnectivity::vih_range(V
return ConstVertexIHalfedgeRange(*this, _vh); return ConstVertexIHalfedgeRange(*this, _vh);
} }
inline PolyConnectivity::ConstVertexIHalfedgeRange PolyConnectivity::vih_range(HalfedgeHandle _heh) const {
return ConstVertexIHalfedgeRange(*this, opposite_halfedge_handle(_heh), 1);
}
inline PolyConnectivity::ConstVertexOHalfedgeRange PolyConnectivity::voh_range(VertexHandle _vh) const { inline PolyConnectivity::ConstVertexOHalfedgeRange PolyConnectivity::voh_range(VertexHandle _vh) const {
return ConstVertexOHalfedgeRange(*this, _vh); return ConstVertexOHalfedgeRange(*this, _vh);
} }
inline PolyConnectivity::ConstVertexOHalfedgeRange PolyConnectivity::voh_range(HalfedgeHandle _heh) const {
return ConstVertexOHalfedgeRange(*this, _heh, 1);
}
inline PolyConnectivity::ConstVertexEdgeRange PolyConnectivity::ve_range(VertexHandle _vh) const { inline PolyConnectivity::ConstVertexEdgeRange PolyConnectivity::ve_range(VertexHandle _vh) const {
return ConstVertexEdgeRange(*this, _vh); return ConstVertexEdgeRange(*this, _vh);
} }
@@ -169,6 +188,104 @@ inline PolyConnectivity::ConstHalfedgeLoopRange PolyConnectivity::hl_range(Halfe
} }
inline PolyConnectivity::ConstVertexVertexCWRange PolyConnectivity::vv_cw_range(VertexHandle _vh) const {
return ConstVertexVertexCWRange(*this, _vh);
}
inline PolyConnectivity::ConstVertexIHalfedgeCWRange PolyConnectivity::vih_cw_range(VertexHandle _vh) const {
return ConstVertexIHalfedgeCWRange(*this, _vh);
}
inline PolyConnectivity::ConstVertexIHalfedgeCWRange PolyConnectivity::vih_cw_range(HalfedgeHandle _heh) const {
return ConstVertexIHalfedgeCWRange(*this, opposite_halfedge_handle(_heh), 1);
}
inline PolyConnectivity::ConstVertexOHalfedgeCWRange PolyConnectivity::voh_cw_range(VertexHandle _vh) const {
return ConstVertexOHalfedgeCWRange(*this, _vh);
}
inline PolyConnectivity::ConstVertexOHalfedgeCWRange PolyConnectivity::voh_cw_range(HalfedgeHandle _heh) const {
return ConstVertexOHalfedgeCWRange(*this, _heh, 1);
}
inline PolyConnectivity::ConstVertexEdgeCWRange PolyConnectivity::ve_cw_range(VertexHandle _vh) const {
return ConstVertexEdgeCWRange(*this, _vh);
}
inline PolyConnectivity::ConstVertexFaceCWRange PolyConnectivity::vf_cw_range(VertexHandle _vh) const {
return ConstVertexFaceCWRange(*this, _vh);
}
inline PolyConnectivity::ConstFaceVertexCWRange PolyConnectivity::fv_cw_range(FaceHandle _fh) const {
return ConstFaceVertexCWRange(*this, _fh);
}
inline PolyConnectivity::ConstFaceHalfedgeCWRange PolyConnectivity::fh_cw_range(FaceHandle _fh) const {
return ConstFaceHalfedgeCWRange(*this, _fh);
}
inline PolyConnectivity::ConstFaceEdgeCWRange PolyConnectivity::fe_cw_range(FaceHandle _fh) const {
return ConstFaceEdgeCWRange(*this, _fh);
}
inline PolyConnectivity::ConstFaceFaceCWRange PolyConnectivity::ff_cw_range(FaceHandle _fh) const {
return ConstFaceFaceCWRange(*this, _fh);
}
inline PolyConnectivity::ConstHalfedgeLoopCWRange PolyConnectivity::hl_cw_range(HalfedgeHandle _heh) const {
return ConstHalfedgeLoopCWRange(*this, _heh);
}
inline PolyConnectivity::ConstVertexVertexCCWRange PolyConnectivity::vv_ccw_range(VertexHandle _vh) const {
return ConstVertexVertexCCWRange(*this, _vh);
}
inline PolyConnectivity::ConstVertexIHalfedgeCCWRange PolyConnectivity::vih_ccw_range(VertexHandle _vh) const {
return ConstVertexIHalfedgeCCWRange(*this, _vh);
}
inline PolyConnectivity::ConstVertexIHalfedgeCCWRange PolyConnectivity::vih_ccw_range(HalfedgeHandle _heh) const {
return ConstVertexIHalfedgeCCWRange(*this, opposite_halfedge_handle(_heh), 1);
}
inline PolyConnectivity::ConstVertexOHalfedgeCCWRange PolyConnectivity::voh_ccw_range(VertexHandle _vh) const {
return ConstVertexOHalfedgeCCWRange(*this, _vh);
}
inline PolyConnectivity::ConstVertexOHalfedgeCCWRange PolyConnectivity::voh_ccw_range(HalfedgeHandle _heh) const {
return ConstVertexOHalfedgeCCWRange(*this, _heh, 1);
}
inline PolyConnectivity::ConstVertexEdgeCCWRange PolyConnectivity::ve_ccw_range(VertexHandle _vh) const {
return ConstVertexEdgeCCWRange(*this, _vh);
}
inline PolyConnectivity::ConstVertexFaceCCWRange PolyConnectivity::vf_ccw_range(VertexHandle _vh) const {
return ConstVertexFaceCCWRange(*this, _vh);
}
inline PolyConnectivity::ConstFaceVertexCCWRange PolyConnectivity::fv_ccw_range(FaceHandle _fh) const {
return ConstFaceVertexCCWRange(*this, _fh);
}
inline PolyConnectivity::ConstFaceHalfedgeCCWRange PolyConnectivity::fh_ccw_range(FaceHandle _fh) const {
return ConstFaceHalfedgeCCWRange(*this, _fh);
}
inline PolyConnectivity::ConstFaceEdgeCCWRange PolyConnectivity::fe_ccw_range(FaceHandle _fh) const {
return ConstFaceEdgeCCWRange(*this, _fh);
}
inline PolyConnectivity::ConstFaceFaceCCWRange PolyConnectivity::ff_ccw_range(FaceHandle _fh) const {
return ConstFaceFaceCCWRange(*this, _fh);
}
inline PolyConnectivity::ConstHalfedgeLoopCCWRange PolyConnectivity::hl_ccw_range(HalfedgeHandle _heh) const {
return ConstHalfedgeLoopCCWRange(*this, _heh);
}
inline PolyConnectivity::VertexIter PolyConnectivity::vertices_begin() inline PolyConnectivity::VertexIter PolyConnectivity::vertices_begin()
@@ -776,70 +893,54 @@ inline PolyConnectivity::ConstHalfedgeLoopCCWIter PolyConnectivity::chl_ccwend(H
{ return ConstHalfedgeLoopCCWIter(*this, _heh, true); } { return ConstHalfedgeLoopCCWIter(*this, _heh, true); }
inline PolyConnectivity::ConstVertexFaceRange SmartVertexHandle::faces() const inline PolyConnectivity::ConstVertexFaceRange SmartVertexHandle::faces() const { assert(mesh() != nullptr); return mesh()->vf_range (*this); }
{ inline PolyConnectivity::ConstVertexFaceCWRange SmartVertexHandle::faces_cw() const { assert(mesh() != nullptr); return mesh()->vf_cw_range (*this); }
assert(mesh() != nullptr); inline PolyConnectivity::ConstVertexFaceCCWRange SmartVertexHandle::faces_ccw() const { assert(mesh() != nullptr); return mesh()->vf_ccw_range(*this); }
return mesh()->vf_range(*this);
}
inline PolyConnectivity::ConstVertexEdgeRange SmartVertexHandle::edges() const inline PolyConnectivity::ConstVertexEdgeRange SmartVertexHandle::edges() const { assert(mesh() != nullptr); return mesh()->ve_range (*this); }
{ inline PolyConnectivity::ConstVertexEdgeCWRange SmartVertexHandle::edges_cw() const { assert(mesh() != nullptr); return mesh()->ve_cw_range (*this); }
assert(mesh() != nullptr); inline PolyConnectivity::ConstVertexEdgeCCWRange SmartVertexHandle::edges_ccw() const { assert(mesh() != nullptr); return mesh()->ve_ccw_range(*this); }
return mesh()->ve_range(*this);
}
inline PolyConnectivity::ConstVertexVertexRange inline PolyConnectivity::ConstVertexVertexRange SmartVertexHandle::vertices() const { assert(mesh() != nullptr); return mesh()->vv_range (*this); }
SmartVertexHandle::vertices() const inline PolyConnectivity::ConstVertexVertexCWRange SmartVertexHandle::vertices_cw() const { assert(mesh() != nullptr); return mesh()->vv_cw_range (*this); }
{ inline PolyConnectivity::ConstVertexVertexCCWRange SmartVertexHandle::vertices_ccw() const { assert(mesh() != nullptr); return mesh()->vv_ccw_range (*this); }
assert(mesh() != nullptr);
return mesh()->vv_range(*this);
}
inline PolyConnectivity::ConstVertexIHalfedgeRange inline PolyConnectivity::ConstVertexIHalfedgeRange SmartVertexHandle::incoming_halfedges() const { assert(mesh() != nullptr); return mesh()->vih_range (*this); }
SmartVertexHandle::incoming_halfedges() const inline PolyConnectivity::ConstVertexIHalfedgeCWRange SmartVertexHandle::incoming_halfedges_cw() const { assert(mesh() != nullptr); return mesh()->vih_cw_range (*this); }
{ inline PolyConnectivity::ConstVertexIHalfedgeCCWRange SmartVertexHandle::incoming_halfedges_ccw() const { assert(mesh() != nullptr); return mesh()->vih_ccw_range(*this); }
assert(mesh() != nullptr);
return mesh()->vih_range(*this);
}
inline PolyConnectivity::ConstVertexOHalfedgeRange inline PolyConnectivity::ConstVertexIHalfedgeRange SmartVertexHandle::incoming_halfedges (HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->vih_range (_heh); }
SmartVertexHandle::outgoing_halfedges() const inline PolyConnectivity::ConstVertexIHalfedgeCWRange SmartVertexHandle::incoming_halfedges_cw (HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->vih_cw_range (_heh); }
{ inline PolyConnectivity::ConstVertexIHalfedgeCCWRange SmartVertexHandle::incoming_halfedges_ccw(HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->vih_ccw_range(_heh); }
assert(mesh() != nullptr);
return mesh()->voh_range(*this);
}
inline PolyConnectivity::ConstHalfedgeLoopRange inline PolyConnectivity::ConstVertexOHalfedgeRange SmartVertexHandle::outgoing_halfedges() const { assert(mesh() != nullptr); return mesh()->voh_range (*this); }
SmartHalfedgeHandle::loop() const inline PolyConnectivity::ConstVertexOHalfedgeCWRange SmartVertexHandle::outgoing_halfedges_cw() const { assert(mesh() != nullptr); return mesh()->voh_cw_range (*this); }
{ inline PolyConnectivity::ConstVertexOHalfedgeCCWRange SmartVertexHandle::outgoing_halfedges_ccw() const { assert(mesh() != nullptr); return mesh()->voh_ccw_range(*this); }
assert(mesh() != nullptr);
return mesh()->hl_range(*this); inline PolyConnectivity::ConstVertexOHalfedgeRange SmartVertexHandle::outgoing_halfedges (HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->voh_range (_heh); }
} inline PolyConnectivity::ConstVertexOHalfedgeCWRange SmartVertexHandle::outgoing_halfedges_cw (HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->voh_cw_range (_heh); }
inline PolyConnectivity::ConstVertexOHalfedgeCCWRange SmartVertexHandle::outgoing_halfedges_ccw(HalfedgeHandle _heh) const { assert(mesh() != nullptr); return mesh()->voh_ccw_range(_heh); }
inline PolyConnectivity::ConstFaceVertexRange SmartFaceHandle::vertices() const inline PolyConnectivity::ConstHalfedgeLoopRange SmartHalfedgeHandle::loop() const { assert(mesh() != nullptr); return mesh()->hl_range (*this); }
{ inline PolyConnectivity::ConstHalfedgeLoopCWRange SmartHalfedgeHandle::loop_cw() const { assert(mesh() != nullptr); return mesh()->hl_cw_range (*this); }
assert(mesh() != nullptr); inline PolyConnectivity::ConstHalfedgeLoopCCWRange SmartHalfedgeHandle::loop_ccw() const { assert(mesh() != nullptr); return mesh()->hl_ccw_range (*this); }
return mesh()->fv_range(*this);
}
inline PolyConnectivity::ConstFaceHalfedgeRange
SmartFaceHandle::halfedges() const
{
assert(mesh() != nullptr);
return mesh()->fh_range(*this);
}
inline PolyConnectivity::ConstFaceEdgeRange SmartFaceHandle::edges() const inline PolyConnectivity::ConstFaceVertexRange SmartFaceHandle::vertices() const { assert(mesh() != nullptr); return mesh()->fv_range (*this); }
{ inline PolyConnectivity::ConstFaceVertexCWRange SmartFaceHandle::vertices_cw() const { assert(mesh() != nullptr); return mesh()->fv_cw_range (*this); }
assert(mesh() != nullptr); inline PolyConnectivity::ConstFaceVertexCCWRange SmartFaceHandle::vertices_ccw() const { assert(mesh() != nullptr); return mesh()->fv_ccw_range(*this); }
return mesh()->fe_range(*this);
}
inline PolyConnectivity::ConstFaceFaceRange SmartFaceHandle::faces() const inline PolyConnectivity::ConstFaceHalfedgeRange SmartFaceHandle::halfedges() const { assert(mesh() != nullptr); return mesh()->fh_range (*this); }
{ inline PolyConnectivity::ConstFaceHalfedgeCWRange SmartFaceHandle::halfedges_cw() const { assert(mesh() != nullptr); return mesh()->fh_cw_range (*this); }
assert(mesh() != nullptr); inline PolyConnectivity::ConstFaceHalfedgeCCWRange SmartFaceHandle::halfedges_ccw() const { assert(mesh() != nullptr); return mesh()->fh_ccw_range(*this); }
return mesh()->ff_range(*this);
} inline PolyConnectivity::ConstFaceEdgeRange SmartFaceHandle::edges() const { assert(mesh() != nullptr); return mesh()->fe_range (*this); }
inline PolyConnectivity::ConstFaceEdgeCWRange SmartFaceHandle::edges_cw() const { assert(mesh() != nullptr); return mesh()->fe_cw_range (*this); }
inline PolyConnectivity::ConstFaceEdgeCCWRange SmartFaceHandle::edges_ccw() const { assert(mesh() != nullptr); return mesh()->fe_ccw_range(*this); }
inline PolyConnectivity::ConstFaceFaceRange SmartFaceHandle::faces() const { assert(mesh() != nullptr); return mesh()->ff_range (*this); }
inline PolyConnectivity::ConstFaceFaceCWRange SmartFaceHandle::faces_cw() const { assert(mesh() != nullptr); return mesh()->ff_cw_range (*this); }
inline PolyConnectivity::ConstFaceFaceCCWRange SmartFaceHandle::faces_ccw() const { assert(mesh() != nullptr); return mesh()->ff_ccw_range(*this); }
}//namespace OpenMesh }//namespace OpenMesh

View File

@@ -118,15 +118,47 @@ struct OPENMESHDLLEXPORT SmartVertexHandle : public SmartBaseHandle, VertexHandl
SmartHalfedgeHandle in() const; SmartHalfedgeHandle in() const;
/// Returns a range of faces incident to the vertex (PolyConnectivity::vf_range()) /// Returns a range of faces incident to the vertex (PolyConnectivity::vf_range())
PolyConnectivity::ConstVertexFaceRange faces() const; PolyConnectivity::ConstVertexFaceRange faces() const;
/// Returns a range of faces incident to the vertex (PolyConnectivity::vf_cw_range())
PolyConnectivity::ConstVertexFaceCWRange faces_cw() const;
/// Returns a range of faces incident to the vertex (PolyConnectivity::vf_ccw_range())
PolyConnectivity::ConstVertexFaceCCWRange faces_ccw() const;
/// Returns a range of edges incident to the vertex (PolyConnectivity::ve_range()) /// Returns a range of edges incident to the vertex (PolyConnectivity::ve_range())
PolyConnectivity::ConstVertexEdgeRange edges() const; PolyConnectivity::ConstVertexEdgeRange edges() const;
/// Returns a range of edges incident to the vertex (PolyConnectivity::ve_cw_range())
PolyConnectivity::ConstVertexEdgeCWRange edges_cw() const;
/// Returns a range of edges incident to the vertex (PolyConnectivity::ve_ccw_range())
PolyConnectivity::ConstVertexEdgeCCWRange edges_ccw() const;
/// Returns a range of vertices adjacent to the vertex (PolyConnectivity::vv_range()) /// Returns a range of vertices adjacent to the vertex (PolyConnectivity::vv_range())
PolyConnectivity::ConstVertexVertexRange vertices() const; PolyConnectivity::ConstVertexVertexRange vertices() const;
/// Returns a range of vertices adjacent to the vertex (PolyConnectivity::vv_cw_range())
PolyConnectivity::ConstVertexVertexCWRange vertices_cw() const;
/// Returns a range of vertices adjacent to the vertex (PolyConnectivity::vv_ccw_range())
PolyConnectivity::ConstVertexVertexCCWRange vertices_ccw() const;
/// Returns a range of outgoing halfedges incident to the vertex (PolyConnectivity::voh_range()) /// Returns a range of outgoing halfedges incident to the vertex (PolyConnectivity::voh_range())
PolyConnectivity::ConstVertexIHalfedgeRange incoming_halfedges() const; PolyConnectivity::ConstVertexIHalfedgeRange incoming_halfedges() const;
/// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::vih_range()) /// Returns a range of outgoing halfedges incident to the vertex (PolyConnectivity::voh_cw_range())
PolyConnectivity::ConstVertexOHalfedgeRange outgoing_halfedges() const; PolyConnectivity::ConstVertexIHalfedgeCWRange incoming_halfedges_cw() const;
/// Returns a range of outgoing halfedges incident to the vertex (PolyConnectivity::voh_ccw_range())
PolyConnectivity::ConstVertexIHalfedgeCCWRange incoming_halfedges_ccw() const;
/// Returns a range of outgoing halfedges incident to the vertex (PolyConnectivity::vih_range())
PolyConnectivity::ConstVertexIHalfedgeRange incoming_halfedges(HalfedgeHandle _heh) const;
/// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::vih_cw_range())
PolyConnectivity::ConstVertexIHalfedgeCWRange incoming_halfedges_cw(HalfedgeHandle _heh) const;
/// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::vih_ccw_range())
PolyConnectivity::ConstVertexIHalfedgeCCWRange incoming_halfedges_ccw(HalfedgeHandle _heh) const;
/// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_range())
PolyConnectivity::ConstVertexOHalfedgeRange outgoing_halfedges() const;
/// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_cw_range())
PolyConnectivity::ConstVertexOHalfedgeCWRange outgoing_halfedges_cw() const;
/// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_ccw_range())
PolyConnectivity::ConstVertexOHalfedgeCCWRange outgoing_halfedges_ccw() const;
/// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_range())
PolyConnectivity::ConstVertexOHalfedgeRange outgoing_halfedges(HalfedgeHandle _heh) const;
/// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_cw_range())
PolyConnectivity::ConstVertexOHalfedgeCWRange outgoing_halfedges_cw(HalfedgeHandle _heh) const;
/// Returns a range of incoming halfedges incident to the vertex (PolyConnectivity::voh_ccw_range())
PolyConnectivity::ConstVertexOHalfedgeCCWRange outgoing_halfedges_ccw(HalfedgeHandle _heh) const;
/// Returns valence of the vertex /// Returns valence of the vertex
uint valence() const; uint valence() const;
@@ -154,7 +186,11 @@ struct OPENMESHDLLEXPORT SmartHalfedgeHandle : public SmartBaseHandle, HalfedgeH
SmartFaceHandle face() const; SmartFaceHandle face() const;
/// Returns a range of halfedges in the face of the halfedge (or along the boundary) (PolyConnectivity::hl_range()) /// Returns a range of halfedges in the face of the halfedge (or along the boundary) (PolyConnectivity::hl_range())
PolyConnectivity::ConstHalfedgeLoopRange loop() const; PolyConnectivity::ConstHalfedgeLoopRange loop() const;
/// Returns a range of halfedges in the face of the halfedge (or along the boundary) (PolyConnectivity::hl_cw_range())
PolyConnectivity::ConstHalfedgeLoopCWRange loop_cw() const;
/// Returns a range of halfedges in the face of the halfedge (or along the boundary) (PolyConnectivity::hl_ccw_range())
PolyConnectivity::ConstHalfedgeLoopCCWRange loop_ccw() const;
}; };
struct OPENMESHDLLEXPORT SmartEdgeHandle : public SmartBaseHandle, EdgeHandle, SmartHandleStatusPredicates<SmartEdgeHandle>, SmartHandleBoundaryPredicate<SmartEdgeHandle> struct OPENMESHDLLEXPORT SmartEdgeHandle : public SmartBaseHandle, EdgeHandle, SmartHandleStatusPredicates<SmartEdgeHandle>, SmartHandleBoundaryPredicate<SmartEdgeHandle>
@@ -187,13 +223,29 @@ struct OPENMESHDLLEXPORT SmartFaceHandle : public SmartBaseHandle, FaceHandle, S
SmartHalfedgeHandle halfedge() const; SmartHalfedgeHandle halfedge() const;
/// Returns a range of vertices incident to the face (PolyConnectivity::fv_range()) /// Returns a range of vertices incident to the face (PolyConnectivity::fv_range())
PolyConnectivity::ConstFaceVertexRange vertices() const; PolyConnectivity::ConstFaceVertexRange vertices() const;
/// Returns a range of vertices incident to the face (PolyConnectivity::fv_cw_range())
PolyConnectivity::ConstFaceVertexCWRange vertices_cw() const;
/// Returns a range of vertices incident to the face (PolyConnectivity::fv_ccw_range())
PolyConnectivity::ConstFaceVertexCCWRange vertices_ccw() const;
/// Returns a range of halfedges of the face (PolyConnectivity::fh_range()) /// Returns a range of halfedges of the face (PolyConnectivity::fh_range())
PolyConnectivity::ConstFaceHalfedgeRange halfedges() const; PolyConnectivity::ConstFaceHalfedgeRange halfedges() const;
/// Returns a range of halfedges of the face (PolyConnectivity::fh_cw_range())
PolyConnectivity::ConstFaceHalfedgeCWRange halfedges_cw() const;
/// Returns a range of halfedges of the face (PolyConnectivity::fh_ccw_range())
PolyConnectivity::ConstFaceHalfedgeCCWRange halfedges_ccw() const;
/// Returns a range of edges of the face (PolyConnectivity::fv_range()) /// Returns a range of edges of the face (PolyConnectivity::fv_range())
PolyConnectivity::ConstFaceEdgeRange edges() const; PolyConnectivity::ConstFaceEdgeRange edges() const;
/// Returns a range of edges of the face (PolyConnectivity::fv_cw_range())
PolyConnectivity::ConstFaceEdgeCWRange edges_cw() const;
/// Returns a range of edges of the face (PolyConnectivity::fv_ccw_range())
PolyConnectivity::ConstFaceEdgeCCWRange edges_ccw() const;
/// Returns a range adjacent faces of the face (PolyConnectivity::ff_range()) /// Returns a range adjacent faces of the face (PolyConnectivity::ff_range())
PolyConnectivity::ConstFaceFaceRange faces() const; PolyConnectivity::ConstFaceFaceRange faces() const;
/// Returns a range adjacent faces of the face (PolyConnectivity::ff_cw_range())
PolyConnectivity::ConstFaceFaceCWRange faces_cw() const;
/// Returns a range adjacent faces of the face (PolyConnectivity::ff_ccw_range())
PolyConnectivity::ConstFaceFaceCCWRange faces_ccw() const;
/// Returns the valence of the face /// Returns the valence of the face
uint valence() const; uint valence() const;

View File

@@ -191,9 +191,9 @@ TEST_F(OpenMeshTrimeshCirculatorFaceEdge, CWAndCCWTest) {
*/ */
int indices[4] = {4, 1, 3, 4}; int indices[3] = {4, 1, 3};
int rev_indices[4]; int rev_indices[3];
std::reverse_copy(indices,indices+4,rev_indices); std::reverse_copy(indices,indices+3,rev_indices);
//CCW //CCW
Mesh::FaceEdgeCCWIter fe_ccwit = mesh_.fe_ccwbegin(mesh_.face_handle(1)); Mesh::FaceEdgeCCWIter fe_ccwit = mesh_.fe_ccwbegin(mesh_.face_handle(1));
@@ -243,29 +243,28 @@ TEST_F(OpenMeshTrimeshCirculatorFaceEdge, CWAndCCWTest) {
/* /*
* conversion properties: * conversion properties:
* a) cw_begin == CWIter(ccw_begin()) * a) *cw_begin == *++CWIter(ccw_end())
* b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators
* c) --cw_iter == CWIter(++ccwIter) for valid iterators * c) --cw_iter == CWIter(++ccwIter) for valid iterators
* d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * * d) *cw_begin == *++CWIter(ccw_end())
*/ */
Mesh::FaceEdgeCWIter fe_cwIter = mesh_.fe_cwbegin(mesh_.face_handle(1)); Mesh::FaceEdgeCWIter fe_cwIter = mesh_.fe_cwbegin(mesh_.face_handle(1));
// a) // a)
EXPECT_TRUE( fe_cwIter == Mesh::FaceEdgeCWIter(mesh_.fe_ccwbegin(mesh_.face_handle(1))) ) << "ccw to cw conversion failed"; EXPECT_TRUE( *fe_cwIter == *++Mesh::FaceEdgeCWIter(mesh_.fe_ccwend(mesh_.face_handle(1)))) << "ccw to cw conversion failed";
EXPECT_TRUE( Mesh::FaceEdgeCCWIter(fe_cwIter) == mesh_.fe_ccwbegin(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; EXPECT_TRUE( *++Mesh::FaceEdgeCCWIter(fe_cwIter) == *mesh_.fe_ccwend(mesh_.face_handle(1)) ) << "cw to ccw conversion failed";
// b) // b)
EXPECT_EQ( fe_cwIter->idx(), Mesh::FaceEdgeCCWIter(fe_cwIter)->idx()) << "iterators doesnt point on the same element"; EXPECT_EQ( fe_cwIter->idx(), Mesh::FaceEdgeCCWIter(fe_cwIter)->idx()) << "iterators doesnt point on the same element";
// c) // c)
auto fe_ccwIter = Mesh::FaceEdgeCCWIter(fe_cwIter);
EXPECT_EQ(fe_cwIter->idx(),fe_ccwIter->idx())<< "iterators dont point on the same element";
++fe_cwIter; ++fe_cwIter;
fe_ccwend = mesh_.fe_ccwend(mesh_.face_handle(1)); --fe_ccwIter;
--fe_ccwend; EXPECT_EQ(fe_cwIter->idx(),fe_ccwIter->idx()) << "iteratoes are not equal after inc/dec";
EXPECT_EQ(fe_cwIter->idx(),fe_ccwend->idx()) << "iteratoes are not equal after inc/dec";
// additional conversion check
fe_ccwend = Mesh::FaceEdgeCCWIter(fe_cwIter);
EXPECT_EQ(fe_cwIter->idx(),fe_ccwend->idx())<< "iterators doesnt point on the same element";
// d) // d)
fe_cwIter = Mesh::FaceEdgeCWIter(mesh_.fe_ccwend(mesh_.face_handle(1))); auto fe_cwEnd = mesh_.fe_ccwend(mesh_.face_handle(1));
fe_cwIter = Mesh::FaceEdgeCWIter(fe_cwEnd);
EXPECT_FALSE(fe_cwIter.is_valid()) << "end iterator is not invalid"; EXPECT_FALSE(fe_cwIter.is_valid()) << "end iterator is not invalid";
EXPECT_TRUE(Mesh::FaceEdgeCCWIter(mesh_.fe_cwend(mesh_.face_handle(1))) == mesh_.fe_ccwend(mesh_.face_handle(1))) << "end iterators are not equal"; EXPECT_TRUE(*mesh_.fe_cwbegin(mesh_.face_handle(1)) == *++fe_cwIter) << "end iterators are not equal";
} }

View File

@@ -267,9 +267,9 @@ TEST_F(OpenMeshTrimeshCirculatorFaceFace, CWAndCCWCheck) {
*/ */
int indices[4] = {2, 0, 3, 2}; int indices[3] = {2, 0, 3};
int rev_indices[4]; int rev_indices[3];
std::reverse_copy(indices,indices+4,rev_indices); std::reverse_copy(indices,indices+3,rev_indices);
//CCW //CCW
Mesh::FaceFaceCCWIter ff_ccwit = mesh_.ff_ccwbegin(mesh_.face_handle(1)); Mesh::FaceFaceCCWIter ff_ccwit = mesh_.ff_ccwbegin(mesh_.face_handle(1));
@@ -322,26 +322,25 @@ TEST_F(OpenMeshTrimeshCirculatorFaceFace, CWAndCCWCheck) {
* a) cw_begin == CWIter(ccw_begin()) * a) cw_begin == CWIter(ccw_begin())
* b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators
* c) --cw_iter == CWIter(++ccwIter) for valid iterators * c) --cw_iter == CWIter(++ccwIter) for valid iterators
* d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * * d) cw_end == CWIter(ccw_end())
*/ */
Mesh::FaceFaceCWIter ff_cwIter = mesh_.ff_cwbegin(mesh_.face_handle(1)); Mesh::FaceFaceCWIter ff_cwIter = mesh_.ff_cwbegin(mesh_.face_handle(1));
// a) // a)
EXPECT_TRUE( ff_cwIter == Mesh::FaceFaceCWIter(mesh_.ff_ccwbegin(mesh_.face_handle(1))) ) << "ccw to cw conversion failed"; EXPECT_TRUE( *ff_cwIter == *++Mesh::FaceFaceCWIter(mesh_.ff_ccwend(mesh_.face_handle(1)))) << "ccw to cw conversion failed";
EXPECT_TRUE( Mesh::FaceFaceCCWIter(ff_cwIter) == mesh_.ff_ccwbegin(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; EXPECT_TRUE( *++Mesh::FaceFaceCCWIter(ff_cwIter) == *mesh_.ff_ccwend(mesh_.face_handle(1)) ) << "cw to ccw conversion failed";
// b) // b)
EXPECT_EQ( ff_cwIter->idx(), Mesh::FaceFaceCCWIter(ff_cwIter)->idx()) << "iterators doesnt point on the same element"; EXPECT_EQ( ff_cwIter->idx(), Mesh::FaceFaceCCWIter(ff_cwIter)->idx()) << "iterators doesnt point on the same element";
// c) // c)
auto ff_ccwIter = Mesh::FaceFaceCCWIter(ff_cwIter);
EXPECT_EQ(ff_cwIter->idx(),ff_ccwIter->idx())<< "iterators dont point on the same element";
++ff_cwIter; ++ff_cwIter;
ff_ccwend = mesh_.ff_ccwend(mesh_.face_handle(1)); --ff_ccwIter;
--ff_ccwend; EXPECT_EQ(ff_cwIter->idx(),ff_ccwIter->idx()) << "iteratoes are not equal after inc/dec";
EXPECT_EQ(ff_cwIter->idx(),ff_ccwend->idx()) << "iteratoes are not equal after inc/dec";
// additional conversion check
ff_ccwend = Mesh::FaceFaceCCWIter(ff_cwIter);
EXPECT_EQ(ff_cwIter->idx(),ff_ccwend->idx())<< "iterators doesnt point on the same element";
// d) // d)
ff_cwIter = Mesh::FaceFaceCWIter(mesh_.ff_ccwend(mesh_.face_handle(1))); auto ff_cwEnd = mesh_.ff_ccwend(mesh_.face_handle(1));
ff_cwIter = Mesh::FaceFaceCWIter(ff_cwEnd);
EXPECT_FALSE(ff_cwIter.is_valid()) << "end iterator is not invalid"; EXPECT_FALSE(ff_cwIter.is_valid()) << "end iterator is not invalid";
EXPECT_TRUE(Mesh::FaceFaceCCWIter(mesh_.ff_cwend(mesh_.face_handle(1))) == mesh_.ff_ccwend(mesh_.face_handle(1))) << "end iterators are not equal"; EXPECT_TRUE(*mesh_.ff_cwbegin(mesh_.face_handle(1)) == *++ff_cwIter) << "end iterators are not equal";
} }

View File

@@ -189,9 +189,9 @@ TEST_F(OpenMeshTrimeshCirculatorFaceHalfEdge, CWAndCCWTest) {
*/ */
int indices[4] = {8, 3, 6, 8}; int indices[3] = {8, 3, 6};
int rev_indices[4]; int rev_indices[3];
std::reverse_copy(indices,indices+4,rev_indices); std::reverse_copy(indices,indices+3,rev_indices);
//CCW //CCW
Mesh::FaceHalfedgeCCWIter fh_ccwit = mesh_.fh_ccwbegin(mesh_.face_handle(1)); Mesh::FaceHalfedgeCCWIter fh_ccwit = mesh_.fh_ccwbegin(mesh_.face_handle(1));
@@ -248,22 +248,21 @@ TEST_F(OpenMeshTrimeshCirculatorFaceHalfEdge, CWAndCCWTest) {
*/ */
Mesh::FaceHalfedgeCWIter fh_cwIter = mesh_.fh_cwbegin(mesh_.face_handle(1)); Mesh::FaceHalfedgeCWIter fh_cwIter = mesh_.fh_cwbegin(mesh_.face_handle(1));
// a) // a)
EXPECT_TRUE( fh_cwIter == Mesh::FaceHalfedgeCWIter(mesh_.fh_ccwbegin(mesh_.face_handle(1))) ) << "ccw to cw conversion failed"; EXPECT_TRUE( *fh_cwIter == *++Mesh::FaceHalfedgeCWIter(mesh_.fh_ccwend(mesh_.face_handle(1)))) << "ccw to cw conversion failed";
EXPECT_TRUE( Mesh::FaceHalfedgeCCWIter(fh_cwIter) == mesh_.fh_ccwbegin(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; EXPECT_TRUE( *++Mesh::FaceHalfedgeCCWIter(fh_cwIter) == *mesh_.fh_ccwend(mesh_.face_handle(1)) ) << "cw to ccw conversion failed";
// b) // b)
EXPECT_EQ( fh_cwIter->idx(), Mesh::FaceHalfedgeCCWIter(fh_cwIter)->idx()) << "iterators doesnt point on the same element"; EXPECT_EQ( fh_cwIter->idx(), Mesh::FaceHalfedgeCCWIter(fh_cwIter)->idx()) << "iterators doesnt point on the same element";
// c) // c)
auto fh_ccwIter = Mesh::FaceHalfedgeCCWIter(fh_cwIter);
EXPECT_EQ(fh_cwIter->idx(),fh_ccwIter->idx())<< "iterators dont point on the same element";
++fh_cwIter; ++fh_cwIter;
fh_ccwend = mesh_.fh_ccwend(mesh_.face_handle(1)); --fh_ccwIter;
--fh_ccwend; EXPECT_EQ(fh_cwIter->idx(),fh_ccwIter->idx()) << "iteratoes are not equal after inc/dec";
EXPECT_EQ(fh_cwIter->idx(),fh_ccwend->idx()) << "iteratoes are not equal after inc/dec";
// additional conversion check
fh_ccwend = Mesh::FaceHalfedgeCCWIter(fh_cwIter);
EXPECT_EQ(fh_cwIter->idx(),fh_ccwend->idx())<< "iterators doesnt point on the same element";
// d) // d)
fh_cwIter = Mesh::FaceHalfedgeCWIter(mesh_.fh_ccwend(mesh_.face_handle(1))); auto fh_cwEnd = mesh_.fh_ccwend(mesh_.face_handle(1));
fh_cwIter = Mesh::FaceHalfedgeCWIter(fh_cwEnd);
EXPECT_FALSE(fh_cwIter.is_valid()) << "end iterator is not invalid"; EXPECT_FALSE(fh_cwIter.is_valid()) << "end iterator is not invalid";
EXPECT_TRUE(Mesh::FaceHalfedgeCCWIter(mesh_.fh_cwend(mesh_.face_handle(1))) == mesh_.fh_ccwend(mesh_.face_handle(1))) << "end iterators are not equal"; EXPECT_TRUE(*mesh_.fh_cwbegin(mesh_.face_handle(1)) == *++fh_cwIter) << "end iterators are not equal";
} }

View File

@@ -261,9 +261,9 @@ TEST_F(OpenMeshTrimeshCirculatorFaceVertex, CWAndCCWCheck) {
3 ==== 4 */ 3 ==== 4 */
int indices[4] = {0, 1, 2, 0}; int indices[3] = {0, 1, 2};
int rev_indices[4]; int rev_indices[3];
std::reverse_copy(indices,indices+4,rev_indices); std::reverse_copy(indices,indices+3,rev_indices);
//CCW //CCW
Mesh::FaceVertexCCWIter fv_ccwit = mesh_.fv_ccwbegin(fh0); Mesh::FaceVertexCCWIter fv_ccwit = mesh_.fv_ccwbegin(fh0);
@@ -320,22 +320,21 @@ TEST_F(OpenMeshTrimeshCirculatorFaceVertex, CWAndCCWCheck) {
*/ */
Mesh::FaceVertexCWIter fv_cwIter = mesh_.fv_cwbegin(mesh_.face_handle(1)); Mesh::FaceVertexCWIter fv_cwIter = mesh_.fv_cwbegin(mesh_.face_handle(1));
// a) // a)
EXPECT_TRUE( fv_cwIter == Mesh::FaceVertexCWIter(mesh_.fv_ccwbegin(mesh_.face_handle(1))) ) << "ccw to cw conversion failed"; EXPECT_TRUE( *fv_cwIter == *++Mesh::FaceVertexCWIter(mesh_.fv_ccwend(mesh_.face_handle(1)))) << "ccw to cw conversion failed";
EXPECT_TRUE( Mesh::FaceVertexCCWIter(fv_cwIter) == mesh_.fv_ccwbegin(mesh_.face_handle(1)) ) << "cw to ccw conversion failed"; EXPECT_TRUE( *++Mesh::FaceVertexCCWIter(fv_cwIter) == *mesh_.fv_ccwend(mesh_.face_handle(1)) ) << "cw to ccw conversion failed";
// b) // b)
EXPECT_EQ( fv_cwIter->idx(), Mesh::FaceVertexCCWIter(fv_cwIter)->idx()) << "iterators doesnt point on the same element"; EXPECT_EQ( fv_cwIter->idx(), Mesh::FaceVertexCCWIter(fv_cwIter)->idx()) << "iterators doesnt point on the same element";
// c) // c)
auto fv_ccwIter = Mesh::FaceVertexCCWIter(fv_cwIter);
EXPECT_EQ(fv_cwIter->idx(),fv_ccwIter->idx())<< "iterators dont point on the same element";
++fv_cwIter; ++fv_cwIter;
fv_ccwend = mesh_.fv_ccwend(mesh_.face_handle(1)); --fv_ccwIter;
--fv_ccwend; EXPECT_EQ(fv_cwIter->idx(),fv_ccwIter->idx()) << "iteratoes are not equal after inc/dec";
EXPECT_EQ(fv_cwIter->idx(),fv_ccwend->idx()) << "iteratoes are not equal after inc/dec";
// additional conversion check
fv_ccwend = Mesh::FaceVertexCCWIter(fv_cwIter);
EXPECT_EQ(fv_cwIter->idx(),fv_ccwend->idx())<< "iterators doesnt point on the same element";
// d) // d)
fv_cwIter = Mesh::FaceVertexCWIter(mesh_.fv_ccwend(mesh_.face_handle(1))); auto fv_cwEnd = mesh_.fv_ccwend(mesh_.face_handle(1));
fv_cwIter = Mesh::FaceVertexCWIter(fv_cwEnd);
EXPECT_FALSE(fv_cwIter.is_valid()) << "end iterator is not invalid"; EXPECT_FALSE(fv_cwIter.is_valid()) << "end iterator is not invalid";
EXPECT_TRUE(Mesh::FaceVertexCCWIter(mesh_.fv_cwend(mesh_.face_handle(1))) == mesh_.fv_ccwend(mesh_.face_handle(1))) << "end iterators are not equal"; EXPECT_TRUE(*mesh_.fv_cwbegin(mesh_.face_handle(1)) == *++fv_cwIter) << "end iterators are not equal";
} }

View File

@@ -336,9 +336,9 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) {
3 ==== 4 */ 3 ==== 4 */
int indices[5] = {5, 1, 0, 3, 5}; int ccw_indices[4] = {1, 0, 3, 5};
int rev_indices[5]; int cw_indices[4];
std::reverse_copy(indices,indices+5,rev_indices); std::reverse_copy(ccw_indices,ccw_indices+4,cw_indices);
Mesh::VertexHandle vh = vhandle[1]; Mesh::VertexHandle vh = vhandle[1];
@@ -348,7 +348,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) {
size_t i = 0; size_t i = 0;
for (;ve_ccwit != ve_ccwend; ++ve_ccwit, ++i) for (;ve_ccwit != ve_ccwend; ++ve_ccwit, ++i)
{ {
EXPECT_EQ(indices[i], ve_ccwit->idx()) << "Index wrong in VertexEdgeCCWIter"; EXPECT_EQ(ccw_indices[i], ve_ccwit->idx()) << "Index wrong in VertexEdgeCCWIter";
} }
EXPECT_FALSE(ve_ccwit.is_valid()) << "Iterator invalid in VertexEdgeCCWIter at end"; EXPECT_FALSE(ve_ccwit.is_valid()) << "Iterator invalid in VertexEdgeCCWIter at end";
@@ -360,7 +360,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) {
i = 0; i = 0;
for (;cve_ccwit != cve_ccwend; ++cve_ccwit, ++i) for (;cve_ccwit != cve_ccwend; ++cve_ccwit, ++i)
{ {
EXPECT_EQ(indices[i], cve_ccwit->idx()) << "Index wrong in ConstVertexEdgeCCWIter"; EXPECT_EQ(ccw_indices[i], cve_ccwit->idx()) << "Index wrong in ConstVertexEdgeCCWIter";
} }
EXPECT_FALSE(cve_ccwit.is_valid()) << "Iterator invalid in ConstVertexEdgeCCWIter at end"; EXPECT_FALSE(cve_ccwit.is_valid()) << "Iterator invalid in ConstVertexEdgeCCWIter at end";
@@ -372,7 +372,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) {
i = 0; i = 0;
for (;ve_cwit != ve_cwend; ++ve_cwit, ++i) for (;ve_cwit != ve_cwend; ++ve_cwit, ++i)
{ {
EXPECT_EQ(rev_indices[i], ve_cwit->idx()) << "Index wrong in VertexEdgeCWIter"; EXPECT_EQ(cw_indices[i], ve_cwit->idx()) << "Index wrong in VertexEdgeCWIter";
} }
EXPECT_FALSE(ve_cwit.is_valid()) << "Iterator invalid in VertexEdgeCWIter at end"; EXPECT_FALSE(ve_cwit.is_valid()) << "Iterator invalid in VertexEdgeCWIter at end";
EXPECT_TRUE( ve_cwit == ve_cwend ) << "End iterator for VertexEdgeCWIter not matching"; EXPECT_TRUE( ve_cwit == ve_cwend ) << "End iterator for VertexEdgeCWIter not matching";
@@ -383,7 +383,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) {
i = 0; i = 0;
for (;cve_cwit != cve_cwend; ++cve_cwit, ++i) for (;cve_cwit != cve_cwend; ++cve_cwit, ++i)
{ {
EXPECT_EQ(rev_indices[i], cve_cwit->idx()) << "Index wrong in ConstVertexEdgeCWIter"; EXPECT_EQ(cw_indices[i], cve_cwit->idx()) << "Index wrong in ConstVertexEdgeCWIter";
} }
EXPECT_FALSE(cve_cwit.is_valid()) << "Iterator invalid in ConstVertexEdgeCWIter at end"; EXPECT_FALSE(cve_cwit.is_valid()) << "Iterator invalid in ConstVertexEdgeCWIter at end";
EXPECT_TRUE( cve_cwit == cve_cwend ) << "End iterator for ConstVertexEdgeCWIter not matching"; EXPECT_TRUE( cve_cwit == cve_cwend ) << "End iterator for ConstVertexEdgeCWIter not matching";
@@ -397,22 +397,21 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) {
*/ */
Mesh::VertexEdgeCWIter ve_cwIter = mesh_.ve_cwbegin(vh); Mesh::VertexEdgeCWIter ve_cwIter = mesh_.ve_cwbegin(vh);
// a) // a)
EXPECT_TRUE( ve_cwIter == Mesh::VertexEdgeCWIter(mesh_.ve_ccwbegin(vh)) ) << "ccw to cw conversion failed"; EXPECT_TRUE( *ve_cwIter == *++Mesh::VertexEdgeCWIter(mesh_.ve_ccwend(vh))) << "ccw to cw conversion failed";
EXPECT_TRUE( Mesh::VertexEdgeCCWIter(ve_cwIter) == mesh_.ve_ccwbegin(vh) ) << "cw to ccw conversion failed"; EXPECT_TRUE( *++Mesh::VertexEdgeCCWIter(ve_cwIter) == *mesh_.ve_ccwend(vh) ) << "cw to ccw conversion failed";
// b) // b)
EXPECT_EQ( ve_cwIter->idx(), Mesh::VertexEdgeCCWIter(ve_cwIter)->idx()) << "iterators doesnt point on the same element"; EXPECT_EQ( ve_cwIter->idx(), Mesh::VertexEdgeCCWIter(ve_cwIter)->idx()) << "iterators doesnt point on the same element";
// c) // c)
auto ve_ccwIter = Mesh::VertexEdgeCCWIter(ve_cwIter);
EXPECT_EQ(ve_cwIter->idx(),ve_ccwIter->idx())<< "iterators dont point on the same element";
++ve_cwIter; ++ve_cwIter;
ve_ccwend = mesh_.ve_ccwend(vh); --ve_ccwIter;
--ve_ccwend; EXPECT_EQ(ve_cwIter->idx(),ve_ccwIter->idx()) << "iteratoes are not equal after inc/dec";
EXPECT_EQ(ve_cwIter->idx(),ve_ccwend->idx()) << "iteratoes are not equal after inc/dec";
// additional conversion check
ve_ccwend = Mesh::VertexEdgeCCWIter(ve_cwIter);
EXPECT_EQ(ve_cwIter->idx(),ve_ccwend->idx())<< "iterators doesnt point on the same element";
// d) // d)
ve_cwIter = Mesh::VertexEdgeCWIter(mesh_.ve_ccwend(vh)); auto ve_cwEnd = mesh_.ve_ccwend(vh);
ve_cwIter = Mesh::VertexEdgeCWIter(ve_cwEnd);
EXPECT_FALSE(ve_cwIter.is_valid()) << "end iterator is not invalid"; EXPECT_FALSE(ve_cwIter.is_valid()) << "end iterator is not invalid";
EXPECT_TRUE(Mesh::VertexEdgeCCWIter(mesh_.ve_cwend(vh)) == mesh_.ve_ccwend(vh)) << "end iterators are not equal"; EXPECT_TRUE(*mesh_.ve_cwbegin(vh) == *++ve_cwIter) << "end iterators are not equal";
} }

View File

@@ -509,9 +509,9 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) {
3 ==== 4 */ 3 ==== 4 */
int indices[5] = {3, 0, 2, 1, 3}; int ccw_indices[4] = {0, 2, 1, 3};
int rev_indices[5]; int cw_indices[4];
std::reverse_copy(indices,indices+5,rev_indices); std::reverse_copy(ccw_indices,ccw_indices+4,cw_indices);
Mesh::VertexHandle vh = vhandle[1]; Mesh::VertexHandle vh = vhandle[1];
@@ -521,7 +521,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) {
size_t i = 0; size_t i = 0;
for (;vf_ccwit != vf_ccwend; ++vf_ccwit, ++i) for (;vf_ccwit != vf_ccwend; ++vf_ccwit, ++i)
{ {
EXPECT_EQ(indices[i], vf_ccwit->idx()) << "Index wrong in VertexFaceCCWIter"; EXPECT_EQ(ccw_indices[i], vf_ccwit->idx()) << "Index wrong in VertexFaceCCWIter";
} }
EXPECT_FALSE(vf_ccwit.is_valid()) << "Iterator invalid in VertexFaceCCWIter at end"; EXPECT_FALSE(vf_ccwit.is_valid()) << "Iterator invalid in VertexFaceCCWIter at end";
@@ -533,7 +533,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) {
i = 0; i = 0;
for (;cvf_ccwit != cvf_ccwend; ++cvf_ccwit, ++i) for (;cvf_ccwit != cvf_ccwend; ++cvf_ccwit, ++i)
{ {
EXPECT_EQ(indices[i], cvf_ccwit->idx()) << "Index wrong in ConstVertexFaceCCWIter"; EXPECT_EQ(ccw_indices[i], cvf_ccwit->idx()) << "Index wrong in ConstVertexFaceCCWIter";
} }
EXPECT_FALSE(cvf_ccwit.is_valid()) << "Iterator invalid in ConstVertexFaceCCWIter at end"; EXPECT_FALSE(cvf_ccwit.is_valid()) << "Iterator invalid in ConstVertexFaceCCWIter at end";
@@ -545,7 +545,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) {
i = 0; i = 0;
for (;vf_cwit != vf_cwend; ++vf_cwit, ++i) for (;vf_cwit != vf_cwend; ++vf_cwit, ++i)
{ {
EXPECT_EQ(rev_indices[i], vf_cwit->idx()) << "Index wrong in VertexFaceCWIter"; EXPECT_EQ(cw_indices[i], vf_cwit->idx()) << "Index wrong in VertexFaceCWIter";
} }
EXPECT_FALSE(vf_cwit.is_valid()) << "Iterator invalid in VertexFaceCWIter at end"; EXPECT_FALSE(vf_cwit.is_valid()) << "Iterator invalid in VertexFaceCWIter at end";
EXPECT_TRUE( vf_cwit == vf_cwend ) << "End iterator for VertexFaceCWIter not matching"; EXPECT_TRUE( vf_cwit == vf_cwend ) << "End iterator for VertexFaceCWIter not matching";
@@ -556,7 +556,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) {
i = 0; i = 0;
for (;cvf_cwit != cvf_cwend; ++cvf_cwit, ++i) for (;cvf_cwit != cvf_cwend; ++cvf_cwit, ++i)
{ {
EXPECT_EQ(rev_indices[i], cvf_cwit->idx()) << "Index wrong in ConstVertexFaceCWIter"; EXPECT_EQ(cw_indices[i], cvf_cwit->idx()) << "Index wrong in ConstVertexFaceCWIter";
} }
EXPECT_FALSE(cvf_cwit.is_valid()) << "Iterator invalid in ConstVertexFaceCWIter at end"; EXPECT_FALSE(cvf_cwit.is_valid()) << "Iterator invalid in ConstVertexFaceCWIter at end";
EXPECT_TRUE( cvf_cwit == cvf_cwend ) << "End iterator for ConstVertexFaceCWIter not matching"; EXPECT_TRUE( cvf_cwit == cvf_cwend ) << "End iterator for ConstVertexFaceCWIter not matching";
@@ -570,22 +570,21 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) {
*/ */
Mesh::VertexFaceCWIter vf_cwIter = mesh_.vf_cwbegin(vh); Mesh::VertexFaceCWIter vf_cwIter = mesh_.vf_cwbegin(vh);
// a) // a)
EXPECT_TRUE( vf_cwIter == Mesh::VertexFaceCWIter(mesh_.vf_ccwbegin(vh)) ) << "ccw to cw conversion failed"; EXPECT_TRUE( *vf_cwIter == *++Mesh::VertexFaceCWIter(mesh_.vf_ccwend(vh))) << "ccw to cw conversion failed";
EXPECT_TRUE( Mesh::VertexFaceCCWIter(vf_cwIter) == mesh_.vf_ccwbegin(vh) ) << "cw to ccw conversion failed"; EXPECT_TRUE( *++Mesh::VertexFaceCCWIter(vf_cwIter) == *mesh_.vf_ccwend(vh) ) << "cw to ccw conversion failed";
// b) // b)
EXPECT_EQ( vf_cwIter->idx(), Mesh::VertexFaceCCWIter(vf_cwIter)->idx()) << "iterators doesnt point on the same element"; EXPECT_EQ( vf_cwIter->idx(), Mesh::VertexFaceCCWIter(vf_cwIter)->idx()) << "iterators doesnt point on the same element";
// c) // c)
auto vf_ccwIter = Mesh::VertexFaceCCWIter(vf_cwIter);
EXPECT_EQ(vf_cwIter->idx(),vf_ccwIter->idx())<< "iterators dont point on the same element";
++vf_cwIter; ++vf_cwIter;
vf_ccwend = mesh_.vf_ccwend(vh); --vf_ccwIter;
--vf_ccwend; EXPECT_EQ(vf_cwIter->idx(),vf_ccwIter->idx()) << "iteratoes are not equal after inc/dec";
EXPECT_EQ(vf_cwIter->idx(),vf_ccwend->idx()) << "iteratoes are not equal after inc/dec";
// additional conversion check
vf_ccwend = Mesh::VertexFaceCCWIter(vf_cwIter);
EXPECT_EQ(vf_cwIter->idx(),vf_ccwend->idx())<< "iterators doesnt point on the same element";
// d) // d)
vf_cwIter = Mesh::VertexFaceCWIter(mesh_.vf_ccwend(vh)); auto vf_cwEnd = mesh_.vf_ccwend(vh);
vf_cwIter = Mesh::VertexFaceCWIter(vf_cwEnd);
EXPECT_FALSE(vf_cwIter.is_valid()) << "end iterator is not invalid"; EXPECT_FALSE(vf_cwIter.is_valid()) << "end iterator is not invalid";
EXPECT_TRUE(Mesh::VertexFaceCCWIter(mesh_.vf_cwend(vh)) == mesh_.vf_ccwend(vh)) << "end iterators are not equal"; EXPECT_TRUE(*mesh_.vf_cwbegin(vh) == *++vf_cwIter) << "end iterators are not equal";
} }

View File

@@ -450,9 +450,9 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) {
3 ==== 4 */ 3 ==== 4 */
int indices[4] = {14, 5, 2, 14}; int cw_indices[3] = {14, 2, 5};
int rev_indices[4]; int ccw_indices[3];
std::reverse_copy(indices,indices+4,rev_indices); std::reverse_copy(cw_indices,cw_indices+3,ccw_indices);
Mesh::VertexHandle vh = vhandle[2]; Mesh::VertexHandle vh = vhandle[2];
@@ -462,7 +462,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) {
size_t i = 0; size_t i = 0;
for (;vih_ccwit != vih_ccwend; ++vih_ccwit, ++i) for (;vih_ccwit != vih_ccwend; ++vih_ccwit, ++i)
{ {
EXPECT_EQ(indices[i], vih_ccwit->idx()) << "Index wrong in VertexIHalfedgeCCWIter"; EXPECT_EQ(ccw_indices[i], vih_ccwit->idx()) << "Index wrong in VertexIHalfedgeCCWIter";
} }
EXPECT_FALSE(vih_ccwit.is_valid()) << "Iterator invalid in VertexIHalfedgeCCWIter at end"; EXPECT_FALSE(vih_ccwit.is_valid()) << "Iterator invalid in VertexIHalfedgeCCWIter at end";
@@ -474,7 +474,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) {
i = 0; i = 0;
for (;cvih_ccwit != cvih_ccwend; ++cvih_ccwit, ++i) for (;cvih_ccwit != cvih_ccwend; ++cvih_ccwit, ++i)
{ {
EXPECT_EQ(indices[i], cvih_ccwit->idx()) << "Index wrong in ConstVertexIHalfedgeCCWIter"; EXPECT_EQ(ccw_indices[i], cvih_ccwit->idx()) << "Index wrong in ConstVertexIHalfedgeCCWIter";
} }
EXPECT_FALSE(cvih_ccwit.is_valid()) << "Iterator invalid in ConstVertexIHalfedgeCCWIter at end"; EXPECT_FALSE(cvih_ccwit.is_valid()) << "Iterator invalid in ConstVertexIHalfedgeCCWIter at end";
@@ -486,7 +486,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) {
i = 0; i = 0;
for (;vih_cwit != vih_cwend; ++vih_cwit, ++i) for (;vih_cwit != vih_cwend; ++vih_cwit, ++i)
{ {
EXPECT_EQ(rev_indices[i], vih_cwit->idx()) << "Index wrong in VertexIHalfedgeCWIter"; EXPECT_EQ(cw_indices[i], vih_cwit->idx()) << "Index wrong in VertexIHalfedgeCWIter";
} }
EXPECT_FALSE(vih_cwit.is_valid()) << "Iterator invalid in VertexIHalfedgeCWIter at end"; EXPECT_FALSE(vih_cwit.is_valid()) << "Iterator invalid in VertexIHalfedgeCWIter at end";
EXPECT_TRUE( vih_cwit == vih_cwend ) << "End iterator for VertexIHalfedgeCWIter not matching"; EXPECT_TRUE( vih_cwit == vih_cwend ) << "End iterator for VertexIHalfedgeCWIter not matching";
@@ -497,7 +497,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) {
i = 0; i = 0;
for (;cvih_cwit != cvih_cwend; ++cvih_cwit, ++i) for (;cvih_cwit != cvih_cwend; ++cvih_cwit, ++i)
{ {
EXPECT_EQ(rev_indices[i], cvih_cwit->idx()) << "Index wrong in ConstVertexIHalfedgeCWIter"; EXPECT_EQ(cw_indices[i], cvih_cwit->idx()) << "Index wrong in ConstVertexIHalfedgeCWIter";
} }
EXPECT_FALSE(cvih_cwit.is_valid()) << "Iterator invalid in ConstVertexIHalfedgeCWIter at end"; EXPECT_FALSE(cvih_cwit.is_valid()) << "Iterator invalid in ConstVertexIHalfedgeCWIter at end";
EXPECT_TRUE( cvih_cwit == cvih_cwend ) << "End iterator for ConstVertexIHalfedgeCWIter not matching"; EXPECT_TRUE( cvih_cwit == cvih_cwend ) << "End iterator for ConstVertexIHalfedgeCWIter not matching";
@@ -511,25 +511,23 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) {
*/ */
Mesh::VertexIHalfedgeCWIter vih_cwIter = mesh_.vih_cwbegin(vh); Mesh::VertexIHalfedgeCWIter vih_cwIter = mesh_.vih_cwbegin(vh);
// a) // a)
EXPECT_TRUE( vih_cwIter == Mesh::VertexIHalfedgeCWIter(mesh_.vih_ccwbegin(vh)) ) << "ccw to cw conversion failed"; EXPECT_TRUE( *vih_cwIter == *++Mesh::VertexIHalfedgeCWIter(mesh_.vih_ccwend(vh))) << "ccw to cw conversion failed";
EXPECT_TRUE( Mesh::VertexIHalfedgeCCWIter(vih_cwIter) == mesh_.vih_ccwbegin(vh) ) << "cw to ccw conversion failed"; EXPECT_TRUE( *++Mesh::VertexIHalfedgeCCWIter(vih_cwIter) == *mesh_.vih_ccwend(vh) ) << "cw to ccw conversion failed";
// b) // b)
EXPECT_EQ( vih_cwIter->idx(), Mesh::VertexIHalfedgeCCWIter(vih_cwIter)->idx()) << "iterators doesnt point on the same element"; EXPECT_EQ( vih_cwIter->idx(), Mesh::VertexIHalfedgeCCWIter(vih_cwIter)->idx()) << "iterators doesnt point on the same element";
// c) // c)
auto vih_ccwIter = Mesh::VertexIHalfedgeCCWIter(vih_cwIter);
EXPECT_EQ(vih_cwIter->idx(),vih_ccwIter->idx())<< "iterators dont point on the same element";
++vih_cwIter; ++vih_cwIter;
vih_ccwend = mesh_.vih_ccwend(vh); --vih_ccwIter;
--vih_ccwend; EXPECT_EQ(vih_cwIter->idx(),vih_ccwIter->idx()) << "iteratoes are not equal after inc/dec";
EXPECT_EQ(vih_cwIter->idx(),vih_ccwend->idx()) << "iteratoes are not equal after inc/dec";
// additional conversion check
vih_ccwend = Mesh::VertexIHalfedgeCCWIter(vih_cwIter);
EXPECT_EQ(vih_cwIter->idx(),vih_ccwend->idx())<< "iterators doesnt point on the same element";
// d) // d)
vih_cwIter = Mesh::VertexIHalfedgeCWIter(mesh_.vih_ccwend(vh)); auto vih_cwEnd = mesh_.vih_ccwend(vh);
vih_cwIter = Mesh::VertexIHalfedgeCWIter(vih_cwEnd);
EXPECT_FALSE(vih_cwIter.is_valid()) << "end iterator is not invalid"; EXPECT_FALSE(vih_cwIter.is_valid()) << "end iterator is not invalid";
EXPECT_TRUE(Mesh::VertexIHalfedgeCCWIter(mesh_.vih_cwend(vh)) == mesh_.vih_ccwend(vh)) << "end iterators are not equal"; EXPECT_TRUE(*mesh_.vih_cwbegin(vh) == *++vih_cwIter) << "end iterators are not equal";
} }
} }

View File

@@ -450,9 +450,9 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) {
3 ==== 4 */ 3 ==== 4 */
int indices[5] = {11, 2, 1, 6, 11}; int cw_indices[4] = {11, 6, 1, 2};
int rev_indices[5]; int ccw_indices[4];
std::reverse_copy(indices,indices+5,rev_indices); std::reverse_copy(cw_indices,cw_indices+4,ccw_indices);
Mesh::VertexHandle vh = vhandle[1]; Mesh::VertexHandle vh = vhandle[1];
@@ -462,7 +462,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) {
size_t i = 0; size_t i = 0;
for (;voh_ccwit != voh_ccwend; ++voh_ccwit, ++i) for (;voh_ccwit != voh_ccwend; ++voh_ccwit, ++i)
{ {
EXPECT_EQ(indices[i], voh_ccwit->idx()) << "Index wrong in VertexOHalfedgeCCWIter"; EXPECT_EQ(ccw_indices[i], voh_ccwit->idx()) << "Index wrong in VertexOHalfedgeCCWIter";
} }
EXPECT_FALSE(voh_ccwit.is_valid()) << "Iterator invalid in VertexOHalfedgeCCWIter at end"; EXPECT_FALSE(voh_ccwit.is_valid()) << "Iterator invalid in VertexOHalfedgeCCWIter at end";
@@ -474,7 +474,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) {
i = 0; i = 0;
for (;cvoh_ccwit != cvoh_ccwend; ++cvoh_ccwit, ++i) for (;cvoh_ccwit != cvoh_ccwend; ++cvoh_ccwit, ++i)
{ {
EXPECT_EQ(indices[i], cvoh_ccwit->idx()) << "Index wrong in ConstVertexOHalfedgeCCWIter"; EXPECT_EQ(ccw_indices[i], cvoh_ccwit->idx()) << "Index wrong in ConstVertexOHalfedgeCCWIter";
} }
EXPECT_FALSE(cvoh_ccwit.is_valid()) << "Iterator invalid in ConstVertexOHalfedgeCCWIter at end"; EXPECT_FALSE(cvoh_ccwit.is_valid()) << "Iterator invalid in ConstVertexOHalfedgeCCWIter at end";
@@ -486,7 +486,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) {
i = 0; i = 0;
for (;voh_cwit != voh_cwend; ++voh_cwit, ++i) for (;voh_cwit != voh_cwend; ++voh_cwit, ++i)
{ {
EXPECT_EQ(rev_indices[i], voh_cwit->idx()) << "Index wrong in VertexOHalfedgeCWIter"; EXPECT_EQ(cw_indices[i], voh_cwit->idx()) << "Index wrong in VertexOHalfedgeCWIter";
} }
EXPECT_FALSE(voh_cwit.is_valid()) << "Iterator invalid in VertexOHalfedgeCWIter at end"; EXPECT_FALSE(voh_cwit.is_valid()) << "Iterator invalid in VertexOHalfedgeCWIter at end";
EXPECT_TRUE( voh_cwit == voh_cwend ) << "End iterator for VertexOHalfedgeCWIter not matching"; EXPECT_TRUE( voh_cwit == voh_cwend ) << "End iterator for VertexOHalfedgeCWIter not matching";
@@ -497,7 +497,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) {
i = 0; i = 0;
for (;cvoh_cwit != cvoh_cwend; ++cvoh_cwit, ++i) for (;cvoh_cwit != cvoh_cwend; ++cvoh_cwit, ++i)
{ {
EXPECT_EQ(rev_indices[i], cvoh_cwit->idx()) << "Index wrong in ConstVertexOHalfedgeCWIter"; EXPECT_EQ(cw_indices[i], cvoh_cwit->idx()) << "Index wrong in ConstVertexOHalfedgeCWIter";
} }
EXPECT_FALSE(cvoh_cwit.is_valid()) << "Iterator invalid in ConstVertexOHalfedgeCWIter at end"; EXPECT_FALSE(cvoh_cwit.is_valid()) << "Iterator invalid in ConstVertexOHalfedgeCWIter at end";
EXPECT_TRUE( cvoh_cwit == cvoh_cwend ) << "End iterator for ConstVertexOHalfedgeCWIter not matching"; EXPECT_TRUE( cvoh_cwit == cvoh_cwend ) << "End iterator for ConstVertexOHalfedgeCWIter not matching";
@@ -511,27 +511,23 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) {
*/ */
Mesh::VertexOHalfedgeCWIter voh_cwIter = mesh_.voh_cwbegin(vh); Mesh::VertexOHalfedgeCWIter voh_cwIter = mesh_.voh_cwbegin(vh);
// a) // a)
EXPECT_TRUE( voh_cwIter == Mesh::VertexOHalfedgeCWIter(mesh_.voh_ccwbegin(vh)) ) << "ccw to cw conversion failed"; EXPECT_TRUE( *voh_cwIter == *++Mesh::VertexOHalfedgeCWIter(mesh_.voh_ccwend(vh))) << "ccw to cw conversion failed";
EXPECT_TRUE( Mesh::VertexOHalfedgeCCWIter(voh_cwIter) == mesh_.voh_ccwbegin(vh) ) << "cw to ccw conversion failed"; EXPECT_TRUE( *++Mesh::VertexOHalfedgeCCWIter(voh_cwIter) == *mesh_.voh_ccwend(vh) ) << "cw to ccw conversion failed";
// b) // b)
EXPECT_EQ( voh_cwIter->idx(), Mesh::VertexOHalfedgeCCWIter(voh_cwIter)->idx()) << "iterators doesnt point on the same element"; EXPECT_EQ( voh_cwIter->idx(), Mesh::VertexOHalfedgeCCWIter(voh_cwIter)->idx()) << "iterators doesnt point on the same element";
// c) // c)
auto voh_ccwIter = Mesh::VertexOHalfedgeCCWIter(voh_cwIter);
EXPECT_EQ(voh_cwIter->idx(),voh_ccwIter->idx())<< "iterators dont point on the same element";
++voh_cwIter; ++voh_cwIter;
voh_ccwend = mesh_.voh_ccwend(vh); --voh_ccwIter;
--voh_ccwend; EXPECT_EQ(voh_cwIter->idx(),voh_ccwIter->idx()) << "iteratoes are not equal after inc/dec";
EXPECT_EQ(voh_cwIter->idx(),voh_ccwend->idx()) << "iteratoes are not equal after inc/dec";
// additional conversion check
voh_ccwend = Mesh::VertexOHalfedgeCCWIter(voh_cwIter);
EXPECT_EQ(voh_cwIter->idx(),voh_ccwend->idx())<< "iterators doesnt point on the same element";
// d) // d)
voh_cwIter = Mesh::VertexOHalfedgeCWIter(mesh_.voh_ccwend(vh)); auto voh_cwEnd = mesh_.voh_ccwend(vh);
voh_cwIter = Mesh::VertexOHalfedgeCWIter(voh_cwEnd);
EXPECT_FALSE(voh_cwIter.is_valid()) << "end iterator is not invalid"; EXPECT_FALSE(voh_cwIter.is_valid()) << "end iterator is not invalid";
EXPECT_TRUE(Mesh::VertexOHalfedgeCCWIter(mesh_.voh_cwend(vh)) == mesh_.voh_ccwend(vh)) << "end iterators are not equal"; EXPECT_TRUE(*mesh_.voh_cwbegin(vh) == *++voh_cwIter) << "end iterators are not equal";
} }
} }

View File

@@ -339,9 +339,9 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) {
3 ==== 4 */ 3 ==== 4 */
int indices[5] = {4, 2, 0, 3, 4}; int cw_indices[4] = {4, 3, 0, 2};
int rev_indices[5]; int ccw_indices[4];
std::reverse_copy(indices,indices+5,rev_indices); std::reverse_copy(cw_indices,cw_indices+4,ccw_indices);
Mesh::VertexHandle vh = vhandle[1]; Mesh::VertexHandle vh = vhandle[1];
@@ -351,7 +351,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) {
size_t i = 0; size_t i = 0;
for (;vv_ccwit != vv_ccwend; ++vv_ccwit, ++i) for (;vv_ccwit != vv_ccwend; ++vv_ccwit, ++i)
{ {
EXPECT_EQ(indices[i], vv_ccwit->idx()) << "Index wrong in VertexVertexCCWIter"; EXPECT_EQ(ccw_indices[i], vv_ccwit->idx()) << "Index wrong in VertexVertexCCWIter";
} }
EXPECT_FALSE(vv_ccwit.is_valid()) << "Iterator invalid in VertexVertexCCWIter at end"; EXPECT_FALSE(vv_ccwit.is_valid()) << "Iterator invalid in VertexVertexCCWIter at end";
@@ -363,7 +363,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) {
i = 0; i = 0;
for (;cvv_ccwit != cvv_ccwend; ++cvv_ccwit, ++i) for (;cvv_ccwit != cvv_ccwend; ++cvv_ccwit, ++i)
{ {
EXPECT_EQ(indices[i], cvv_ccwit->idx()) << "Index wrong in ConstVertexVertexCCWIter"; EXPECT_EQ(ccw_indices[i], cvv_ccwit->idx()) << "Index wrong in ConstVertexVertexCCWIter";
} }
EXPECT_FALSE(cvv_ccwit.is_valid()) << "Iterator invalid in ConstVertexVertexCCWIter at end"; EXPECT_FALSE(cvv_ccwit.is_valid()) << "Iterator invalid in ConstVertexVertexCCWIter at end";
@@ -375,7 +375,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) {
i = 0; i = 0;
for (;vv_cwit != vv_cwend; ++vv_cwit, ++i) for (;vv_cwit != vv_cwend; ++vv_cwit, ++i)
{ {
EXPECT_EQ(rev_indices[i], vv_cwit->idx()) << "Index wrong in VertexVertexCWIter"; EXPECT_EQ(cw_indices[i], vv_cwit->idx()) << "Index wrong in VertexVertexCWIter";
} }
EXPECT_FALSE(vv_cwit.is_valid()) << "Iterator invalid in VertexVertexCWIter at end"; EXPECT_FALSE(vv_cwit.is_valid()) << "Iterator invalid in VertexVertexCWIter at end";
EXPECT_TRUE( vv_cwit == vv_cwend ) << "End iterator for VertexVertexCWIter not matching"; EXPECT_TRUE( vv_cwit == vv_cwend ) << "End iterator for VertexVertexCWIter not matching";
@@ -386,7 +386,7 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) {
i = 0; i = 0;
for (;cvv_cwit != cvv_cwend; ++cvv_cwit, ++i) for (;cvv_cwit != cvv_cwend; ++cvv_cwit, ++i)
{ {
EXPECT_EQ(rev_indices[i], cvv_cwit->idx()) << "Index wrong in ConstVertexVertexCWIter"; EXPECT_EQ(cw_indices[i], cvv_cwit->idx()) << "Index wrong in ConstVertexVertexCWIter";
} }
EXPECT_FALSE(cvv_cwit.is_valid()) << "Iterator invalid in ConstVertexVertexCWIter at end"; EXPECT_FALSE(cvv_cwit.is_valid()) << "Iterator invalid in ConstVertexVertexCWIter at end";
EXPECT_TRUE( cvv_cwit == cvv_cwend ) << "End iterator for ConstVertexVertexCWIter not matching"; EXPECT_TRUE( cvv_cwit == cvv_cwend ) << "End iterator for ConstVertexVertexCWIter not matching";
@@ -400,22 +400,21 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) {
*/ */
Mesh::VertexVertexCWIter vv_cwIter = mesh_.vv_cwbegin(vh); Mesh::VertexVertexCWIter vv_cwIter = mesh_.vv_cwbegin(vh);
// a) // a)
EXPECT_TRUE( vv_cwIter == Mesh::VertexVertexCWIter(mesh_.vv_ccwbegin(vh)) ) << "ccw to cw convvrsion failed"; EXPECT_TRUE( *vv_cwIter == *++Mesh::VertexVertexCWIter(mesh_.vv_ccwend(vh))) << "ccw to cw conversion failed";
EXPECT_TRUE( Mesh::VertexVertexCCWIter(vv_cwIter) == mesh_.vv_ccwbegin(vh) ) << "cw to ccw convvrsion failed"; EXPECT_TRUE( *++Mesh::VertexVertexCCWIter(vv_cwIter) == *mesh_.vv_ccwend(vh) ) << "cw to ccw conversion failed";
// b) // b)
EXPECT_EQ( vv_cwIter->idx(), Mesh::VertexVertexCCWIter(vv_cwIter)->idx()) << "iterators doesnt point on the same element"; EXPECT_EQ( vv_cwIter->idx(), Mesh::VertexVertexCCWIter(vv_cwIter)->idx()) << "iterators doesnt point on the same element";
// c) // c)
auto vv_ccwIter = Mesh::VertexVertexCCWIter(vv_cwIter);
EXPECT_EQ(vv_cwIter->idx(),vv_ccwIter->idx())<< "iterators dont point on the same element";
++vv_cwIter; ++vv_cwIter;
vv_ccwend = mesh_.vv_ccwend(vh); --vv_ccwIter;
--vv_ccwend; EXPECT_EQ(vv_cwIter->idx(),vv_ccwIter->idx()) << "iteratoes are not equal after inc/dec";
EXPECT_EQ(vv_cwIter->idx(),vv_ccwend->idx()) << "iteratoes are not equal after inc/dec";
// additional conversion check
vv_ccwend = Mesh::VertexVertexCCWIter(vv_cwIter);
EXPECT_EQ(vv_cwIter->idx(),vv_ccwend->idx())<< "iterators doesnt point on the same element";
// d) // d)
vv_cwIter = Mesh::VertexVertexCWIter(mesh_.vv_ccwend(vh)); auto vv_cwEnd = mesh_.vv_ccwend(vh);
vv_cwIter = Mesh::VertexVertexCWIter(vv_cwEnd);
EXPECT_FALSE(vv_cwIter.is_valid()) << "end iterator is not invalid"; EXPECT_FALSE(vv_cwIter.is_valid()) << "end iterator is not invalid";
EXPECT_TRUE(Mesh::VertexVertexCCWIter(mesh_.vv_cwend(vh)) == mesh_.vv_ccwend(vh)) << "end iterators are not equal"; EXPECT_TRUE(*mesh_.vv_cwbegin(vh) == *++vv_cwIter) << "end iterators are not equal";
} }

View File

@@ -0,0 +1,384 @@
#include <gtest/gtest.h>
#include <Unittests/unittests_common.hh>
#include <OpenMesh/Core/Utils/Predicates.hh>
#include <iostream>
namespace {
class OpenMeshTrimeshRange : public OpenMeshBase {
protected:
// This function is called before each test is run
virtual void SetUp()
{
mesh_.clear();
// Add some vertices
Mesh::VertexHandle vhandle[5];
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0));
vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0));
// Add two faces
std::vector<Mesh::VertexHandle> face_vhandles;
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[2]);
mesh_.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[4]);
mesh_.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[1]);
mesh_.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[4]);
mesh_.add_face(face_vhandles);
/* Test setup:
0 ==== 2
|\ 0 /|
| \ / |
|2 1 3|
| / \ |
|/ 1 \|
3 ==== 4 */
}
// This function is called after all tests are through
virtual void TearDown() {
// Do some final stuff with the member data here...
}
// Member already defined in OpenMeshBase
//Mesh mesh_;
};
/*
* ====================================================================
* Define tests below
* ====================================================================
*/
template <typename RangeT1, typename RangeT2>
void compare_ranges(RangeT1&& range1, RangeT2&& range2, int offset, bool reverse)
{
auto vec1 = range1.to_vector();
auto vec2 = range2.to_vector();
ASSERT_EQ(vec1.size(), vec2.size()) << "Ranges have different number of elements";
ASSERT_GT(vec1.size(), 0) << "Ranges are empty";
size_t n = vec1.size();
std::cout << "Vec1 elements: ";
for (auto el : vec1)
std::cout << el.idx() << " ";
std::cout << std::endl;
std::cout << "Vec2 elements: ";
for (auto el : vec2)
std::cout << el.idx() << " ";
std::cout << std::endl;
for (size_t i = 0; i < n; ++i)
{
size_t id1 = (i+offset)%n;
size_t id2 = reverse ? (n-i-1)%n : i;
EXPECT_EQ(vec1[id1].idx(), vec2[id2].idx()) << "Elements are not the same with offset = " << offset << " and reverse = " << std::to_string(reverse);
}
}
TEST_F(OpenMeshTrimeshRange, VertexVertexRangeMeshVsSmartHandle)
{
for (auto vh : mesh_.vertices())
{
compare_ranges(mesh_.vv_range(vh) , vh.vertices() , 0, false);
compare_ranges(mesh_.vv_cw_range(vh) , vh.vertices_cw() , 0, false);
compare_ranges(mesh_.vv_ccw_range(vh), vh.vertices_ccw(), 0, false);
}
}
TEST_F(OpenMeshTrimeshRange, VertexVertexRangeCWVsCCW)
{
for (auto vh : mesh_.vertices())
compare_ranges(vh.vertices_cw(), vh.vertices_ccw(), 0, true);
}
TEST_F(OpenMeshTrimeshRange, VertexEdgeRangeMeshVsSmartHandle)
{
for (auto vh : mesh_.vertices())
{
compare_ranges(mesh_.ve_range(vh) , vh.edges() , 0, false);
compare_ranges(mesh_.ve_cw_range(vh) , vh.edges_cw() , 0, false);
compare_ranges(mesh_.ve_ccw_range(vh), vh.edges_ccw(), 0, false);
}
}
TEST_F(OpenMeshTrimeshRange, VertexEdgeRangeCWVsCCW)
{
for (auto vh : mesh_.vertices())
compare_ranges(vh.edges_cw(), vh.edges_ccw(), 0, true);
}
TEST_F(OpenMeshTrimeshRange, VertexFaceRangeMeshVsSmartHandle)
{
for (auto vh : mesh_.vertices())
{
compare_ranges(mesh_.vf_range(vh) , vh.faces() , 0, false);
compare_ranges(mesh_.vf_cw_range(vh) , vh.faces_cw() , 0, false);
compare_ranges(mesh_.vf_ccw_range(vh), vh.faces_ccw(), 0, false);
}
}
TEST_F(OpenMeshTrimeshRange, VertexFaceRangeCWVsCCW)
{
for (auto vh : mesh_.vertices())
compare_ranges(vh.faces_cw(), vh.faces_ccw(), 0, true);
}
TEST_F(OpenMeshTrimeshRange, VertexIncomingHalfedgesRangeMeshVsSmartHandle)
{
for (auto vh : mesh_.vertices())
{
compare_ranges(mesh_.vih_range(vh) , vh.incoming_halfedges() , 0, false);
compare_ranges(mesh_.vih_cw_range(vh) , vh.incoming_halfedges_cw() , 0, false);
compare_ranges(mesh_.vih_ccw_range(vh), vh.incoming_halfedges_ccw(), 0, false);
}
}
TEST_F(OpenMeshTrimeshRange, VertexIncomingHalfedgesRangeCWVsCCW)
{
for (auto vh : mesh_.vertices())
compare_ranges(vh.incoming_halfedges_cw(), vh.incoming_halfedges_ccw(), 0, true);
}
TEST_F(OpenMeshTrimeshRange, VertexIncomingHalfedgesRangeCustomStart)
{
const int offset = 2;
for (auto vh : mesh_.vertices())
{
// mesh vs smart handle access
auto it_cw = mesh_.vih_begin(vh);
auto it_ccw = mesh_.vih_ccwbegin(vh);
for (int i = 0; i < offset; ++i)
{
++it_cw;
++it_ccw;
}
OpenMesh::HalfedgeHandle start_heh_cw = *it_cw;
OpenMesh::HalfedgeHandle start_heh_ccw = *it_ccw;
compare_ranges(mesh_.vih_range(vh) , mesh_.vih_range(start_heh_cw) , offset, false);
compare_ranges(mesh_.vih_cw_range(vh) , mesh_.vih_cw_range(start_heh_cw) , offset, false);
compare_ranges(mesh_.vih_ccw_range(vh) , mesh_.vih_ccw_range(start_heh_ccw) , offset, false);
compare_ranges(vh.incoming_halfedges() , vh.incoming_halfedges(start_heh_cw) , offset, false);
compare_ranges(vh.incoming_halfedges_cw() , vh.incoming_halfedges_cw(start_heh_cw) , offset, false);
compare_ranges(vh.incoming_halfedges_ccw(), vh.incoming_halfedges_ccw(start_heh_ccw), offset, false);
// check that ranges with custom start actually start at that start
auto hes = vh.incoming_halfedges();
for (auto heh : hes)
{
EXPECT_EQ(heh, *vh.incoming_halfedges (heh).begin()) << "Range does not start at desired start";
EXPECT_EQ(heh, *vh.incoming_halfedges_cw (heh).begin()) << "Range does not start at desired start";
EXPECT_EQ(heh, *vh.incoming_halfedges_ccw(heh).begin()) << "Range does not start at desired start";
}
}
}
TEST_F(OpenMeshTrimeshRange, VertexIncomingHalfedgesRangeBoundaryConsistency)
{
// for boundary vertices cw iterations should start at boundary halfedge
for (auto vh : mesh_.vertices().filtered(OpenMesh::Predicates::Boundary()))
{
EXPECT_TRUE(mesh_.vih_begin(vh)->opp().is_boundary());
EXPECT_TRUE(mesh_.vih_range(vh).begin()->opp().is_boundary());
EXPECT_TRUE(mesh_.vih_cwbegin(vh)->opp().is_boundary());
EXPECT_TRUE(mesh_.vih_cw_range(vh).begin()->opp().is_boundary());
EXPECT_TRUE(mesh_.vih_ccwbegin(vh)->is_boundary());
EXPECT_TRUE(mesh_.vih_ccw_range(vh).begin()->is_boundary());
}
}
TEST_F(OpenMeshTrimeshRange, VertexOutgoingHalfedgesRangeMeshVsSmartHandle)
{
for (auto vh : mesh_.vertices())
{
compare_ranges(mesh_.voh_range(vh) , vh.outgoing_halfedges() , 0, false);
compare_ranges(mesh_.voh_cw_range(vh) , vh.outgoing_halfedges_cw() , 0, false);
compare_ranges(mesh_.voh_ccw_range(vh), vh.outgoing_halfedges_ccw(), 0, false);
}
}
TEST_F(OpenMeshTrimeshRange, VertexOutgoingHalfedgesRangeCWVsCCW)
{
for (auto vh : mesh_.vertices())
compare_ranges(vh.outgoing_halfedges_cw(), vh.outgoing_halfedges_ccw(), 0, true);
}
TEST_F(OpenMeshTrimeshRange, VertexOutgoingHalfedgesRangeCustomStart)
{
const int offset = 2;
for (auto vh : mesh_.vertices())
{
// mesh vs smart handle access
auto it_cw = mesh_.voh_begin(vh);
auto it_ccw = mesh_.voh_ccwbegin(vh);
for (int i = 0; i < offset; ++i)
{
++it_cw;
++it_ccw;
}
OpenMesh::HalfedgeHandle start_heh_cw = *it_cw;
OpenMesh::HalfedgeHandle start_heh_ccw = *it_ccw;
compare_ranges(mesh_.voh_range(vh) , mesh_.voh_range(start_heh_cw) , offset, false);
compare_ranges(mesh_.voh_cw_range(vh) , mesh_.voh_cw_range(start_heh_cw) , offset, false);
compare_ranges(mesh_.voh_ccw_range(vh) , mesh_.voh_ccw_range(start_heh_ccw) , offset, false);
compare_ranges(vh.outgoing_halfedges() , vh.outgoing_halfedges(start_heh_cw) , offset, false);
compare_ranges(vh.outgoing_halfedges_cw() , vh.outgoing_halfedges_cw(start_heh_cw) , offset, false);
compare_ranges(vh.outgoing_halfedges_ccw(), vh.outgoing_halfedges_ccw(start_heh_ccw), offset, false);
// check that ranges with custom start actually start at that start
auto hes = vh.outgoing_halfedges();
for (auto heh : hes)
{
EXPECT_EQ(heh, *vh.outgoing_halfedges (heh).begin()) << "Range does not start at desired start";
EXPECT_EQ(heh, *vh.outgoing_halfedges_cw (heh).begin()) << "Range does not start at desired start";
EXPECT_EQ(heh, *vh.outgoing_halfedges_ccw(heh).begin()) << "Range does not start at desired start";
}
}
}
TEST_F(OpenMeshTrimeshRange, VertexOutgoingHalfedgesRangeBoundaryConsistency)
{
// for boundary vertices cw iterations should start at boundary halfedge
for (auto vh : mesh_.vertices().filtered(OpenMesh::Predicates::Boundary()))
{
EXPECT_TRUE(mesh_.voh_begin(vh)->is_boundary());
EXPECT_TRUE(mesh_.voh_range(vh).begin()->is_boundary());
EXPECT_TRUE(mesh_.voh_cwbegin(vh)->is_boundary());
EXPECT_TRUE(mesh_.voh_cw_range(vh).begin()->is_boundary());
EXPECT_TRUE(mesh_.voh_ccwbegin(vh)->opp().is_boundary());
EXPECT_TRUE(mesh_.voh_ccw_range(vh).begin()->opp().is_boundary());
}
}
TEST_F(OpenMeshTrimeshRange, HalfedgeLoopRangeMeshVsSmartHandle)
{
for (auto heh : mesh_.halfedges())
{
compare_ranges(mesh_.hl_range(heh) , heh.loop() , 0, false);
compare_ranges(mesh_.hl_cw_range(heh) , heh.loop_cw() , 0, false);
compare_ranges(mesh_.hl_ccw_range(heh), heh.loop_ccw(), 0, false);
}
}
TEST_F(OpenMeshTrimeshRange, HalfedgeLoopRangeCWVsCCW)
{
// Halfedge Loops are initialized from a halfedge and always start on that halfedge
// Thus, cw and ccw ranges start on the same element. We account for that by
// setting the offset to 1 for the comparison check.
// TODO: do we want to change that behavior?
for (auto heh : mesh_.halfedges())
compare_ranges(heh.loop_cw(), heh.loop_ccw(), 1, true);
}
TEST_F(OpenMeshTrimeshRange, FaceVertexRangeMeshVsSmartHandle)
{
for (auto fh : mesh_.faces())
{
compare_ranges(mesh_.fv_range(fh) , fh.vertices() , 0, false);
compare_ranges(mesh_.fv_cw_range(fh) , fh.vertices_cw() , 0, false);
compare_ranges(mesh_.fv_ccw_range(fh), fh.vertices_ccw(), 0, false);
}
}
TEST_F(OpenMeshTrimeshRange, FaceVertexRangeCWVsCCW)
{
for (auto fh : mesh_.faces())
compare_ranges(fh.vertices_cw(), fh.vertices_ccw(), 0, true);
}
TEST_F(OpenMeshTrimeshRange, FaceEdgeRangeMeshVsSmartHandle)
{
for (auto fh : mesh_.faces())
{
compare_ranges(mesh_.fe_range(fh) , fh.edges() , 0, false);
compare_ranges(mesh_.fe_cw_range(fh) , fh.edges_cw() , 0, false);
compare_ranges(mesh_.fe_ccw_range(fh), fh.edges_ccw(), 0, false);
}
}
TEST_F(OpenMeshTrimeshRange, FaceEdgeRangeCWVsCCW)
{
for (auto fh : mesh_.faces())
compare_ranges(fh.edges_cw(), fh.edges_ccw(), 0, true);
}
TEST_F(OpenMeshTrimeshRange, FaceHalfedgeRangeMeshVsSmartHandle)
{
for (auto fh : mesh_.faces())
{
compare_ranges(mesh_.fh_range(fh) , fh.halfedges() , 0, false);
compare_ranges(mesh_.fh_cw_range(fh) , fh.halfedges_cw() , 0, false);
compare_ranges(mesh_.fh_ccw_range(fh), fh.halfedges_ccw(), 0, false);
}
}
TEST_F(OpenMeshTrimeshRange, FaceHalfedgeRangeCWVsCCW)
{
for (auto fh : mesh_.faces())
compare_ranges(fh.halfedges_cw(), fh.halfedges_ccw(), 0, true);
}
TEST_F(OpenMeshTrimeshRange, FaceFaceRangeMeshVsSmartHandle)
{
for (auto fh : mesh_.faces())
{
compare_ranges(mesh_.ff_range(fh) , fh.faces() , 0, false);
compare_ranges(mesh_.ff_cw_range(fh) , fh.faces_cw() , 0, false);
compare_ranges(mesh_.ff_ccw_range(fh), fh.faces_ccw(), 0, false);
}
}
TEST_F(OpenMeshTrimeshRange, FaceFaceRangeCWVsCCW)
{
for (auto fh : mesh_.faces())
compare_ranges(fh.faces_cw(), fh.faces_ccw(), 0, true);
}
}