From 04bed7f239c0477a8cdfa4f9ae58e549f1b15411 Mon Sep 17 00:00:00 2001 From: "zhou.xu" Date: Tue, 11 Mar 2025 16:20:42 +0800 Subject: [PATCH] FIX:cancle does_bound_a_volume check and try boolean with warning jira: STUDIO-10754 Change-Id: I0aadd9fe63b0dfeed13b03b62753405040e12e11 --- .../CSGMesh/PerformCSGMeshBooleans.hpp | 6 +- src/libslic3r/MeshBoolean.cpp | 69 ++++++++++--------- src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp | 22 ++++-- src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp | 3 +- 4 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp b/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp index 7e861cde5..fa2e1e234 100644 --- a/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp +++ b/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp @@ -254,7 +254,7 @@ void perform_csgmesh_booleans_mcut(MeshBoolean::mcut::McutMeshPtr& mcutm, } mcutm = std::move(opstack.top().mcutptr); - + } @@ -286,12 +286,12 @@ std::tuple check_csgmesh_booleans(const Range return; } - if (!MeshBoolean::cgal::does_bound_a_volume(*m)) { + /*if (!MeshBoolean::cgal::does_bound_a_volume(*m)) {//has crash problem BOOST_LOG_TRIVIAL(info) << "check_csgmesh_booleans fails! mesh "< src_parts = its_split(tri_src.its); + try { + TriangleMesh tri_src = mcut_to_triangle_mesh(srcMesh); + std::vector src_parts = its_split(tri_src.its); - TriangleMesh tri_cut = mcut_to_triangle_mesh(cutMesh); - std::vector cut_parts = its_split(tri_cut.its); + TriangleMesh tri_cut = mcut_to_triangle_mesh(cutMesh); + std::vector cut_parts = its_split(tri_cut.its); - if (src_parts.empty() && boolean_opts == "UNION") { - srcMesh = cutMesh; - return; - } - if(cut_parts.empty()) return; - - // when src mesh has multiple connected components, mcut refuses to work. - // But we can force it to work by spliting the src mesh into disconnected components, - // and do booleans seperately, then merge all the results. - indexed_triangle_set all_its; - if (boolean_opts == "UNION" || boolean_opts == "A_NOT_B") { - for (size_t i = 0; i < src_parts.size(); i++) { - auto src_part = triangle_mesh_to_mcut(src_parts[i]); - for (size_t j = 0; j < cut_parts.size(); j++) { - auto cut_part = triangle_mesh_to_mcut(cut_parts[j]); - do_boolean_single(*src_part, *cut_part, boolean_opts); - } - TriangleMesh tri_part = mcut_to_triangle_mesh(*src_part); - its_merge(all_its, tri_part.its); + if (src_parts.empty() && boolean_opts == "UNION") { + srcMesh = cutMesh; + return; } - } - else if (boolean_opts == "INTERSECTION") { - for (size_t i = 0; i < src_parts.size(); i++) { - for (size_t j = 0; j < cut_parts.size(); j++) { + if (cut_parts.empty()) return; + + // when src mesh has multiple connected components, mcut refuses to work. + // But we can force it to work by spliting the src mesh into disconnected components, + // and do booleans seperately, then merge all the results. + indexed_triangle_set all_its; + if (boolean_opts == "UNION" || boolean_opts == "A_NOT_B") { + for (size_t i = 0; i < src_parts.size(); i++) { auto src_part = triangle_mesh_to_mcut(src_parts[i]); - auto cut_part = triangle_mesh_to_mcut(cut_parts[j]); - bool success = do_boolean_single(*src_part, *cut_part, boolean_opts); - if (success) { - TriangleMesh tri_part = mcut_to_triangle_mesh(*src_part); - its_merge(all_its, tri_part.its); + for (size_t j = 0; j < cut_parts.size(); j++) { + auto cut_part = triangle_mesh_to_mcut(cut_parts[j]); + do_boolean_single(*src_part, *cut_part, boolean_opts); + } + TriangleMesh tri_part = mcut_to_triangle_mesh(*src_part); + its_merge(all_its, tri_part.its); + } + } else if (boolean_opts == "INTERSECTION") { + for (size_t i = 0; i < src_parts.size(); i++) { + for (size_t j = 0; j < cut_parts.size(); j++) { + auto src_part = triangle_mesh_to_mcut(src_parts[i]); + auto cut_part = triangle_mesh_to_mcut(cut_parts[j]); + bool success = do_boolean_single(*src_part, *cut_part, boolean_opts); + if (success) { + TriangleMesh tri_part = mcut_to_triangle_mesh(*src_part); + its_merge(all_its, tri_part.its); + } } } } + srcMesh = *triangle_mesh_to_mcut(all_its); + } catch (const std::exception &e) { + BOOST_LOG_TRIVIAL(error) << "check error:" << e.what(); } - srcMesh = *triangle_mesh_to_mcut(all_its); } void make_boolean(const TriangleMesh &src_mesh, const TriangleMesh &cut_mesh, std::vector &dst_mesh, const std::string &boolean_opts) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp index fa480546f..49ee020df 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp @@ -19,7 +19,7 @@ namespace Slic3r { namespace GUI { static const std::string warning_text_common = _u8L("Unable to perform boolean operation on selected parts"); -static const std::string warning_text_intersection = _u8L("Performed boolean intersection fails \n because the selected parts have no intersection"); +static const std::string warning_text_intersection = _u8L("Performed boolean intersection fails because the selected parts have no intersection"); GLGizmoMeshBoolean::GLGizmoMeshBoolean(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) @@ -361,6 +361,10 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l m_selecting_state = (m_src.mv == nullptr) ? MeshBooleanSelectingState::SelectSource : MeshBooleanSelectingState::SelectTool; } ImGui::PopStyleColor(5); + m_full_width = ImGui::GetWindowWidth(); + } else { + float space_size = m_imgui->get_style_scaling() * 8; + m_full_width = max_tab_length * 3 + space_size *3; } bool enable_button = m_src.mv && m_tool.mv; @@ -368,9 +372,10 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l if (m_operation_mode == MeshBooleanOperation::Union) { if (operate_button(_L("Union") + "##btn", enable_button)) { + wxBusyCursor temp_cursor; csg::BooleanFailReason fail_reason; m_warning_texts[index] = check_boolean_possible({m_src.mv, m_tool.mv}, fail_reason); - if(m_warning_texts[index] == "") { + if (m_warning_texts[index] == "" || fail_reason == csg::BooleanFailReason::SelfIntersect) { TriangleMesh temp_src_mesh = m_src.mv->mesh(); temp_src_mesh.transform(m_src.trafo); TriangleMesh temp_tool_mesh = m_tool.mv->mesh(); @@ -393,9 +398,10 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l else if (m_operation_mode == MeshBooleanOperation::Difference) { m_imgui->bbl_checkbox(_L("Delete input"), m_diff_delete_input); if (operate_button(_L("Difference") + "##btn", enable_button)) { + wxBusyCursor temp_cursor; csg::BooleanFailReason fail_reason; m_warning_texts[index] = check_boolean_possible({m_src.mv, m_tool.mv}, fail_reason); - if (m_warning_texts[index] == "") { + if (m_warning_texts[index] == "" || fail_reason == csg::BooleanFailReason::SelfIntersect) { TriangleMesh temp_src_mesh = m_src.mv->mesh(); temp_src_mesh.transform(m_src.trafo); TriangleMesh temp_tool_mesh = m_tool.mv->mesh(); @@ -418,9 +424,10 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l else if (m_operation_mode == MeshBooleanOperation::Intersection){ m_imgui->bbl_checkbox(_L("Delete input"), m_inter_delete_input); if (operate_button(_L("Intersection") + "##btn", enable_button)) { + wxBusyCursor temp_cursor; csg::BooleanFailReason fail_reason; m_warning_texts[index] = check_boolean_possible({m_src.mv, m_tool.mv}, fail_reason); - if (m_warning_texts[index] == "") { + if (m_warning_texts[index] == "" || fail_reason == csg::BooleanFailReason::SelfIntersect) { TriangleMesh temp_src_mesh = m_src.mv->mesh(); temp_src_mesh.transform(m_src.trafo); TriangleMesh temp_tool_mesh = m_tool.mv->mesh(); @@ -441,7 +448,7 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l } } if (index >= 0 && index < m_warning_texts.size()) { - render_input_window_warning(m_warning_texts[index]); + render_input_window_warning(m_warning_texts[index], m_full_width); } float win_w = ImGui::GetWindowWidth(); @@ -460,9 +467,10 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l ImGuiWrapper::pop_toolbar_style(); } -void GLGizmoMeshBoolean::render_input_window_warning(const std::string &text) { +void GLGizmoMeshBoolean::render_input_window_warning(const std::string &text, int width) +{ if (text.size() > 0) { - m_imgui->warning_text(_L("Warning") + ": " + _L(text)); + m_imgui->warning_text_wrapped(_L("Warning") + ": " + _L(text), width); } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp index 3fe71f39b..0dcf2e78e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp @@ -59,12 +59,13 @@ protected: virtual void on_set_state() override; virtual CommonGizmosDataID on_get_requirements() const override; virtual void on_render_input_window(float x, float y, float bottom_limit); - virtual void render_input_window_warning(const std::string &text); + virtual void render_input_window_warning(const std::string &text,int width); void on_load(cereal::BinaryInputArchive &ar) override; void on_save(cereal::BinaryOutputArchive &ar) const override; private: bool m_enable{ false }; + int m_full_width; MeshBooleanOperation m_operation_mode; MeshBooleanSelectingState m_selecting_state; bool m_diff_delete_input = false;