Fixed a crash in measuring backend when handling broken models
This commit is contained in:
parent
a59f8aea6e
commit
dda0b50b5c
@ -87,6 +87,10 @@ void MeasuringImpl::update_planes()
|
|||||||
return (std::abs(a(0) - b(0)) < 0.001 && std::abs(a(1) - b(1)) < 0.001 && std::abs(a(2) - b(2)) < 0.001);
|
return (std::abs(a(0) - b(0)) < 0.001 && std::abs(a(1) - b(1)) < 0.001 && std::abs(a(2) - b(2)) < 0.001);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// First go through all the triangles and fill in m_planes vector. For each "plane"
|
||||||
|
// detected on the model, it will contain list of facets that are part of it.
|
||||||
|
// We will also fill in m_face_to_plane, which contains index into m_planes
|
||||||
|
// for each of the source facets.
|
||||||
while (1) {
|
while (1) {
|
||||||
// Find next unvisited triangle:
|
// Find next unvisited triangle:
|
||||||
for (; seed_facet_idx < num_of_facets; ++ seed_facet_idx)
|
for (; seed_facet_idx < num_of_facets; ++ seed_facet_idx)
|
||||||
@ -117,20 +121,29 @@ void MeasuringImpl::update_planes()
|
|||||||
m_planes.back().normal = normal_ptr->cast<double>();
|
m_planes.back().normal = normal_ptr->cast<double>();
|
||||||
std::sort(m_planes.back().facets.begin(), m_planes.back().facets.end());
|
std::sort(m_planes.back().facets.begin(), m_planes.back().facets.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that each facet is part of one of the planes.
|
||||||
assert(std::none_of(m_face_to_plane.begin(), m_face_to_plane.end(), [](size_t val) { return val == size_t(-1); }));
|
assert(std::none_of(m_face_to_plane.begin(), m_face_to_plane.end(), [](size_t val) { return val == size_t(-1); }));
|
||||||
|
|
||||||
|
// Now we will walk around each of the planes and save vertices which form the border.
|
||||||
SurfaceMesh sm(m_its);
|
SurfaceMesh sm(m_its);
|
||||||
for (int plane_id=0; plane_id < int(m_planes.size()); ++plane_id) {
|
for (int plane_id=0; plane_id < int(m_planes.size()); ++plane_id) {
|
||||||
//int plane_id = 5; {
|
|
||||||
const auto& facets = m_planes[plane_id].facets;
|
const auto& facets = m_planes[plane_id].facets;
|
||||||
m_planes[plane_id].borders.clear();
|
m_planes[plane_id].borders.clear();
|
||||||
std::vector<std::array<bool, 3>> visited(facets.size(), {false, false, false});
|
std::vector<std::array<bool, 3>> visited(facets.size(), {false, false, false});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (int face_id=0; face_id<int(facets.size()); ++face_id) {
|
for (int face_id=0; face_id<int(facets.size()); ++face_id) {
|
||||||
assert(m_face_to_plane[facets[face_id]] == plane_id);
|
assert(m_face_to_plane[facets[face_id]] == plane_id);
|
||||||
|
|
||||||
for (int edge_id=0; edge_id<3; ++edge_id) {
|
for (int edge_id=0; edge_id<3; ++edge_id) {
|
||||||
if (visited[face_id][edge_id] || (int)m_face_to_plane[face_neighbors[facets[face_id]][edge_id]] == plane_id) {
|
// Every facet's edge which has a neighbor from a different plane is
|
||||||
|
// part of an edge that we want to walk around. Skip the others.
|
||||||
|
int neighbor_idx = face_neighbors[facets[face_id]][edge_id];
|
||||||
|
if (neighbor_idx == -1)
|
||||||
|
goto PLANE_FAILURE;
|
||||||
|
if (visited[face_id][edge_id] || (int)m_face_to_plane[neighbor_idx] == plane_id) {
|
||||||
visited[face_id][edge_id] = true;
|
visited[face_id][edge_id] = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -156,14 +169,22 @@ void MeasuringImpl::update_planes()
|
|||||||
do {
|
do {
|
||||||
const Halfedge_index he_orig = he;
|
const Halfedge_index he_orig = he;
|
||||||
he = sm.next_around_target(he);
|
he = sm.next_around_target(he);
|
||||||
while ( (int)m_face_to_plane[sm.face(he)] == plane_id && he != he_orig)
|
if (he.is_invalid())
|
||||||
|
goto PLANE_FAILURE;
|
||||||
|
while ( (int)m_face_to_plane[sm.face(he)] == plane_id && he != he_orig) {
|
||||||
he = sm.next_around_target(he);
|
he = sm.next_around_target(he);
|
||||||
|
if (he.is_invalid())
|
||||||
|
goto PLANE_FAILURE;
|
||||||
|
}
|
||||||
he = sm.opposite(he);
|
he = sm.opposite(he);
|
||||||
|
if (he.is_invalid())
|
||||||
|
goto PLANE_FAILURE;
|
||||||
|
|
||||||
Face_index fi = he.face();
|
Face_index fi = he.face();
|
||||||
auto face_it = std::lower_bound(facets.begin(), facets.end(), int(fi));
|
auto face_it = std::lower_bound(facets.begin(), facets.end(), int(fi));
|
||||||
assert(face_it != facets.end());
|
if (face_it == facets.end() || *face_it != int(fi)) // This indicates a broken mesh.
|
||||||
assert(*face_it == int(fi));
|
goto PLANE_FAILURE;
|
||||||
|
|
||||||
if (visited[face_it - facets.begin()][he.side()] && he != he_start) {
|
if (visited[face_it - facets.begin()][he.side()] && he != he_start) {
|
||||||
last_border.resize(1);
|
last_border.resize(1);
|
||||||
break;
|
break;
|
||||||
@ -177,11 +198,12 @@ void MeasuringImpl::update_planes()
|
|||||||
m_planes[plane_id].borders.pop_back();
|
m_planes[plane_id].borders.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
m_planes.erase(std::remove_if(m_planes.begin(), m_planes.end(),
|
continue; // There was no failure.
|
||||||
[](const PlaneData& p) { return p.borders.empty(); }),
|
|
||||||
m_planes.end());
|
PLANE_FAILURE:
|
||||||
|
m_planes[plane_id].borders.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -209,7 +231,8 @@ void MeasuringImpl::extract_features()
|
|||||||
trafo.rotate(q);
|
trafo.rotate(q);
|
||||||
|
|
||||||
for (const std::vector<Vec3d>& border : plane.borders) {
|
for (const std::vector<Vec3d>& border : plane.borders) {
|
||||||
assert(border.size() > 1);
|
if (border.size() <= 1)
|
||||||
|
continue;
|
||||||
int start_idx = -1;
|
int start_idx = -1;
|
||||||
|
|
||||||
// First calculate angles at all the vertices.
|
// First calculate angles at all the vertices.
|
||||||
|
Loading…
Reference in New Issue
Block a user