From 61d59a7a2e6118c9a5f67207c0ae648f1385d84b Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 28 Jan 2019 11:58:25 +0100 Subject: [PATCH 1/3] Fix for erroneous support slicing. Adding upper and lower closure for pillars and bridges. --- src/libslic3r/SLA/SLABoilerPlate.hpp | 17 +++++++++-- src/libslic3r/SLA/SLASupportTree.cpp | 43 ++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/SLA/SLABoilerPlate.hpp b/src/libslic3r/SLA/SLABoilerPlate.hpp index 1436be17f3..c1096206a2 100644 --- a/src/libslic3r/SLA/SLABoilerPlate.hpp +++ b/src/libslic3r/SLA/SLABoilerPlate.hpp @@ -5,8 +5,8 @@ #include #include -#include "ExPolygon.hpp" -#include "TriangleMesh.hpp" +#include +#include namespace Slic3r { namespace sla { @@ -53,7 +53,7 @@ struct Contour3D { void merge(const Contour3D& ctr) { auto s3 = coord_t(points.size()); - auto s = coord_t(indices.size()); + auto s = indices.size(); points.insert(points.end(), ctr.points.begin(), ctr.points.end()); indices.insert(indices.end(), ctr.indices.begin(), ctr.indices.end()); @@ -62,6 +62,17 @@ struct Contour3D { auto& idx = indices[n]; x(idx) += s3; y(idx) += s3; z(idx) += s3; } } + + // Write the index triangle structure to OBJ file for debugging purposes. + void to_obj(std::ostream& stream) { + for(auto& p : points) { + stream << "v " << p.transpose() << "\n"; + } + + for(auto& f : indices) { + stream << "f " << (f + Vec3i(1, 1, 1)).transpose() << "\n"; + } + } }; //using PointSet = Eigen::Matrix; //Eigen::MatrixXd; diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index 1d7858ead0..b7ae95fdab 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -9,8 +9,8 @@ #include "SLASpatIndex.hpp" #include "SLABasePool.hpp" -#include "ClipperUtils.hpp" -#include "Model.hpp" +#include +#include #include @@ -176,6 +176,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) { Vec3d jp = {0, 0, 0}; Vec3d endp = {0, 0, h}; + // Upper circle points for(int i = 0; i < steps; ++i) { double phi = i*a; double ex = endp(X) + r*std::cos(phi); @@ -183,6 +184,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) { points.emplace_back(ex, ey, endp(Z)); } + // Lower circle points for(int i = 0; i < steps; ++i) { double phi = i*a; double x = jp(X) + r*std::cos(phi); @@ -190,6 +192,7 @@ Contour3D cylinder(double r, double h, size_t ssteps) { points.emplace_back(x, y, jp(Z)); } + // Now create long triangles connecting upper and lower circles indices.reserve(2*ssteps); auto offs = steps; for(int i = 0; i < steps - 1; ++i) { @@ -197,10 +200,26 @@ Contour3D cylinder(double r, double h, size_t ssteps) { indices.emplace_back(i, offs + i + 1, i + 1); } + // Last triangle connecting the first and last vertices auto last = steps - 1; indices.emplace_back(0, last, offs); indices.emplace_back(last, offs + last, offs); + // According to the slicing algorithms, we need to aid them with generating + // a watertight body. So we create a triangle fan for the upper and lower + // ending of the cylinder to close the geometry. + points.emplace_back(jp); size_t ci = points.size() - 1; + for(int i = 0; i < steps - 1; ++i) + indices.emplace_back(i + offs + 1, i + offs, ci); + + indices.emplace_back(offs, steps + offs - 1, ci); + + points.emplace_back(endp); ci = points.size() - 1; + for(int i = 0; i < steps - 1; ++i) + indices.emplace_back(ci, i, i + 1); + + indices.emplace_back(steps - 1, 0, ci); + return ret; } @@ -352,6 +371,8 @@ struct Pillar { r(radius), steps(st), endpoint(endp), starts_from_head(false) { assert(steps > 0); + assert(jp(Z) > endp(Z)); // Endpoint is below the starting point + int steps_1 = int(steps - 1); auto& points = mesh.points; @@ -382,6 +403,22 @@ struct Pillar { indices.emplace_back(0, steps_1, offs); indices.emplace_back(steps_1, offs + steps_1, offs); + + // According to the slicing algorithms, we need to aid them with + // generating a watertight body. So we create a triangle fan for the + // upper and lower ending of the cylinder to close the geometry. + points.emplace_back(jp); size_t ci = points.size() - 1; + int stepsi = int(steps); + for(int i = 0; i < stepsi - 1; ++i) + indices.emplace_back(ci, i, i + 1); + + indices.emplace_back(stepsi - 1, 0, ci); + + points.emplace_back(endp); ci = points.size() - 1; + for(int i = 0; i < stepsi - 1; ++i) + indices.emplace_back(i + offs + 1, i + offs, ci); + + indices.emplace_back(offs, stepsi + offs - 1, ci); } Pillar(const Junction& junc, const Vec3d& endp): @@ -461,6 +498,8 @@ struct Bridge { Vec3d dir = (j2 - j1).normalized(); double d = distance(j2, j1); + assert(d > 0); + mesh = cylinder(r, d, steps); auto quater = Quaternion::FromTwoVectors(Vec3d{0,0,1}, dir); From ddcb2b1c232041ac8739620bc1acd65b203414bf Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 28 Jan 2019 12:12:14 +0100 Subject: [PATCH 2/3] Fixed a crash caused by double-free on application close event (Linux) --- src/slic3r/GUI/GUI_App.cpp | 22 ++++------------------ src/slic3r/GUI/GUI_App.hpp | 1 - src/slic3r/GUI/MainFrame.cpp | 11 ++++------- 3 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index c22219fea2..9991d98ea4 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -270,16 +270,11 @@ void GUI_App::set_label_clr_sys(const wxColour& clr) { void GUI_App::recreate_GUI() { - std::cerr << "recreate_GUI" << std::endl; + // to make sure nobody accesses data from the soon-to-be-destroyed widgets: + tabs_list.clear(); + plater_ = nullptr; - clear_tabs_list(); - if (plater_) { - // before creating a new plater let's delete old one - plater_->Destroy(); - plater_ = nullptr; - } - - MainFrame* topwindow = dynamic_cast(GetTopWindow()); + MainFrame* topwindow = mainframe; mainframe = new MainFrame(); sidebar().obj_list()->init_objects(); // propagate model objects to object list @@ -691,15 +686,6 @@ void GUI_App::load_current_presets() } } -void GUI_App::clear_tabs_list() -{ - for (auto tab : tabs_list) { - tab->Destroy(); - tab = nullptr; - } - tabs_list.clear(); -} - #ifdef __APPLE__ // wxWidgets override to get an event on open files. void GUI_App::MacOpenFiles(const wxArrayString &fileNames) diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index a5b96598fd..79da4531de 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -134,7 +134,6 @@ public: bool check_unsaved_changes(); bool checked_tab(Tab* tab); void load_current_presets(); - void clear_tabs_list(); #ifdef __APPLE__ // wxWidgets override to get an event on open files. diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index d47c7f4e86..2df3429fe1 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -95,14 +95,10 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL _3DScene::remove_all_canvases(); // Slic3r::GUI::deregister_on_request_update_callback(); - // destroy and set to null tabs and a platter + // set to null tabs and a platter // to avoid any manipulations with them from App->wxEVT_IDLE after of the mainframe closing - wxGetApp().clear_tabs_list(); - if (wxGetApp().plater_) { - // before creating a new plater let's delete old one - wxGetApp().plater_->Destroy(); - wxGetApp().plater_ = nullptr; - } + wxGetApp().tabs_list.clear(); + wxGetApp().plater_ = nullptr; // propagate event event.Skip(); @@ -113,6 +109,7 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL update_ui_from_settings(); // FIXME (?) } + void MainFrame::init_tabpanel() { m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL); From c5152d04f8be8324eb0518ef04144bd13778496f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 28 Jan 2019 12:13:53 +0100 Subject: [PATCH 3/3] Set options value from edited preset instead of default preset, when call "Add Settings" + added code for custom editing of the frequently used settings bundle (it's commented for this moment) + some code refactoring --- src/slic3r/GUI/GUI_ObjectList.cpp | 145 ++++++++++++++++++++++++------ src/slic3r/GUI/GUI_ObjectList.hpp | 14 +++ 2 files changed, 132 insertions(+), 27 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 62c00d02d9..24e8644985 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -21,8 +21,6 @@ namespace GUI wxDEFINE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent); -typedef std::map> FreqSettingsBundle; - // pt_FFF FreqSettingsBundle FREQ_SETTINGS_BUNDLE_FFF = { @@ -587,9 +585,9 @@ void ObjectList::OnDrop(wxDataViewEvent &event) // Context Menu -std::vector get_options(const bool is_part, const bool is_sla) +std::vector ObjectList::get_options(const bool is_part) { - if (is_sla) { + if (wxGetApp().plater()->printer_technology() == ptSLA) { SLAPrintObjectConfig full_sla_config; auto options = full_sla_config.keys(); options.erase(find(options.begin(), options.end(), "layer_height")); @@ -605,13 +603,8 @@ std::vector get_options(const bool is_part, const bool is_sla) } return options; } - -std::vector get_options(const bool is_part) -{ - return get_options(is_part, wxGetApp().plater()->printer_technology() == ptSLA); -} -const std::vector& get_options_for_bundle(const wxString& bundle_name) +const std::vector& ObjectList::get_options_for_bundle(const wxString& bundle_name) { const FreqSettingsBundle& bundle = wxGetApp().plater()->printer_technology() == ptSLA ? FREQ_SETTINGS_BUNDLE_SLA : FREQ_SETTINGS_BUNDLE_FFF; @@ -621,14 +614,24 @@ const std::vector& get_options_for_bundle(const wxString& bundle_na if (bundle_name == _(it.first)) return it.second; } +#if 0 + // if "Quick menu" is selected + FreqSettingsBundle& bundle_quick = wxGetApp().plater()->printer_technology() == ptSLA ? + m_freq_settings_sla: m_freq_settings_fff; + + for (auto& it : bundle_quick) + { + if ( bundle_name == wxString::Format(_(L("Quick Add Settings (%s)")), _(it.first)) ) + return it.second; + } +#endif + return std::vector {}; } -// category -> vector ( option ; label ) -typedef std::map< std::string, std::vector< std::pair > > settings_menu_hierarchy; -void get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part, const bool is_sla) +void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part) { - auto options = get_options(is_part, is_sla); + auto options = get_options(is_part); auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : wxGetApp().preset_bundle->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); @@ -653,11 +656,6 @@ void get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part } } -void get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part) -{ - get_options_menu(settings_menu, is_part, wxGetApp().plater()->printer_technology() == ptSLA); -} - void ObjectList::get_settings_choice(const wxString& category_name) { wxArrayString names; @@ -691,10 +689,59 @@ void ObjectList::get_settings_choice(const wxString& category_name) if (wxGetSelectedChoices(selections, _(L("Select showing settings")), category_name, names) == -1) return; + const int selection_cnt = selections.size(); +#if 0 + if (selection_cnt > 0) + { + // Add selected items to the "Quick menu" + FreqSettingsBundle& freq_settings = wxGetApp().plater()->printer_technology() == ptSLA ? + m_freq_settings_sla : m_freq_settings_fff; + bool changed_existing = false; + + std::vector tmp_freq_cat = {}; + + for (auto& cat : freq_settings) + { + if (_(cat.first) == category_name) + { + std::vector& freq_settings_category = cat.second; + freq_settings_category.clear(); + freq_settings_category.reserve(selection_cnt); + for (auto sel : selections) + freq_settings_category.push_back((*settings_list)[sel].first); + + changed_existing = true; + break; + } + } + + if (!changed_existing) + { + // Create new "Quick menu" item + for (auto& cat : settings_menu) + { + if (_(cat.first) == category_name) + { + freq_settings[cat.first] = std::vector {}; + + std::vector& freq_settings_category = freq_settings.find(cat.first)->second; + freq_settings_category.reserve(selection_cnt); + for (auto sel : selections) + freq_settings_category.push_back((*settings_list)[sel].first); + break; + } + } + } + } +#endif + std::vector selected_options; + selected_options.reserve(selection_cnt); for (auto sel : selections) selected_options.push_back((*settings_list)[sel].first); + const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + for (auto& setting : (*settings_list)) { auto& opt_key = setting.first; @@ -703,8 +750,17 @@ void ObjectList::get_settings_choice(const wxString& category_name) m_config->erase(opt_key); if (find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end() && - find(selected_options.begin(), selected_options.end(), opt_key) != selected_options.end()) - m_config->set_key_value(opt_key, m_default_config->option(opt_key)->clone()); + find(selected_options.begin(), selected_options.end(), opt_key) != selected_options.end()) { + const ConfigOption* option = from_config.option(opt_key); + if (!option) { + // if current option doesn't exist in prints.get_edited_preset(), + // get it from m_default_config + if (m_default_config) delete m_default_config; + m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(false)); + option = m_default_config->option(opt_key); + } + m_config->set_key_value(opt_key, option->clone()); + } } @@ -718,10 +774,20 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name) auto opt_keys = m_config->keys(); + const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; for (auto& opt_key : options) { - if ( find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end() ) - m_config->set_key_value(opt_key, m_default_config->option(opt_key)->clone()); + if (find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end()) { + const ConfigOption* option = from_config.option(opt_key); + if (!option) { + // if current option doesn't exist in prints.get_edited_preset(), + // get it from m_default_config + if (m_default_config) delete m_default_config; + m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(false)); + option = m_default_config->option(opt_key); + } + m_config->set_key_value(opt_key, option->clone()); + } } // Add settings item for object @@ -835,7 +901,20 @@ wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_) if (settings_id != wxNOT_FOUND) menu->Destroy(settings_id); } - +#if 0 + for (auto& it : m_freq_settings_fff) + { + settings_id = menu->FindItem(wxString::Format(_(L("Quick Add Settings (%s)")), _(it.first))); + if (settings_id != wxNOT_FOUND) + menu->Destroy(settings_id); + } + for (auto& it : m_freq_settings_sla) + { + settings_id = menu->FindItem(wxString::Format(_(L("Quick Add Settings (%s)")), _(it.first))); + if (settings_id != wxNOT_FOUND) + menu->Destroy(settings_id); + } +#endif menu->DestroySeparators(); // delete old separators const auto sel_vol = get_selected_model_volume(); @@ -937,6 +1016,7 @@ wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu) void ObjectList::create_freq_settings_popupmenu(wxMenu *menu) { + // Add default settings bundles const FreqSettingsBundle& bundle = wxGetApp().plater()->printer_technology() == ptFFF ? FREQ_SETTINGS_BUNDLE_FFF : FREQ_SETTINGS_BUNDLE_SLA; @@ -951,6 +1031,20 @@ void ObjectList::create_freq_settings_popupmenu(wxMenu *menu) [menu, this](wxCommandEvent& event) { get_freq_settings_choice(menu->GetLabel(event.GetId())); }, CATEGORY_ICON.find(it.first) == CATEGORY_ICON.end() ? wxNullBitmap : CATEGORY_ICON.at(it.first), menu); } +#if 0 + // Add "Quick" settings bundles + const FreqSettingsBundle& bundle_quick = wxGetApp().plater()->printer_technology() == ptFFF ? + m_freq_settings_fff : m_freq_settings_sla; + + for (auto& it : bundle_quick) { + if (it.first.empty() || it.first == "Extruders" && extruders_cnt == 1) + continue; + + append_menu_item(menu, wxID_ANY, wxString::Format(_(L("Quick Add Settings (%s)")), _(it.first)), "", + [menu, this](wxCommandEvent& event) { get_freq_settings_choice(menu->GetLabel(event.GetId())); }, + CATEGORY_ICON.find(it.first) == CATEGORY_ICON.end() ? wxNullBitmap : CATEGORY_ICON.at(it.first), menu); + } +#endif } void ObjectList::update_opt_keys(t_config_option_keys& opt_keys) @@ -1381,9 +1475,6 @@ void ObjectList::part_selection_changed() m_config = &(*m_objects)[obj_idx_]->config; } } - - if (m_default_config) delete m_default_config; - m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(is_part)); } } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 060659049d..93a3ba60f1 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -25,6 +25,11 @@ class ModelVolume; // FIXME: broken build on mac os because of this is missing: typedef std::vector t_config_option_keys; +typedef std::map> FreqSettingsBundle; + +// category -> vector ( option ; label ) +typedef std::map< std::string, std::vector< std::pair > > settings_menu_hierarchy; + namespace GUI { wxDECLARE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent); @@ -129,6 +134,11 @@ class ObjectList : public wxDataViewCtrl int m_selected_row = 0; +#if 0 + FreqSettingsBundle m_freq_settings_fff; + FreqSettingsBundle m_freq_settings_sla; +#endif + public: ObjectList(wxWindow* parent); ~ObjectList(); @@ -264,6 +274,10 @@ private: void ItemValueChanged(wxDataViewEvent &event); void OnEditingDone(wxDataViewEvent &event); + + std::vector get_options(const bool is_part); + const std::vector& get_options_for_bundle(const wxString& bundle_name); + void get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part); };