diff --git a/src/libslic3r/MeshSplitImpl.hpp b/src/libslic3r/MeshSplitImpl.hpp index f01d1d799..ca94cd2fe 100644 --- a/src/libslic3r/MeshSplitImpl.hpp +++ b/src/libslic3r/MeshSplitImpl.hpp @@ -184,6 +184,81 @@ std::vector its_split(const Its &its) return ret; } +// Splits a mesh into multiple meshes when possible. +template +void its_split_and_keep_relationship(const Its &m, OutputIt out_it, OutputIt_ship out_ship) +{ + using namespace meshsplit_detail; + + const indexed_triangle_set &its = ItsWithNeighborsIndex_::get_its(m); + + struct VertexConv + { + size_t part_id = std::numeric_limits::max(); + size_t vertex_image; + }; + std::vector vidx_conv(its.vertices.size()); + + meshsplit_detail::NeighborVisitor visitor(its, meshsplit_detail::ItsWithNeighborsIndex_::get_index(m)); + + std::vector facets; + for (size_t part_id = 0;; ++part_id) { + // Collect all faces of the next patch. + facets.clear(); + visitor.visit([&facets](size_t idx) { + facets.emplace_back(idx); + return true; + }); + if (facets.empty()) break; + std::sort(facets.begin(), facets.end()); + // Create a new mesh for the part that was just split off. + indexed_triangle_set mesh; + mesh.indices.reserve(facets.size()); + mesh.vertices.reserve(std::min(facets.size() * 3, its.vertices.size())); + std::unordered_map relationship; + // Assign the facets to the new mesh. + for (size_t face_id : facets) { + const auto &face = its.indices[face_id]; + Vec3i new_face; + for (size_t v = 0; v < 3; ++v) { + auto vi = face(v); + + if (vidx_conv[vi].part_id != part_id) { + vidx_conv[vi] = {part_id, mesh.vertices.size()}; + mesh.vertices.emplace_back(its.vertices[size_t(vi)]); + } + + new_face(v) = vidx_conv[vi].vertex_image; + } + relationship[mesh.indices.size()] = face_id; + mesh.indices.emplace_back(new_face); + } + + *out_it = std::move(mesh); + *out_ship = std::move(relationship); + ++out_it; + } +} +class MeshAndShip +{ +public: + std::vector itses; + std::vector> ships; +}; + +template +MeshAndShip its_split_and_save_relationship(const Its &its) +{ + auto ret = reserve_vector(3); + auto ret_ship = reserve_vector>(3); + + its_split_and_keep_relationship(its, std::back_inserter(ret), std::back_inserter(ret_ship)); + MeshAndShip mesh_ship; + mesh_ship.itses = ret; + mesh_ship.ships = ret_ship; + return mesh_ship; +} + template bool its_is_splittable(const Its &m) { diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 4f8cffd54..82328083c 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -3243,9 +3243,12 @@ std::string ModelVolume::type_to_string(const ModelVolumeType t) // This is useful to assign different materials to different volumes of an object. size_t ModelVolume::split(unsigned int max_extruders) { - std::vector meshes = this->mesh().split(); + std::vector> ships; + std::vector meshes = this->mesh().split_and_save_relationship(ships); if (meshes.size() <= 1) return 1; + if (meshes.size() != ships.size()) + return 1; // splited volume should not be text object size_t idx = 0; size_t ivolume = std::find(this->object->volumes.begin(), this->object->volumes.end(), this) - this->object->volumes.begin(); @@ -3279,17 +3282,23 @@ size_t ModelVolume::split(unsigned int max_extruders) this->exterior_facets.reset(); this->supported_facets.reset(); this->seam_facets.reset(); - for (size_t i = 0; i < tris_split_strs.size(); i++) { - if (i < cur_face_count && tris_split_strs[i].size()>0) { - mmu_segmentation_facets.set_triangle_from_string(i, tris_split_strs[i]); + for (size_t i = 0; i < cur_face_count; i++) { + if (ships[idx].find(i) != ships[idx].end()) { + auto index = ships[idx][i]; + if (tris_split_strs[index].size() > 0) { + mmu_segmentation_facets.set_triangle_from_string(i, tris_split_strs[index]); + } } } } else { auto new_mv =new ModelVolume(object, *this, std::move(mesh)); this->object->volumes.insert(this->object->volumes.begin() + (++ivolume), new_mv); - for (size_t i = last_all_mesh_face_count; i < tris_split_strs.size(); i++) { - if (i < last_all_mesh_face_count + cur_face_count && tris_split_strs[i].size() > 0) { - new_mv->mmu_segmentation_facets.set_triangle_from_string(i - last_all_mesh_face_count, tris_split_strs[i]); + for (size_t i = 0; i < new_mv->mesh_ptr()->its.indices.size(); i++) { + if (ships[idx].find(i) != ships[idx].end()) { + auto index = ships[idx][i]; + if (tris_split_strs[index].size() > 0) { + new_mv->mmu_segmentation_facets.set_triangle_from_string(i, tris_split_strs[index]); + } } } } diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 676780a4d..006d9fe16 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -406,6 +406,29 @@ std::vector TriangleMesh::split() const return out; } +std::vector TriangleMesh::split_and_save_relationship(std::vector> &result) const { + auto itss_and_ships = its_split_and_save_relationship<>(this->its); + std::vector out; + out.reserve(itss_and_ships.itses.size()); + result.reserve(itss_and_ships.itses.size()); + unsigned int index = 0; + for (indexed_triangle_set &m : itss_and_ships.itses) { + // The TriangleMesh constructor shall fill in the mesh statistics including volume. + TriangleMesh temp_triangle_mesh(std::move(m)); + if (abs(temp_triangle_mesh.volume() < 0.01)) { // 0.01mm^3 + index++; + continue; + } + if (temp_triangle_mesh.volume() < 0) { // Some source mesh parts may be incorrectly oriented. Correct them. + temp_triangle_mesh.flip_triangles(); + } + out.emplace_back(temp_triangle_mesh); + result.emplace_back(itss_and_ships.ships[index]); + index++; + } + return out; +} + void TriangleMesh::merge(const TriangleMesh &mesh) { its_merge(this->its, mesh.its); diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index c3815af0a..4b1a7a0e5 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -119,6 +119,7 @@ public: void align_to_origin(); void rotate(double angle, Point* center); std::vector split() const; + std::vector split_and_save_relationship(std::vector> &result) const; void merge(const TriangleMesh &mesh); ExPolygons horizontal_projection() const; // 2D convex hull of a 3D mesh projected into the Z=0 plane.