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 size_t n_halfedges = 2*mesh_.n_edges();
151 for (
const auto hh: mesh_.halfedges())
153 if (!hh.to().halfedge().is_valid()) {
154 _os <<
"MeshChecker: vertex " << hh.from()
155 <<
" has no outgoing halfedge, but it is not isolated.\n";
159 if (mesh_.from_vertex_handle(hh) == mesh_.to_vertex_handle(hh))
161 _os <<
"MeshChecker: halfedge " << hh
162 <<
": to-vertex == from-vertex\n";
168 if (mesh_.next_halfedge_handle(mesh_.prev_halfedge_handle(hh)) != hh)
170 _os <<
"MeshChecker: halfedge " << hh
171 <<
": prev->next != this\n";
176 if (mesh_.to_vertex_handle(hh) != mesh_.from_vertex_handle(
177 mesh_.next_halfedge_handle(hh)))
179 _os <<
"MeshChecker: halfedge " << hh
180 <<
".to != he.next.from\n";
184 if (mesh_.from_vertex_handle(hh) != mesh_.to_vertex_handle(
185 mesh_.prev_halfedge_handle(hh)))
187 _os <<
"MeshChecker: halfedge " << hh
188 <<
".from != he.prev.to\n";
194 size_t count=0; hstart=hhh=hh;
197 hhh = mesh_.next_halfedge_handle(hhh);
199 }
while (hhh != hstart && count < n_halfedges);
201 if (count == n_halfedges)
203 _os <<
"MeshChecker: halfedges starting from " << hh
204 <<
" do not form a cycle\n";
214 if (_targets & CHECK_FACES)
218 for(
const auto fh: mesh_.faces()) {
219 for(
const auto heh: fh.halfedges()) {
220 if (heh.face() != fh) {
221 _os <<
"MeshChecker: face " << fh
222 <<
": 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::ConstFaceHalfedgeIter ConstFaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:178
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