Measurement: prevent ending up in an infinite loop with broken models
This commit is contained in:
parent
d4ad4aff01
commit
b27653493a
@ -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)
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user