45#define OPENMESH_MESHCHECKER_C
51#include <OpenMesh/Tools/Utils/MeshCheckerT.hh>
66check(
unsigned int _targets, std::ostream& _os)
74 if (_targets & CHECK_VERTICES)
77 const unsigned int max_valence(10000);
80 for (
const auto vh: mesh_.vertices())
83 auto heh = vh.halfedge();
84 if (heh.is_valid() && !mesh_.is_boundary(heh))
87 vh_it.is_valid(); ++vh_it)
89 if (mesh_.is_boundary(*vh_it))
91 _os <<
"MeshChecker: vertex " << vh
92 <<
": outgoing halfedge not on boundary error\n";
98 if (heh.idx() < -1 || heh.idx() >= (
int)mesh_.n_halfedges()) {
99 _os <<
"MeshChecker: vertex " << vh
100 <<
" has out-of-bounds outgoing HE: " << heh;
103 if (is_deleted(heh.edge())) {
104 _os <<
"MeshChecker: vertex " << vh
105 <<
" has deleted outgoing HE: " << heh;
113 if (mesh_.halfedge_handle(vh).is_valid() &&
114 mesh_.from_vertex_handle(mesh_.halfedge_handle(vh)) != vh)
116 _os <<
"MeshChecker: vertex " << vh
117 <<
": outgoing halfedge does not reference vertex\n";
123 auto vv_it = mesh_.cvv_cwiter(vh);
124 for (count=0; vv_it.is_valid() && (count < max_valence); ++vv_it, ++count) {};
125 if (count == max_valence)
127 _os <<
"MeshChecker: vertex " << vh
128 <<
": ++circulator problem, one ring corrupt\n";
131 vv_it = mesh_.cvv_cwiter(vh);
132 for (count=0; vv_it.is_valid() && (count < max_valence); --vv_it, ++count) {};
133 if (count == max_valence)
135 _os <<
"MeshChecker: vertex " << vh
136 <<
": --circulator problem, one ring corrupt\n";
146 if (_targets & CHECK_EDGES)
149 h_end(mesh_.halfedges_end());
151 size_t n_halfedges = 2*mesh_.n_edges();
153 for (
const auto hh: mesh_.halfedges())
155 if (!hh.to().halfedge().is_valid()) {
156 _os <<
"MeshChecker: vertex " << hh.from()
157 <<
" has no outgoing halfedge, but it is not isolated.\n";
161 if (mesh_.from_vertex_handle(hh) == mesh_.to_vertex_handle(hh))
163 _os <<
"MeshChecker: halfedge " << hh
164 <<
": to-vertex == from-vertex\n";
170 if (mesh_.next_halfedge_handle(mesh_.prev_halfedge_handle(hh)) != hh)
172 _os <<
"MeshChecker: halfedge " << hh
173 <<
": prev->next != this\n";
178 if (mesh_.to_vertex_handle(hh) != mesh_.from_vertex_handle(
179 mesh_.next_halfedge_handle(hh)))
181 _os <<
"MeshChecker: halfedge " << hh
182 <<
".to != he.next.from\n";
186 if (mesh_.from_vertex_handle(hh) != mesh_.to_vertex_handle(
187 mesh_.prev_halfedge_handle(hh)))
189 _os <<
"MeshChecker: halfedge " << hh
190 <<
".from != he.prev.to\n";
196 size_t count=0; hstart=hhh=hh;
199 hhh = mesh_.next_halfedge_handle(hhh);
201 }
while (hhh != hstart && count < n_halfedges);
203 if (count == n_halfedges)
205 _os <<
"MeshChecker: halfedges starting from " << hh
206 <<
" do not form a cycle\n";
216 if (_targets & CHECK_FACES)
219 f_end(mesh_.faces_end());
222 for(
const auto fh: mesh_.faces()) {
223 for(
const auto heh: fh.halfedges()) {
224 if (heh.face() != fh) {
225 _os <<
"MeshChecker: face " << fh
226 <<
": its halfedge " << heh <<
" references a different face: "
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
Kernel::ConstFaceIter ConstFaceIter
Scalar type.
Definition: PolyMeshT.hh:151
Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:178
Kernel::ConstHalfedgeIter ConstHalfedgeIter
Scalar type.
Definition: PolyMeshT.hh:149
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Definition: PolyMeshT.hh:137
Kernel::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:173
bool check(unsigned int _targets=CHECK_ALL, std::ostream &_os=omerr())
check it, return true iff ok
Definition: MeshCheckerT_impl.hh:66