Fix filtration after triangulation

This commit is contained in:
Filip Sykala 2021-10-06 13:15:16 +02:00
parent ffba045734
commit 5aadd690be

View File

@ -24,7 +24,7 @@ inline void insert_edge(Slic3r::Triangulation::HalfEdges &edges, uint32_t &offse
offset += size; offset += size;
} }
} } // namespace Private
Triangulation::Indices Triangulation::triangulate(const Points &points, const HalfEdges &half_edges) Triangulation::Indices Triangulation::triangulate(const Points &points, const HalfEdges &half_edges)
{ {
@ -134,23 +134,37 @@ Triangulation::Indices Triangulation::triangulate(const ExPolygons &expolygons)
void Triangulation::remove_outer(Indices &indices, const HalfEdges &half_edges) void Triangulation::remove_outer(Indices &indices, const HalfEdges &half_edges)
{ {
uint32_t no_triangle = indices.size(); // convert half edge to triangle index
std::map<HalfEdge, uint32_t> edge2triangle; std::map<HalfEdge, uint32_t> edge2triangle;
// triangles with all edges out of half_edge, candidate to remove // triangles with all edges out of half_edge, candidate to remove
std::vector<uint32_t> triangles_to_check; std::vector<uint32_t> triangles_to_check;
triangles_to_check.reserve(indices.size() / 3); triangles_to_check.reserve(indices.size() / 3);
// triangle half edge
auto create_half_edge = [](const Vec3i& triangle, size_t index) {
size_t next_index = (index == 2) ? 0 : (index + 1);
return HalfEdge(triangle[index], triangle[next_index]);
};
// neighbor triangle half edge
auto create_opposit_half_edge = [](const Vec3i &triangle, size_t index) {
size_t prev_index = (index == 0) ? 2 : (index - 1);
return HalfEdge(triangle[index], triangle[prev_index]);
};
for (const auto &t : indices) { for (const auto &t : indices) {
uint32_t index = &t - &indices.front(); uint32_t index = &t - &indices.front();
bool is_border = false; bool is_border = false;
for (size_t j = 0; j < 3; ++j) { for (size_t j = 0; j < 3; ++j) {
size_t j2 = (j == 0) ? 2 : (j - 1); HalfEdge he = create_half_edge(t, j);
HalfEdge he(t[j2], t[j]);
if (half_edges.find(he) != half_edges.end()) if (half_edges.find(he) != half_edges.end())
is_border = true; is_border = true;
else else {
assert(edge2triangle.find(he) == edge2triangle.end());
edge2triangle[he] = index; edge2triangle[he] = index;
}
} }
if (!is_border) { triangles_to_check.push_back(index); } if (!is_border) triangles_to_check.push_back(index);
} }
std::set<uint32_t> remove; std::set<uint32_t> remove;
@ -159,33 +173,39 @@ void Triangulation::remove_outer(Indices &indices, const HalfEdges &half_edges)
auto it = remove.find(index); auto it = remove.find(index);
if (it != remove.end()) continue; // already removed if (it != remove.end()) continue; // already removed
bool is_edge = false; bool is_edge = false;
const Vec3i &t = indices[index]; const Vec3i &t = indices[index];
// check if exist opposit triangle
for (size_t j = 0; j < 3; ++j) { for (size_t j = 0; j < 3; ++j) {
size_t j2 = (j == 0) ? 2 : (j - 1); HalfEdge he = create_opposit_half_edge(t, j);
// opposit auto it = edge2triangle.find(he);
HalfEdge he(t[j], t[j2]); if (it == edge2triangle.end()) {
if (edge2triangle.find(he) == edge2triangle.end()) is_edge = true; is_edge = true;
break;
}
assert(it->second != index);
} }
if (!is_edge) continue; // correct if (!is_edge) continue; // correct
// when there is no opposit edge, remove triangle and all neighbors recursive
insert.push(index); insert.push(index);
while (!insert.empty()) { do {
uint32_t i = insert.front(); uint32_t triangle_index = insert.front();
insert.pop(); insert.pop();
if (remove.find(i) != remove.end()) continue; if (remove.find(triangle_index) != remove.end()) continue; // already removed
remove.insert(i); remove.insert(triangle_index);
for (size_t j = 0; j < 3; ++j) { for (size_t j = 0; j < 3; ++j) {
size_t j2 = (j == 0) ? 2 : (j - 1); const Vec3i &t = indices[triangle_index];
// opposit HalfEdge he = create_opposit_half_edge(t, j);
HalfEdge he(t[j], t[j2]);
auto it = edge2triangle.find(he); auto it = edge2triangle.find(he);
if (it == edge2triangle.end()) continue; // edge if (it == edge2triangle.end()) continue; // edge triangle without neighbor
insert.push(it->second); // process neighbor
uint32_t neighbor_index = it->second;
assert(neighbor_index != triangle_index);
insert.push(neighbor_index);
} }
} } while (!insert.empty());
} }
// remove indices // remove indices