From 4103086a6e8a1b1ce84350deab4f7cb82f795095 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 4 Oct 2021 11:12:29 +0200 Subject: [PATCH 1/8] #7056 - Gizmo cut input set to use current locale --- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 2 +- src/slic3r/GUI/ImGuiWrapper.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index c8142ba34..b14819671 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -182,7 +182,7 @@ void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit) double cut_z = m_cut_z; if (imperial_units) cut_z *= ObjectManipulation::mm_to_in; - ImGui::InputDouble("", &cut_z, 0.0f, 0.0f, "%.2f"); + ImGui::InputDouble("", &cut_z, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_CharsDecimal); ImGui::SameLine(); m_imgui->text(imperial_units ? _L("in") : _L("mm")); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index b8b2337fb..03e5bdc09 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -359,7 +359,7 @@ bool ImGuiWrapper::image_button() bool ImGuiWrapper::input_double(const std::string &label, const double &value, const std::string &format) { - return ImGui::InputDouble(label.c_str(), const_cast(&value), 0.0f, 0.0f, format.c_str()); + return ImGui::InputDouble(label.c_str(), const_cast(&value), 0.0f, 0.0f, format.c_str(), ImGuiInputTextFlags_CharsDecimal); } bool ImGuiWrapper::input_double(const wxString &label, const double &value, const std::string &format) From 580f157d283757889c4eba7d486bedd9a7a7eee2 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 4 Oct 2021 11:35:27 +0200 Subject: [PATCH 2/8] ConfigWizard: Suppress to select SLA printer if a multi-parts object is on a Plater --- src/slic3r/GUI/ConfigWizard.cpp | 50 +++++++++++++++++++++++++++++---- src/slic3r/GUI/GUI_App.cpp | 24 +++++++++++----- src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/Tab.cpp | 17 +---------- src/slic3r/GUI/Tab.hpp | 1 - 5 files changed, 64 insertions(+), 29 deletions(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index ee6e3d5ab..4d50e1490 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -30,6 +30,8 @@ #include "libslic3r/Platform.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Config.hpp" +#include "libslic3r/libslic3r.h" +#include "libslic3r/Model.hpp" #include "GUI.hpp" #include "GUI_App.hpp" #include "GUI_Utils.hpp" @@ -40,7 +42,6 @@ #include "slic3r/Utils/PresetUpdater.hpp" #include "format.hpp" #include "MsgDialog.hpp" -#include "libslic3r/libslic3r.h" #include "UnsavedChangesDialog.hpp" #if defined(__linux__) && defined(__WXGTK3__) @@ -2477,6 +2478,46 @@ static std::string get_first_added_preset(const std::mapmodels) { + if (const auto model_it = config->second.find(model.id); + model_it != config->second.end() && model_it->second.size() > 0) { + if (pt == ptAny) + pt = model.technology; + // if preferred printer model has SLA printer technology it's important to check the model for multypart state + if (pt == ptSLA && suppress_sla_printer) + continue; + else + return pt; + } + } + } + return pt; + }; + // Prusa printers are considered first, then 3rd party. + if (preferred_pt = get_preferred_printer_technology("PrusaResearch", bundles.prusa_bundle()); + preferred_pt == ptAny || (preferred_pt == ptSLA && suppress_sla_printer)) { + for (const auto& bundle : bundles) { + if (bundle.second.is_prusa_bundle) { continue; } + if (PrinterTechnology pt = get_preferred_printer_technology(bundle.first, bundle.second); pt == ptAny) + continue; + else if (preferred_pt == ptAny) + preferred_pt = pt; + if(!(preferred_pt == ptAny || (preferred_pt == ptSLA && suppress_sla_printer))) + break; + } + } + + if (preferred_pt == ptSLA && !wxGetApp().may_switch_to_SLA_preset(caption)) + return false; + bool check_unsaved_preset_changes = page_welcome->reset_user_profile(); if (check_unsaved_preset_changes) header = _L("All user presets will be deleted."); @@ -2484,8 +2525,6 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese if (!check_unsaved_preset_changes) act_btns |= UnsavedChangesDialog::ActionButtons::SAVE; - const auto enabled_vendors = appconfig_new.vendors(); - // Install bundles from resources if needed: std::vector install_bundles; for (const auto &pair : bundles) { @@ -2564,13 +2603,14 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese std::string preferred_model; std::string preferred_variant; const auto enabled_vendors_old = app_config->vendors(); - auto get_preferred_printer_model = [enabled_vendors, enabled_vendors_old](const std::string& bundle_name, const Bundle& bundle, std::string& variant) { + auto get_preferred_printer_model = [enabled_vendors, enabled_vendors_old, preferred_pt](const std::string& bundle_name, const Bundle& bundle, std::string& variant) { const auto config = enabled_vendors.find(bundle_name); if (config == enabled_vendors.end()) return std::string(); for (const auto& model : bundle.vendor_profile->models) { if (const auto model_it = config->second.find(model.id); - model_it != config->second.end() && model_it->second.size() > 0) { + model_it != config->second.end() && model_it->second.size() > 0 && + preferred_pt == model.technology) { variant = *model_it->second.begin(); const auto config_old = enabled_vendors_old.find(bundle_name); if (config_old == enabled_vendors_old.end()) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 9c08159fc..41f4c4b89 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2432,6 +2432,20 @@ void GUI_App::open_web_page_localized(const std::string &http_address) open_browser_with_warning_dialog(http_address + "&lng=" + this->current_language_code_safe()); } +// If we are switching from the FFF-preset to the SLA, we should to control the printed objects if they have a part(s). +// Because of we can't to print the multi-part objects with SLA technology. +bool GUI_App::may_switch_to_SLA_preset(const wxString& caption) +{ + if (model_has_multi_part_objects(model())) { + show_info(nullptr, + _L("It's impossible to print multi-part object(s) with SLA technology.") + "\n\n" + + _L("Please check your object list before preset changing."), + caption); + return false; + } + return true; +} + bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page) { wxCHECK_MSG(mainframe != nullptr, false, "Internal error: Main frame not created / null"); @@ -2447,13 +2461,9 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage if (res) { load_current_presets(); - if (preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA - && Slic3r::model_has_multi_part_objects(wxGetApp().model())) { - GUI::show_info(nullptr, - _L("It's impossible to print multi-part object(s) with SLA technology.") + "\n\n" + - _L("Please check and fix your object list."), - _L("Attention!")); - } + // #ysFIXME - delete after testing: This part of code looks redundant. All checks are inside ConfigWizard::priv::apply_config() + if (preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA) + may_switch_to_SLA_preset(_L("Configuration is editing from ConfigWizard")); } return res; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 60a143144..a581cf8b3 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -309,6 +309,7 @@ public: PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); } void open_web_page_localized(const std::string &http_address); + bool may_switch_to_SLA_preset(const wxString& caption); bool run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page = ConfigWizard::SP_WELCOME); void show_desktop_integration_dialog(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index c91ac4784..8b3cd4cf8 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3236,7 +3236,7 @@ void Tab::select_preset(std::string preset_name, bool delete_current /*=false*/, const PresetWithVendorProfile new_printer_preset_with_vendor_profile = m_presets->get_preset_with_vendor_profile(new_printer_preset); PrinterTechnology old_printer_technology = m_presets->get_edited_preset().printer_technology(); PrinterTechnology new_printer_technology = new_printer_preset.printer_technology(); - if (new_printer_technology == ptSLA && old_printer_technology == ptFFF && !may_switch_to_SLA_preset()) + if (new_printer_technology == ptSLA && old_printer_technology == ptFFF && !wxGetApp().may_switch_to_SLA_preset(_L("New printer preset is selecting"))) canceled = true; else { struct PresetUpdate { @@ -3409,21 +3409,6 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr return true; } -// If we are switching from the FFF-preset to the SLA, we should to control the printed objects if they have a part(s). -// Because of we can't to print the multi-part objects with SLA technology. -bool Tab::may_switch_to_SLA_preset() -{ - if (model_has_multi_part_objects(wxGetApp().model())) - { - show_info( parent(), - _(L("It's impossible to print multi-part object(s) with SLA technology.")) + "\n\n" + - _(L("Please check your object list before preset changing.")), - _(L("Attention!")) ); - return false; - } - return true; -} - void Tab::clear_pages() { // invalidated highlighter, if any exists diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 5b7983711..6a7b56fe4 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -282,7 +282,6 @@ public: // Select a new preset, possibly delete the current one. void select_preset(std::string preset_name = "", bool delete_current = false, const std::string& last_selected_ph_printer_name = ""); bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = ""); - bool may_switch_to_SLA_preset(); virtual void clear_pages(); virtual void update_description_lines(); From 39a98e97b4c38850173b73e5b8a321d3c75c664b Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Mon, 4 Oct 2021 12:29:45 +0200 Subject: [PATCH 3/8] Fix. Allow simplify volume inside object, fix drawing wireframe --- src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp | 58 +++++++++++++++-------- src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp | 4 +- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index e5f42e9a9..c09d67317 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -60,8 +60,9 @@ void GLGizmoSimplify::on_render_for_picking() {} void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limit) { create_gui_cfg(); - int obj_index; - ModelVolume *act_volume = get_selected_volume(&obj_index); + const Selection &selection = m_parent.get_selection(); + int obj_index = selection.get_object_idx(); + ModelVolume *act_volume = get_volume(selection, wxGetApp().plater()->model()); if (act_volume == nullptr) { switch (m_state) { case State::settings: close(); break; @@ -427,17 +428,34 @@ bool GLGizmoSimplify::exist_volume(ModelVolume *volume) { return false; } -ModelVolume *GLGizmoSimplify::get_selected_volume(int *object_idx_ptr) const +ModelVolume * GLGizmoSimplify::get_volume(const Selection &selection, Model &model) { - const Selection &selection = m_parent.get_selection(); - int object_idx = selection.get_object_idx(); - if (object_idx_ptr != nullptr) *object_idx_ptr = object_idx; - if (object_idx < 0) return nullptr; - ModelObjectPtrs &objs = wxGetApp().plater()->model().objects; - if (static_cast(objs.size()) <= object_idx) return nullptr; - ModelObject *obj = objs[object_idx]; - if (obj->volumes.empty()) return nullptr; - return obj->volumes.front(); + const Selection::IndicesList& idxs = selection.get_volume_idxs(); + if (idxs.empty()) return nullptr; + // only one selected volume + if (idxs.size() != 1) return nullptr; + const GLVolume *selected_volume = selection.get_volume(*idxs.begin()); + if (selected_volume == nullptr) return nullptr; + + const GLVolume::CompositeID &cid = selected_volume->composite_id; + const ModelObjectPtrs& objs = model.objects; + if (cid.object_id < 0 || objs.size() <= static_cast(cid.object_id)) + return nullptr; + const ModelObject* obj = objs[cid.object_id]; + if (cid.volume_id < 0 || obj->volumes.size() <= static_cast(cid.volume_id)) + return nullptr; + return obj->volumes[cid.volume_id]; +} + +const ModelVolume *GLGizmoSimplify::get_volume(const GLVolume::CompositeID &cid, const Model &model) +{ + const ModelObjectPtrs &objs = model.objects; + if (cid.object_id < 0 || objs.size() <= static_cast(cid.object_id)) + return nullptr; + const ModelObject *obj = objs[cid.object_id]; + if (cid.volume_id < 0 || obj->volumes.size() <= static_cast(cid.volume_id)) + return nullptr; + return obj->volumes[cid.volume_id]; } void GLGizmoSimplify::init_wireframe() @@ -479,14 +497,16 @@ void GLGizmoSimplify::render_wireframe() const if (m_wireframe_VBO_id == 0 || m_wireframe_IBO_id == 0) return; if (!m_show_wireframe) return; - const GLVolume *selected_volume = m_parent.get_selection().get_volume(0); - - // check selected_volume == m_volume - const auto& cid = selected_volume->composite_id; - assert(wxGetApp().plater()->model().objects[cid.object_id]->volumes[cid.volume_id] == m_volume); - - const Transform3d trafo_matrix = m_parent.get_selection().get_volume(0)->world_matrix(); + const auto& selection = m_parent.get_selection(); + const auto& volume_idxs = selection.get_volume_idxs(); + if (volume_idxs.empty() || volume_idxs.size() != 1) return; + const GLVolume *selected_volume = selection.get_volume(*volume_idxs.begin()); + + // check that selected model is wireframe initialized + if (m_volume != get_volume(selected_volume->composite_id, *m_parent.get_model())) + return; + const Transform3d trafo_matrix = selected_volume->world_matrix(); glsafe(::glPushMatrix()); glsafe(::glMultMatrixd(trafo_matrix.data())); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp index d2358b2d3..d624e3351 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp @@ -43,7 +43,9 @@ private: void set_its(indexed_triangle_set &its); void create_gui_cfg(); void request_rerender(); - ModelVolume *get_selected_volume(int *object_idx = nullptr) const; + // move to global functions + static ModelVolume *get_volume(const Selection &selection, Model &model); + static const ModelVolume *get_volume(const GLVolume::CompositeID &cid, const Model &model); // return false when volume was deleted static bool exist_volume(ModelVolume *volume); From a5a6c0e09aff7fc9c454d55978db051f49ecd89d Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 4 Oct 2021 13:57:01 +0200 Subject: [PATCH 4/8] Fix for #7012 - Dark mode + colored axis: Can't read the Manipulation panel --- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 28 +++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 6eaa6316d..7d5f80a30 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -497,14 +497,19 @@ void ObjectManipulation::update_ui_from_settings() int axis_id = 0; for (ManipulationEditor* editor : m_editors) { // editor->SetForegroundColour(m_use_colors ? wxColour(axes_color_text[axis_id]) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); -#ifdef _WIN32 - if (m_use_colors) + if (m_use_colors) { editor->SetBackgroundColour(wxColour(axes_color_back[axis_id])); - else + if (wxGetApp().dark_mode()) + editor->SetForegroundColour(*wxBLACK); + } + else { +#ifdef _WIN32 wxGetApp().UpdateDarkUI(editor); #else - editor->SetBackgroundColour(m_use_colors ? wxColour(axes_color_back[axis_id]) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + editor->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + editor->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); #endif /* _WIN32 */ + } editor->Refresh(); if (++axis_id == 3) axis_id = 0; @@ -1009,10 +1014,10 @@ void ObjectManipulation::sys_color_changed() get_og()->sys_color_changed(); wxGetApp().UpdateDarkUI(m_word_local_combo); wxGetApp().UpdateDarkUI(m_check_inch); - +#endif for (ManipulationEditor* editor : m_editors) editor->sys_color_changed(this); -#endif + // btn...->msw_rescale() updates icon on button, so use it m_mirror_bitmap_on.msw_rescale(); m_mirror_bitmap_off.msw_rescale(); @@ -1045,6 +1050,7 @@ ManipulationEditor::ManipulationEditor(ObjectManipulation* parent, #endif // __WXOSX__ if (parent->use_colors()) { this->SetBackgroundColour(wxColour(axes_color_back[axis])); + this->SetForegroundColour(*wxBLACK); } else { wxGetApp().UpdateDarkUI(this); } @@ -1097,10 +1103,14 @@ void ManipulationEditor::msw_rescale() void ManipulationEditor::sys_color_changed(ObjectManipulation* parent) { - if (!parent->use_colors()) - wxGetApp().UpdateDarkUI(this); - else + if (parent->use_colors()) SetForegroundColour(*wxBLACK); + else +#ifdef _WIN32 + wxGetApp().UpdateDarkUI(this); +#else + SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); +#endif // _WIN32 } double ManipulationEditor::get_value() From 8c89abc9fb1f5a07d7e9d5b2e0872dcb09987bea Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 4 Oct 2021 14:13:42 +0200 Subject: [PATCH 5/8] Fixed inconsistent modifier context menu in the right panel and in the 3d scene --- src/slic3r/GUI/Plater.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 1f91b3589..590d4a913 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4172,12 +4172,14 @@ void Plater::priv::on_right_click(RBtnEvent& evt) if (printer_technology == ptSLA) menu = menus.sla_object_menu(); else { + const Selection& selection = get_selection(); // show "Object menu" for each one or several FullInstance instead of FullObject - const bool is_some_full_instances = get_selection().is_single_full_instance() || - get_selection().is_single_full_object() || - get_selection().is_multiple_full_instance(); - menu = is_some_full_instances ? menus.object_menu() : - get_selection().is_single_volume() ? menus.part_menu() : menus.multi_selection_menu(); + const bool is_some_full_instances = selection.is_single_full_instance() || + selection.is_single_full_object() || + selection.is_multiple_full_instance(); + const bool is_part = selection.is_single_volume() || selection.is_single_modifier(); + menu = is_some_full_instances ? menus.object_menu() : + is_part ? menus.part_menu() : menus.multi_selection_menu(); } } From 4cc1b2740d0deb3391affdafc884fb975228b7e0 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 4 Oct 2021 14:16:13 +0200 Subject: [PATCH 6/8] Don't report intersection if two polygons are only touching. --- src/libslic3r/Geometry.cpp | 35 +++++++++++++------------------ src/libslic3r/Geometry.hpp | 4 +++- tests/libslic3r/test_geometry.cpp | 22 ++++++++++++------- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index 10c617c60..d1b78a02c 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -1554,14 +1554,16 @@ namespace rotcalip { using int256_t = boost::multiprecision::int256_t; using int128_t = boost::multiprecision::int128_t; -inline int128_t magnsq(const Point &p) +template +inline Scalar magnsq(const Point &p) { - return int128_t(p.x()) * p.x() + int64_t(p.y()) * p.y(); + return Scalar(p.x()) * p.x() + Scalar(p.y()) * p.y(); } -inline int128_t dot(const Point &a, const Point &b) +template +inline Scalar dot(const Point &a, const Point &b) { - return int128_t(a.x()) * b.x() + int64_t(a.y()) * b.y(); + return Scalar(a.x()) * b.x() + Scalar(a.y()) * b.y(); } template @@ -1667,7 +1669,6 @@ bool intersects(const Polygon &A, const Polygon &B) // Establish starting antipodals as extremes in XY plane. Use the // easily obtainable bounding boxes to check if A and B is disjoint // and return false if the are. - struct BB { size_t xmin = 0, xmax = 0, ymin = 0, ymax = 0; @@ -1724,24 +1725,18 @@ bool intersects(const Polygon &A, const Polygon &B) bool is_left_a = dotperp( dir, ref_a - A[ia]) > 0; bool is_left_b = dotperp(-dir, ref_b - B[ib]) > 0; - // If both reference points are on the left (or right) of the - // support line and the opposite support line is to the righ (or - // left), the divisor line is found. We only test the reference - // point, as by definition, if that is on one side, all the other - // points must be on the same side of a support line. + // If both reference points are on the left (or right) of their + // respective support lines and the opposite support line is to + // the right (or left), the divisor line is found. We only test + // the reference point, as by definition, if that is on one side, + // all the other points must be on the same side of a support + // line. If the support lines are collinear, the polygons must be + // on the same side of their respective support lines. auto d = dotperp(dir, B[ib] - A[ia]); - if (d == 0 && ((is_left_a && is_left_b) || (!is_left_a && !is_left_b))) { + if (d == 0) { // The caliper lines are collinear, not just parallel - - // Check if the lines are overlapping and if they do ignore the divisor - Point a = A[ia], b = A[(ia + 1) % A.size()]; - if (b < a) std::swap(a, b); - Point c = B[ib], d = B[(ib + 1) % B.size()]; - if (d < c) std::swap(c, d); - - found_divisor = b < c; - + found_divisor = (is_left_a && is_left_b) || (!is_left_a && !is_left_b); } else if (d > 0) { // B is to the left of (A, A+1) found_divisor = !is_left_a && !is_left_b; } else { // B is to the right of (A, A+1) diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index bb583c33c..505ff3d96 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -532,7 +532,9 @@ inline bool is_rotation_ninety_degrees(const Vec3d &rotation) return is_rotation_ninety_degrees(rotation.x()) && is_rotation_ninety_degrees(rotation.y()) && is_rotation_ninety_degrees(rotation.z()); } -bool intersects(const Polygon &convex_poly1, const Polygon &convex_poly2); +// Returns true if the intersection of the two convex polygons A and B +// is not an empty set. +bool intersects(const Polygon &A, const Polygon &B); } } // namespace Slicer::Geometry diff --git a/tests/libslic3r/test_geometry.cpp b/tests/libslic3r/test_geometry.cpp index 308e29fca..b183de1b4 100644 --- a/tests/libslic3r/test_geometry.cpp +++ b/tests/libslic3r/test_geometry.cpp @@ -470,7 +470,7 @@ TEST_CASE("Convex polygon intersection on two disjoint squares", "[Geometry][Rot bool is_inters = Geometry::intersects(A, B); - REQUIRE(is_inters != true); + REQUIRE(is_inters == false); } TEST_CASE("Convex polygon intersection on two intersecting squares", "[Geometry][Rotcalip]") { @@ -494,7 +494,7 @@ TEST_CASE("Convex polygon intersection on two squares touching one edge", "[Geom bool is_inters = Geometry::intersects(A, B); - REQUIRE(is_inters == true); + REQUIRE(is_inters == false); } TEST_CASE("Convex polygon intersection on two squares touching one vertex", "[Geometry][Rotcalip]") { @@ -502,11 +502,16 @@ TEST_CASE("Convex polygon intersection on two squares touching one vertex", "[Ge A.scale(1. / SCALING_FACTOR); Polygon B = A; - B.translate(10 / SCALING_FACTOR, 10); + B.translate(10 / SCALING_FACTOR, 10 / SCALING_FACTOR); + + SVG svg{std::string("one_vertex_touch") + ".svg"}; + svg.draw(A, "blue"); + svg.draw(B, "green"); + svg.Close(); bool is_inters = Geometry::intersects(A, B); - REQUIRE(is_inters == true); + REQUIRE(is_inters == false); } TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][Rotcalip]") { @@ -520,7 +525,7 @@ TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][ REQUIRE(is_inters == true); } -// Only for benchmarking +//// Only for benchmarking //static Polygon gen_convex_poly(std::mt19937_64 &rg, size_t point_cnt) //{ // std::uniform_int_distribution dist(0, 100); @@ -540,7 +545,9 @@ TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][ // constexpr size_t TEST_CNT = 1000; // constexpr size_t POINT_CNT = 1000; -// std::mt19937_64 rg{std::random_device{}()}; +// auto seed = std::random_device{}(); +//// unsigned long seed = 2525634386; +// std::mt19937_64 rg{seed}; // Benchmark bench; // auto tests = reserve_vector>(TEST_CNT); @@ -567,11 +574,12 @@ TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][ // REQUIRE(results.size() == expects.size()); +// auto seedstr = std::to_string(seed); // for (size_t i = 0; i < results.size(); ++i) { // // std::cout << expects[i] << " "; // if (results[i] != expects[i]) { -// SVG svg{std::string("fail") + std::to_string(i) + ".svg"}; +// SVG svg{std::string("fail_seed") + seedstr + "_" + std::to_string(i) + ".svg"}; // svg.draw(tests[i].first, "blue"); // svg.draw(tests[i].second, "green"); // svg.Close(); From d214e09400776e24d15bbccf0e4dfe44f88cec65 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 4 Oct 2021 15:33:08 +0200 Subject: [PATCH 7/8] Fix for #7040 - Missing auto slice after Undo / Redo of deletion of height range modifier --- src/slic3r/GUI/Plater.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 590d4a913..90dce0a13 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2109,13 +2109,14 @@ void Plater::priv::update(unsigned int flags) } unsigned int update_status = 0; - if (this->printer_technology == ptSLA || (flags & (unsigned int)UpdateParams::FORCE_BACKGROUND_PROCESSING_UPDATE)) + const bool force_background_processing_restart = this->printer_technology == ptSLA || (flags & (unsigned int)UpdateParams::FORCE_BACKGROUND_PROCESSING_UPDATE); + if (force_background_processing_restart) // Update the SLAPrint from the current Model, so that the reload_scene() // pulls the correct data. update_status = this->update_background_process(false, flags & (unsigned int)UpdateParams::POSTPONE_VALIDATION_ERROR_MESSAGE); this->view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH); this->preview->reload_print(); - if (this->printer_technology == ptSLA) + if (force_background_processing_restart) this->restart_background_process(update_status); else this->schedule_background_process(); From 577632d8922ad764e5a1dd93e76bfa73f1118d15 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 4 Oct 2021 16:20:46 +0200 Subject: [PATCH 8/8] Check unsaved preset changes only if project is dirty and it wasn't saved --- src/slic3r/GUI/MainFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 6538c0a9a..66e22c694 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -228,7 +228,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S return; } // check unsaved changes only if project wasn't saved - else if (saved_project == wxID_NO && event.CanVeto() && + else if (plater()->is_project_dirty() && saved_project == wxID_NO && event.CanVeto() && !wxGetApp().check_and_save_current_preset_changes(_L("PrusaSlicer is closing"), _L("Closing PrusaSlicer while some presets are modified."))) { event.Veto(); return;