From 48a94ebae14cf99726bb83369eb7886db0d70340 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 14 Dec 2018 09:52:54 +0100 Subject: [PATCH 01/10] Fixed scroll the Object List to selected item on OSX & GTK + fixed #1395 (maximum PresetComboBox's width limit on Ubuntu) --- src/slic3r/GUI/GUI_ObjectList.cpp | 8 +++----- src/slic3r/GUI/GUI_ObjectList.hpp | 2 -- src/slic3r/GUI/Plater.cpp | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 575444c4b..a90dff621 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1459,13 +1459,11 @@ void ObjectList::update_selections() select_items(sels); -#ifdef __WXMSW__ if (GetSelection()) { - const int sel_item_row = GetRowByItem(GetSelection()); - ScrollLines(sel_item_row - m_selected_row); - m_selected_row = sel_item_row; + const wxRect& top_rc = GetItemRect(GetTopItem()); + const wxRect& sel_rc = GetItemRect(GetSelection()); + ScrollLines(int((sel_rc.y - top_rc.y) / top_rc.GetHeight()) - 0.5*GetCountPerPage()); } -#endif //__WXMSW__ } void ObjectList::update_selections_on_canvas() diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 7631782df..3664e6fda 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -108,8 +108,6 @@ class ObjectList : public wxDataViewCtrl bool m_parts_changed = false; bool m_part_settings_changed = false; - int m_selected_row = 0; - public: ObjectList(wxWindow* parent); ~ObjectList(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b1526fdb4..381a9e864 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -213,7 +213,7 @@ void SlicedInfo::SetTextAndShow(SlisedInfoIdx idx, const wxString& text, const w } PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : - wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY), + wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200,-1), 0, nullptr, wxCB_READONLY), preset_type(preset_type), last_selected(wxNOT_FOUND) { From 2be23c8b149e4c4713707861f0528da06b9def59 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 14 Dec 2018 13:45:58 +0100 Subject: [PATCH 02/10] Eliminate build warning with TBB_USE_CAPTURED_EXCEPTION also make small adjustment on wxWidgets detection on Unix. --- src/CMakeLists.txt | 13 ++++++++++++- src/libnest2d/CMakeLists.txt | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d714eb91a..31c801379 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -46,7 +46,18 @@ endif() add_subdirectory(libslic3r) if (SLIC3R_GUI) - message(STATUS "WXWIN environment set to: $ENV{WXWIN}") + if(WIN32) + message(STATUS "WXWIN environment set to: $ENV{WXWIN}") + elseif(UNIX) + message(STATUS "wx-config path: ${wxWidgets_CONFIG_EXECUTABLE}") + set(wxWidgets_USE_UNICODE ON) + if(SLIC3R_STATIC) + set(wxWidgets_USE_STATIC ON) + else() + set(wxWidgets_USE_STATIC OFF) + endif() + endif() + find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl) include(${wxWidgets_USE_FILE}) endif() diff --git a/src/libnest2d/CMakeLists.txt b/src/libnest2d/CMakeLists.txt index 163143bcb..1faf542dd 100644 --- a/src/libnest2d/CMakeLists.txt +++ b/src/libnest2d/CMakeLists.txt @@ -68,7 +68,7 @@ if(TBB_FOUND) target_compile_definitions(libnest2d INTERFACE -D__TBB_NO_IMPLICIT_LINKAGE) endif() # The Intel TBB library will use the std::exception_ptr feature of C++11. - target_compile_definitions(libnest2d INTERFACE -DTBB_USE_CAPTURED_EXCEPTION=1) + target_compile_definitions(libnest2d INTERFACE -DTBB_USE_CAPTURED_EXCEPTION=0) target_link_libraries(libnest2d INTERFACE tbb) else() From dae01af2aca8a872a0393c9461c98691e3de9332 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 14 Dec 2018 16:58:55 +0100 Subject: [PATCH 03/10] Logging during sla processing. --- src/libslic3r/SLAPrint.cpp | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 0c61b591b..96b304ac2 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -420,6 +420,12 @@ void swapXY(ExPolygon& expoly) { } +template +void report_status(SLAPrint& p, int st, const std::string& msg, Args&&...args) { + BOOST_LOG_TRIVIAL(info) << st << "% " << msg; + p.set_status(st, msg, std::forward(args)...); +} + void SLAPrint::process() { using namespace sla; @@ -524,9 +530,11 @@ void SLAPrint::process() // scaling for the sub operations double d = *stthis / (objcount * 100.0); - ctl.statuscb = [this, init, d](unsigned st, const std::string& msg){ - set_status(int(init + st*d), msg); + ctl.statuscb = [this, init, d](unsigned st, const std::string& msg) + { + report_status(*this, int(init + st*d), msg); }; + ctl.stopcondition = [this](){ return canceled(); }; ctl.cancelfn = [this]() { throw_if_canceled(); }; @@ -536,9 +544,9 @@ void SLAPrint::process() // Create the unified mesh auto rc = SlicingStatus::RELOAD_SCENE; - set_status(-1, L("Visualizing supports")); + report_status(*this, -1, L("Visualizing supports")); po.m_supportdata->support_tree_ptr->merged_mesh(); - set_status(-1, L("Visualizing supports"), rc); + report_status(*this, -1, L("Visualizing supports"), rc); } catch(sla::SLASupportsStoppedException&) { // no need to rethrow // throw_if_canceled(); @@ -581,7 +589,7 @@ void SLAPrint::process() po.throw_if_canceled(); auto rc = SlicingStatus::RELOAD_SCENE; - set_status(-1, L("Visualizing supports"), rc); + report_status(*this, -1, L("Visualizing supports"), rc); }; // Slicing the support geometries similarly to the model slicing procedure. @@ -740,8 +748,12 @@ void SLAPrint::process() auto lvlcnt = unsigned(m_printer_input.size()); printer.layers(lvlcnt); + // slot is the portion of 100% that is realted to rasterization unsigned slot = PRINT_STEP_LEVELS[slapsRasterize]; + // ist: initial state; pst: previous state unsigned ist = max_objstatus, pst = ist; + // coefficient to map the rasterization state (0-99) to the allocated + // portion (slot) of the process state double sd = (100 - ist) / 100.0; SpinMutex slck; @@ -778,11 +790,11 @@ void SLAPrint::process() // Finish the layer for later saving it. printer.finish_layer(level_id); - // Status indication + // Status indication guarded with the spinlock auto st = ist + unsigned(sd*level_id*slot/m_printer_input.size()); { std::lock_guard lck(slck); if( st > pst) { - set_status(int(st), PRINT_STEP_LABELS[slapsRasterize]); + report_status(*this, int(st), PRINT_STEP_LABELS[slapsRasterize]); pst = st; } } @@ -832,9 +844,14 @@ void SLAPrint::process() unsigned st = min_objstatus; unsigned incr = 0; + BOOST_LOG_TRIVIAL(info) << "Start slicing process."; + // TODO: this loop could run in parallel but should not exhaust all the CPU // power available for(SLAPrintObject * po : m_objects) { + + BOOST_LOG_TRIVIAL(info) << "Slicing object " << po->model_object()->name; + for(size_t s = 0; s < objectsteps.size(); ++s) { auto currentstep = objectsteps[s]; @@ -846,8 +863,7 @@ void SLAPrint::process() st += unsigned(incr * ostepd); if(po->m_stepmask[currentstep] && po->set_started(currentstep)) { - - set_status(int(st), OBJ_STEP_LABELS[currentstep]); + report_status(*this, int(st), OBJ_STEP_LABELS[currentstep]); pobj_program[currentstep](*po); po->set_done(currentstep); } @@ -872,7 +888,7 @@ void SLAPrint::process() if(m_stepmask[currentstep] && set_started(currentstep)) { - set_status(int(st), PRINT_STEP_LABELS[currentstep]); + report_status(*this, int(st), PRINT_STEP_LABELS[currentstep]); print_program[currentstep](); set_done(currentstep); } @@ -881,7 +897,7 @@ void SLAPrint::process() } // If everything vent well - set_status(100, L("Slicing done")); + report_status(*this, 100, L("Slicing done")); } bool SLAPrint::invalidate_state_by_config_options(const std::vector &opt_keys) From 907e51053553e393e95768b1a7bc2f9e7c5135c7 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 14 Dec 2018 16:07:28 +0100 Subject: [PATCH 04/10] Changed PrusaBitmapTextRenderer's inheritance to wxDataViewRenderer instead of wxDataViewCustomRenderer : to fix name editing under OSX --- src/slic3r/GUI/GUI_ObjectList.cpp | 4 +++- src/slic3r/GUI/wxExtensions.cpp | 34 +++++++++++++++++++++++++++---- src/slic3r/GUI/wxExtensions.hpp | 14 +++++++------ 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index a90dff621..78310443d 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1654,7 +1654,9 @@ void ObjectList::change_part_type() void ObjectList::last_volume_is_deleted(const int obj_idx) { - if (obj_idx < 0 || (*m_objects).empty() || (*m_objects)[obj_idx]->volumes.empty()) + if (obj_idx < 0 || m_objects->empty() || + obj_idx <= m_objects->size() || + (*m_objects)[obj_idx]->volumes.empty()) return; auto volume = (*m_objects)[obj_idx]->volumes[0]; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 2e5a37040..710710913 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -1228,6 +1228,14 @@ void PrusaObjectDataViewModel::SetVolumeType(const wxDataViewItem &item, const i ItemChanged(item); } +PrusaBitmapTextRenderer::PrusaBitmapTextRenderer(wxDataViewCellMode mode /*= wxDATAVIEW_CELL_EDITABLE*/, + int align /*= wxDVR_DEFAULT_ALIGNMENT*/): +wxDataViewRenderer(wxT("PrusaDataViewBitmapText"), mode, align) +{ + SetMode(mode); + SetAlignment(align); +} + //----------------------------------------------------------------------------- // PrusaDataViewBitmapText //----------------------------------------------------------------------------- @@ -1251,6 +1259,13 @@ bool PrusaBitmapTextRenderer::GetValue(wxVariant& WXUNUSED(value)) const return false; } +#if wxUSE_ACCESSIBILITY +wxString PrusaBitmapTextRenderer::GetAccessibleDescription() const +{ + return m_value.GetText(); +} +#endif // wxUSE_ACCESSIBILITY + bool PrusaBitmapTextRenderer::Render(wxRect rect, wxDC *dc, int state) { int xoffset = 0; @@ -1291,12 +1306,12 @@ wxWindow* PrusaBitmapTextRenderer::CreateEditorCtrl(wxWindow* parent, wxRect lab PrusaDataViewBitmapText data; data << value; - m_bmp_from_editing_item = data.GetBitmap(); + m_was_unusable_symbol = false; wxPoint position = labelRect.GetPosition(); - if (m_bmp_from_editing_item.IsOk()) { - const int bmp_width = m_bmp_from_editing_item.GetWidth(); + if (data.GetBitmap().IsOk()) { + const int bmp_width = data.GetBitmap().GetWidth(); position.x += bmp_width; labelRect.SetWidth(labelRect.GetWidth() - bmp_width); } @@ -1304,6 +1319,7 @@ wxWindow* PrusaBitmapTextRenderer::CreateEditorCtrl(wxWindow* parent, wxRect lab wxTextCtrl* text_editor = new wxTextCtrl(parent, wxID_ANY, data.GetText(), position, labelRect.GetSize(), wxTE_PROCESS_ENTER); text_editor->SetInsertionPointEnd(); + text_editor->SelectAll(); return text_editor; } @@ -1323,7 +1339,17 @@ bool PrusaBitmapTextRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& } } - value << PrusaDataViewBitmapText(text_editor->GetValue(), m_bmp_from_editing_item); + // The icon can't be edited so get its old value and reuse it. + wxVariant valueOld; + GetView()->GetModel()->GetValue(valueOld, m_item, 0); + + PrusaDataViewBitmapText bmpText; + bmpText << valueOld; + + // But replace the text with the value entered by user. + bmpText.SetText(text_editor->GetValue()); + + value << bmpText; return true; } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 3fbf9a083..e3fd1cbf6 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -519,15 +519,18 @@ public: // PrusaBitmapTextRenderer // ---------------------------------------------------------------------------- -class PrusaBitmapTextRenderer : public wxDataViewCustomRenderer +class PrusaBitmapTextRenderer : public wxDataViewRenderer//CustomRenderer { public: - PrusaBitmapTextRenderer( wxDataViewCellMode mode = wxDATAVIEW_CELL_EDITABLE, - int align = wxDVR_DEFAULT_ALIGNMENT): - wxDataViewCustomRenderer(wxT("PrusaDataViewBitmapText"), mode, align) {} + PrusaBitmapTextRenderer(wxDataViewCellMode mode = wxDATAVIEW_CELL_EDITABLE, + int align = wxDVR_DEFAULT_ALIGNMENT);//: +// wxDataViewRenderer/*CustomRenderer*/(wxT("PrusaDataViewBitmapText"), mode, align) {} bool SetValue(const wxVariant &value); bool GetValue(wxVariant &value) const; +#if wxUSE_ACCESSIBILITY + virtual wxString GetAccessibleDescription() const override; +#endif // wxUSE_ACCESSIBILITY virtual bool Render(wxRect cell, wxDC *dc, int state); virtual wxSize GetSize() const; @@ -542,8 +545,7 @@ public: private: PrusaDataViewBitmapText m_value; - wxBitmap m_bmp_from_editing_item; - bool m_was_unusable_symbol; + bool m_was_unusable_symbol {false}; }; From 880c1ef2b4ea05cef2d5db28531efe80db06fc57 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 14 Dec 2018 17:09:44 +0100 Subject: [PATCH 05/10] Next try to fix scroll the Object List to selected item (OSX & GTK) --- src/slic3r/GUI/GUI_ObjectList.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 78310443d..a7f1ca608 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1460,9 +1460,12 @@ void ObjectList::update_selections() select_items(sels); if (GetSelection()) { - const wxRect& top_rc = GetItemRect(GetTopItem()); const wxRect& sel_rc = GetItemRect(GetSelection()); - ScrollLines(int((sel_rc.y - top_rc.y) / top_rc.GetHeight()) - 0.5*GetCountPerPage()); + if (!sel_rc.IsEmpty()) { + const int rc_h = sel_rc.height; + const int displ = GetMainWindow()->GetClientRect().GetHeight()/(2*rc_h)+1; + ScrollLines(int(sel_rc.y / rc_h - displ)); + } } } From 506cbcb4a7027834bd07038c8e186cda197915bd Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 14 Dec 2018 17:17:51 +0100 Subject: [PATCH 06/10] Fix of G-code invalidation on "wipe_into_object" "wipe_into_infill" changes. WIP: Fix of "levitating objects cannot be sliced". --- src/libslic3r/Layer.cpp | 10 ++++++++++ src/libslic3r/Layer.hpp | 3 ++- src/libslic3r/PrintObject.cpp | 24 +++++++++++++++--------- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index 7878bffab..fa5d29692 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -17,6 +17,16 @@ Layer::~Layer() m_regions.clear(); } +// Test whether whether there are any slices assigned to this layer. +bool Layer::empty() const +{ + for (const LayerRegion *layerm : m_regions) + if (layerm != nullptr && ! layerm->slices.empty()) + // Non empty layer. + return false; + return true; +} + LayerRegion* Layer::add_region(PrintRegion* print_region) { m_regions.emplace_back(new LayerRegion(this, print_region)); diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 8dbe850cc..78897a2db 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -114,7 +114,8 @@ public: LayerRegion* get_region(int idx) { return m_regions[idx]; } LayerRegion* add_region(PrintRegion* print_region); const LayerRegionPtrs& regions() const { return m_regions; } - + // Test whether whether there are any slices assigned to this layer. + bool empty() const; void make_slices(); void merge_slices(); template bool any_internal_region_slice_contains(const T &item) const { diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 4b7a8906f..772d930aa 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -384,6 +384,12 @@ void PrintObject::generate_support_material() m_print->set_status(85, "Generating support material"); this->_generate_support_material(); m_print->throw_if_canceled(); + } else { + // Printing without supports. Empty layer means some objects or object parts are levitating, + // therefore they cannot be printed without supports. + for (const Layer *layer : m_layers) + if (layer->empty()) + throw std::runtime_error("Levitating objects cannot be printed without supports."); } this->set_done(posSupportMaterial); } @@ -522,11 +528,13 @@ bool PrintObject::invalidate_state_by_config_options(const std::vectorinvalidate_step(psGCodeExport); + } else if ( + opt_key == "wipe_into_infill" + || opt_key == "wipe_into_objects") { + invalidated |= m_print->invalidate_step(psWipeTower); + invalidated |= m_print->invalidate_step(psGCodeExport); } else { // for legacy, if we can't handle this option let's invalidate all steps this->invalidate_all_steps(); @@ -1463,10 +1471,8 @@ void PrintObject::_slice() BOOST_LOG_TRIVIAL(debug) << "Slicing objects - removing top empty layers"; while (! m_layers.empty()) { const Layer *layer = m_layers.back(); - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) - if (layer->m_regions[region_id] != nullptr && ! layer->m_regions[region_id]->slices.empty()) - // Non empty layer. - goto end; + if (! layer->empty()) + goto end; delete layer; m_layers.pop_back(); if (! m_layers.empty()) From d6471e7b071129a49f936a85697d5e8c3759730f Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 14 Dec 2018 17:19:17 +0100 Subject: [PATCH 07/10] Fix of SLADisplayOrientation updates --- src/libslic3r/PrintConfig.cpp | 6 ++++-- src/libslic3r/PrintConfig.hpp | 4 ++-- src/slic3r/GUI/Field.cpp | 2 ++ src/slic3r/GUI/GUI.cpp | 2 ++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index ab26f5d54..8a564b6b5 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2394,8 +2394,10 @@ void PrintConfigDef::init_sla_params() def->tooltip = L("Display orientation"); def->cli = "display-orientation=s"; def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); - def->enum_values.push_back("Landscape"); - def->enum_values.push_back("Portrait"); + def->enum_values.push_back("landscape"); + def->enum_values.push_back("portrait"); + def->enum_labels.push_back(L("Landscape")); + def->enum_labels.push_back(L("Portrait")); def->default_value = new ConfigOptionEnum(sladoPortrait); def = this->add("printer_correction", coFloats); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index f639cad76..1949a8ac8 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -155,8 +155,8 @@ template<> inline const t_config_enum_values& ConfigOptionEnum::ge template<> inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { static const t_config_enum_values keys_map = { - { "Landscape", sladoLandscape}, - { "Portrait", sladoPortrait} + { "landscape", sladoLandscape}, + { "portrait", sladoPortrait} }; return keys_map; diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index ebc7f3665..d4126d933 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -638,6 +638,8 @@ boost::any& Choice::get_value() m_value = static_cast(ret_enum); else if (m_opt_id.compare("host_type") == 0) m_value = static_cast(ret_enum); + else if (m_opt_id.compare("display_orientation") == 0) + m_value = static_cast(ret_enum); } return m_value; diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index bc7ea9899..fb6676aed 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -195,6 +195,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("host_type") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + else if (opt_key.compare("display_orientation") == 0) + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); } break; case coPoints:{ From 77d37f108c3ba68afaebda9f54933f2b4185aaab Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 14 Dec 2018 19:29:58 +0100 Subject: [PATCH 08/10] Iterative, not recursive, version of the Douglas-Peucker-Ramer algorithm based on the work by @fuchstraumer https://github.com/slic3r/Slic3r/pull/3825 https://gist.github.com/fuchstraumer/9421573fc281b946e5f561758961212a which was based on http://anis-moussa.blogspot.com/2014/03/ramer-douglas-peucker-algorithm-for.html --- src/libslic3r/Line.cpp | 23 +++++------ src/libslic3r/Line.hpp | 6 ++- src/libslic3r/MultiPoint.cpp | 78 +++++++++++++++++++----------------- 3 files changed, 58 insertions(+), 49 deletions(-) diff --git a/src/libslic3r/Line.cpp b/src/libslic3r/Line.cpp index 35cfa2b76..02f1cb7c2 100644 --- a/src/libslic3r/Line.cpp +++ b/src/libslic3r/Line.cpp @@ -34,23 +34,22 @@ bool Line::intersection_infinite(const Line &other, Point* point) const return true; } -/* distance to the closest point of line */ -double Line::distance_to(const Point &point) const +// Distance to the closest point of line. +double Line::distance_to_squared(const Point &point, const Point &a, const Point &b) { - const Line &line = *this; - const Vec2d v = (line.b - line.a).cast(); - const Vec2d va = (point - line.a).cast(); + const Vec2d v = (b - a).cast(); + const Vec2d va = (point - a).cast(); const double l2 = v.squaredNorm(); // avoid a sqrt if (l2 == 0.0) - // line.a == line.b case - return va.norm(); - // Consider the line extending the segment, parameterized as line.a + t (line.b - line.a). + // a == b case + return va.squaredNorm(); + // Consider the line extending the segment, parameterized as a + t (b - a). // We find projection of this point onto the line. - // It falls where t = [(this-line.a) . (line.b-line.a)] / |line.b-line.a|^2 + // It falls where t = [(this-a) . (b-a)] / |b-a|^2 const double t = va.dot(v) / l2; - if (t < 0.0) return va.norm(); // beyond the 'a' end of the segment - else if (t > 1.0) return (point - line.b).cast().norm(); // beyond the 'b' end of the segment - return (t * v - va).norm(); + if (t < 0.0) return va.squaredNorm(); // beyond the 'a' end of the segment + else if (t > 1.0) return (point - b).cast().squaredNorm(); // beyond the 'b' end of the segment + return (t * v - va).squaredNorm(); } double Line::perp_distance_to(const Point &point) const diff --git a/src/libslic3r/Line.hpp b/src/libslic3r/Line.hpp index 36e02247c..559ca946a 100644 --- a/src/libslic3r/Line.hpp +++ b/src/libslic3r/Line.hpp @@ -31,7 +31,8 @@ public: Point midpoint() const { return (this->a + this->b) / 2; } bool intersection_infinite(const Line &other, Point* point) const; bool operator==(const Line &rhs) const { return this->a == rhs.a && this->b == rhs.b; } - double distance_to(const Point &point) const; + double distance_to_squared(const Point &point) const { return distance_to_squared(point, this->a, this->b); } + double distance_to(const Point &point) const { return distance_to(point, this->a, this->b); } double perp_distance_to(const Point &point) const; bool parallel_to(double angle) const; bool parallel_to(const Line &line) const { return this->parallel_to(line.direction()); } @@ -43,6 +44,9 @@ public: bool intersection(const Line& line, Point* intersection) const; double ccw(const Point& point) const { return point.ccw(*this); } + static double distance_to_squared(const Point &point, const Point &a, const Point &b); + static double distance_to(const Point &point, const Point &a, const Point &b) { return sqrt(distance_to_squared(point, a, b)); } + Point a; Point b; }; diff --git a/src/libslic3r/MultiPoint.cpp b/src/libslic3r/MultiPoint.cpp index 93c63c4cf..795ee38c2 100644 --- a/src/libslic3r/MultiPoint.cpp +++ b/src/libslic3r/MultiPoint.cpp @@ -162,45 +162,51 @@ bool MultiPoint::first_intersection(const Line& line, Point* intersection) const return found; } -//FIXME This is very inefficient in term of memory use. -// The recursive algorithm shall run in place, not allocating temporary data in each recursion. -Points -MultiPoint::_douglas_peucker(const Points &points, const double tolerance) +std::vector MultiPoint::_douglas_peucker(const std::vector& pts, const double tolerance) { - assert(points.size() >= 2); - Points results; - double dmax = 0; - size_t index = 0; - Line full(points.front(), points.back()); - for (Points::const_iterator it = points.begin() + 1; it != points.end(); ++it) { - // we use shortest distance, not perpendicular distance - double d = full.distance_to(*it); - if (d > dmax) { - index = it - points.begin(); - dmax = d; + std::vector result_pts; + if (! pts.empty()) { + const Point *anchor = &pts.front(); + size_t anchor_idx = 0; + const Point *floater = &pts.back(); + size_t floater_idx = pts.size() - 1; + result_pts.reserve(pts.size()); + result_pts.emplace_back(*anchor); + if (anchor_idx != floater_idx) { + assert(pts.size() > 1); + std::vector dpStack; + dpStack.reserve(pts.size()); + dpStack.emplace_back(floater_idx); + for (;;) { + double max_distSq = 0.0; + size_t furthest_idx = anchor_idx; + // find point furthest from line seg created by (anchor, floater) and note it + for (size_t i = anchor_idx + 1; i < floater_idx; ++ i) { + double dist = Line::distance_to_squared(pts[i], *anchor, *floater); + if (dist > max_distSq) { + max_distSq = dist; + furthest_idx = i; + } + } + // remove point if less than tolerance + if (max_distSq <= tolerance) { + result_pts.emplace_back(*floater); + anchor_idx = floater_idx; + anchor = floater; + assert(dpStack.back() == floater_idx); + dpStack.pop_back(); + if (dpStack.empty()) + break; + floater_idx = dpStack.back(); + } else { + floater_idx = furthest_idx; + dpStack.emplace_back(floater_idx); + } + floater = &pts[floater_idx]; + } } } - if (dmax >= tolerance) { - Points dp0; - dp0.reserve(index + 1); - dp0.insert(dp0.end(), points.begin(), points.begin() + index + 1); - // Recursive call. - Points dp1 = MultiPoint::_douglas_peucker(dp0, tolerance); - results.reserve(results.size() + dp1.size() - 1); - results.insert(results.end(), dp1.begin(), dp1.end() - 1); - - dp0.clear(); - dp0.reserve(points.size() - index); - dp0.insert(dp0.end(), points.begin() + index, points.end()); - // Recursive call. - dp1 = MultiPoint::_douglas_peucker(dp0, tolerance); - results.reserve(results.size() + dp1.size()); - results.insert(results.end(), dp1.begin(), dp1.end()); - } else { - results.push_back(points.front()); - results.push_back(points.back()); - } - return results; + return result_pts; } // Visivalingam simplification algorithm https://github.com/slic3r/Slic3r/pull/3825 From 37806c020a1e4bcc54d9349ba009c7d4acd0d73b Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 14 Dec 2018 19:40:02 +0100 Subject: [PATCH 09/10] Temporarily disabled the following check: "Levitating objects cannot be printed without support" until the unit tests are adjusted. --- src/libslic3r/PrintObject.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 772d930aa..fdf950ee5 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -385,11 +385,13 @@ void PrintObject::generate_support_material() this->_generate_support_material(); m_print->throw_if_canceled(); } else { +#if 0 // Printing without supports. Empty layer means some objects or object parts are levitating, // therefore they cannot be printed without supports. for (const Layer *layer : m_layers) if (layer->empty()) throw std::runtime_error("Levitating objects cannot be printed without supports."); +#endif } this->set_done(posSupportMaterial); } From 6da83c797690afbb4c455e2a90e54fe3d6cc9ed3 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 14 Dec 2018 20:09:10 +0100 Subject: [PATCH 10/10] Make the increase of extruder motor current during MM filament exchange sequences configurable. --- src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 24 +++++++++++++----------- src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 5 ++++- src/libslic3r/Print.cpp | 4 +++- src/libslic3r/PrintConfig.cpp | 9 +++++++++ src/libslic3r/PrintConfig.hpp | 2 ++ src/slic3r/GUI/Preset.cpp | 3 ++- src/slic3r/GUI/Tab.cpp | 1 + 7 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 5c24cd71c..db38a7462 100644 --- a/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -505,8 +505,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( .speed_override(100); writer.set_initial_position(xy(0.f, 0.f)) // Always move to the starting position - .travel(cleaning_box.ld, 7200) - .set_extruder_trimpot(750); // Increase the extruder driver current to allow fast ramming. + .travel(cleaning_box.ld, 7200); + if (m_set_extruder_trimpot) + writer.set_extruder_trimpot(750); // Increase the extruder driver current to allow fast ramming. for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) { unsigned int tool = tools[idx_tool]; @@ -533,8 +534,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // in the output gcode - we should not remember emitting them (we will output them twice in the worst case) // Reset the extruder current to a normal value. - writer.set_extruder_trimpot(550) - .feedrate(6000) + if (m_set_extruder_trimpot) + writer.set_extruder_trimpot(550); + writer.feedrate(6000) .flush_planner_queue() .reset_extruder() .append("; CP PRIMING END\n" @@ -607,7 +609,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); // Increase the extruder driver current to allow fast ramming. - writer.set_extruder_trimpot(750); + if (m_set_extruder_trimpot) + writer.set_extruder_trimpot(550); // Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool. if (tool != (unsigned int)-1){ // This is not the last change. @@ -635,8 +638,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo } } - writer.set_extruder_trimpot(550) // Reset the extruder current to a normal value. - .feedrate(6000) + if (m_set_extruder_trimpot) + writer.set_extruder_trimpot(550); // Reset the extruder current to a normal value. + writer.feedrate(6000) .flush_planner_queue() .reset_extruder() .append("; CP TOOLCHANGE END\n" @@ -916,12 +920,10 @@ void WipeTowerPrusaMM::toolchange_Load( .resume_preview(); // Reset the extruder current to the normal value. - writer.set_extruder_trimpot(550); + if (m_set_extruder_trimpot) + writer.set_extruder_trimpot(550); } - - - // Wipe the newly loaded filament until the end of the assigned wipe area. void WipeTowerPrusaMM::toolchange_Wipe( PrusaMultiMaterial::Writer &writer, diff --git a/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 06625d189..c0aeee3ae 100644 --- a/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -44,7 +44,8 @@ public: // width -- width of wipe tower in mm ( default 60 mm - leave as it is ) // wipe_area -- space available for one toolchange in mm WipeTowerPrusaMM(float x, float y, float width, float rotation_angle, float cooling_tube_retraction, - float cooling_tube_length, float parking_pos_retraction, float extra_loading_move, float bridging, + float cooling_tube_length, float parking_pos_retraction, float extra_loading_move, + float bridging, bool set_extruder_trimpot, const std::vector>& wiping_matrix, unsigned int initial_tool) : m_wipe_tower_pos(x, y), m_wipe_tower_width(width), @@ -57,6 +58,7 @@ public: m_parking_pos_retraction(parking_pos_retraction), m_extra_loading_move(extra_loading_move), m_bridging(bridging), + m_set_extruder_trimpot(set_extruder_trimpot), m_current_tool(initial_tool), wipe_volumes(wiping_matrix) {} @@ -212,6 +214,7 @@ private: float m_parking_pos_retraction = 0.f; float m_extra_loading_move = 0.f; float m_bridging = 0.f; + bool m_set_extruder_trimpot = false; bool m_adhesion = true; float m_perimeter_width = 0.4 * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 77cf9c0f6..e3382573c 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -213,6 +213,7 @@ bool Print::invalidate_state_by_config_options(const std::vectormode = comExpert; def->default_value = new ConfigOptionEnum(gcfRepRap); + def = this->add("high_current_on_filament_swap", coBool); + def->label = L("High extruder current on filament swap"); + def->tooltip = L("It may be beneficial to increase the extruder motor current during the filament exchange" + " sequence to allow for rapid ramming feed rates and to overcome resistance when loading" + " a filament with an ugly shaped tip."); + def->cli = "high-current-on-filament-swap!"; + def->mode = comExpert; + def->default_value = new ConfigOptionBool(0); + def = this->add("infill_acceleration", coFloat); def->label = L("Infill"); def->tooltip = L("This is the acceleration your printer will use for infill. Set zero to disable " diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 1949a8ac8..487e35bf2 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -627,6 +627,7 @@ public: ConfigOptionBool variable_layer_height; ConfigOptionFloat cooling_tube_retraction; ConfigOptionFloat cooling_tube_length; + ConfigOptionBool high_current_on_filament_swap; ConfigOptionFloat parking_pos_retraction; ConfigOptionBool remaining_times; ConfigOptionBool silent_mode; @@ -695,6 +696,7 @@ protected: OPT_PTR(variable_layer_height); OPT_PTR(cooling_tube_retraction); OPT_PTR(cooling_tube_length); + OPT_PTR(high_current_on_filament_swap); OPT_PTR(parking_pos_retraction); OPT_PTR(remaining_times); OPT_PTR(silent_mode); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 639f70cf7..90372ecd4 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -366,7 +366,8 @@ const std::vector& Preset::printer_options() "host_type", "print_host", "printhost_apikey", "printhost_cafile", "single_extruder_multi_material", "start_gcode", "end_gcode", "before_layer_gcode", "layer_gcode", "toolchange_gcode", "between_objects_gcode", "printer_vendor", "printer_model", "printer_variant", "printer_notes", "cooling_tube_retraction", - "cooling_tube_length", "parking_pos_retraction", "extra_loading_move", "max_print_height", "default_print_profile", "inherits", + "cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "max_print_height", + "default_print_profile", "inherits", "remaining_times", "silent_mode", "machine_max_acceleration_extruding", "machine_max_acceleration_retracting", "machine_max_acceleration_x", "machine_max_acceleration_y", "machine_max_acceleration_z", "machine_max_acceleration_e", "machine_max_feedrate_x", "machine_max_feedrate_y", "machine_max_feedrate_z", "machine_max_feedrate_e", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6372f7321..30d83d845 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2041,6 +2041,7 @@ void TabPrinter::build_extruder_pages() optgroup->append_single_option_line("cooling_tube_length"); optgroup->append_single_option_line("parking_pos_retraction"); optgroup->append_single_option_line("extra_loading_move"); + optgroup->append_single_option_line("high_current_on_filament_swap"); m_pages.insert(m_pages.end() - n_after_single_extruder_MM, page); m_has_single_extruder_MM_page = true; }