From fbce7b001b8449d2a5bcee3a6fc4185e6626462c Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 1 Apr 2019 14:50:40 +0200 Subject: [PATCH] Some optimizations of "Fix crash on splitting some models #2042" replaced std::vector with std::vector as std::vector is a specialized version optimized for memory, not speed (8 bools are packed into a single boolean). The triangle neighbor traversal was optimized to not push visited or non-neighbors into the queue. --- src/libslic3r/TriangleMesh.cpp | 43 +++++++++++++++++----------------- src/libslic3r/TriangleMesh.hpp | 2 +- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 759568860..c145380c9 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -343,7 +343,7 @@ void TriangleMesh::rotate(double angle, Point* center) */ bool TriangleMesh::is_splittable() const { - std::vector visited; + std::vector visited; find_unvisited_neighbors(visited); // Try finding an unvisited facet. If there are none, the mesh is not splittable. @@ -359,36 +359,37 @@ bool TriangleMesh::is_splittable() const * facet with the same index has been visited. * @return A deque with all newly visited facets. */ -std::deque TriangleMesh::find_unvisited_neighbors(std::vector &facet_visited) const +std::deque TriangleMesh::find_unvisited_neighbors(std::vector &facet_visited) const { // Make sure we're not operating on a broken mesh. if (!this->repaired) - throw std::runtime_error("split() requires repair()"); + throw std::runtime_error("find_unvisited_neighbors() requires repair()"); // If the visited list is empty, populate it with false for every facet. - if (facet_visited.empty()) { - facet_visited = std::vector(this->stl.stats.number_of_facets, false); - } + if (facet_visited.empty()) + facet_visited = std::vector(this->stl.stats.number_of_facets, false); // Find the first unvisited facet. - std::queue facet_queue; + std::queue facet_queue; + std::deque facets; auto facet = std::find(facet_visited.begin(), facet_visited.end(), false); - if (facet != facet_visited.end()) - facet_queue.push(facet - facet_visited.begin()); + if (facet != facet_visited.end()) { + uint32_t idx = uint32_t(facet - facet_visited.begin()); + facet_queue.push(idx); + facet_visited[idx] = true; + facets.emplace_back(idx); + } // Traverse all reachable neighbors and mark them as visited. - std::deque facets; - while (!facet_queue.empty()) { - int facet_idx = facet_queue.front(); + while (! facet_queue.empty()) { + uint32_t facet_idx = facet_queue.front(); facet_queue.pop(); - - if (facet_idx != -1 && !facet_visited[facet_idx]) { - facet_visited[facet_idx] = true; - - facets.emplace_back(facet_idx); - for (int facet : this->stl.neighbors_start[facet_idx].neighbor) - facet_queue.push(facet); - } + for (int neighbor_idx : this->stl.neighbors_start[facet_idx].neighbor) + if (neighbor_idx != -1 && ! facet_visited[neighbor_idx]) { + facet_queue.push(uint32_t(neighbor_idx)); + facet_visited[neighbor_idx] = true; + facets.emplace_back(uint32_t(neighbor_idx)); + } } return facets; @@ -402,7 +403,7 @@ std::deque TriangleMesh::find_unvisited_neighbors(std::vector &f TriangleMeshPtrs TriangleMesh::split() const { // Loop while we have remaining facets. - std::vector facet_visited; + std::vector facet_visited; TriangleMeshPtrs meshes; for (;;) { std::deque facets = find_unvisited_neighbors(facet_visited); diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index b204a9a3e..a65a4be75 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -69,13 +69,13 @@ public: bool empty() const { return this->facets_count() == 0; } bool is_splittable() const; - std::deque find_unvisited_neighbors(std::vector &facet_visited) const; stl_file stl; bool repaired; private: void require_shared_vertices(); + std::deque find_unvisited_neighbors(std::vector &facet_visited) const; friend class TriangleMeshSlicer; };