Merge branch 'feature/extend-meshchecker' into 'master'

Extend MeshChecker to detect more invalid configurations.

See merge request OpenMesh/OpenMesh!334
This commit is contained in:
Jan Möbius
2023-07-22 17:38:41 +00:00

View File

@@ -73,23 +73,14 @@ check(unsigned int _targets, std::ostream& _os)
if (_targets & CHECK_VERTICES) if (_targets & CHECK_VERTICES)
{ {
typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()), v_end(mesh_.vertices_end());
typename Mesh::VertexHandle vh;
typename Mesh::ConstVertexVertexCWIter vv_it;
typename Mesh::HalfedgeHandle heh;
unsigned int count; unsigned int count;
const unsigned int max_valence(10000); const unsigned int max_valence(10000);
for (; v_it != v_end; ++v_it) for (const auto vh: mesh_.vertices())
{ {
if (!is_deleted(*v_it))
{
vh = *v_it;
/* The outgoing halfedge of a boundary vertex has to be a boundary halfedge */ /* The outgoing halfedge of a boundary vertex has to be a boundary halfedge */
heh = mesh_.halfedge_handle(vh); auto heh = vh.halfedge();
if (heh.is_valid() && !mesh_.is_boundary(heh)) if (heh.is_valid() && !mesh_.is_boundary(heh))
{ {
for (typename Mesh::ConstVertexOHalfedgeIter vh_it(mesh_, vh); for (typename Mesh::ConstVertexOHalfedgeIter vh_it(mesh_, vh);
@@ -103,6 +94,18 @@ check(unsigned int _targets, std::ostream& _os)
} }
} }
} }
if (heh.is_valid()) {
if (heh.idx() < -1 || heh.idx() >= mesh_.n_halfedges()) {
_os << "MeshChecker: vertex " << vh
<< " has out-of-bounds outgoing HE: " << heh;
ok = false;
}
if (is_deleted(heh.edge())) {
_os << "MeshChecker: vertex " << vh
<< " has deleted outgoing HE: " << heh;
ok = false;
}
}
@@ -117,7 +120,7 @@ check(unsigned int _targets, std::ostream& _os)
// check whether circulators are still in order // check whether circulators are still in order
vv_it = mesh_.cvv_cwiter(vh); auto vv_it = mesh_.cvv_cwiter(vh);
for (count=0; vv_it.is_valid() && (count < max_valence); ++vv_it, ++count) {}; for (count=0; vv_it.is_valid() && (count < max_valence); ++vv_it, ++count) {};
if (count == max_valence) if (count == max_valence)
{ {
@@ -135,7 +138,6 @@ check(unsigned int _targets, std::ostream& _os)
} }
} }
} }
}
@@ -148,13 +150,13 @@ check(unsigned int _targets, std::ostream& _os)
typename Mesh::HalfedgeHandle hh, hstart, hhh; typename Mesh::HalfedgeHandle hh, hstart, hhh;
size_t count, n_halfedges = 2*mesh_.n_edges(); size_t count, n_halfedges = 2*mesh_.n_edges();
for (; h_it != h_end; ++h_it) for (const auto hh: mesh_.halfedges())
{ {
if (!is_deleted(mesh_.edge_handle(*h_it))) if (!hh.to().halfedge().is_valid()) {
{ _os << "MeshChecker: vertex " << hh.from()
hh = *h_it; << " has no outgoing halfedge, but it is not isolated.\n";
ok = false;
}
// degenerated halfedge ? // degenerated halfedge ?
if (mesh_.from_vertex_handle(hh) == mesh_.to_vertex_handle(hh)) if (mesh_.from_vertex_handle(hh) == mesh_.to_vertex_handle(hh))
{ {
@@ -172,6 +174,23 @@ check(unsigned int _targets, std::ostream& _os)
ok = false; ok = false;
} }
// heh.to == heh.next.from?
if (mesh_.to_vertex_handle(hh) != mesh_.from_vertex_handle(
mesh_.next_halfedge_handle(hh)))
{
_os << "MeshChecker: halfedge " << hh
<< ".to != he.next.from\n";
ok = false;
}
// heh.from == heh.prev.to?
if (mesh_.from_vertex_handle(hh) != mesh_.to_vertex_handle(
mesh_.prev_halfedge_handle(hh)))
{
_os << "MeshChecker: halfedge " << hh
<< ".from != he.prev.to\n";
ok = false;
}
// halfedges should form a cycle // halfedges should form a cycle
count=0; hstart=hhh=hh; count=0; hstart=hhh=hh;
@@ -189,7 +208,6 @@ check(unsigned int _targets, std::ostream& _os)
} }
} }
} }
}
@@ -202,24 +220,18 @@ check(unsigned int _targets, std::ostream& _os)
typename Mesh::FaceHandle fh; typename Mesh::FaceHandle fh;
typename Mesh::ConstFaceHalfedgeIter fh_it; typename Mesh::ConstFaceHalfedgeIter fh_it;
for (; f_it != f_end; ++f_it) for(const auto fh: mesh_.faces()) {
{ for(const auto heh: fh.halfedges()) {
if (!is_deleted(*f_it)) if (heh.face() != fh) {
{
fh = *f_it;
for (fh_it=mesh_.cfh_iter(fh); fh_it.is_valid(); ++fh_it)
{
if (mesh_.face_handle(*fh_it) != fh)
{
_os << "MeshChecker: face " << fh _os << "MeshChecker: face " << fh
<< ": its halfedge does not reference face\n"; << ": its halfedge " << heh << " references a different face: "
<< heh.face()
<< ".\n";
ok = false; ok = false;
} }
} }
} }
} }
}