Measurement: prevent ending up in an infinite loop with broken models

This commit is contained in:
Lukas Matena 2022-11-25 13:45:23 +01:00 committed by enricoturri1966
parent d4ad4aff01
commit b27653493a
2 changed files with 23 additions and 2 deletions

View File

@ -189,9 +189,15 @@ void MeasuringImpl::update_planes()
he = sm.next_around_target(he); he = sm.next_around_target(he);
if (he.is_invalid()) if (he.is_invalid())
goto PLANE_FAILURE; goto PLANE_FAILURE;
// For broken meshes, the iteration might never get back to he_orig.
// Remember all halfedges we saw to break out of such infinite loops.
boost::container::small_vector<Halfedge_index, 10> he_seen;
while ( (int)m_face_to_plane[sm.face(he)] == plane_id && he != he_orig) { while ( (int)m_face_to_plane[sm.face(he)] == plane_id && he != he_orig) {
he_seen.emplace_back(he);
he = sm.next_around_target(he); he = sm.next_around_target(he);
if (he.is_invalid()) if (he.is_invalid() || std::find(he_seen.begin(), he_seen.end(), he) != he_seen.end())
goto PLANE_FAILURE; goto PLANE_FAILURE;
} }
he = sm.opposite(he); he = sm.opposite(he);
@ -210,6 +216,12 @@ void MeasuringImpl::update_planes()
visited[face_it - facets.begin()][he.side()] = true; visited[face_it - facets.begin()][he.side()] = true;
last_border.emplace_back(sm.point(sm.source(he)).cast<double>()); last_border.emplace_back(sm.point(sm.source(he)).cast<double>());
// In case of broken meshes, this loop might be infinite. Break
// out in case it is clearly going bad.
if (last_border.size() > 3*facets.size())
goto PLANE_FAILURE;
} while (he != he_start); } while (he != he_start);
if (last_border.size() == 1) if (last_border.size() == 1)

View File

@ -4,6 +4,8 @@
#include <admesh/stl.h> #include <admesh/stl.h>
#include <libslic3r/TriangleMesh.hpp> #include <libslic3r/TriangleMesh.hpp>
#include "boost/container/small_vector.hpp"
namespace Slic3r { namespace Slic3r {
class TriangleMesh; class TriangleMesh;
@ -115,11 +117,18 @@ public:
size_t degree(Vertex_index v) const size_t degree(Vertex_index v) const
{ {
// In case the mesh is broken badly, the loop might end up to be infinite,
// never getting back to the first halfedge. Remember list of all half-edges
// and trip if any is encountered for the second time.
Halfedge_index h_first = halfedge(v); Halfedge_index h_first = halfedge(v);
boost::container::small_vector<Halfedge_index, 10> he_visited;
Halfedge_index h = next_around_target(h_first); Halfedge_index h = next_around_target(h_first);
size_t degree = 2; size_t degree = 2;
while (! h.is_invalid() && h != h_first) { while (! h.is_invalid() && h != h_first) {
he_visited.emplace_back(h);
h = next_around_target(h); h = next_around_target(h);
if (std::find(he_visited.begin(), he_visited.end(), h) == he_visited.end())
return 0;
++degree; ++degree;
} }
return h.is_invalid() ? 0 : degree - 1; return h.is_invalid() ? 0 : degree - 1;