diff --git a/Doc/mesh.docu b/Doc/mesh.docu index 1dba8eac..0b7fca37 100644 --- a/Doc/mesh.docu +++ b/Doc/mesh.docu @@ -845,6 +845,10 @@ All circulators provide the operations listed in CirculatorT, which are basically the same as the iterator funtions. +\note Circulators are similar to bidirectional iterators and therefore they have the bidirectional_iterator_tag. +However, the bidirectional requires that the attribute OpenMesh::Attributes::PrevHalfedge is available. +Otherwise it is just a forward iterator. + \deprecated While it is possible to use \c operator \c bool(), which returns true, as long as the circulator hasn't reached the end of the sequence, this function is @@ -855,6 +859,35 @@ to get circulators around a specified center item: \include circulator_functions.cc +Additionally to the normal circulators there exists some for each +direction (clock-wise, counterclock-wise). Those circulators might be slower +than the normal one, but the direction of circulation is guaranteed. +You can get these types of circulators by adding the infix "ccw" or "cw" to +the function used to request the circulator of an item after the underscore. +Example: + +\code +VertexVertexIter vvit = mesh.vv_iter(some_vertex_handle); // fastest (clock or counterclockwise) +VertexVertexCWIter vvcwit = mesh.vv_cwiter(some_vertex_handle); // clockwise +VertexVertexCCWIter vvccwit = mesh.vv_ccwiter(some_vertex_handle); // counter-clockwise +\endcode + +It is also possible to convert a cw circulator to a ccw circulator and vice versa. +For this purpose, each circulator provides a constructor taking the other circulator as input. +If a cw circulator is converted, the ccw circulator points on the same element as +the cw circulator pointed on, but the direction for the increment and decrement changed.\n +The conversion is only valid for valid circulators. The resulting circulator from a invalid circulator is still invalid, +but might behave in a fashion not expected by normal iterators. Example: +\code + VertexVertexCWIter vvcwit = mesh.vv_cwend(some_vertex_handle); + VertexVertexCCWIter vvccwit = VertexVertexCCWIter(vvcwit); //conversion of an invalid circulator + --vvcwit; //is valid now (if the range >= 1) + ++vvccwit; //can still be invalid +\endcode + +CW and CCW circulators requires that OpenMesh::Attributes::PrevHalfedge is available. + + \note For every circulator there also exists a constant version. To make use of these constant circulators just add the prefix
"Const" to the type specifier and add the prefix "c" to the function used to request diff --git a/src/OpenMesh/Core/Mesh/CirculatorsT.hh b/src/OpenMesh/Core/Mesh/CirculatorsT.hh index 18fb03e0..e897f149 100644 --- a/src/OpenMesh/Core/Mesh/CirculatorsT.hh +++ b/src/OpenMesh/Core/Mesh/CirculatorsT.hh @@ -61,7 +61,7 @@ namespace OpenMesh { namespace Iterators { -template +template class GenericCirculator_CenterEntityFnsT { public: static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter); @@ -69,31 +69,61 @@ class GenericCirculator_CenterEntityFnsT { }; template -class GenericCirculator_CenterEntityFnsT { +class GenericCirculator_CenterEntityFnsT { public: inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { heh = mesh->cw_rotated_halfedge_handle(heh); - if (heh == start) lap_counter++; + if (heh == start) ++lap_counter; } inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { - if (heh == start) lap_counter--; + if (heh == start) --lap_counter; heh = mesh->ccw_rotated_halfedge_handle(heh); } }; template -class GenericCirculator_CenterEntityFnsT { +class GenericCirculator_CenterEntityFnsT { public: inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { heh = mesh->next_halfedge_handle(heh); - if (heh == start) lap_counter++; + if (heh == start) ++lap_counter; } inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { - if (heh == start) lap_counter--; + if (heh == start) --lap_counter; heh = mesh->prev_halfedge_handle(heh); } }; +///////////////////////////////////////////////////////////// +// CCW + +template +class GenericCirculator_CenterEntityFnsT { + public: + inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { + heh = mesh->ccw_rotated_halfedge_handle(heh); + if (heh == start) ++lap_counter; + } + inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { + if (heh == start) --lap_counter; + heh = mesh->cw_rotated_halfedge_handle(heh); + } +}; + +template +class GenericCirculator_CenterEntityFnsT { + public: + inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { + heh = mesh->prev_halfedge_handle(heh); + if (heh == start) ++lap_counter; + } + inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { + if (heh == start) --lap_counter; + heh = mesh->next_halfedge_handle(heh); + } +}; +///////////////////////////////////////////////////////////// + template class GenericCirculator_DereferenciabilityCheckT { public: @@ -116,7 +146,7 @@ class GenericCirculator_DereferenciabilityCheckT +template class GenericCirculator_ValueHandleFnsT { public: inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) { @@ -124,15 +154,15 @@ class GenericCirculator_ValueHandleFnsT { } inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {}; inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { - GenericCirculator_CenterEntityFnsT::increment(mesh, heh, start, lap_counter); + GenericCirculator_CenterEntityFnsT::increment(mesh, heh, start, lap_counter); } inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { - GenericCirculator_CenterEntityFnsT::decrement(mesh, heh, start, lap_counter); + GenericCirculator_CenterEntityFnsT::decrement(mesh, heh, start, lap_counter); } }; -template -class GenericCirculator_ValueHandleFnsT { +template +class GenericCirculator_ValueHandleFnsT { public: typedef GenericCirculator_DereferenciabilityCheckT GenericCirculator_DereferenciabilityCheck; @@ -145,12 +175,12 @@ class GenericCirculator_ValueHandleFnsT::increment(mesh, heh, start, lap_counter); + GenericCirculator_CenterEntityFnsT::increment(mesh, heh, start, lap_counter); } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh)); } inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) { do { - GenericCirculator_CenterEntityFnsT::decrement(mesh, heh, start, lap_counter); + GenericCirculator_CenterEntityFnsT::decrement(mesh, heh, start, lap_counter); } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh)); } }; @@ -217,7 +247,7 @@ class GenericCirculatorBaseT { }; template::*Handle2Value)() const> + ValueHandle (GenericCirculatorBaseT::*Handle2Value)() const, bool CW = true > class GenericCirculatorT : protected GenericCirculatorBaseT { public: typedef std::ptrdiff_t difference_type; @@ -228,7 +258,7 @@ class GenericCirculatorT : protected GenericCirculatorBaseT { typedef typename GenericCirculatorBaseT::mesh_ptr mesh_ptr; typedef typename GenericCirculatorBaseT::mesh_ref mesh_ref; - typedef GenericCirculator_ValueHandleFnsT GenericCirculator_ValueHandleFns; + typedef GenericCirculator_ValueHandleFnsT GenericCirculator_ValueHandleFns; public: GenericCirculatorT() {} @@ -244,6 +274,10 @@ class GenericCirculatorT : protected GenericCirculatorBaseT { } GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT(rhs) {} + friend class GenericCirculatorT; + explicit GenericCirculatorT( const GenericCirculatorT& rhs ) + :GenericCirculatorBaseT(rhs){} + GenericCirculatorT& operator++() { assert(this->mesh_); GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_); diff --git a/src/OpenMesh/Core/Mesh/PolyConnectivity.hh b/src/OpenMesh/Core/Mesh/PolyConnectivity.hh index 10f91114..802998a4 100644 --- a/src/OpenMesh/Core/Mesh/PolyConnectivity.hh +++ b/src/OpenMesh/Core/Mesh/PolyConnectivity.hh @@ -105,6 +105,14 @@ public: typedef Iterators::GenericCirculatorT::toVertexHandle> VertexVertexIter; + typedef VertexVertexIter VertexVertexCWIter; + + /** + * Enumerates 1-ring vertices in a counter clockwise fashion. + */ + typedef Iterators::GenericCirculatorT::toVertexHandle, false> + VertexVertexCCWIter; /** * Enumerates outgoing half edges in a clockwise fashion. @@ -112,6 +120,14 @@ public: typedef Iterators::GenericCirculatorT::toHalfedgeHandle> VertexOHalfedgeIter; + typedef VertexOHalfedgeIter VertexOHalfedgeCWIter; + + /** + * Enumerates outgoing half edges in a counter clockwise fashion. + */ + typedef Iterators::GenericCirculatorT::toHalfedgeHandle, false> + VertexOHalfedgeCCWIter; /** * Enumerates incoming half edges in a clockwise fashion. @@ -119,6 +135,14 @@ public: typedef Iterators::GenericCirculatorT::toOppositeHalfedgeHandle> VertexIHalfedgeIter; + typedef VertexIHalfedgeIter VertexIHalfedgeCWIter; + + /** + * Enumerates incoming half edges in a counter clockwise fashion. + */ + typedef Iterators::GenericCirculatorT::toOppositeHalfedgeHandle, false> + VertexIHalfedgeCCWIter; /** * Enumerates incident faces in a clockwise fashion. @@ -126,6 +150,14 @@ public: typedef Iterators::GenericCirculatorT::toFaceHandle> VertexFaceIter; + typedef VertexFaceIter VertexFaceCWIter; + + /** + * Enumerates incident faces in a counter clockwise fashion. + */ + typedef Iterators::GenericCirculatorT::toFaceHandle, false> + VertexFaceCCWIter; /** * Enumerates incident edges in a clockwise fashion. @@ -133,6 +165,13 @@ public: typedef Iterators::GenericCirculatorT::toEdgeHandle> VertexEdgeIter; + typedef VertexEdgeIter VertexEdgeCWIter; + /** + * Enumerates incident edges in a counter clockwise fashion. + */ + typedef Iterators::GenericCirculatorT::toEdgeHandle, false> + VertexEdgeCCWIter; /** * Identical to #FaceHalfedgeIter. God knows why this typedef exists. @@ -140,12 +179,29 @@ public: typedef Iterators::GenericCirculatorT::toHalfedgeHandle> HalfedgeLoopIter; + typedef HalfedgeLoopIter HalfedgeLoopCWIter; + /** + * Identical to #FaceHalfedgeIter. God knows why this typedef exists. + */ + typedef Iterators::GenericCirculatorT::toHalfedgeHandle, false> + HalfedgeLoopCCWIter; - typedef VertexVertexIter ConstVertexVertexIter; - typedef VertexOHalfedgeIter ConstVertexOHalfedgeIter; - typedef VertexIHalfedgeIter ConstVertexIHalfedgeIter; - typedef VertexFaceIter ConstVertexFaceIter; - typedef VertexEdgeIter ConstVertexEdgeIter; + typedef VertexVertexIter ConstVertexVertexIter; + typedef VertexVertexCWIter ConstVertexVertexCWIter; + typedef VertexVertexCCWIter ConstVertexVertexCCWIter; + typedef VertexOHalfedgeIter ConstVertexOHalfedgeIter; + typedef VertexOHalfedgeCWIter ConstVertexOHalfedgeCWIter; + typedef VertexOHalfedgeCCWIter ConstVertexOHalfedgeCCWIter; + typedef VertexIHalfedgeIter ConstVertexIHalfedgeIter; + typedef VertexIHalfedgeCWIter ConstVertexIHalfedgeCWIter; + typedef VertexIHalfedgeCCWIter ConstVertexIHalfedgeCCWIter; + typedef VertexFaceIter ConstVertexFaceIter; + typedef VertexFaceCWIter ConstVertexFaceCWIter; + typedef VertexFaceCCWIter ConstVertexFaceCCWIter; + typedef VertexEdgeIter ConstVertexEdgeIter; + typedef VertexEdgeCWIter ConstVertexEdgeCWIter; + typedef VertexEdgeCCWIter ConstVertexEdgeCCWIter; /* * Face-centered circulators @@ -157,6 +213,14 @@ public: typedef Iterators::GenericCirculatorT::toVertexHandle> FaceVertexIter; + typedef FaceVertexIter FaceVertexCCWIter; + + /** + * Enumerate incident vertices in a clockwise fashion. + */ + typedef Iterators::GenericCirculatorT::toVertexHandle, false> + FaceVertexCWIter; /** * Enumerate incident half edges in a counter clockwise fashion. @@ -164,6 +228,14 @@ public: typedef Iterators::GenericCirculatorT::toHalfedgeHandle> FaceHalfedgeIter; + typedef FaceHalfedgeIter FaceHalfedgeCCWIter; + + /** + * Enumerate incident half edges in a clockwise fashion. + */ + typedef Iterators::GenericCirculatorT::toHalfedgeHandle, false> + FaceHalfedgeCWIter; /** * Enumerate incident edges in a counter clockwise fashion. @@ -171,6 +243,14 @@ public: typedef Iterators::GenericCirculatorT::toEdgeHandle> FaceEdgeIter; + typedef FaceEdgeIter FaceEdgeCCWIter; + + /** + * Enumerate incident edges in a clockwise fashion. + */ + typedef Iterators::GenericCirculatorT::toEdgeHandle, false> + FaceEdgeCWIter; /** * Enumerate adjacent faces in a counter clockwise fashion. @@ -178,16 +258,34 @@ public: typedef Iterators::GenericCirculatorT::toOppositeFaceHandle> FaceFaceIter; + typedef FaceFaceIter FaceFaceCCWIter; - typedef FaceVertexIter ConstFaceVertexIter; - typedef FaceHalfedgeIter ConstFaceHalfedgeIter; - typedef FaceEdgeIter ConstFaceEdgeIter; - typedef FaceFaceIter ConstFaceFaceIter; + /** + * Enumerate adjacent faces in a clockwise fashion. + */ + typedef Iterators::GenericCirculatorT::toOppositeFaceHandle, false> + FaceFaceCWIter; + + typedef FaceVertexIter ConstFaceVertexIter; + typedef FaceVertexCWIter ConstFaceVertexCWIter; + typedef FaceVertexCCWIter ConstFaceVertexCCWIter; + typedef FaceHalfedgeIter ConstFaceHalfedgeIter; + typedef FaceHalfedgeCWIter ConstFaceHalfedgeCWIter; + typedef FaceHalfedgeCCWIter ConstFaceHalfedgeCCWIter; + typedef FaceEdgeIter ConstFaceEdgeIter; + typedef FaceEdgeCWIter ConstFaceEdgeCWIter; + typedef FaceEdgeCCWIter ConstFaceEdgeCCWIter; + typedef FaceFaceIter ConstFaceFaceIter; + typedef FaceFaceCWIter ConstFaceFaceCWIter; + typedef FaceFaceCCWIter ConstFaceFaceCCWIter; /* * Halfedge circulator */ - typedef HalfedgeLoopIter ConstHalfedgeLoopIter; + typedef HalfedgeLoopIter ConstHalfedgeLoopIter; + typedef HalfedgeLoopCWIter ConstHalfedgeLoopCWIter; + typedef HalfedgeLoopCCWIter ConstHalfedgeLoopCCWIter; //@} @@ -213,25 +311,59 @@ public: typedef ConstEdgeIter CEIter; typedef ConstFaceIter CFIter; - typedef VertexVertexIter VVIter; - typedef VertexOHalfedgeIter VOHIter; - typedef VertexIHalfedgeIter VIHIter; - typedef VertexEdgeIter VEIter; - typedef VertexFaceIter VFIter; - typedef FaceVertexIter FVIter; - typedef FaceHalfedgeIter FHIter; - typedef FaceEdgeIter FEIter; - typedef FaceFaceIter FFIter; + typedef VertexVertexIter VVIter; + typedef VertexVertexCWIter VVCWIter; + typedef VertexVertexCCWIter VVCCWIter; + typedef VertexOHalfedgeIter VOHIter; + typedef VertexOHalfedgeCWIter VOHCWIter; + typedef VertexOHalfedgeCCWIter VOHCCWIter; + typedef VertexIHalfedgeIter VIHIter; + typedef VertexIHalfedgeCWIter VIHICWter; + typedef VertexIHalfedgeCCWIter VIHICCWter; + typedef VertexEdgeIter VEIter; + typedef VertexEdgeCWIter VECWIter; + typedef VertexEdgeCCWIter VECCWIter; + typedef VertexFaceIter VFIter; + typedef VertexFaceCWIter VFCWIter; + typedef VertexFaceCCWIter VFCCWIter; + typedef FaceVertexIter FVIter; + typedef FaceVertexCWIter FVCWIter; + typedef FaceVertexCCWIter FVCCWIter; + typedef FaceHalfedgeIter FHIter; + typedef FaceHalfedgeCWIter FHCWIter; + typedef FaceHalfedgeCCWIter FHCWWIter; + typedef FaceEdgeIter FEIter; + typedef FaceEdgeCWIter FECWIter; + typedef FaceEdgeCCWIter FECWWIter; + typedef FaceFaceIter FFIter; - typedef ConstVertexVertexIter CVVIter; - typedef ConstVertexOHalfedgeIter CVOHIter; - typedef ConstVertexIHalfedgeIter CVIHIter; - typedef ConstVertexEdgeIter CVEIter; - typedef ConstVertexFaceIter CVFIter; - typedef ConstFaceVertexIter CFVIter; - typedef ConstFaceHalfedgeIter CFHIter; - typedef ConstFaceEdgeIter CFEIter; - typedef ConstFaceFaceIter CFFIter; + typedef ConstVertexVertexIter CVVIter; + typedef ConstVertexVertexCWIter CVVCWIter; + typedef ConstVertexVertexCCWIter CVVCCWIter; + typedef ConstVertexOHalfedgeIter CVOHIter; + typedef ConstVertexOHalfedgeCWIter CVOHCWIter; + typedef ConstVertexOHalfedgeCCWIter CVOHCCWIter; + typedef ConstVertexIHalfedgeIter CVIHIter; + typedef ConstVertexIHalfedgeCWIter CVIHCWIter; + typedef ConstVertexIHalfedgeCCWIter CVIHCCWIter; + typedef ConstVertexEdgeIter CVEIter; + typedef ConstVertexEdgeCWIter CVECWIter; + typedef ConstVertexEdgeCCWIter CVECCWIter; + typedef ConstVertexFaceIter CVFIter; + typedef ConstVertexFaceCWIter CVFCWIter; + typedef ConstVertexFaceCCWIter CVFCCWIter; + typedef ConstFaceVertexIter CFVIter; + typedef ConstFaceVertexCWIter CFVCWIter; + typedef ConstFaceVertexCCWIter CFVCCWIter; + typedef ConstFaceHalfedgeIter CFHIter; + typedef ConstFaceHalfedgeCWIter CFHCWIter; + typedef ConstFaceHalfedgeCCWIter CFHCCWIter; + typedef ConstFaceEdgeIter CFEIter; + typedef ConstFaceEdgeCWIter CFECWIter; + typedef ConstFaceEdgeCCWIter CFECCWIter; + typedef ConstFaceFaceIter CFFIter; + typedef ConstFaceFaceCWIter CFFCWIter; + typedef ConstFaceFaceCCWIter CFFCCWIter; //@} public: @@ -426,192 +558,541 @@ public: /// vertex - vertex circulator VertexVertexIter vv_iter(VertexHandle _vh) { return VertexVertexIter(*this, _vh); } + /// vertex - vertex circulator cw + VertexVertexCWIter vv_cwiter(VertexHandle _vh) + { return VertexVertexCWIter(*this, _vh); } + /// vertex - vertex circulator ccw + VertexVertexCCWIter vv_ccwiter(VertexHandle _vh) + { return VertexVertexCCWIter(*this, _vh); } /// vertex - incoming halfedge circulator VertexIHalfedgeIter vih_iter(VertexHandle _vh) { return VertexIHalfedgeIter(*this, _vh); } + /// vertex - incoming halfedge circulator cw + VertexIHalfedgeCWIter vih_cwiter(VertexHandle _vh) + { return VertexIHalfedgeCWIter(*this, _vh); } + /// vertex - incoming halfedge circulator ccw + VertexIHalfedgeCCWIter vih_ccwiter(VertexHandle _vh) + { return VertexIHalfedgeCCWIter(*this, _vh); } /// vertex - outgoing halfedge circulator VertexOHalfedgeIter voh_iter(VertexHandle _vh) { return VertexOHalfedgeIter(*this, _vh); } + /// vertex - outgoing halfedge circulator cw + VertexOHalfedgeCWIter voh_cwiter(VertexHandle _vh) + { return VertexOHalfedgeCWIter(*this, _vh); } + /// vertex - outgoing halfedge circulator ccw + VertexOHalfedgeCCWIter voh_ccwiter(VertexHandle _vh) + { return VertexOHalfedgeCCWIter(*this, _vh); } /// vertex - edge circulator VertexEdgeIter ve_iter(VertexHandle _vh) { return VertexEdgeIter(*this, _vh); } + /// vertex - edge circulator cw + VertexEdgeCWIter ve_cwiter(VertexHandle _vh) + { return VertexEdgeCWIter(*this, _vh); } + /// vertex - edge circulator ccw + VertexEdgeCCWIter ve_ccwiter(VertexHandle _vh) + { return VertexEdgeCCWIter(*this, _vh); } /// vertex - face circulator VertexFaceIter vf_iter(VertexHandle _vh) { return VertexFaceIter(*this, _vh); } + /// vertex - face circulator cw + VertexFaceCWIter vf_cwiter(VertexHandle _vh) + { return VertexFaceCWIter(*this, _vh); } + /// vertex - face circulator ccw + VertexFaceCCWIter vf_ccwiter(VertexHandle _vh) + { return VertexFaceCCWIter(*this, _vh); } /// const vertex circulator ConstVertexVertexIter cvv_iter(VertexHandle _vh) const { return ConstVertexVertexIter(*this, _vh); } + /// const vertex circulator cw + ConstVertexVertexCWIter cvv_cwiter(VertexHandle _vh) const + { return ConstVertexVertexCWIter(*this, _vh); } + /// const vertex circulator ccw + ConstVertexVertexCCWIter cvv_ccwiter(VertexHandle _vh) const + { return ConstVertexVertexCCWIter(*this, _vh); } /// const vertex - incoming halfedge circulator ConstVertexIHalfedgeIter cvih_iter(VertexHandle _vh) const { return ConstVertexIHalfedgeIter(*this, _vh); } + /// const vertex - incoming halfedge circulator cw + ConstVertexIHalfedgeCWIter cvih_cwiter(VertexHandle _vh) const + { return ConstVertexIHalfedgeCWIter(*this, _vh); } + /// const vertex - incoming halfedge circulator ccw + ConstVertexIHalfedgeCCWIter cvih_ccwiter(VertexHandle _vh) const + { return ConstVertexIHalfedgeCCWIter(*this, _vh); } /// const vertex - outgoing halfedge circulator ConstVertexOHalfedgeIter cvoh_iter(VertexHandle _vh) const { return ConstVertexOHalfedgeIter(*this, _vh); } + /// const vertex - outgoing halfedge circulator cw + ConstVertexOHalfedgeCWIter cvoh_cwiter(VertexHandle _vh) const + { return ConstVertexOHalfedgeCWIter(*this, _vh); } + /// const vertex - outgoing halfedge circulator ccw + ConstVertexOHalfedgeCCWIter cvoh_ccwiter(VertexHandle _vh) const + { return ConstVertexOHalfedgeCCWIter(*this, _vh); } /// const vertex - edge circulator ConstVertexEdgeIter cve_iter(VertexHandle _vh) const { return ConstVertexEdgeIter(*this, _vh); } + /// const vertex - edge circulator cw + ConstVertexEdgeCWIter cve_cwiter(VertexHandle _vh) const + { return ConstVertexEdgeCWIter(*this, _vh); } + /// const vertex - edge circulator ccw + ConstVertexEdgeCCWIter cve_ccwiter(VertexHandle _vh) const + { return ConstVertexEdgeCCWIter(*this, _vh); } /// const vertex - face circulator ConstVertexFaceIter cvf_iter(VertexHandle _vh) const { return ConstVertexFaceIter(*this, _vh); } + /// const vertex - face circulator cw + ConstVertexFaceCWIter cvf_cwiter(VertexHandle _vh) const + { return ConstVertexFaceCWIter(*this, _vh); } + /// const vertex - face circulator ccw + ConstVertexFaceCCWIter cvf_ccwiter(VertexHandle _vh) const + { return ConstVertexFaceCCWIter(*this, _vh); } /// face - vertex circulator FaceVertexIter fv_iter(FaceHandle _fh) { return FaceVertexIter(*this, _fh); } + /// face - vertex circulator cw + FaceVertexCWIter fv_cwiter(FaceHandle _fh) + { return FaceVertexCWIter(*this, _fh); } + /// face - vertex circulator ccw + FaceVertexCCWIter fv_ccwiter(FaceHandle _fh) + { return FaceVertexCCWIter(*this, _fh); } /// face - halfedge circulator FaceHalfedgeIter fh_iter(FaceHandle _fh) { return FaceHalfedgeIter(*this, _fh); } + /// face - halfedge circulator cw + FaceHalfedgeCWIter fh_cwiter(FaceHandle _fh) + { return FaceHalfedgeCWIter(*this, _fh); } + /// face - halfedge circulator ccw + FaceHalfedgeCCWIter fh_ccwiter(FaceHandle _fh) + { return FaceHalfedgeCCWIter(*this, _fh); } /// face - edge circulator FaceEdgeIter fe_iter(FaceHandle _fh) { return FaceEdgeIter(*this, _fh); } + /// face - edge circulator cw + FaceEdgeCWIter fe_cwiter(FaceHandle _fh) + { return FaceEdgeCWIter(*this, _fh); } + /// face - edge circulator ccw + FaceEdgeCCWIter fe_ccwiter(FaceHandle _fh) + { return FaceEdgeCCWIter(*this, _fh); } /// face - face circulator FaceFaceIter ff_iter(FaceHandle _fh) { return FaceFaceIter(*this, _fh); } + /// face - face circulator cw + FaceFaceCWIter ff_cwiter(FaceHandle _fh) + { return FaceFaceCWIter(*this, _fh); } + /// face - face circulator ccw + FaceFaceCCWIter ff_ccwiter(FaceHandle _fh) + { return FaceFaceCCWIter(*this, _fh); } /// const face - vertex circulator ConstFaceVertexIter cfv_iter(FaceHandle _fh) const { return ConstFaceVertexIter(*this, _fh); } + /// const face - vertex circulator cw + ConstFaceVertexCWIter cfv_cwiter(FaceHandle _fh) const + { return ConstFaceVertexCWIter(*this, _fh); } + /// const face - vertex circulator ccw + ConstFaceVertexCCWIter cfv_ccwiter(FaceHandle _fh) const + { return ConstFaceVertexCCWIter(*this, _fh); } /// const face - halfedge circulator ConstFaceHalfedgeIter cfh_iter(FaceHandle _fh) const { return ConstFaceHalfedgeIter(*this, _fh); } + /// const face - halfedge circulator cw + ConstFaceHalfedgeCWIter cfh_cwiter(FaceHandle _fh) const + { return ConstFaceHalfedgeCWIter(*this, _fh); } + /// const face - halfedge circulator ccw + ConstFaceHalfedgeCCWIter cfh_ccwiter(FaceHandle _fh) const + { return ConstFaceHalfedgeCCWIter(*this, _fh); } /// const face - edge circulator ConstFaceEdgeIter cfe_iter(FaceHandle _fh) const { return ConstFaceEdgeIter(*this, _fh); } + /// const face - edge circulator cw + ConstFaceEdgeCWIter cfe_cwiter(FaceHandle _fh) const + { return ConstFaceEdgeCWIter(*this, _fh); } + /// const face - edge circulator ccw + ConstFaceEdgeCCWIter cfe_ccwiter(FaceHandle _fh) const + { return ConstFaceEdgeCCWIter(*this, _fh); } /// const face - face circulator ConstFaceFaceIter cff_iter(FaceHandle _fh) const { return ConstFaceFaceIter(*this, _fh); } + /// const face - face circulator cw + ConstFaceFaceCWIter cff_cwiter(FaceHandle _fh) const + { return ConstFaceFaceCWIter(*this, _fh); } + /// const face - face circulator + ConstFaceFaceCCWIter cff_ccwiter(FaceHandle _fh) const + { return ConstFaceFaceCCWIter(*this, _fh); } // 'begin' circulators /// vertex - vertex circulator VertexVertexIter vv_begin(VertexHandle _vh) { return VertexVertexIter(*this, _vh); } + /// vertex - vertex circulator cw + VertexVertexCWIter vv_cwbegin(VertexHandle _vh) + { return VertexVertexCWIter(*this, _vh); } + /// vertex - vertex circulator ccw + VertexVertexCCWIter vv_ccwbegin(VertexHandle _vh) + { return VertexVertexCCWIter(*this, _vh); } /// vertex - incoming halfedge circulator VertexIHalfedgeIter vih_begin(VertexHandle _vh) { return VertexIHalfedgeIter(*this, _vh); } + /// vertex - incoming halfedge circulator cw + VertexIHalfedgeCWIter vih_cwbegin(VertexHandle _vh) + { return VertexIHalfedgeCWIter(*this, _vh); } + /// vertex - incoming halfedge circulator ccw + VertexIHalfedgeCCWIter vih_ccwbegin(VertexHandle _vh) + { return VertexIHalfedgeCCWIter(*this, _vh); } /// vertex - outgoing halfedge circulator VertexOHalfedgeIter voh_begin(VertexHandle _vh) { return VertexOHalfedgeIter(*this, _vh); } + /// vertex - outgoing halfedge circulator cw + VertexOHalfedgeCWIter voh_cwbegin(VertexHandle _vh) + { return VertexOHalfedgeCWIter(*this, _vh); } + /// vertex - outgoing halfedge circulator ccw + VertexOHalfedgeCCWIter voh_ccwbegin(VertexHandle _vh) + { return VertexOHalfedgeCCWIter(*this, _vh); } /// vertex - edge circulator VertexEdgeIter ve_begin(VertexHandle _vh) { return VertexEdgeIter(*this, _vh); } + /// vertex - edge circulator cw + VertexEdgeCWIter ve_cwbegin(VertexHandle _vh) + { return VertexEdgeCWIter(*this, _vh); } + /// vertex - edge circulator ccw + VertexEdgeCCWIter ve_ccwbegin(VertexHandle _vh) + { return VertexEdgeCCWIter(*this, _vh); } /// vertex - face circulator VertexFaceIter vf_begin(VertexHandle _vh) { return VertexFaceIter(*this, _vh); } + /// vertex - face circulator cw + VertexFaceCWIter vf_cwbegin(VertexHandle _vh) + { return VertexFaceCWIter(*this, _vh); } + /// vertex - face circulator ccw + VertexFaceCCWIter vf_ccwbegin(VertexHandle _vh) + { return VertexFaceCCWIter(*this, _vh); } + /// const vertex circulator ConstVertexVertexIter cvv_begin(VertexHandle _vh) const { return ConstVertexVertexIter(*this, _vh); } + /// const vertex circulator cw + ConstVertexVertexCWIter cvv_cwbegin(VertexHandle _vh) const + { return ConstVertexVertexCWIter(*this, _vh); } + /// const vertex circulator ccw + ConstVertexVertexCCWIter cvv_ccwbegin(VertexHandle _vh) const + { return ConstVertexVertexCCWIter(*this, _vh); } /// const vertex - incoming halfedge circulator ConstVertexIHalfedgeIter cvih_begin(VertexHandle _vh) const { return ConstVertexIHalfedgeIter(*this, _vh); } + /// const vertex - incoming halfedge circulator cw + ConstVertexIHalfedgeCWIter cvih_cwbegin(VertexHandle _vh) const + { return ConstVertexIHalfedgeCWIter(*this, _vh); } + /// const vertex - incoming halfedge circulator ccw + ConstVertexIHalfedgeCCWIter cvih_ccwbegin(VertexHandle _vh) const + { return ConstVertexIHalfedgeCCWIter(*this, _vh); } /// const vertex - outgoing halfedge circulator ConstVertexOHalfedgeIter cvoh_begin(VertexHandle _vh) const { return ConstVertexOHalfedgeIter(*this, _vh); } + /// const vertex - outgoing halfedge circulator cw + ConstVertexOHalfedgeCWIter cvoh_cwbegin(VertexHandle _vh) const + { return ConstVertexOHalfedgeCWIter(*this, _vh); } + /// const vertex - outgoing halfedge circulator ccw + ConstVertexOHalfedgeCCWIter cvoh_ccwbegin(VertexHandle _vh) const + { return ConstVertexOHalfedgeCCWIter(*this, _vh); } /// const vertex - edge circulator ConstVertexEdgeIter cve_begin(VertexHandle _vh) const { return ConstVertexEdgeIter(*this, _vh); } + /// const vertex - edge circulator cw + ConstVertexEdgeCWIter cve_cwbegin(VertexHandle _vh) const + { return ConstVertexEdgeCWIter(*this, _vh); } + /// const vertex - edge circulator ccw + ConstVertexEdgeCCWIter cve_ccwbegin(VertexHandle _vh) const + { return ConstVertexEdgeCCWIter(*this, _vh); } /// const vertex - face circulator ConstVertexFaceIter cvf_begin(VertexHandle _vh) const { return ConstVertexFaceIter(*this, _vh); } + /// const vertex - face circulator cw + ConstVertexFaceCWIter cvf_cwbegin(VertexHandle _vh) const + { return ConstVertexFaceCWIter(*this, _vh); } + /// const vertex - face circulator ccw + ConstVertexFaceCCWIter cvf_ccwbegin(VertexHandle _vh) const + { return ConstVertexFaceCCWIter(*this, _vh); } /// face - vertex circulator FaceVertexIter fv_begin(FaceHandle _fh) { return FaceVertexIter(*this, _fh); } + /// face - vertex circulator cw + FaceVertexCWIter fv_cwbegin(FaceHandle _fh) + { return FaceVertexCWIter(*this, _fh); } + /// face - vertex circulator ccw + FaceVertexCCWIter fv_ccwbegin(FaceHandle _fh) + { return FaceVertexCCWIter(*this, _fh); } /// face - halfedge circulator FaceHalfedgeIter fh_begin(FaceHandle _fh) { return FaceHalfedgeIter(*this, _fh); } + /// face - halfedge circulator cw + FaceHalfedgeCWIter fh_cwbegin(FaceHandle _fh) + { return FaceHalfedgeCWIter(*this, _fh); } + /// face - halfedge circulator ccw + FaceHalfedgeCCWIter fh_ccwbegin(FaceHandle _fh) + { return FaceHalfedgeCCWIter(*this, _fh); } /// face - edge circulator FaceEdgeIter fe_begin(FaceHandle _fh) { return FaceEdgeIter(*this, _fh); } + /// face - edge circulator cw + FaceEdgeCWIter fe_cwbegin(FaceHandle _fh) + { return FaceEdgeCWIter(*this, _fh); } + /// face - edge circulator ccw + FaceEdgeCCWIter fe_ccwbegin(FaceHandle _fh) + { return FaceEdgeCCWIter(*this, _fh); } /// face - face circulator FaceFaceIter ff_begin(FaceHandle _fh) { return FaceFaceIter(*this, _fh); } + /// face - face circulator cw + FaceFaceCWIter ff_cwbegin(FaceHandle _fh) + { return FaceFaceCWIter(*this, _fh); } + /// face - face circulator ccw + FaceFaceCCWIter ff_ccwbegin(FaceHandle _fh) + { return FaceFaceCCWIter(*this, _fh); } /// halfedge circulator HalfedgeLoopIter hl_begin(HalfedgeHandle _heh) { return HalfedgeLoopIter(*this, _heh); } + /// halfedge circulator + HalfedgeLoopCWIter hl_cwbegin(HalfedgeHandle _heh) + { return HalfedgeLoopCWIter(*this, _heh); } + /// halfedge circulator ccw + HalfedgeLoopCCWIter hl_ccwbegin(HalfedgeHandle _heh) + { return HalfedgeLoopCCWIter(*this, _heh); } /// const face - vertex circulator ConstFaceVertexIter cfv_begin(FaceHandle _fh) const { return ConstFaceVertexIter(*this, _fh); } + /// const face - vertex circulator cw + ConstFaceVertexCWIter cfv_cwbegin(FaceHandle _fh) const + { return ConstFaceVertexCWIter(*this, _fh); } + /// const face - vertex circulator ccw + ConstFaceVertexCCWIter cfv_ccwbegin(FaceHandle _fh) const + { return ConstFaceVertexCCWIter(*this, _fh); } /// const face - halfedge circulator ConstFaceHalfedgeIter cfh_begin(FaceHandle _fh) const { return ConstFaceHalfedgeIter(*this, _fh); } + /// const face - halfedge circulator cw + ConstFaceHalfedgeCWIter cfh_cwbegin(FaceHandle _fh) const + { return ConstFaceHalfedgeCWIter(*this, _fh); } + /// const face - halfedge circulator ccw + ConstFaceHalfedgeCCWIter cfh_ccwbegin(FaceHandle _fh) const + { return ConstFaceHalfedgeCCWIter(*this, _fh); } /// const face - edge circulator ConstFaceEdgeIter cfe_begin(FaceHandle _fh) const { return ConstFaceEdgeIter(*this, _fh); } + /// const face - edge circulator cw + ConstFaceEdgeCWIter cfe_cwbegin(FaceHandle _fh) const + { return ConstFaceEdgeCWIter(*this, _fh); } + /// const face - edge circulator ccw + ConstFaceEdgeCCWIter cfe_ccwbegin(FaceHandle _fh) const + { return ConstFaceEdgeCCWIter(*this, _fh); } /// const face - face circulator ConstFaceFaceIter cff_begin(FaceHandle _fh) const { return ConstFaceFaceIter(*this, _fh); } + /// const face - face circulator cw + ConstFaceFaceCWIter cff_cwbegin(FaceHandle _fh) const + { return ConstFaceFaceCWIter(*this, _fh); } + /// const face - face circulator ccw + ConstFaceFaceCCWIter cff_ccwbegin(FaceHandle _fh) const + { return ConstFaceFaceCCWIter(*this, _fh); } /// const halfedge circulator ConstHalfedgeLoopIter chl_begin(HalfedgeHandle _heh) const { return ConstHalfedgeLoopIter(*this, _heh); } + /// const halfedge circulator cw + ConstHalfedgeLoopCWIter chl_cwbegin(HalfedgeHandle _heh) const + { return ConstHalfedgeLoopCWIter(*this, _heh); } + /// const halfedge circulator ccw + ConstHalfedgeLoopCCWIter chl_ccwbegin(HalfedgeHandle _heh) const + { return ConstHalfedgeLoopCCWIter(*this, _heh); } // 'end' circulators /// vertex - vertex circulator VertexVertexIter vv_end(VertexHandle _vh) { return VertexVertexIter(*this, _vh, true); } + /// vertex - vertex circulator cw + VertexVertexCWIter vv_cwend(VertexHandle _vh) + { return VertexVertexCWIter(*this, _vh, true); } + /// vertex - vertex circulator ccw + VertexVertexCCWIter vv_ccwend(VertexHandle _vh) + { return VertexVertexCCWIter(*this, _vh, true); } /// vertex - incoming halfedge circulator VertexIHalfedgeIter vih_end(VertexHandle _vh) { return VertexIHalfedgeIter(*this, _vh, true); } + /// vertex - incoming halfedge circulator cw + VertexIHalfedgeCWIter vih_cwend(VertexHandle _vh) + { return VertexIHalfedgeCWIter(*this, _vh, true); } + /// vertex - incoming halfedge circulator ccw + VertexIHalfedgeCCWIter vih_ccwend(VertexHandle _vh) + { return VertexIHalfedgeCCWIter(*this, _vh, true); } /// vertex - outgoing halfedge circulator VertexOHalfedgeIter voh_end(VertexHandle _vh) { return VertexOHalfedgeIter(*this, _vh, true); } + /// vertex - outgoing halfedge circulator cw + VertexOHalfedgeCWIter voh_cwend(VertexHandle _vh) + { return VertexOHalfedgeCWIter(*this, _vh, true); } + /// vertex - outgoing halfedge circulator ccw + VertexOHalfedgeCCWIter voh_ccwend(VertexHandle _vh) + { return VertexOHalfedgeCCWIter(*this, _vh, true); } /// vertex - edge circulator VertexEdgeIter ve_end(VertexHandle _vh) { return VertexEdgeIter(*this, _vh, true); } + /// vertex - edge circulator cw + VertexEdgeCWIter ve_cwend(VertexHandle _vh) + { return VertexEdgeCWIter(*this, _vh, true); } + /// vertex - edge circulator ccw + VertexEdgeCCWIter ve_ccwend(VertexHandle _vh) + { return VertexEdgeCCWIter(*this, _vh, true); } /// vertex - face circulator VertexFaceIter vf_end(VertexHandle _vh) { return VertexFaceIter(*this, _vh, true); } + /// vertex - face circulator cw + VertexFaceCWIter vf_cwend(VertexHandle _vh) + { return VertexFaceCWIter(*this, _vh, true); } + /// vertex - face circulator ccw + VertexFaceCCWIter vf_ccwend(VertexHandle _vh) + { return VertexFaceCCWIter(*this, _vh, true); } /// const vertex circulator ConstVertexVertexIter cvv_end(VertexHandle _vh) const { return ConstVertexVertexIter(*this, _vh, true); } + /// const vertex circulator cw + ConstVertexVertexCWIter cvv_cwend(VertexHandle _vh) const + { return ConstVertexVertexCWIter(*this, _vh, true); } + /// const vertex circulator ccw + ConstVertexVertexCCWIter cvv_ccwend(VertexHandle _vh) const + { return ConstVertexVertexCCWIter(*this, _vh, true); } /// const vertex - incoming halfedge circulator ConstVertexIHalfedgeIter cvih_end(VertexHandle _vh) const { return ConstVertexIHalfedgeIter(*this, _vh, true); } + /// const vertex - incoming halfedge circulator cw + ConstVertexIHalfedgeCWIter cvih_cwend(VertexHandle _vh) const + { return ConstVertexIHalfedgeCWIter(*this, _vh, true); } + /// const vertex - incoming halfedge circulator ccw + ConstVertexIHalfedgeCCWIter cvih_ccwend(VertexHandle _vh) const + { return ConstVertexIHalfedgeCCWIter(*this, _vh, true); } /// const vertex - outgoing halfedge circulator ConstVertexOHalfedgeIter cvoh_end(VertexHandle _vh) const { return ConstVertexOHalfedgeIter(*this, _vh, true); } + /// const vertex - outgoing halfedge circulator cw + ConstVertexOHalfedgeCWIter cvoh_cwend(VertexHandle _vh) const + { return ConstVertexOHalfedgeCWIter(*this, _vh, true); } + /// const vertex - outgoing halfedge circulator ccw + ConstVertexOHalfedgeCCWIter cvoh_ccwend(VertexHandle _vh) const + { return ConstVertexOHalfedgeCCWIter(*this, _vh, true); } /// const vertex - edge circulator ConstVertexEdgeIter cve_end(VertexHandle _vh) const { return ConstVertexEdgeIter(*this, _vh, true); } + /// const vertex - edge circulator cw + ConstVertexEdgeCWIter cve_cwend(VertexHandle _vh) const + { return ConstVertexEdgeCWIter(*this, _vh, true); } + /// const vertex - edge circulator ccw + ConstVertexEdgeCCWIter cve_ccwend(VertexHandle _vh) const + { return ConstVertexEdgeCCWIter(*this, _vh, true); } /// const vertex - face circulator ConstVertexFaceIter cvf_end(VertexHandle _vh) const { return ConstVertexFaceIter(*this, _vh, true); } + /// const vertex - face circulator cw + ConstVertexFaceCWIter cvf_cwend(VertexHandle _vh) const + { return ConstVertexFaceCWIter(*this, _vh, true); } + /// const vertex - face circulator ccw + ConstVertexFaceCCWIter cvf_ccwend(VertexHandle _vh) const + { return ConstVertexFaceCCWIter(*this, _vh, true); } /// face - vertex circulator FaceVertexIter fv_end(FaceHandle _fh) { return FaceVertexIter(*this, _fh, true); } + /// face - vertex circulator cw + FaceVertexCWIter fv_cwend(FaceHandle _fh) + { return FaceVertexCWIter(*this, _fh, true); } + /// face - vertex circulator ccw + FaceVertexCCWIter fv_ccwend(FaceHandle _fh) + { return FaceVertexCCWIter(*this, _fh, true); } /// face - halfedge circulator FaceHalfedgeIter fh_end(FaceHandle _fh) { return FaceHalfedgeIter(*this, _fh, true); } + /// face - halfedge circulator cw + FaceHalfedgeCWIter fh_cwend(FaceHandle _fh) + { return FaceHalfedgeCWIter(*this, _fh, true); } + /// face - halfedge circulator ccw + FaceHalfedgeCCWIter fh_ccwend(FaceHandle _fh) + { return FaceHalfedgeCCWIter(*this, _fh, true); } /// face - edge circulator FaceEdgeIter fe_end(FaceHandle _fh) { return FaceEdgeIter(*this, _fh, true); } + /// face - edge circulator cw + FaceEdgeCWIter fe_cwend(FaceHandle _fh) + { return FaceEdgeCWIter(*this, _fh, true); } + /// face - edge circulator ccw + FaceEdgeCCWIter fe_ccwend(FaceHandle _fh) + { return FaceEdgeCCWIter(*this, _fh, true); } /// face - face circulator FaceFaceIter ff_end(FaceHandle _fh) { return FaceFaceIter(*this, _fh, true); } + /// face - face circulator cw + FaceFaceCWIter ff_cwend(FaceHandle _fh) + { return FaceFaceCWIter(*this, _fh, true); } + /// face - face circulator ccw + FaceFaceCCWIter ff_ccwend(FaceHandle _fh) + { return FaceFaceCCWIter(*this, _fh, true); } /// face - face circulator HalfedgeLoopIter hl_end(HalfedgeHandle _heh) { return HalfedgeLoopIter(*this, _heh, true); } + /// face - face circulator cw + HalfedgeLoopCWIter hl_cwend(HalfedgeHandle _heh) + { return HalfedgeLoopCWIter(*this, _heh, true); } + /// face - face circulator ccw + HalfedgeLoopCCWIter hl_ccwend(HalfedgeHandle _heh) + { return HalfedgeLoopCCWIter(*this, _heh, true); } /// const face - vertex circulator ConstFaceVertexIter cfv_end(FaceHandle _fh) const { return ConstFaceVertexIter(*this, _fh, true); } + /// const face - vertex circulator cw + ConstFaceVertexCWIter cfv_cwend(FaceHandle _fh) const + { return ConstFaceVertexCWIter(*this, _fh, true); } + /// const face - vertex circulator ccw + ConstFaceVertexCCWIter cfv_ccwend(FaceHandle _fh) const + { return ConstFaceVertexCCWIter(*this, _fh, true); } /// const face - halfedge circulator ConstFaceHalfedgeIter cfh_end(FaceHandle _fh) const { return ConstFaceHalfedgeIter(*this, _fh, true); } + /// const face - halfedge circulator cw + ConstFaceHalfedgeCWIter cfh_cwend(FaceHandle _fh) const + { return ConstFaceHalfedgeCWIter(*this, _fh, true); } + /// const face - halfedge circulator ccw + ConstFaceHalfedgeCCWIter cfh_ccwend(FaceHandle _fh) const + { return ConstFaceHalfedgeCCWIter(*this, _fh, true); } /// const face - edge circulator ConstFaceEdgeIter cfe_end(FaceHandle _fh) const { return ConstFaceEdgeIter(*this, _fh, true); } + /// const face - edge circulator cw + ConstFaceEdgeCWIter cfe_cwend(FaceHandle _fh) const + { return ConstFaceEdgeCWIter(*this, _fh, true); } + /// const face - edge circulator ccw + ConstFaceEdgeCCWIter cfe_ccwend(FaceHandle _fh) const + { return ConstFaceEdgeCCWIter(*this, _fh, true); } /// const face - face circulator ConstFaceFaceIter cff_end(FaceHandle _fh) const { return ConstFaceFaceIter(*this, _fh, true); } /// const face - face circulator + ConstFaceFaceCWIter cff_cwend(FaceHandle _fh) const + { return ConstFaceFaceCWIter(*this, _fh, true); } + /// const face - face circulator + ConstFaceFaceCCWIter cff_ccwend(FaceHandle _fh) const + { return ConstFaceFaceCCWIter(*this, _fh, true); } + /// const face - face circulator ConstHalfedgeLoopIter chl_end(HalfedgeHandle _heh) const { return ConstHalfedgeLoopIter(*this, _heh, true); } + /// const face - face circulator cw + ConstHalfedgeLoopCWIter chl_cwend(HalfedgeHandle _heh) const + { return ConstHalfedgeLoopCWIter(*this, _heh, true); } + /// const face - face circulator ccw + ConstHalfedgeLoopCCWIter chl_ccwend(HalfedgeHandle _heh) const + { return ConstHalfedgeLoopCCWIter(*this, _heh, true); } //@} /** @name Range based iterators and circulators */ diff --git a/src/Unittests/unittests_trimesh_circulator_face_edge.cc b/src/Unittests/unittests_trimesh_circulator_face_edge.cc index aae2dcd0..579d8c13 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_edge.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_edge.cc @@ -2,6 +2,7 @@ #include #include +#include namespace { @@ -129,6 +130,145 @@ TEST_F(OpenMeshTrimeshCirculatorFaceEdge, FaceEdgeIterWithoutHolesIncrement) { } } +/* + * test CW and CCW iterators + */ +TEST_F(OpenMeshTrimeshCirculatorFaceEdge, CWAndCCWTest) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[6]; + + 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(3, 0, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(4, 1, 0)); + vhandle[5] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add three faces + std::vector 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[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + 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[1]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[3]); + mesh_.add_face(face_vhandles); + + /* Test setup: + * + * 0 ------ 2 ------ 4 + * \ / \ / + * \ 0 / \ 2 / + * \ / 1 \ / + * 1 ------- 3 + * \ / + * \ 3 / + * \ / + * \ / + * 5 + */ + + + int indices[4] = {4, 1, 3, 4}; + int rev_indices[4]; + std::reverse_copy(indices,indices+4,rev_indices); + + //CCW + Mesh::FaceEdgeCCWIter fe_ccwit = mesh_.fe_ccwbegin(mesh_.face_handle(1)); + Mesh::FaceEdgeCCWIter fe_ccwend = mesh_.fe_ccwend(mesh_.face_handle(1)); + size_t i = 0; + for (;fe_ccwit != fe_ccwend; ++fe_ccwit, ++i) + { + EXPECT_EQ(indices[i], fe_ccwit->idx()) << "Index wrong in FaceEdgeCCWIter"; + } + + EXPECT_FALSE(fe_ccwit.is_valid()) << "Iterator invalid in FaceEdgeCCWIter at end"; + EXPECT_TRUE( fe_ccwit == fe_ccwend ) << "End iterator for FaceEdgeCCWIter not matching"; + + //constant CCW + Mesh::ConstFaceEdgeCCWIter cfe_ccwit = mesh_.cfe_ccwbegin(mesh_.face_handle(1)); + Mesh::ConstFaceEdgeCCWIter cfe_ccwend = mesh_.cfe_ccwend(mesh_.face_handle(1)); + i = 0; + for (;cfe_ccwit != cfe_ccwend; ++cfe_ccwit, ++i) + { + EXPECT_EQ(indices[i], cfe_ccwit->idx()) << "Index wrong in ConstFaceEdgeCCWIter"; + } + + EXPECT_FALSE(cfe_ccwit.is_valid()) << "Iterator invalid in ConstFaceEdgeCCWIter at end"; + EXPECT_TRUE( cfe_ccwit == cfe_ccwend ) << "End iterator for ConstFaceEdgeCCWIter not matching"; + + //CW + Mesh::FaceEdgeCWIter fe_cwit = mesh_.fe_cwbegin(mesh_.face_handle(1)); + Mesh::FaceEdgeCWIter fe_cwend = mesh_.fe_cwend(mesh_.face_handle(1)); + i = 0; + for (;fe_cwit != fe_cwend; ++fe_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], fe_cwit->idx()) << "Index wrong in FaceEdgeCWIter"; + } + EXPECT_FALSE(fe_cwit.is_valid()) << "Iterator invalid in FaceEdgeCWIter at end"; + EXPECT_TRUE( fe_cwit == fe_cwend ) << "End iterator for FaceEdgeCWIter not matching"; + + //constant CW + Mesh::ConstFaceEdgeCWIter cfe_cwit = mesh_.cfe_cwbegin(mesh_.face_handle(1)); + Mesh::ConstFaceEdgeCWIter cfe_cwend = mesh_.cfe_cwend(mesh_.face_handle(1)); + i = 0; + for (;cfe_cwit != cfe_cwend; ++cfe_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], cfe_cwit->idx()) << "Index wrong in ConstFaceEdgeCWIter"; + } + EXPECT_FALSE(cfe_cwit.is_valid()) << "Iterator invalid in ConstFaceEdgeCWIter at end"; + EXPECT_TRUE( cfe_cwit == cfe_cwend ) << "End iterator for ConstFaceEdgeCWIter not matching"; + + /* + * conversion properties: + * a) cw_begin == CWIter(ccw_begin()) + * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators + * c) --cw_iter == CWIter(++ccwIter) for valid iterators + * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + */ + Mesh::FaceEdgeCWIter fe_cwIter = mesh_.fe_cwbegin(mesh_.face_handle(1)); + // a) + EXPECT_TRUE( fe_cwIter == Mesh::FaceEdgeCWIter(mesh_.fe_ccwbegin(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"; + // b) + EXPECT_EQ( fe_cwIter->idx(), Mesh::FaceEdgeCCWIter(fe_cwIter)->idx()) << "iterators doesnt point on the same element"; + // c) + ++fe_cwIter; + fe_ccwend = mesh_.fe_ccwend(mesh_.face_handle(1)); + --fe_ccwend; + 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) + fe_cwIter = Mesh::FaceEdgeCWIter(mesh_.fe_ccwend(mesh_.face_handle(1))); + 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"; + +} + /* * Test if the end iterator stays invalid after one lap diff --git a/src/Unittests/unittests_trimesh_circulator_face_face.cc b/src/Unittests/unittests_trimesh_circulator_face_face.cc index 99e48e26..fdd4ac8a 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_face.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_face.cc @@ -2,6 +2,7 @@ #include #include +#include namespace { @@ -205,6 +206,146 @@ TEST_F(OpenMeshTrimeshCirculatorFaceFace, FaceFaceIterWithoutHoles) { } +/* + * Test CW and CCW iterators + */ +TEST_F(OpenMeshTrimeshCirculatorFaceFace, CWAndCCWCheck) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[6]; + + 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(3, 0, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(4, 1, 0)); + vhandle[5] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add three faces + std::vector 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[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + 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[1]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[3]); + mesh_.add_face(face_vhandles); + + /* Test setup: + * + * 0 ------ 2 ------ 4 + * \ / \ / + * \ 0 / \ 2 / + * \ / 1 \ / + * 1 ------- 3 + * \ / + * \ 3 / + * \ / + * \ / + * 5 + */ + + + int indices[4] = {2, 0, 3, 2}; + int rev_indices[4]; + std::reverse_copy(indices,indices+4,rev_indices); + + //CCW + Mesh::FaceFaceCCWIter ff_ccwit = mesh_.ff_ccwbegin(mesh_.face_handle(1)); + Mesh::FaceFaceCCWIter ff_ccwend = mesh_.ff_ccwend(mesh_.face_handle(1)); + size_t i = 0; + for (;ff_ccwit != ff_ccwend; ++ff_ccwit, ++i) + { + EXPECT_EQ(indices[i], ff_ccwit->idx()) << "Index wrong in FaceFaceCCWIter"; + } + + EXPECT_FALSE(ff_ccwit.is_valid()) << "Iterator invalid in FaceFaceCCWIter at end"; + EXPECT_TRUE( ff_ccwit == ff_ccwend ) << "End iterator for FaceFaceCCWIter not matching"; + + //constant CCW + Mesh::ConstFaceFaceCCWIter cff_ccwit = mesh_.cff_ccwbegin(mesh_.face_handle(1)); + Mesh::ConstFaceFaceCCWIter cff_ccwend = mesh_.cff_ccwend(mesh_.face_handle(1)); + i = 0; + for (;cff_ccwit != cff_ccwend; ++cff_ccwit, ++i) + { + EXPECT_EQ(indices[i], cff_ccwit->idx()) << "Index wrong in ConstFaceFaceCCWIter"; + } + + EXPECT_FALSE(cff_ccwit.is_valid()) << "Iterator invalid in ConstFaceFaceCCWIter at end"; + EXPECT_TRUE( cff_ccwit == cff_ccwend ) << "End iterator for ConstFaceFaceCCWIter not matching"; + + //CW + Mesh::FaceFaceCWIter ff_cwit = mesh_.ff_cwbegin(mesh_.face_handle(1)); + Mesh::FaceFaceCWIter ff_cwend = mesh_.ff_cwend(mesh_.face_handle(1)); + i = 0; + for (;ff_cwit != ff_cwend; ++ff_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], ff_cwit->idx()) << "Index wrong in FaceFaceCWIter"; + } + EXPECT_FALSE(ff_cwit.is_valid()) << "Iterator invalid in FaceFaceCWIter at end"; + EXPECT_TRUE( ff_cwit == ff_cwend ) << "End iterator for FaceFaceCWIter not matching"; + + //constant CW + Mesh::ConstFaceFaceCWIter cff_cwit = mesh_.cff_cwbegin(mesh_.face_handle(1)); + Mesh::ConstFaceFaceCWIter cff_cwend = mesh_.cff_cwend(mesh_.face_handle(1)); + i = 0; + for (;cff_cwit != cff_cwend; ++cff_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], cff_cwit->idx()) << "Index wrong in ConstFaceFaceCWIter"; + } + EXPECT_FALSE(cff_cwit.is_valid()) << "Iterator invalid in ConstFaceFaceCWIter at end"; + EXPECT_TRUE( cff_cwit == cff_cwend ) << "End iterator for ConstFaceFaceCWIter not matching"; + + /* + * conversion properties: + * a) cw_begin == CWIter(ccw_begin()) + * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators + * c) --cw_iter == CWIter(++ccwIter) for valid iterators + * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + */ + Mesh::FaceFaceCWIter ff_cwIter = mesh_.ff_cwbegin(mesh_.face_handle(1)); + // a) + EXPECT_TRUE( ff_cwIter == Mesh::FaceFaceCWIter(mesh_.ff_ccwbegin(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"; + // b) + EXPECT_EQ( ff_cwIter->idx(), Mesh::FaceFaceCCWIter(ff_cwIter)->idx()) << "iterators doesnt point on the same element"; + // c) + ++ff_cwIter; + ff_ccwend = mesh_.ff_ccwend(mesh_.face_handle(1)); + --ff_ccwend; + 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) + ff_cwIter = Mesh::FaceFaceCWIter(mesh_.ff_ccwend(mesh_.face_handle(1))); + 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"; + + +} + /* diff --git a/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc b/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc index 6ceb9d77..88262f35 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_halfedge.cc @@ -2,6 +2,7 @@ #include #include +#include namespace { @@ -127,6 +128,146 @@ TEST_F(OpenMeshTrimeshCirculatorFaceHalfEdge, FaceHalfedgeIterWithoutHolesIncrem } +/* + * test CW and CCW iterators + */ +TEST_F(OpenMeshTrimeshCirculatorFaceHalfEdge, CWAndCCWTest) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[6]; + + 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(3, 0, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(4, 1, 0)); + vhandle[5] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add three faces + std::vector 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[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + 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[1]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[3]); + mesh_.add_face(face_vhandles); + + /* Test setup: + * + * 0 ------ 2 ------ 4 + * \ / \ / + * \ 0 / \ 2 / + * \ / 1 \ / + * 1 ------- 3 + * \ / + * \ 3 / + * \ / + * \ / + * 5 + */ + + + int indices[4] = {8, 3, 6, 8}; + int rev_indices[4]; + std::reverse_copy(indices,indices+4,rev_indices); + + //CCW + Mesh::FaceHalfedgeIter fh_ccwit = mesh_.fh_ccwbegin(mesh_.face_handle(1)); + Mesh::FaceHalfedgeIter fh_ccwend = mesh_.fh_ccwend(mesh_.face_handle(1)); + size_t i = 0; + for (;fh_ccwit != fh_ccwend; ++fh_ccwit, ++i) + { + EXPECT_EQ(indices[i], fh_ccwit->idx()) << "Index wrong in FaceHalfedgeIter"; + } + + EXPECT_FALSE(fh_ccwit.is_valid()) << "Iterator invalid in FaceHalfedgeIter at end"; + EXPECT_TRUE( fh_ccwit == fh_ccwend ) << "End iterator for FaceHalfedgeIter not matching"; + + //constant CCW + Mesh::ConstFaceHalfedgeIter cfh_ccwit = mesh_.cfh_ccwbegin(mesh_.face_handle(1)); + Mesh::ConstFaceHalfedgeIter cfh_ccwend = mesh_.cfh_ccwend(mesh_.face_handle(1)); + i = 0; + for (;cfh_ccwit != cfh_ccwend; ++cfh_ccwit, ++i) + { + EXPECT_EQ(indices[i], cfh_ccwit->idx()) << "Index wrong in ConstFaceHalfedgeIter"; + } + + EXPECT_FALSE(cfh_ccwit.is_valid()) << "Iterator invalid in ConstFaceHalfedgeIter at end"; + EXPECT_TRUE( cfh_ccwit == cfh_ccwend ) << "End iterator for ConstFaceHalfedgeIter not matching"; + + //CW + Mesh::FaceHalfedgeCWIter fh_cwit = mesh_.fh_cwbegin(mesh_.face_handle(1)); + Mesh::FaceHalfedgeCWIter fh_cwend = mesh_.fh_cwend(mesh_.face_handle(1)); + i = 0; + for (;fh_cwit != fh_cwend; ++fh_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], fh_cwit->idx()) << "Index wrong in FaceHalfedgeCWIter"; + } + EXPECT_FALSE(fh_cwit.is_valid()) << "Iterator invalid in FaceHalfedgeCWIter at end"; + EXPECT_TRUE( fh_cwit == fh_cwend ) << "End iterator for FaceHalfedgeCWIter not matching"; + + //constant CW + Mesh::ConstFaceHalfedgeCWIter cfh_cwit = mesh_.cfh_cwbegin(mesh_.face_handle(1)); + Mesh::ConstFaceHalfedgeCWIter cfh_cwend = mesh_.cfh_cwend(mesh_.face_handle(1)); + i = 0; + for (;cfh_cwit != cfh_cwend; ++cfh_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], cfh_cwit->idx()) << "Index wrong in ConstFaceHalfedgeCWIter"; + } + EXPECT_FALSE(cfh_cwit.is_valid()) << "Iterator invalid in ConstFaceHalfedgeCWIter at end"; + EXPECT_TRUE( cfh_cwit == cfh_cwend ) << "End iterator for ConstFaceHalfedgeCWIter not matching"; + + /* + * conversion properties: + * a) cw_begin == CWIter(ccw_begin()) + * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators + * c) --cw_iter == CWIter(++ccwIter) for valid iterators + * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + */ + Mesh::FaceHalfedgeCWIter fh_cwIter = mesh_.fh_cwbegin(mesh_.face_handle(1)); + // a) + EXPECT_TRUE( fh_cwIter == Mesh::FaceHalfedgeCWIter(mesh_.fh_ccwbegin(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"; + // b) + EXPECT_EQ( fh_cwIter->idx(), Mesh::FaceHalfedgeCCWIter(fh_cwIter)->idx()) << "iterators doesnt point on the same element"; + // c) + ++fh_cwIter; + fh_ccwend = mesh_.fh_ccwend(mesh_.face_handle(1)); + --fh_ccwend; + 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) + fh_cwIter = Mesh::FaceHalfedgeCWIter(mesh_.fh_ccwend(mesh_.face_handle(1))); + 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"; + + +} + /* * Test if the end iterator stays invalid after one lap diff --git a/src/Unittests/unittests_trimesh_circulator_face_vertex.cc b/src/Unittests/unittests_trimesh_circulator_face_vertex.cc index 4526ae94..320396d2 100644 --- a/src/Unittests/unittests_trimesh_circulator_face_vertex.cc +++ b/src/Unittests/unittests_trimesh_circulator_face_vertex.cc @@ -206,5 +206,139 @@ TEST_F(OpenMeshTrimeshCirculatorFaceVertex, FaceVertexIterCheckInvalidationAtEnd } +/* + * Test CW and CCW iterators + */ +TEST_F(OpenMeshTrimeshCirculatorFaceVertex, CWAndCCWCheck) { + + 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 face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = 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 */ + + + int indices[4] = {0, 1, 2, 0}; + int rev_indices[4]; + std::reverse_copy(indices,indices+4,rev_indices); + + //CCW + Mesh::FaceVertexCCWIter fv_ccwit = mesh_.fv_ccwbegin(fh0); + Mesh::FaceVertexCCWIter fv_ccwend = mesh_.fv_ccwend(fh0); + size_t i = 0; + for (;fv_ccwit != fv_ccwend; ++fv_ccwit, ++i) + { + EXPECT_EQ(indices[i], fv_ccwit->idx()) << "Index wrong in FaceVertexCCWIter"; + } + + EXPECT_FALSE(fv_ccwit.is_valid()) << "Iterator invalid in FaceVertexCCWIter at end"; + EXPECT_TRUE( fv_ccwit == fv_ccwend ) << "End iterator for FaceVertexCCWIter not matching"; + + //constant CCW + Mesh::ConstFaceVertexCCWIter cfv_ccwit = mesh_.cfv_ccwbegin(fh0); + Mesh::ConstFaceVertexCCWIter cfv_ccwend = mesh_.cfv_ccwend(fh0); + i = 0; + for (;cfv_ccwit != cfv_ccwend; ++cfv_ccwit, ++i) + { + EXPECT_EQ(indices[i], cfv_ccwit->idx()) << "Index wrong in ConstFaceVertexCCWIter"; + } + + EXPECT_FALSE(cfv_ccwit.is_valid()) << "Iterator invalid in ConstFaceVertexCCWIter at end"; + EXPECT_TRUE( cfv_ccwit == cfv_ccwend ) << "End iterator for ConstFaceVertexCCWIter not matching"; + + //CW + Mesh::FaceVertexCWIter fv_cwit = mesh_.fv_cwbegin(fh0); + Mesh::FaceVertexCWIter fv_cwend = mesh_.fv_cwend(fh0); + i = 0; + for (;fv_cwit != fv_cwend; ++fv_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], fv_cwit->idx()) << "Index wrong in FaceVertexCWIter"; + } + EXPECT_FALSE(fv_cwit.is_valid()) << "Iterator invalid in FaceVertexCWIter at end"; + EXPECT_TRUE( fv_cwit == fv_cwend ) << "End iterator for FaceVertexCWIter not matching"; + + //constant CW + Mesh::ConstFaceVertexCWIter cfv_cwit = mesh_.cfv_cwbegin(fh0); + Mesh::ConstFaceVertexCWIter cfv_cwend = mesh_.cfv_cwend(fh0); + i = 0; + for (;cfv_cwit != cfv_cwend; ++cfv_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], cfv_cwit->idx()) << "Index wrong in ConstFaceVertexCWIter"; + } + EXPECT_FALSE(cfv_cwit.is_valid()) << "Iterator invalid in ConstFaceVertexCWIter at end"; + EXPECT_TRUE( cfv_cwit == cfv_cwend ) << "End iterator for ConstFaceVertexCWIter not matching"; + + /* + * conversion properties: + * a) cw_begin == CWIter(ccw_begin()) + * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators + * c) --cw_iter == CWIter(++ccwIter) for valid iterators + * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + */ + Mesh::FaceVertexCWIter fv_cwIter = mesh_.fv_cwbegin(mesh_.face_handle(1)); + // a) + EXPECT_TRUE( fv_cwIter == Mesh::FaceVertexCWIter(mesh_.fv_ccwbegin(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"; + // b) + EXPECT_EQ( fv_cwIter->idx(), Mesh::FaceVertexCCWIter(fv_cwIter)->idx()) << "iterators doesnt point on the same element"; + // c) + ++fv_cwIter; + fv_ccwend = mesh_.fv_ccwend(mesh_.face_handle(1)); + --fv_ccwend; + 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) + fv_cwIter = Mesh::FaceVertexCWIter(mesh_.fv_ccwend(mesh_.face_handle(1))); + 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"; + + +} + } diff --git a/src/Unittests/unittests_trimesh_circulator_halfedge_loop.cc b/src/Unittests/unittests_trimesh_circulator_halfedge_loop.cc index c4aad270..14283856 100644 --- a/src/Unittests/unittests_trimesh_circulator_halfedge_loop.cc +++ b/src/Unittests/unittests_trimesh_circulator_halfedge_loop.cc @@ -226,4 +226,144 @@ TEST_F(OpenMeshTrimeshCirculatorHalfedgeLoop, HalfedgeLoopWithoutFace) { } +/* + * Test CW and CCW iterators + */ +TEST_F(OpenMeshTrimeshCirculatorHalfedgeLoop, CWAndCCWCheck) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[6]; + + 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(3, 0, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(4, 1, 0)); + vhandle[5] = mesh_.add_vertex(Mesh::Point(2,-1, 0)); + + // Add three faces + std::vector 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[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[3]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + 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[1]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[3]); + mesh_.add_face(face_vhandles); + + /* Test setup: + * + * 0 ------ 2 ------ 4 + * \ / \ / + * \ 0 / \ 2 / + * \ / 1 \ / + * 1 ------- 3 + * \ / + * \ 3 / + * \ / + * \ / + * 5 + */ + + + int indices[4] = {3, 8, 6, 3}; + int rev_indices[4]; + std::reverse_copy(indices,indices+4,rev_indices); + + //CCW + Mesh::HalfedgeLoopCCWIter hl_ccwit = mesh_.hl_ccwbegin(mesh_.halfedge_handle(3)); + Mesh::HalfedgeLoopCCWIter hl_ccwend = mesh_.hl_ccwend(mesh_.halfedge_handle(3)); + size_t i = 0; + for (;hl_ccwit != hl_ccwend; ++hl_ccwit, ++i) + { + EXPECT_EQ(indices[i], hl_ccwit->idx()) << "Index wrong in HalfedgeLoopCCWIter"; + } + + EXPECT_FALSE(hl_ccwit.is_valid()) << "Iterator invalid in HalfedgeLoopCCWIter at end"; + EXPECT_TRUE( hl_ccwit == hl_ccwend ) << "End iterator for HalfedgeLoopCCWIter not matching"; + + //constant CCW + Mesh::ConstHalfedgeLoopCCWIter chl_ccwit = mesh_.chl_ccwbegin(mesh_.halfedge_handle(3)); + Mesh::ConstHalfedgeLoopCCWIter chl_ccwend = mesh_.chl_ccwend(mesh_.halfedge_handle(3)); + i = 0; + for (;chl_ccwit != chl_ccwend; ++chl_ccwit, ++i) + { + EXPECT_EQ(indices[i], chl_ccwit->idx()) << "Index wrong in ConstHalfedgeLoopCCWIter"; + } + + EXPECT_FALSE(chl_ccwit.is_valid()) << "Iterator invalid in ConstHalfedgeLoopCCWIter at end"; + EXPECT_TRUE( chl_ccwit == chl_ccwend ) << "End iterator for ConstHalfedgeLoopCCWIter not matching"; + + //CW + Mesh::HalfedgeLoopCWIter hl_cwit = mesh_.hl_cwbegin(mesh_.halfedge_handle(3)); + Mesh::HalfedgeLoopCWIter hl_cwend = mesh_.hl_cwend(mesh_.halfedge_handle(3)); + i = 0; + for (;hl_cwit != hl_cwend; ++hl_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], hl_cwit->idx()) << "Index wrong in HalfedgeLoopCWIter"; + } + EXPECT_FALSE(hl_cwit.is_valid()) << "Iterator invalid in HalfedgeLoopCWIter at end"; + EXPECT_TRUE( hl_cwit == hl_cwend ) << "End iterator for HalfedgeLoopCWIter not matching"; + + //constant CW + Mesh::ConstHalfedgeLoopCWIter chl_cwit = mesh_.chl_cwbegin(mesh_.halfedge_handle(3)); + Mesh::ConstHalfedgeLoopCWIter chl_cwend = mesh_.chl_cwend(mesh_.halfedge_handle(3)); + i = 0; + for (;chl_cwit != chl_cwend; ++chl_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], chl_cwit->idx()) << "Index wrong in ConstHalfedgeLoopCWIter"; + } + EXPECT_FALSE(chl_cwit.is_valid()) << "Iterator invalid in ConstHalfedgeLoopCWIter at end"; + EXPECT_TRUE( chl_cwit == chl_cwend ) << "End iterator for ConstHalfedgeLoopCWIter not matching"; + + /* + * conversion properties: + * a) cw_begin == CWIter(ccw_begin()) + * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators + * c) --cw_iter == CWIter(++ccwIter) for valid iterators + * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + */ + Mesh::HalfedgeLoopCWIter hl_cwIter = mesh_.hl_cwbegin(mesh_.halfedge_handle(3)); + // a) + EXPECT_TRUE( hl_cwIter == Mesh::HalfedgeLoopCWIter(mesh_.hl_ccwbegin(mesh_.halfedge_handle(3))) ) << "ccw to cw conversion failed"; + EXPECT_TRUE( Mesh::HalfedgeLoopCCWIter(hl_cwIter) == mesh_.hl_ccwbegin(mesh_.halfedge_handle(3)) ) << "cw to ccw conversion failed"; + // b) + EXPECT_EQ( hl_cwIter->idx(), Mesh::HalfedgeLoopCCWIter(hl_cwIter)->idx()) << "iterators doesnt point on the same element"; + // c) + ++hl_cwIter; + hl_ccwend = mesh_.hl_ccwend(mesh_.halfedge_handle(3)); + --hl_ccwend; + EXPECT_EQ(hl_cwIter->idx(),hl_ccwend->idx()) << "iteratoes are not equal after inc/dec"; + // additional conversion check + hl_ccwend = Mesh::HalfedgeLoopCCWIter(hl_cwIter); + EXPECT_EQ(hl_cwIter->idx(),hl_ccwend->idx())<< "iterators doesnt point on the same element"; + // d) + hl_cwIter = Mesh::HalfedgeLoopCWIter(mesh_.hl_ccwend(mesh_.halfedge_handle(3))); + EXPECT_FALSE(hl_cwIter.is_valid()) << "end iterator is not invalid"; + EXPECT_TRUE(Mesh::HalfedgeLoopCCWIter(mesh_.hl_cwend(mesh_.halfedge_handle(3))) == mesh_.hl_ccwend(mesh_.halfedge_handle(3))) << "end iterators are not equal"; + + +} + } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc index c0e78b1e..df842ccb 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_edge.cc @@ -280,4 +280,138 @@ TEST_F(OpenMeshTrimeshCirculatorVertexEdge, VertexEdgeIterCheckInvalidationAtEnd } +/* + * Test CW and CCW iterators + */ +TEST_F(OpenMeshTrimeshCirculatorVertexEdge, CWAndCCWCheck) { + + 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 face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = 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 */ + + + int indices[5] = {5, 1, 0, 3, 5}; + int rev_indices[5]; + std::reverse_copy(indices,indices+5,rev_indices); + + //CCW + Mesh::VertexEdgeCCWIter ve_ccwit = mesh_.ve_ccwbegin(vhandle[1]); + Mesh::VertexEdgeCCWIter ve_ccwend = mesh_.ve_ccwend(vhandle[1]); + size_t i = 0; + for (;ve_ccwit != ve_ccwend; ++ve_ccwit, ++i) + { + EXPECT_EQ(indices[i], ve_ccwit->idx()) << "Index wrong in VertexEdgeCCWIter"; + } + + EXPECT_FALSE(ve_ccwit.is_valid()) << "Iterator invalid in VertexEdgeCCWIter at end"; + EXPECT_TRUE( ve_ccwit == ve_ccwend ) << "End iterator for VertexEdgeCCWIter not matching"; + + //constant CCW + Mesh::ConstVertexEdgeCCWIter cve_ccwit = mesh_.cve_ccwbegin(vhandle[1]); + Mesh::ConstVertexEdgeCCWIter cve_ccwend = mesh_.cve_ccwend(vhandle[1]); + i = 0; + for (;cve_ccwit != cve_ccwend; ++cve_ccwit, ++i) + { + EXPECT_EQ(indices[i], cve_ccwit->idx()) << "Index wrong in ConstVertexEdgeCCWIter"; + } + + EXPECT_FALSE(cve_ccwit.is_valid()) << "Iterator invalid in ConstVertexEdgeCCWIter at end"; + EXPECT_TRUE( cve_ccwit == cve_ccwend ) << "End iterator for ConstVertexEdgeCCWIter not matching"; + + //CW + Mesh::VertexEdgeCWIter ve_cwit = mesh_.ve_cwbegin(vhandle[1]); + Mesh::VertexEdgeCWIter ve_cwend = mesh_.ve_cwend(vhandle[1]); + i = 0; + for (;ve_cwit != ve_cwend; ++ve_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], ve_cwit->idx()) << "Index wrong in VertexEdgeCWIter"; + } + EXPECT_FALSE(ve_cwit.is_valid()) << "Iterator invalid in VertexEdgeCWIter at end"; + EXPECT_TRUE( ve_cwit == ve_cwend ) << "End iterator for VertexEdgeCWIter not matching"; + + //constant CW + Mesh::ConstVertexEdgeCWIter cve_cwit = mesh_.cve_cwbegin(vhandle[1]); + Mesh::ConstVertexEdgeCWIter cve_cwend = mesh_.cve_cwend(vhandle[1]); + i = 0; + for (;cve_cwit != cve_cwend; ++cve_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], cve_cwit->idx()) << "Index wrong in ConstVertexEdgeCWIter"; + } + EXPECT_FALSE(cve_cwit.is_valid()) << "Iterator invalid in ConstVertexEdgeCWIter at end"; + EXPECT_TRUE( cve_cwit == cve_cwend ) << "End iterator for ConstVertexEdgeCWIter not matching"; + + /* + * conversion properties: + * a) cw_begin == CWIter(ccw_begin()) + * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators + * c) --cw_iter == CWIter(++ccwIter) for valid iterators + * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + */ + Mesh::VertexEdgeCWIter ve_cwIter = mesh_.ve_cwbegin(vhandle[1]); + // a) + EXPECT_TRUE( ve_cwIter == Mesh::VertexEdgeCWIter(mesh_.ve_ccwbegin(vhandle[1])) ) << "ccw to cw conversion failed"; + EXPECT_TRUE( Mesh::VertexEdgeCCWIter(ve_cwIter) == mesh_.ve_ccwbegin(vhandle[1]) ) << "cw to ccw conversion failed"; + // b) + EXPECT_EQ( ve_cwIter->idx(), Mesh::VertexEdgeCCWIter(ve_cwIter)->idx()) << "iterators doesnt point on the same element"; + // c) + ++ve_cwIter; + ve_ccwend = mesh_.ve_ccwend(vhandle[1]); + --ve_ccwend; + 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) + ve_cwIter = Mesh::VertexEdgeCWIter(mesh_.ve_ccwend(vhandle[1])); + EXPECT_FALSE(ve_cwIter.is_valid()) << "end iterator is not invalid"; + EXPECT_TRUE(Mesh::VertexEdgeCCWIter(mesh_.ve_cwend(vhandle[1])) == mesh_.ve_ccwend(vhandle[1])) << "end iterators are not equal"; + + +} + } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_face.cc b/src/Unittests/unittests_trimesh_circulator_vertex_face.cc index d6e1659d..55f09fd4 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_face.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_face.cc @@ -451,4 +451,139 @@ TEST_F(OpenMeshTrimeshCirculatorVertexFace, VertexFaceIterWithoutHolesDecrement) } +/* + * Test CW and CCW iterators + */ +TEST_F(OpenMeshTrimeshCirculatorVertexFace, CWAndCCWCheck) { + + 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 face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = 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 */ + + + int indices[5] = {3, 0, 2, 1, 3}; + int rev_indices[5]; + std::reverse_copy(indices,indices+5,rev_indices); + + //CCW + Mesh::VertexFaceCCWIter vf_ccwit = mesh_.vf_ccwbegin(vhandle[1]); + Mesh::VertexFaceCCWIter vf_ccwend = mesh_.vf_ccwend(vhandle[1]); + size_t i = 0; + for (;vf_ccwit != vf_ccwend; ++vf_ccwit, ++i) + { + EXPECT_EQ(indices[i], vf_ccwit->idx()) << "Index wrong in VertexFaceCCWIter"; + } + + EXPECT_FALSE(vf_ccwit.is_valid()) << "Iterator invalid in VertexFaceCCWIter at end"; + EXPECT_TRUE( vf_ccwit == vf_ccwend ) << "End iterator for VertexFaceCCWIter not matching"; + + //constant CCW + Mesh::ConstVertexFaceCCWIter cvf_ccwit = mesh_.cvf_ccwbegin(vhandle[1]); + Mesh::ConstVertexFaceCCWIter cvf_ccwend = mesh_.cvf_ccwend(vhandle[1]); + i = 0; + for (;cvf_ccwit != cvf_ccwend; ++cvf_ccwit, ++i) + { + EXPECT_EQ(indices[i], cvf_ccwit->idx()) << "Index wrong in ConstVertexFaceCCWIter"; + } + + EXPECT_FALSE(cvf_ccwit.is_valid()) << "Iterator invalid in ConstVertexFaceCCWIter at end"; + EXPECT_TRUE( cvf_ccwit == cvf_ccwend ) << "End iterator for ConstVertexFaceCCWIter not matching"; + + //CW + Mesh::VertexFaceCWIter vf_cwit = mesh_.vf_cwbegin(vhandle[1]); + Mesh::VertexFaceCWIter vf_cwend = mesh_.vf_cwend(vhandle[1]); + i = 0; + for (;vf_cwit != vf_cwend; ++vf_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], vf_cwit->idx()) << "Index wrong in VertexFaceCWIter"; + } + EXPECT_FALSE(vf_cwit.is_valid()) << "Iterator invalid in VertexFaceCWIter at end"; + EXPECT_TRUE( vf_cwit == vf_cwend ) << "End iterator for VertexFaceCWIter not matching"; + + //constant CW + Mesh::ConstVertexFaceCWIter cvf_cwit = mesh_.cvf_cwbegin(vhandle[1]); + Mesh::ConstVertexFaceCWIter cvf_cwend = mesh_.cvf_cwend(vhandle[1]); + i = 0; + for (;cvf_cwit != cvf_cwend; ++cvf_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], cvf_cwit->idx()) << "Index wrong in ConstVertexFaceCWIter"; + } + EXPECT_FALSE(cvf_cwit.is_valid()) << "Iterator invalid in ConstVertexFaceCWIter at end"; + EXPECT_TRUE( cvf_cwit == cvf_cwend ) << "End iterator for ConstVertexFaceCWIter not matching"; + + /* + * conversion properties: + * a) cw_begin == CWIter(ccw_begin()) + * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators + * c) --cw_iter == CWIter(++ccwIter) for valid iterators + * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + */ + Mesh::VertexFaceCWIter vf_cwIter = mesh_.vf_cwbegin(vhandle[1]); + // a) + EXPECT_TRUE( vf_cwIter == Mesh::VertexFaceCWIter(mesh_.vf_ccwbegin(vhandle[1])) ) << "ccw to cw conversion failed"; + EXPECT_TRUE( Mesh::VertexFaceCCWIter(vf_cwIter) == mesh_.vf_ccwbegin(vhandle[1]) ) << "cw to ccw conversion failed"; + // b) + EXPECT_EQ( vf_cwIter->idx(), Mesh::VertexFaceCCWIter(vf_cwIter)->idx()) << "iterators doesnt point on the same element"; + // c) + ++vf_cwIter; + vf_ccwend = mesh_.vf_ccwend(vhandle[1]); + --vf_ccwend; + 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) + vf_cwIter = Mesh::VertexFaceCWIter(mesh_.vf_ccwend(vhandle[1])); + EXPECT_FALSE(vf_cwIter.is_valid()) << "end iterator is not invalid"; + EXPECT_TRUE(Mesh::VertexFaceCCWIter(mesh_.vf_cwend(vhandle[1])) == mesh_.vf_ccwend(vhandle[1])) << "end iterators are not equal"; + + +} + + } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc index 51d7c55a..4513c219 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_ihalfedge.cc @@ -394,5 +394,139 @@ TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, VertexIHalfEdgeIterCheckInvalid } +/* + * Test CW and CCW iterators + */ +TEST_F(OpenMeshTrimeshCirculatorVertexIHalfEdge, CWAndCCWCheck) { + + 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 face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = 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 */ + + + int indices[4] = {14, 5, 2, 14}; + int rev_indices[4]; + std::reverse_copy(indices,indices+4,rev_indices); + + //CCW + Mesh::VertexIHalfedgeCCWIter vih_ccwit = mesh_.vih_ccwbegin(vhandle[2]); + Mesh::VertexIHalfedgeCCWIter vih_ccwend = mesh_.vih_ccwend(vhandle[2]); + size_t i = 0; + for (;vih_ccwit != vih_ccwend; ++vih_ccwit, ++i) + { + EXPECT_EQ(indices[i], vih_ccwit->idx()) << "Index wrong in VertexIHalfedgeCCWIter"; + } + + EXPECT_FALSE(vih_ccwit.is_valid()) << "Iterator invalid in VertexIHalfedgeCCWIter at end"; + EXPECT_TRUE( vih_ccwit == vih_ccwend ) << "End iterator for VertexIHalfedgeCCWIter not matching"; + + //constant CCW + Mesh::ConstVertexIHalfedgeCCWIter cvih_ccwit = mesh_.cvih_ccwbegin(vhandle[2]); + Mesh::ConstVertexIHalfedgeCCWIter cvih_ccwend = mesh_.cvih_ccwend(vhandle[2]); + i = 0; + for (;cvih_ccwit != cvih_ccwend; ++cvih_ccwit, ++i) + { + EXPECT_EQ(indices[i], cvih_ccwit->idx()) << "Index wrong in ConstVertexIHalfedgeCCWIter"; + } + + EXPECT_FALSE(cvih_ccwit.is_valid()) << "Iterator invalid in ConstVertexIHalfedgeCCWIter at end"; + EXPECT_TRUE( cvih_ccwit == cvih_ccwend ) << "End iterator for ConstVertexIHalfedgeCCWIter not matching"; + + //CW + Mesh::VertexIHalfedgeCWIter vih_cwit = mesh_.vih_cwbegin(vhandle[2]); + Mesh::VertexIHalfedgeCWIter vih_cwend = mesh_.vih_cwend(vhandle[2]); + i = 0; + for (;vih_cwit != vih_cwend; ++vih_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], vih_cwit->idx()) << "Index wrong in VertexIHalfedgeCWIter"; + } + EXPECT_FALSE(vih_cwit.is_valid()) << "Iterator invalid in VertexIHalfedgeCWIter at end"; + EXPECT_TRUE( vih_cwit == vih_cwend ) << "End iterator for VertexIHalfedgeCWIter not matching"; + + //constant CW + Mesh::ConstVertexIHalfedgeCWIter cvih_cwit = mesh_.cvih_cwbegin(vhandle[2]); + Mesh::ConstVertexIHalfedgeCWIter cvih_cwend = mesh_.cvih_cwend(vhandle[2]); + i = 0; + for (;cvih_cwit != cvih_cwend; ++cvih_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], cvih_cwit->idx()) << "Index wrong in ConstVertexIHalfedgeCWIter"; + } + EXPECT_FALSE(cvih_cwit.is_valid()) << "Iterator invalid in ConstVertexIHalfedgeCWIter at end"; + EXPECT_TRUE( cvih_cwit == cvih_cwend ) << "End iterator for ConstVertexIHalfedgeCWIter not matching"; + + /* + * conversion properties: + * a) cw_begin == CWIter(ccw_begin()) + * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators + * c) --cw_iter == CWIter(++ccwIter) for valid iterators + * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + */ + Mesh::VertexIHalfedgeCWIter vih_cwIter = mesh_.vih_cwbegin(vhandle[2]); + // a) + EXPECT_TRUE( vih_cwIter == Mesh::VertexIHalfedgeCWIter(mesh_.vih_ccwbegin(vhandle[2])) ) << "ccw to cw conversion failed"; + EXPECT_TRUE( Mesh::VertexIHalfedgeCCWIter(vih_cwIter) == mesh_.vih_ccwbegin(vhandle[2]) ) << "cw to ccw conversion failed"; + // b) + EXPECT_EQ( vih_cwIter->idx(), Mesh::VertexIHalfedgeCCWIter(vih_cwIter)->idx()) << "iterators doesnt point on the same element"; + // c) + ++vih_cwIter; + vih_ccwend = mesh_.vih_ccwend(vhandle[2]); + --vih_ccwend; + 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) + vih_cwIter = Mesh::VertexIHalfedgeCWIter(mesh_.vih_ccwend(vhandle[2])); + EXPECT_FALSE(vih_cwIter.is_valid()) << "end iterator is not invalid"; + EXPECT_TRUE(Mesh::VertexIHalfedgeCCWIter(mesh_.vih_cwend(vhandle[2])) == mesh_.vih_ccwend(vhandle[2])) << "end iterators are not equal"; + + +} + } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc b/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc index fa101b53..9fe39cd9 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_ohalfedge.cc @@ -394,6 +394,141 @@ TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, VertexOHalfEdgeIterCheckInvalid } +/* + * Test CW and CCW iterators + */ +TEST_F(OpenMeshTrimeshCirculatorVertexOHalfEdge, CWAndCCWCheck) { + + 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 face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = 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 */ + + + int indices[5] = {11, 2, 1, 6, 11}; + int rev_indices[5]; + std::reverse_copy(indices,indices+5,rev_indices); + + //CCW + Mesh::VertexOHalfedgeCCWIter voh_ccwit = mesh_.voh_ccwbegin(vhandle[1]); + Mesh::VertexOHalfedgeCCWIter voh_ccwend = mesh_.voh_ccwend(vhandle[1]); + size_t i = 0; + for (;voh_ccwit != voh_ccwend; ++voh_ccwit, ++i) + { + EXPECT_EQ(indices[i], voh_ccwit->idx()) << "Index wrong in VertexOHalfedgeCCWIter"; + } + + EXPECT_FALSE(voh_ccwit.is_valid()) << "Iterator invalid in VertexOHalfedgeCCWIter at end"; + EXPECT_TRUE( voh_ccwit == voh_ccwend ) << "End iterator for VertexOHalfedgeCCWIter not matching"; + + //constant CCW + Mesh::ConstVertexOHalfedgeCCWIter cvoh_ccwit = mesh_.cvoh_ccwbegin(vhandle[1]); + Mesh::ConstVertexOHalfedgeCCWIter cvoh_ccwend = mesh_.cvoh_ccwend(vhandle[1]); + i = 0; + for (;cvoh_ccwit != cvoh_ccwend; ++cvoh_ccwit, ++i) + { + EXPECT_EQ(indices[i], cvoh_ccwit->idx()) << "Index wrong in ConstVertexOHalfedgeCCWIter"; + } + + EXPECT_FALSE(cvoh_ccwit.is_valid()) << "Iterator invalid in ConstVertexOHalfedgeCCWIter at end"; + EXPECT_TRUE( cvoh_ccwit == cvoh_ccwend ) << "End iterator for ConstVertexOHalfedgeCCWIter not matching"; + + //CW + Mesh::VertexOHalfedgeCWIter voh_cwit = mesh_.voh_cwbegin(vhandle[1]); + Mesh::VertexOHalfedgeCWIter voh_cwend = mesh_.voh_cwend(vhandle[1]); + i = 0; + for (;voh_cwit != voh_cwend; ++voh_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], voh_cwit->idx()) << "Index wrong in VertexOHalfedgeCWIter"; + } + EXPECT_FALSE(voh_cwit.is_valid()) << "Iterator invalid in VertexOHalfedgeCWIter at end"; + EXPECT_TRUE( voh_cwit == voh_cwend ) << "End iterator for VertexOHalfedgeCWIter not matching"; + + //constant CW + Mesh::ConstVertexOHalfedgeCWIter cvoh_cwit = mesh_.cvoh_cwbegin(vhandle[1]); + Mesh::ConstVertexOHalfedgeCWIter cvoh_cwend = mesh_.cvoh_cwend(vhandle[1]); + i = 0; + for (;cvoh_cwit != cvoh_cwend; ++cvoh_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], cvoh_cwit->idx()) << "Index wrong in ConstVertexOHalfedgeCWIter"; + } + EXPECT_FALSE(cvoh_cwit.is_valid()) << "Iterator invalid in ConstVertexOHalfedgeCWIter at end"; + EXPECT_TRUE( cvoh_cwit == cvoh_cwend ) << "End iterator for ConstVertexOHalfedgeCWIter not matching"; + + /* + * conversion properties: + * a) cw_begin == CWIter(ccw_begin()) + * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators + * c) --cw_iter == CWIter(++ccwIter) for valid iterators + * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + */ + Mesh::VertexOHalfedgeCWIter voh_cwIter = mesh_.voh_cwbegin(vhandle[1]); + // a) + EXPECT_TRUE( voh_cwIter == Mesh::VertexOHalfedgeCWIter(mesh_.voh_ccwbegin(vhandle[1])) ) << "ccw to cw conversion failed"; + EXPECT_TRUE( Mesh::VertexOHalfedgeCCWIter(voh_cwIter) == mesh_.voh_ccwbegin(vhandle[1]) ) << "cw to ccw conversion failed"; + // b) + EXPECT_EQ( voh_cwIter->idx(), Mesh::VertexOHalfedgeCCWIter(voh_cwIter)->idx()) << "iterators doesnt point on the same element"; + // c) + ++voh_cwIter; + voh_ccwend = mesh_.voh_ccwend(vhandle[1]); + --voh_ccwend; + 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) + voh_cwIter = Mesh::VertexOHalfedgeCWIter(mesh_.voh_ccwend(vhandle[1])); + EXPECT_FALSE(voh_cwIter.is_valid()) << "end iterator is not invalid"; + EXPECT_TRUE(Mesh::VertexOHalfedgeCCWIter(mesh_.voh_cwend(vhandle[1])) == mesh_.voh_ccwend(vhandle[1])) << "end iterators are not equal"; + + +} + + } diff --git a/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc b/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc index b6b301d8..7e46e696 100644 --- a/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc +++ b/src/Unittests/unittests_trimesh_circulator_vertex_vertex.cc @@ -283,6 +283,140 @@ TEST_F(OpenMeshTrimeshCirculatorVertexVertex, VertexVertexIterCheckInvalidationA } +/* + * Test CW and CCW iterators + */ +TEST_F(OpenMeshTrimeshCirculatorVertexVertex, CWAndCCWCheck) { + + 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 face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + Mesh::FaceHandle fh0 = 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 */ + + + int indices[5] = {4, 2, 0, 3, 4}; + int rev_indices[5]; + std::reverse_copy(indices,indices+5,rev_indices); + + //CCW + Mesh::VertexVertexCCWIter vv_ccwit = mesh_.vv_ccwbegin(vhandle[1]); + Mesh::VertexVertexCCWIter vv_ccwend = mesh_.vv_ccwend(vhandle[1]); + size_t i = 0; + for (;vv_ccwit != vv_ccwend; ++vv_ccwit, ++i) + { + EXPECT_EQ(indices[i], vv_ccwit->idx()) << "Index wrong in VertexVertexCCWIter"; + } + + EXPECT_FALSE(vv_ccwit.is_valid()) << "Iterator invalid in VertexVertexCCWIter at end"; + EXPECT_TRUE( vv_ccwit == vv_ccwend ) << "End iterator for VertexVertexCCWIter not matching"; + + //constant CCW + Mesh::ConstVertexVertexCCWIter cvv_ccwit = mesh_.cvv_ccwbegin(vhandle[1]); + Mesh::ConstVertexVertexCCWIter cvv_ccwend = mesh_.cvv_ccwend(vhandle[1]); + i = 0; + for (;cvv_ccwit != cvv_ccwend; ++cvv_ccwit, ++i) + { + EXPECT_EQ(indices[i], cvv_ccwit->idx()) << "Index wrong in ConstVertexVertexCCWIter"; + } + + EXPECT_FALSE(cvv_ccwit.is_valid()) << "Iterator invalid in ConstVertexVertexCCWIter at end"; + EXPECT_TRUE( cvv_ccwit == cvv_ccwend ) << "End iterator for ConstVertexVertexCCWIter not matching"; + + //CW + Mesh::VertexVertexCWIter vv_cwit = mesh_.vv_cwbegin(vhandle[1]); + Mesh::VertexVertexCWIter vv_cwend = mesh_.vv_cwend(vhandle[1]); + i = 0; + for (;vv_cwit != vv_cwend; ++vv_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], vv_cwit->idx()) << "Index wrong in VertexVertexCWIter"; + } + EXPECT_FALSE(vv_cwit.is_valid()) << "Iterator invalid in VertexVertexCWIter at end"; + EXPECT_TRUE( vv_cwit == vv_cwend ) << "End iterator for VertexVertexCWIter not matching"; + + //constant CW + Mesh::ConstVertexVertexCWIter cvv_cwit = mesh_.cvv_cwbegin(vhandle[1]); + Mesh::ConstVertexVertexCWIter cvv_cwend = mesh_.cvv_cwend(vhandle[1]); + i = 0; + for (;cvv_cwit != cvv_cwend; ++cvv_cwit, ++i) + { + EXPECT_EQ(rev_indices[i], cvv_cwit->idx()) << "Index wrong in ConstVertexVertexCWIter"; + } + EXPECT_FALSE(cvv_cwit.is_valid()) << "Iterator invalid in ConstVertexVertexCWIter at end"; + EXPECT_TRUE( cvv_cwit == cvv_cwend ) << "End iterator for ConstVertexVertexCWIter not matching"; + + /* + * conversion properties: + * a) cw_begin == CWIter(ccw_begin()) + * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators + * c) --cw_iter == CWIter(++ccwIter) for valid iterators + * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) * + */ + Mesh::VertexVertexCWIter vv_cwIter = mesh_.vv_cwbegin(vhandle[1]); + // a) + EXPECT_TRUE( vv_cwIter == Mesh::VertexVertexCWIter(mesh_.vv_ccwbegin(vhandle[1])) ) << "ccw to cw convvrsion failed"; + EXPECT_TRUE( Mesh::VertexVertexCCWIter(vv_cwIter) == mesh_.vv_ccwbegin(vhandle[1]) ) << "cw to ccw convvrsion failed"; + // b) + EXPECT_EQ( vv_cwIter->idx(), Mesh::VertexVertexCCWIter(vv_cwIter)->idx()) << "iterators doesnt point on the same element"; + // c) + ++vv_cwIter; + vv_ccwend = mesh_.vv_ccwend(vhandle[1]); + --vv_ccwend; + 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) + vv_cwIter = Mesh::VertexVertexCWIter(mesh_.vv_ccwend(vhandle[1])); + EXPECT_FALSE(vv_cwIter.is_valid()) << "end iterator is not invalid"; + EXPECT_TRUE(Mesh::VertexVertexCCWIter(mesh_.vv_cwend(vhandle[1])) == mesh_.vv_ccwend(vhandle[1])) << "end iterators are not equal"; + + +} + }