From 9d37d1a0840e193c4c128d3c90d074144a2b382f Mon Sep 17 00:00:00 2001 From: vovodroid Date: Sat, 5 Oct 2024 21:48:16 +0300 Subject: [PATCH] Export negative parts. --- src/libslic3r/CSGMesh/CSGMesh.hpp | 34 +++++++++++++++++ .../CSGMesh/PerformCSGMeshBooleans.hpp | 28 +++++++------- src/slic3r/GUI/Plater.cpp | 37 +++++++++++++++---- 3 files changed, 78 insertions(+), 21 deletions(-) diff --git a/src/libslic3r/CSGMesh/CSGMesh.hpp b/src/libslic3r/CSGMesh/CSGMesh.hpp index 177d3432965..ea16eae52ab 100644 --- a/src/libslic3r/CSGMesh/CSGMesh.hpp +++ b/src/libslic3r/CSGMesh/CSGMesh.hpp @@ -82,6 +82,40 @@ struct CSGPart { {} }; +//Prusa +// Check if there are only positive parts (Union) within the collection. +template bool is_all_positive(const Cont &csgmesh) +{ + bool is_all_pos = + std::all_of(csgmesh.begin(), + csgmesh.end(), + [](auto &part) { + return csg::get_operation(part) == csg::CSGType::Union; + }); + + return is_all_pos; +} + +//Prusa +// Merge all the positive parts of the collection into a single triangle mesh without performing +// any booleans. +template +indexed_triangle_set csgmesh_merge_positive_parts(const Cont &csgmesh) +{ + indexed_triangle_set m; + for (auto &csgpart : csgmesh) { + auto op = csg::get_operation(csgpart); + const indexed_triangle_set * pmesh = csg::get_mesh(csgpart); + if (pmesh && op == csg::CSGType::Union) { + indexed_triangle_set mcpy = *pmesh; + its_transform(mcpy, csg::get_transform(csgpart), true); + its_merge(m, mcpy); + } + } + + return m; +} + }} // namespace Slic3r::csg #endif // CSGMESH_HPP diff --git a/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp b/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp index a9a48b48c02..df4a6033827 100644 --- a/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp +++ b/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp @@ -257,7 +257,7 @@ void perform_csgmesh_booleans_mcut(MeshBoolean::mcut::McutMeshPtr& mcutm, template -std::tuple check_csgmesh_booleans(const Range &csgrange, Visitor &&vfn) +std::tuple check_csgmesh_booleans(const Range &csgrange, Visitor &&vfn) { using namespace detail_cgal; BooleanFailReason fail_reason = BooleanFailReason::OK; @@ -304,23 +304,23 @@ std::tuple check_csgmesh_booleans(const Range }; execution::for_each(ex_tbb, size_t(0), csgrange.size(), check_part); - //It ret = csgrange.end(); - //for (size_t i = 0; i < csgrange.size(); ++i) { - // if (!cgalmeshes[i]) { - // auto it = csgrange.begin(); - // std::advance(it, i); - // vfn(it); + It ret = csgrange.end(); + for (size_t i = 0; i < csgrange.size(); ++i) { + if (!cgalmeshes[i]) { + auto it = csgrange.begin(); + std::advance(it, i); + vfn(it); - // if (ret == csgrange.end()) - // ret = it; - // } - //} + if (ret == csgrange.end()) + ret = it; + } + } - return { fail_reason,fail_part_name }; + return { fail_reason,fail_part_name, ret}; } template -std::tuple check_csgmesh_booleans(const Range &csgrange, bool use_mcut=false) +std::tuple check_csgmesh_booleans(const Range &csgrange, bool use_mcut=false) { if(!use_mcut) return check_csgmesh_booleans(csgrange, [](auto &) {}); @@ -354,7 +354,7 @@ std::tuple check_csgmesh_booleans(const Rangeis_model_part()) { - TriangleMesh vol_mesh(v->mesh()); - vol_mesh.transform(v->get_matrix(), true); - mesh.merge(vol_mesh); - } + + //Prusa export negative parts + std::vector csgmesh; + csgmesh.reserve(2 * mo.volumes.size()); + csg::model_to_csgmesh(mo, Transform3d::Identity(), std::back_inserter(csgmesh), + csg::mpartsPositive | csg::mpartsNegative | csg::mpartsDoSplits); + + auto csgrange = range(csgmesh); + if (csg::is_all_positive(csgrange)) { + mesh = TriangleMesh{csg::csgmesh_merge_positive_parts(csgrange)}; + } else if (std::get<2>(csg::check_csgmesh_booleans(csgrange)) == csgrange.end()) { + try { + auto cgalm = csg::perform_csgmesh_booleans(csgrange); + mesh = MeshBoolean::cgal::cgal_to_triangle_mesh(*cgalm); + } catch (...) {} + } + + if (mesh.empty()) { + get_notification_manager()->push_plater_error_notification( + _u8L("Unable to perform boolean operation on model meshes. " + "Only positive parts will be exported.")); + + for (const ModelVolume* v : mo.volumes) + if (v->is_model_part()) { + TriangleMesh vol_mesh(v->mesh()); + vol_mesh.transform(v->get_matrix(), true); + mesh.merge(vol_mesh); + } + } if (instance_id == -1) { TriangleMesh vols_mesh(mesh); mesh = TriangleMesh();