From 0e9e487930b3172bcf21580fedb2adc1232eac56 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 28 Nov 2017 17:32:11 +0100 Subject: [PATCH 01/81] First implementation of wipe tower rotation --- xs/src/libslic3r/GCode/WipeTower.hpp | 10 ++++ xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 52 +++++++++++++++------ 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index c5fa27392..329d92b22 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -23,6 +23,16 @@ public: xy& operator-=(const xy &rhs) { x -= rhs.x; y -= rhs.y; return *this; } bool operator==(const xy &rhs) { return x == rhs.x && y == rhs.y; } bool operator!=(const xy &rhs) { return x != rhs.x || y != rhs.y; } + + // Rotate the point around given point about given angle (in degrees) + xy rotate(const xy& origin, float angle) const { + xy out(0,0); + angle *= M_PI/180.; + out.x=(x-origin.x) * cos(angle) - (y-origin.y) * sin(angle); + out.y=(x-origin.x) * sin(angle) + (y-origin.y) * cos(angle); + return out+origin; + } + float x; float y; }; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 951d71075..5a7ee0002 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -14,6 +14,9 @@ #define strcasecmp _stricmp #endif +#define ROTATION_ANGLE 30 + + namespace Slic3r { @@ -47,6 +50,9 @@ public: Writer& set_extrusion_flow(float flow) { m_extrusion_flow = flow; return *this; } + + Writer& set_rotation(WipeTower::xy pos,float angle) + { m_wipe_tower_pos = pos; m_angle_deg = angle; return (*this); } // Suppress / resume G-code preview in Slic3r. Slic3r will have difficulty to differentiate the various // filament loading and cooling moves from normal extrusion moves. Therefore the writer @@ -67,6 +73,7 @@ public: float y() const { return m_current_pos.y; } const WipeTower::xy& start_pos() const { return m_start_pos; } const WipeTower::xy& pos() const { return m_current_pos; } + const WipeTower::xy printer_pos() const { return m_current_pos.rotate(m_wipe_tower_pos,m_angle_deg); } float elapsed_time() const { return m_elapsed_time; } // Extrude with an explicitely provided amount of extrusion. @@ -79,29 +86,43 @@ public: float dx = x - m_current_pos.x; float dy = y - m_current_pos.y; double len = sqrt(dx*dx+dy*dy); + + // For rotated wipe tower, transform position to printer coordinates + //Q zavadet nove promenne? rotace o zaporny uhel? + WipeTower::xy rotated_current_pos( m_current_pos.rotate(m_wipe_tower_pos,m_angle_deg) ); + WipeTower::xy rot( WipeTower::xy(x,y).rotate(m_wipe_tower_pos,m_angle_deg ) ); + + if (! m_preview_suppressed && e > 0.f && len > 0.) { // Width of a squished extrusion, corrected for the roundings of the squished extrusions. // This is left zero if it is a travel move. float width = float(double(e) * m_filament_area / (len * m_layer_height)); // Correct for the roundings of a squished extrusion. width += float(m_layer_height * (1. - M_PI / 4.)); - if (m_extrusions.empty() || m_extrusions.back().pos != m_current_pos) - m_extrusions.emplace_back(WipeTower::Extrusion(m_current_pos, 0, m_current_tool)); - m_extrusions.emplace_back(WipeTower::Extrusion(WipeTower::xy(x, y), width, m_current_tool)); + if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos) + m_extrusions.emplace_back(WipeTower::Extrusion(rotated_current_pos, 0, m_current_tool)); + m_extrusions.emplace_back(WipeTower::Extrusion(WipeTower::xy(rot.x, rot.y), width, m_current_tool)); } m_gcode += "G1"; - if (x != m_current_pos.x) - m_gcode += set_format_X(x); - if (y != m_current_pos.y) - m_gcode += set_format_Y(y); + if (rot.x != rotated_current_pos.x) + m_gcode += set_format_X(rot.x); + if (rot.y != rotated_current_pos.y) + m_gcode += set_format_Y(rot.y); + + // Transform current position back to wipe tower coordinates (was updated by set_format_X) + m_current_pos.x = x; + m_current_pos.y = y; if (e != 0.f) m_gcode += set_format_E(e); if (f != 0.f && f != m_current_feedrate) m_gcode += set_format_F(f); - + + + + // Update the elapsed time with a rough estimate. m_elapsed_time += ((len == 0) ? std::abs(e) : len) / m_current_feedrate * 60.f; m_gcode += "\n"; @@ -278,6 +299,8 @@ private: std::vector m_extrusions; float m_elapsed_time; const double m_filament_area = 0.25*M_PI*1.75*1.75; + float m_angle_deg = 0; + WipeTower::xy m_wipe_tower_pos; std::string set_format_X(float x) { char buf[64]; @@ -338,7 +361,7 @@ public: }; */ -} // namespace PrusaMultiMaterial +}; // namespace PrusaMultiMaterial WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *name) { @@ -470,7 +493,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( result.elapsed_time = writer.elapsed_time(); result.extrusions = writer.extrusions(); result.start_pos = writer.start_pos(); - result.end_pos = writer.pos(); + result.end_pos = writer.printer_pos(); return result; } @@ -525,6 +548,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .set_z(m_z_pos) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) + .set_rotation(this->m_wipe_tower_pos,ROTATION_ANGLE) .append(";--------------------\n" "; CP TOOLCHANGE START\n") .comment_with_value(" toolchange #", m_num_tool_changes) @@ -605,7 +629,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo result.elapsed_time = writer.elapsed_time(); result.extrusions = writer.extrusions(); result.start_pos = writer.start_pos(); - result.end_pos = writer.pos(); + result.end_pos = writer.printer_pos(); return result; } @@ -622,6 +646,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b .set_z(m_z_pos) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) + .set_rotation(this->m_wipe_tower_pos,ROTATION_ANGLE) .append( ";-------------------------------------\n" "; CP WIPE TOWER FIRST LAYER BRIM START\n"); @@ -705,7 +730,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b result.elapsed_time = writer.elapsed_time(); result.extrusions = writer.extrusions(); result.start_pos = writer.start_pos(); - result.end_pos = writer.pos(); + result.end_pos = writer.printer_pos(); return result; } @@ -910,6 +935,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) .set_z(m_z_pos) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) + .set_rotation(this->m_wipe_tower_pos,ROTATION_ANGLE) .append(";--------------------\n" "; CP EMPTY GRID START\n") // m_num_layer_changes is incremented by set_z, so it is 1 based. @@ -1025,7 +1051,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) result.elapsed_time = writer.elapsed_time(); result.extrusions = writer.extrusions(); result.start_pos = writer.start_pos(); - result.end_pos = writer.pos(); + result.end_pos = writer.printer_pos(); return result; } From 2921302fe9602dae3974cb8bbdaea8dcb17677c4 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 30 Nov 2017 12:08:22 +0100 Subject: [PATCH 02/81] GUI integration of rotation angle setting --- lib/Slic3r/GUI/Plater.pm | 2 +- lib/Slic3r/GUI/Tab.pm | 3 ++- xs/src/libslic3r/GCode/WipeTower.hpp | 2 +- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 7 +++---- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 8 +++++++- xs/src/libslic3r/Print.cpp | 3 ++- xs/src/libslic3r/PrintConfig.cpp | 7 +++++++ xs/src/libslic3r/PrintConfig.hpp | 2 ++ xs/src/slic3r/GUI/Preset.cpp | 2 +- 9 files changed, 26 insertions(+), 10 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index a6915bb7c..cdb03e791 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -52,7 +52,7 @@ sub new { bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height serial_port serial_speed octoprint_host octoprint_apikey nozzle_diameter single_extruder_multi_material - wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe extruder_colour filament_colour + wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe wipe_tower_rotation_angle extruder_colour filament_colour )]); # C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm $self->{model} = Slic3r::Model->new; diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 907be7872..d43c33ff1 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -725,6 +725,7 @@ sub build { $optgroup->append_single_option_line('wipe_tower_y'); $optgroup->append_single_option_line('wipe_tower_width'); $optgroup->append_single_option_line('wipe_tower_per_color_wipe'); + $optgroup->append_single_option_line('wipe_tower_rotation_angle'); } { my $optgroup = $page->new_optgroup('Advanced'); @@ -1032,7 +1033,7 @@ sub _update { my $have_wipe_tower = $config->wipe_tower; $self->get_field($_)->toggle($have_wipe_tower) - for qw(wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe); + for qw(wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe wipe_tower_rotation_angle); $self->Thaw; } diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index f55fd5c2f..8a97333de 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -32,7 +32,7 @@ public: out.y=(x-origin.x) * sin(angle) + (y-origin.y) * cos(angle); return out+origin; } - + float x; float y; }; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 5a7ee0002..3df1e9d4a 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -14,7 +14,6 @@ #define strcasecmp _stricmp #endif -#define ROTATION_ANGLE 30 namespace Slic3r @@ -548,7 +547,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .set_z(m_z_pos) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) - .set_rotation(this->m_wipe_tower_pos,ROTATION_ANGLE) + .set_rotation(this->m_wipe_tower_pos,m_wipe_tower_rotation_angle) .append(";--------------------\n" "; CP TOOLCHANGE START\n") .comment_with_value(" toolchange #", m_num_tool_changes) @@ -646,7 +645,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b .set_z(m_z_pos) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) - .set_rotation(this->m_wipe_tower_pos,ROTATION_ANGLE) + .set_rotation(this->m_wipe_tower_pos,m_wipe_tower_rotation_angle) .append( ";-------------------------------------\n" "; CP WIPE TOWER FIRST LAYER BRIM START\n"); @@ -935,7 +934,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) .set_z(m_z_pos) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) - .set_rotation(this->m_wipe_tower_pos,ROTATION_ANGLE) + .set_rotation(this->m_wipe_tower_pos,m_wipe_tower_rotation_angle) .append(";--------------------\n" "; CP EMPTY GRID START\n") // m_num_layer_changes is incremented by set_z, so it is 1 based. diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 15a96d367..fd9c55cb7 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -8,6 +8,8 @@ #include "WipeTower.hpp" + + namespace Slic3r { @@ -39,10 +41,11 @@ public: // y -- y coordinates of wipe tower in mm ( left bottom corner ) // 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 wipe_area, unsigned int initial_tool) : + WipeTowerPrusaMM(float x, float y, float width, float wipe_area, float rotation_angle, unsigned int initial_tool) : m_wipe_tower_pos(x, y), m_wipe_tower_width(width), m_wipe_area(wipe_area), + m_wipe_tower_rotation_angle(rotation_angle), m_z_pos(0.f), m_current_tool(initial_tool) { @@ -96,6 +99,7 @@ public: // Extrusion rate for an extrusion aka perimeter width 0.35mm. // Clamp the extrusion height to a 0.2mm layer height, independent of the nozzle diameter. // m_extrusion_flow = std::min(0.2f, layer_height) * 0.145f; + // Use a strictly m_extrusion_flow = layer_height * 0.145f; } @@ -149,6 +153,8 @@ private: float m_wipe_tower_width; // Per color Y span. float m_wipe_area; + // Wipe tower rotation angle in degrees (with respect to x axis + float m_wipe_tower_rotation_angle; // Current Z position. float m_z_pos = 0.f; // Current layer height. diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 78ebf9294..3bd07d3eb 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -191,6 +191,7 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.wipe_tower_x.value), float(this->config.wipe_tower_y.value), float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value), - initial_extruder_id); + float(this->config.wipe_tower_rotation_angle.value), initial_extruder_id); //wipe_tower.set_retract(); //wipe_tower.set_zhop(); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 217f9bdef..65ae56961 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1708,6 +1708,13 @@ PrintConfigDef::PrintConfigDef() def->cli = "wipe-tower-per-color-wipe=f"; def->default_value = new ConfigOptionFloat(15.); + def = this->add("wipe_tower_rotation_angle", coFloat); + def->label = "Wipe tower rotation angle"; + def->tooltip = "Wipe tower rotation angle with respect to x-asis "; + def->sidetext = "degrees"; + def->cli = "wipe-tower-rotation-angle=f"; + def->default_value = new ConfigOptionFloat(0.); + def = this->add("xy_size_compensation", coFloat); def->label = "XY Size Compensation"; def->category = "Advanced"; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index ab58aa356..ea4e07dd9 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -607,6 +607,7 @@ public: ConfigOptionFloat wipe_tower_y; ConfigOptionFloat wipe_tower_width; ConfigOptionFloat wipe_tower_per_color_wipe; + ConfigOptionFloat wipe_tower_rotation_angle; ConfigOptionFloat z_offset; protected: @@ -671,6 +672,7 @@ protected: OPT_PTR(wipe_tower_y); OPT_PTR(wipe_tower_width); OPT_PTR(wipe_tower_per_color_wipe); + OPT_PTR(wipe_tower_rotation_angle); OPT_PTR(z_offset); } }; diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index e4b0448cf..2d6ff59b0 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -178,7 +178,7 @@ const std::vector& Preset::print_options() "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", - "wipe_tower_width", "wipe_tower_per_color_wipe", + "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "compatible_printers" }; return s_opts; From a733df8f375901ed3fbd0a1f0721ce5bb4c33407 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 30 Nov 2017 14:43:47 +0100 Subject: [PATCH 03/81] Wipe tower rotation - preview box --- lib/Slic3r/GUI/Plater/3D.pm | 2 +- xs/src/slic3r/GUI/3DScene.cpp | 10 ++++++---- xs/src/slic3r/GUI/3DScene.hpp | 4 ++-- xs/xsp/GUI_3DScene.xsp | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/Slic3r/GUI/Plater/3D.pm b/lib/Slic3r/GUI/Plater/3D.pm index 503a3d159..2bc7dd90f 100644 --- a/lib/Slic3r/GUI/Plater/3D.pm +++ b/lib/Slic3r/GUI/Plater/3D.pm @@ -198,7 +198,7 @@ sub reload_scene { $self->volumes->load_wipe_tower_preview(1000, $self->{config}->wipe_tower_x, $self->{config}->wipe_tower_y, $self->{config}->wipe_tower_width, $self->{config}->wipe_tower_per_color_wipe * ($extruders_count - 1), - $self->{model}->bounding_box->z_max, $self->UseVBOs); + $self->{model}->bounding_box->z_max, $self->{config}->wipe_tower_rotation_angle, $self->UseVBOs); } } } diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 81dbcdacc..6679b5515 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -301,17 +301,19 @@ std::vector GLVolumeCollection::load_object( int GLVolumeCollection::load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, bool use_VBOs) + int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs) { float color[4] = { 1.0f, 1.0f, 0.0f, 0.5f }; this->volumes.emplace_back(new GLVolume(color)); GLVolume &v = *this->volumes.back(); auto mesh = make_cube(width, depth, height); - v.indexed_vertex_array.load_mesh_flat_shading(mesh); - v.origin = Pointf3(pos_x, pos_y, 0.); + v.origin = Pointf3(pos_x, pos_y, 0.); + Point origin = Point(pos_x,pos_y); + mesh.rotate(rotation_angle,&origin); + v.indexed_vertex_array.load_mesh_flat_shading(mesh); // finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry(). v.bounding_box = v.indexed_vertex_array.bounding_box(); - v.indexed_vertex_array.finalize_geometry(use_VBOs); + v.indexed_vertex_array.finalize_geometry(use_VBOs); v.composite_id = obj_idx * 1000000; v.select_group_id = obj_idx * 1000000; v.drag_group_id = obj_idx * 1000; diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 27eeb7ca8..3649db779 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -226,7 +226,7 @@ public: const std::string &drag_by); int load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, bool use_VBOs); + int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs); // Bounding box of this volume, in unscaled coordinates. BoundingBoxf3 bounding_box; @@ -315,7 +315,7 @@ public: bool use_VBOs); int load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, bool use_VBOs); + int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs); // Render the volumes by OpenGL. void render_VBOs() const; diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 13f0d42f2..d19744f25 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -76,7 +76,7 @@ std::vector load_object(ModelObject *object, int obj_idx, std::vector instance_idxs, std::string color_by, std::string select_by, std::string drag_by, bool use_VBOs); - int load_wipe_tower_preview(int obj_idx, float pos_x, float pos_y, float width, float depth, float height, bool use_VBOs); + int load_wipe_tower_preview(int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs); void erase() %code{% THIS->clear(); %}; From 55570119f7f8fe9d218d2d895e44f487b764df0a Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 30 Nov 2017 16:11:20 +0100 Subject: [PATCH 04/81] Correction of previous commit --- xs/src/slic3r/GUI/3DScene.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 6679b5515..bb4183bdf 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -307,10 +307,9 @@ int GLVolumeCollection::load_wipe_tower_preview( this->volumes.emplace_back(new GLVolume(color)); GLVolume &v = *this->volumes.back(); auto mesh = make_cube(width, depth, height); - v.origin = Pointf3(pos_x, pos_y, 0.); - Point origin = Point(pos_x,pos_y); - mesh.rotate(rotation_angle,&origin); + mesh.rotate_z(rotation_angle*M_PI/180.); v.indexed_vertex_array.load_mesh_flat_shading(mesh); + v.origin = Pointf3(pos_x, pos_y, 0.); // finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry(). v.bounding_box = v.indexed_vertex_array.bounding_box(); v.indexed_vertex_array.finalize_geometry(use_VBOs); From cb84a6cfceb8151ddd0d8ec647ffd87cf4c9d060 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 1 Dec 2017 11:10:01 +0100 Subject: [PATCH 05/81] Wipe tower rotation - bug fix (now returning start_pos correctly) --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 3df1e9d4a..cec3e0cf9 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -70,9 +70,9 @@ public: const std::vector& extrusions() const { return m_extrusions; } float x() const { return m_current_pos.x; } float y() const { return m_current_pos.y; } - const WipeTower::xy& start_pos() const { return m_start_pos; } const WipeTower::xy& pos() const { return m_current_pos; } - const WipeTower::xy printer_pos() const { return m_current_pos.rotate(m_wipe_tower_pos,m_angle_deg); } + const WipeTower::xy start_pos_rotated() const { return m_start_pos.rotate(m_wipe_tower_pos,m_angle_deg); } + const WipeTower::xy pos_rotated() const { return m_current_pos.rotate(m_wipe_tower_pos,m_angle_deg); } float elapsed_time() const { return m_elapsed_time; } // Extrude with an explicitely provided amount of extrusion. @@ -87,7 +87,6 @@ public: double len = sqrt(dx*dx+dy*dy); // For rotated wipe tower, transform position to printer coordinates - //Q zavadet nove promenne? rotace o zaporny uhel? WipeTower::xy rotated_current_pos( m_current_pos.rotate(m_wipe_tower_pos,m_angle_deg) ); WipeTower::xy rot( WipeTower::xy(x,y).rotate(m_wipe_tower_pos,m_angle_deg ) ); @@ -491,8 +490,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( result.gcode = writer.gcode(); result.elapsed_time = writer.elapsed_time(); result.extrusions = writer.extrusions(); - result.start_pos = writer.start_pos(); - result.end_pos = writer.printer_pos(); + result.start_pos = writer.start_pos_rotated(); + result.end_pos = writer.pos_rotated(); return result; } @@ -627,8 +626,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo result.gcode = writer.gcode(); result.elapsed_time = writer.elapsed_time(); result.extrusions = writer.extrusions(); - result.start_pos = writer.start_pos(); - result.end_pos = writer.printer_pos(); + result.start_pos = writer.start_pos_rotated(); + result.end_pos = writer.pos_rotated(); return result; } @@ -728,8 +727,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b result.gcode = writer.gcode(); result.elapsed_time = writer.elapsed_time(); result.extrusions = writer.extrusions(); - result.start_pos = writer.start_pos(); - result.end_pos = writer.printer_pos(); + result.start_pos = writer.start_pos_rotated(); + result.end_pos = writer.pos_rotated(); return result; } @@ -1049,8 +1048,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) result.gcode = writer.gcode(); result.elapsed_time = writer.elapsed_time(); result.extrusions = writer.extrusions(); - result.start_pos = writer.start_pos(); - result.end_pos = writer.printer_pos(); + result.start_pos = writer.start_pos_rotated(); + result.end_pos = writer.pos_rotated(); return result; } From c34fd10e23eef14c083fcd14f55e36acda2afa84 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 5 Dec 2017 11:25:38 +0100 Subject: [PATCH 06/81] Wipe tower rotation around center point --- xs/src/libslic3r/GCode/WipeTower.hpp | 11 ++-- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 65 +++++++++++---------- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 7 ++- xs/src/libslic3r/PrintConfig.cpp | 2 +- xs/src/slic3r/GUI/3DScene.cpp | 7 ++- 5 files changed, 52 insertions(+), 40 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index 8a97333de..c5ce9b727 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -25,12 +25,15 @@ public: bool operator!=(const xy &rhs) const { return x != rhs.x || y != rhs.y; } // Rotate the point around given point about given angle (in degrees) - xy rotate(const xy& origin, float angle) const { + // shifts the result so that point of rotation is in the middle of the tower + xy rotate(const xy& origin, float width, float depth, float angle) const { xy out(0,0); + float temp_x = x - width / 2.f; + float temp_y = y - depth / 2.f; angle *= M_PI/180.; - out.x=(x-origin.x) * cos(angle) - (y-origin.y) * sin(angle); - out.y=(x-origin.x) * sin(angle) + (y-origin.y) * cos(angle); - return out+origin; + out.x += (temp_x - origin.x) * cos(angle) - (temp_y - origin.y) * sin(angle); + out.y += (temp_x - origin.x) * sin(angle) + (temp_y - origin.y) * cos(angle); + return out + origin; } float x; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index cec3e0cf9..de772060d 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -15,7 +15,6 @@ #endif - namespace Slic3r { @@ -50,8 +49,8 @@ public: Writer& set_extrusion_flow(float flow) { m_extrusion_flow = flow; return *this; } - Writer& set_rotation(WipeTower::xy pos,float angle) - { m_wipe_tower_pos = pos; m_angle_deg = angle; return (*this); } + Writer& set_rotation(WipeTower::xy pos,float width,float depth,float angle) + { m_wipe_tower_pos = pos; m_wipe_tower_depth = depth; m_wipe_tower_width = width; m_angle_deg = angle; return (*this); } // Suppress / resume G-code preview in Slic3r. Slic3r will have difficulty to differentiate the various // filament loading and cooling moves from normal extrusion moves. Therefore the writer @@ -71,8 +70,8 @@ public: float x() const { return m_current_pos.x; } float y() const { return m_current_pos.y; } const WipeTower::xy& pos() const { return m_current_pos; } - const WipeTower::xy start_pos_rotated() const { return m_start_pos.rotate(m_wipe_tower_pos,m_angle_deg); } - const WipeTower::xy pos_rotated() const { return m_current_pos.rotate(m_wipe_tower_pos,m_angle_deg); } + const WipeTower::xy start_pos_rotated() const { return m_start_pos.rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } + const WipeTower::xy pos_rotated() const { return m_current_pos.rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } float elapsed_time() const { return m_elapsed_time; } // Extrude with an explicitely provided amount of extrusion. @@ -87,10 +86,9 @@ public: double len = sqrt(dx*dx+dy*dy); // For rotated wipe tower, transform position to printer coordinates - WipeTower::xy rotated_current_pos( m_current_pos.rotate(m_wipe_tower_pos,m_angle_deg) ); - WipeTower::xy rot( WipeTower::xy(x,y).rotate(m_wipe_tower_pos,m_angle_deg ) ); - - + WipeTower::xy rotated_current_pos(m_current_pos.rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); + WipeTower::xy rot(WipeTower::xy(x, y).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); + if (! m_preview_suppressed && e > 0.f && len > 0.) { // Width of a squished extrusion, corrected for the roundings of the squished extrusions. // This is left zero if it is a travel move. @@ -160,7 +158,7 @@ public: m_gcode += "\n"; return *this; } - + // Derectract while moving in the X direction. // If |x| > 0, the feed rate relates to the x distance, // otherwise the feed rate relates to the e distance. @@ -299,6 +297,8 @@ private: const double m_filament_area = 0.25*M_PI*1.75*1.75; float m_angle_deg = 0; WipeTower::xy m_wipe_tower_pos; + float m_wipe_tower_width; + float m_wipe_tower_depth; std::string set_format_X(float x) { char buf[64]; @@ -543,18 +543,18 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow) - .set_z(m_z_pos) - .set_layer_height(m_layer_height) - .set_initial_tool(m_current_tool) - .set_rotation(this->m_wipe_tower_pos,m_wipe_tower_rotation_angle) - .append(";--------------------\n" - "; CP TOOLCHANGE START\n") - .comment_with_value(" toolchange #", m_num_tool_changes) - .comment_material(m_material[m_current_tool]) - .append(";--------------------\n") - .speed_override(100); + .set_z(m_z_pos) + .set_layer_height(m_layer_height) + .set_initial_tool(m_current_tool) + .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) + .append(";--------------------\n" + "; CP TOOLCHANGE START\n") + .comment_with_value(" toolchange #", m_num_tool_changes) + .comment_material(m_material[m_current_tool]) + .append(";--------------------\n") + .speed_override(100); - xy initial_position = ((m_current_shape == SHAPE_NORMAL) ? cleaning_box.ld : cleaning_box.lu) + + xy initial_position = ((m_current_shape == SHAPE_NORMAL) ? cleaning_box.ld : cleaning_box.lu) + xy(m_perimeter_width, ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width); if (purpose == PURPOSE_MOVE_TO_TOWER || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { @@ -640,11 +640,12 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow * 1.1f) - // Let the writer know the current Z position as a base for Z-hop. + // Let the writer know the current Z position as a base for Z-hop. .set_z(m_z_pos) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) - .set_rotation(this->m_wipe_tower_pos,m_wipe_tower_rotation_angle) + .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) + //.set_offset(xy(-)) .append( ";-------------------------------------\n" "; CP WIPE TOWER FIRST LAYER BRIM START\n"); @@ -866,7 +867,7 @@ void WipeTowerPrusaMM::toolchange_Load( writer.extrude(xr, writer.y(), 1600); bool colorInit = false; size_t pass = colorInit ? 1 : 2; - float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width * 0.85f; + float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width * 0.85f; for (int i = 0; i < pass; ++ i) { writer.travel (xr, writer.y() + dy, 7200); writer.extrude(xl, writer.y(), 2200); @@ -930,14 +931,14 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow) - .set_z(m_z_pos) - .set_layer_height(m_layer_height) - .set_initial_tool(m_current_tool) - .set_rotation(this->m_wipe_tower_pos,m_wipe_tower_rotation_angle) - .append(";--------------------\n" - "; CP EMPTY GRID START\n") - // m_num_layer_changes is incremented by set_z, so it is 1 based. - .comment_with_value(" layer #", m_num_layer_changes - 1); + .set_z(m_z_pos) + .set_layer_height(m_layer_height) + .set_initial_tool(m_current_tool) + .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) + .append(";--------------------\n" + "; CP EMPTY GRID START\n") + // m_num_layer_changes is incremented by set_z, so it is 1 based. + .comment_with_value(" layer #", m_num_layer_changes - 1); // Slow down on the 1st layer. float speed_factor = m_is_first_layer ? 0.5f : 1.f; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index fd9c55cb7..8f3e7ccaf 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -9,7 +9,6 @@ #include "WipeTower.hpp" - namespace Slic3r { @@ -86,6 +85,9 @@ public: // Is this the last layer of the waste tower? bool is_last_layer) { + if (is_first_layer) + m_wipe_tower_depth = m_wipe_area * max_tool_changes; // tower depth (y-range) of the bottom + m_z_pos = print_z; m_layer_height = layer_height; m_max_color_changes = max_tool_changes; @@ -151,6 +153,8 @@ private: xy m_wipe_tower_pos; // Width of the wipe tower. float m_wipe_tower_width; + // Depth of the wipe tower (wipe_area * max_color_changes at the base) + float m_wipe_tower_depth; // Per color Y span. float m_wipe_area; // Wipe tower rotation angle in degrees (with respect to x axis @@ -171,6 +175,7 @@ private: float m_retract = 4.f; // Width of an extrusion line, also a perimeter spacing for 100% infill. float m_perimeter_width = 0.5f; + // Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. float m_extrusion_flow = 0.029f; diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 65ae56961..b561388fd 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1710,7 +1710,7 @@ PrintConfigDef::PrintConfigDef() def = this->add("wipe_tower_rotation_angle", coFloat); def->label = "Wipe tower rotation angle"; - def->tooltip = "Wipe tower rotation angle with respect to x-asis "; + def->tooltip = "Wipe tower rotation angle with respect to x-axis "; def->sidetext = "degrees"; def->cli = "wipe-tower-rotation-angle=f"; def->default_value = new ConfigOptionFloat(0.); diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index bb4183bdf..83432446a 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -306,8 +306,11 @@ int GLVolumeCollection::load_wipe_tower_preview( float color[4] = { 1.0f, 1.0f, 0.0f, 0.5f }; this->volumes.emplace_back(new GLVolume(color)); GLVolume &v = *this->volumes.back(); - auto mesh = make_cube(width, depth, height); - mesh.rotate_z(rotation_angle*M_PI/180.); + auto mesh = make_cube(width, depth, height); + mesh.translate(-width/2.f,-depth/2.f,0.f); + Point origin_of_rotation(0.f,0.f); + mesh.rotate(rotation_angle,&origin_of_rotation); + v.indexed_vertex_array.load_mesh_flat_shading(mesh); v.origin = Pointf3(pos_x, pos_y, 0.); // finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry(). From 87c67636dfecc8612dcc4825708560fc1fa57b62 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 7 Dec 2017 11:59:14 +0100 Subject: [PATCH 07/81] Extrusion flow calculation based on nozzle diameter etc --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 11 +++++----- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 23 +++++++++++++++++---- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index de772060d..03a5f0b15 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -406,7 +406,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( float e_length = this->tool_change(0, false, PURPOSE_EXTRUDE).total_extrusion_length_in_plane(); // Shrink wipe_area by the amount of extrusion extruded by the finish_layer(). // Y stepping of the wipe extrusions. - float dy = m_perimeter_width * 0.8f; + float dy = m_line_width; // Number of whole wipe lines, that would be extruded to wipe as much material as the finish_layer(). // Minimum wipe area is 5mm wide. //FIXME calculate the purge_lines_width precisely. @@ -453,7 +453,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( if (last_wipe_inside_wipe_tower) { // Shrink the last wipe area to the area of the other purge areas, // remember the last initial wipe width to be purged into the 1st layer of the wipe tower. - this->m_initial_extra_wipe = std::max(0.f, wipe_area - (y_end + 0.5f * 0.85f * m_perimeter_width - cleaning_box.ld.y)); + this->m_initial_extra_wipe = std::max(0.f, wipe_area - (y_end + 0.5f * m_line_width - cleaning_box.ld.y)); cleaning_box.lu.y -= this->m_initial_extra_wipe; cleaning_box.ru.y -= this->m_initial_extra_wipe; } @@ -524,7 +524,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo } // Shrink wipe_area by the amount of extrusion extruded by the finish_layer(). // Y stepping of the wipe extrusions. - float dy = m_perimeter_width * 0.8f; + float dy = m_line_width; // Number of whole wipe lines, that would be extruded to wipe as much material as the finish_layer(). float num_lines_extruded = floor(e_length / m_wipe_tower_width); // Minimum wipe area is 5mm wide. @@ -645,7 +645,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) - //.set_offset(xy(-)) .append( ";-------------------------------------\n" "; CP WIPE TOWER FIRST LAYER BRIM START\n"); @@ -867,7 +866,7 @@ void WipeTowerPrusaMM::toolchange_Load( writer.extrude(xr, writer.y(), 1600); bool colorInit = false; size_t pass = colorInit ? 1 : 2; - float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width * 0.85f; + float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_line_width; for (int i = 0; i < pass; ++ i) { writer.travel (xr, writer.y() + dy, 7200); writer.extrude(xl, writer.y(), 2200); @@ -896,7 +895,7 @@ void WipeTowerPrusaMM::toolchange_Wipe( float wipe_speed_inc = 50.f; float wipe_speed_max = 4800.f; // Y increment per wipe line. - float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width * 0.8f; + float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_line_width; for (bool p = true; // Next wipe line fits the cleaning box. ((m_current_shape == SHAPE_NORMAL) ? diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 8f3e7ccaf..80ccb7ee9 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -8,6 +8,18 @@ #include "WipeTower.hpp" +// Following is used to calculate extrusion flow - should be taken from config in future +constexpr float Filament_Diameter = 1.75f; // filament diameter in mm +constexpr float Nozzle_Diameter = 0.4f; // nozzle diameter in mm +// desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust +constexpr float Width_To_Nozzle_Ratio = 1.f; +// m_perimeter_width was hardcoded until now as 0.5 (for 0.4 nozzle and 0.2 layer height) +// Konst = 1.25 implies same result +constexpr float Konst = 1.25f; +constexpr float m_perimeter_width = Nozzle_Diameter * Width_To_Nozzle_Ratio * Konst; + + + namespace Slic3r { @@ -63,7 +75,7 @@ public: // _zHop - z hop value in mm void set_zhop(float zhop) { m_zhop = zhop; } - + // Set the extruder properties. void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp) { @@ -101,9 +113,12 @@ public: // Extrusion rate for an extrusion aka perimeter width 0.35mm. // Clamp the extrusion height to a 0.2mm layer height, independent of the nozzle diameter. // m_extrusion_flow = std::min(0.2f, layer_height) * 0.145f; - // Use a strictly - m_extrusion_flow = layer_height * 0.145f; + //m_extrusion_flow = layer_height * 0.145f; + + // Calculates extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height + m_extrusion_flow = 4.f * layer_height * ( Width_To_Nozzle_Ratio * Nozzle_Diameter - layer_height * (1-M_PI/4.f)) / + (M_PI * pow(Filament_Diameter,2.f)); } // Return the wipe tower position. @@ -174,7 +189,7 @@ private: float m_zhop = 0.5f; float m_retract = 4.f; // Width of an extrusion line, also a perimeter spacing for 100% infill. - float m_perimeter_width = 0.5f; + float m_line_width = Nozzle_Diameter * Width_To_Nozzle_Ratio; // Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. float m_extrusion_flow = 0.029f; From b7a326a550131ba91e4b9651e45d12808d52425e Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 21 Dec 2017 13:28:26 +0100 Subject: [PATCH 08/81] First attempts of variable wipe implementation, sparse infill modified to sawtooth --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 248 ++++++++++++++++---- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 109 +++++++-- xs/src/libslic3r/Print.cpp | 28 ++- 3 files changed, 310 insertions(+), 75 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 03a5f0b15..3890a3626 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -49,8 +49,8 @@ public: Writer& set_extrusion_flow(float flow) { m_extrusion_flow = flow; return *this; } - Writer& set_rotation(WipeTower::xy pos,float width,float depth,float angle) - { m_wipe_tower_pos = pos; m_wipe_tower_depth = depth; m_wipe_tower_width = width; m_angle_deg = angle; return (*this); } + Writer& set_rotation(WipeTower::xy& pos, float width, float depth, float angle) + { m_wipe_tower_pos = pos; m_wipe_tower_width = width; m_wipe_tower_depth=depth; m_angle_deg = angle; return (*this); } // Suppress / resume G-code preview in Slic3r. Slic3r will have difficulty to differentiate the various // filament loading and cooling moves from normal extrusion moves. Therefore the writer @@ -87,17 +87,17 @@ public: // For rotated wipe tower, transform position to printer coordinates WipeTower::xy rotated_current_pos(m_current_pos.rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); - WipeTower::xy rot(WipeTower::xy(x, y).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); + WipeTower::xy rot(WipeTower::xy(x,y).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); if (! m_preview_suppressed && e > 0.f && len > 0.) { // Width of a squished extrusion, corrected for the roundings of the squished extrusions. // This is left zero if it is a travel move. float width = float(double(e) * m_filament_area / (len * m_layer_height)); // Correct for the roundings of a squished extrusion. - width += float(m_layer_height * (1. - M_PI / 4.)); + width += m_layer_height * float(1. - M_PI / 4.); if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos) m_extrusions.emplace_back(WipeTower::Extrusion(rotated_current_pos, 0, m_current_tool)); - m_extrusions.emplace_back(WipeTower::Extrusion(WipeTower::xy(rot.x, rot.y), width, m_current_tool)); + m_extrusions.emplace_back(WipeTower::Extrusion(WipeTower::xy(rot.x, rot.y), width, m_current_tool)); } m_gcode += "G1"; @@ -401,7 +401,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( float wipe_area = m_wipe_area; // Calculate the amount of wipe over the wipe tower brim following the prime, decrease wipe_area // with the amount of material extruded over the brim. - { + // DOESN'T MAKE SENSE NOW, wipe tower dimensions are still unknown at this point + /*{ // Simulate the brim extrusions, summ the length of the extrusion. float e_length = this->tool_change(0, false, PURPOSE_EXTRUDE).total_extrusion_length_in_plane(); // Shrink wipe_area by the amount of extrusion extruded by the finish_layer(). @@ -414,7 +415,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( wipe_area = std::max(5.f, m_wipe_area - float(floor(e_length / m_wipe_tower_width)) * dy - purge_lines_width); } - this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false); + this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false);*/ this->m_num_layer_changes = 0; this->m_current_tool = tools.front(); @@ -422,7 +423,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // Due to the XYZ calibration, this working space may shrink slightly from all directions, // therefore the homing position is shifted inside the bed by 0.2 in the firmware to [0.2, -2.0]. // box_coordinates cleaning_box(xy(0.5f, - 1.5f), m_wipe_tower_width, wipe_area); - box_coordinates cleaning_box(xy(5.f, 0.f), m_wipe_tower_width, wipe_area); + //FIXME: set the width properly + constexpr float prime_section_width = 60.f; + box_coordinates cleaning_box(xy(5.f, 0.f), prime_section_width, wipe_area); PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow) @@ -465,7 +468,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], m_first_layer_temperature[tools[idx_tool+1]]); // Save the y end of the non-last priming area. y_end = writer.y(); - cleaning_box.translate(m_wipe_tower_width, 0.f); + cleaning_box.translate(prime_section_width, 0.f); writer.travel(cleaning_box.ld, 7200); } ++ m_num_tool_changes; @@ -482,7 +485,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( "\n\n"); // Force m_idx_tool_change_in_layer to -1, so that tool_change() will know to extrude the wipe tower brim. - m_idx_tool_change_in_layer = (unsigned int)(-1); + ///m_idx_tool_change_in_layer = (unsigned int)(-1); + m_print_brim = true; ToolChangeResult result; result.print_z = this->m_z_pos; @@ -501,13 +505,14 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo // or there must be a nonzero wipe tower partitions available. // assert(tool < 0 || it_layer_tools->wipe_tower_partitions > 0); - if (m_idx_tool_change_in_layer == (unsigned int)(-1)) { + if ( m_print_brim ) { + ///if (m_idx_tool_change_in_layer == (unsigned int)(-1)) { // First layer, prime the extruder. return toolchange_Brim(purpose); } - - float wipe_area = m_wipe_area; - if (++ m_idx_tool_change_in_layer < (unsigned int)m_max_color_changes && last_in_layer) { + + float wipe_area = 0.f; + /*if (++ m_idx_tool_change_in_layer < (unsigned int)m_max_color_changes && last_in_layer) { // This tool_change() call will be followed by a finish_layer() call. // Try to shrink the wipe_area to save material, as less than usual wipe is required // if this step is foolowed by finish_layer() extrusions wiping the same extruder. @@ -534,11 +539,20 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo break; } } - } + }*/ + if (tool != (unsigned int)(-1)) { + for (const auto &b : m_layer_info->tool_changes) + if ( b.new_tool == tool ) + wipe_area = b.required_depth; + } + else { + // Otherwise we are going to Unload only. And m_layer_info would be invalid. + } + box_coordinates cleaning_box( m_wipe_tower_pos + xy(0.f, m_current_wipe_start_y + 0.5f * m_perimeter_width), - m_wipe_tower_width, + m_wipe_tower_width, wipe_area - m_perimeter_width); PrusaMultiMaterial::Writer writer; @@ -546,7 +560,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .set_z(m_z_pos) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) - .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) + .set_rotation(m_wipe_tower_pos,m_wipe_tower_width,m_wipe_tower_depth,m_wipe_tower_rotation_angle) .append(";--------------------\n" "; CP TOOLCHANGE START\n") .comment_with_value(" toolchange #", m_num_tool_changes) @@ -636,16 +650,16 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b const box_coordinates wipeTower_box( m_wipe_tower_pos, m_wipe_tower_width, - m_wipe_area * float(m_max_color_changes) - m_perimeter_width / 2); + m_wipe_tower_depth - m_perimeter_width / 2); PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow * 1.1f) // Let the writer know the current Z position as a base for Z-hop. - .set_z(m_z_pos) - .set_layer_height(m_layer_height) - .set_initial_tool(m_current_tool) - .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) - .append( + .set_z(m_z_pos) + .set_layer_height(m_layer_height) + .set_initial_tool(m_current_tool) + .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) + .append( ";-------------------------------------\n" "; CP WIPE TOWER FIRST LAYER BRIM START\n"); @@ -718,7 +732,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b ";-----------------------------------\n"); // Mark the brim as extruded. - m_idx_tool_change_in_layer = 0; + ///m_idx_tool_change_in_layer = 0; + m_print_brim = false; } ToolChangeResult result; @@ -896,11 +911,12 @@ void WipeTowerPrusaMM::toolchange_Wipe( float wipe_speed_max = 4800.f; // Y increment per wipe line. float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_line_width; + for (bool p = true; - // Next wipe line fits the cleaning box. + // Next wipe line fits the cleaning box (and not forgetting about border) ((m_current_shape == SHAPE_NORMAL) ? - (writer.y() <= cleaning_box.lu.y - m_perimeter_width) : - (writer.y() >= cleaning_box.ld.y + m_perimeter_width)); + (writer.y() <= cleaning_box.lu.y - 1.5f * m_perimeter_width) : + (writer.y() >= cleaning_box.ld.y + 1.5f * m_perimeter_width)); p = ! p) { wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc); @@ -922,6 +938,9 @@ void WipeTowerPrusaMM::toolchange_Wipe( writer.set_extrusion_flow(m_extrusion_flow); } + + + WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) { // This should only be called if the layer is not finished yet. @@ -942,17 +961,20 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) // Slow down on the 1st layer. float speed_factor = m_is_first_layer ? 0.5f : 1.f; + float current_depth = m_wipe_tower_depth; + if (m_is_first_layer) + current_depth = m_wipe_tower_depth; + else + current_depth = m_layer_info->depth; + + box_coordinates fill_box(m_wipe_tower_pos + xy(0.f, m_current_wipe_start_y), - m_wipe_tower_width, float(m_max_color_changes) * m_wipe_area - m_current_wipe_start_y); + m_wipe_tower_width, current_depth - m_current_wipe_start_y); fill_box.expand(0.f, - 0.5f * m_perimeter_width); - { - float firstLayerOffset = 0.f; - fill_box.ld.y += firstLayerOffset; - fill_box.rd.y += firstLayerOffset; - } + if (purpose == PURPOSE_MOVE_TO_TOWER || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { - if (m_idx_tool_change_in_layer == 0) { + if ( m_layer_info->tool_changes.size() == 0) { // There were no tool changes at all in this layer. writer.retract(m_retract * 1.5f, 3600) // Jump with retract to fill_box.ld + a random shift in +x. @@ -992,12 +1014,14 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) box.rd.y = box.ld.y; int nsteps = int(floor((box.lu.y - box.ld.y) / (2. * (1.0 * m_perimeter_width)))); float step = (box.lu.y - box.ld.y) / nsteps; - for (size_t i = 0; i < nsteps; ++ i) { - writer.extrude(box.ld.x, writer.y() + 0.5f * step); - writer.extrude(box.rd.x, writer.y()); - writer.extrude(box.rd.x, writer.y() + 0.5f * step); - writer.extrude(box.ld.x, writer.y()); - } + //FIXME: + if (nsteps >= 0) + for (size_t i = 0; i < nsteps; ++i) { + writer.extrude(box.ld.x, writer.y() + 0.5f * step); + writer.extrude(box.rd.x, writer.y()); + writer.extrude(box.rd.x, writer.y() + 0.5f * step); + writer.extrude(box.ld.x, writer.y()); + } } else { // Extrude a sparse infill to support the material to be printed above. @@ -1008,10 +1032,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) .extrude(fill_box.lu + xy(m_perimeter_width * 6, - m_perimeter_width)) .extrude(fill_box.ld + xy(m_perimeter_width * 6, m_perimeter_width)); - if (fill_box.lu.y - fill_box.ld.y > 4.f) { - // Extrude three zig-zags. - float step = (m_wipe_tower_width - m_perimeter_width * 12.f) / 12.f; - for (size_t i = 0; i < 3; ++ i) { + /*if (fill_box.lu.y - fill_box.ld.y > 4.f) { + const float max_bridge_distance = 10.f; // in mm + size_t zig_zags_num = int((m_wipe_tower_width - m_perimeter_width * 12.f) / ( max_bridge_distance * 2.f ) ) + 1 ; + float step = (m_wipe_tower_width - m_perimeter_width * 12.f) / (zig_zags_num * 4); + for (size_t i = 0; i < zig_zags_num; ++ i) { writer.extrude(writer.x() + step, fill_box.ld.y + m_perimeter_width * 8, 3200 * speed_factor); writer.extrude(writer.x() , fill_box.lu.y - m_perimeter_width * 8); writer.extrude(writer.x() + step, fill_box.lu.y - m_perimeter_width ); @@ -1020,12 +1045,42 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) writer.extrude(writer.x() + step, fill_box.ld.y + m_perimeter_width ); } } + // Extrude an inverse U at the left of the region. + writer.extrude(fill_box.ru + xy(-m_perimeter_width * 6, -m_perimeter_width), 2900 * speed_factor) + .extrude(fill_box.ru + xy(-m_perimeter_width * 3, -m_perimeter_width)) + .extrude(fill_box.rd + xy(-m_perimeter_width * 3, m_perimeter_width)) + .extrude(fill_box.rd + xy(-m_perimeter_width, m_perimeter_width));*/ + + const float dy = (fill_box.lu.y - fill_box.ld.y - 2.f * m_perimeter_width); + if (dy > m_perimeter_width) + { + const float max_bridge_distance = 10.f; // in mm + const size_t zig_zags_num = (fill_box.rd.x - fill_box.ld.x - m_perimeter_width * 12.f) / max_bridge_distance; + const float step = (fill_box.rd.x - fill_box.ld.x - m_perimeter_width * 12.f) / (float)zig_zags_num; + + float offsety = std::max(0.f, dy - m_last_infill_tan * (step - m_perimeter_width)); + if (offsety < m_last_infill_tan * m_perimeter_width + WT_EPSILON || offsety > dy / 2.f) + offsety = 0.f; + float offsetx = ( offsety != 0 ? 0 : std::max(0.f, dy / m_last_infill_tan > step / 2.f ? step - dy / m_last_infill_tan : 0.f ) ); + + for (size_t i = 0; i < zig_zags_num; ++i) + { + writer.extrude(writer.x() + offsetx, writer.y(), 3200 * speed_factor); + if ( offsety != 0 ) { + writer.extrude(writer.x() + m_perimeter_width, writer.y()); + writer.extrude(writer.x(), writer.y() + offsety); + } + writer.extrude(writer.x() + step - offsetx - (offsety==0 ? 0 : m_perimeter_width), fill_box.lu.y - m_perimeter_width); + writer.extrude(writer.x() , fill_box.ld.y + m_perimeter_width); + } + m_last_infill_tan = (dy - offsety) / (step - offsetx - (offsety==0 ? 0 : m_perimeter_width)); + } // Extrude an inverse U at the left of the region. - writer.extrude(fill_box.ru + xy(- m_perimeter_width * 6, - m_perimeter_width), 2900 * speed_factor) - .extrude(fill_box.ru + xy(- m_perimeter_width * 3, - m_perimeter_width)) - .extrude(fill_box.rd + xy(- m_perimeter_width * 3, m_perimeter_width)) - .extrude(fill_box.rd + xy(- m_perimeter_width, m_perimeter_width)); + writer.extrude(fill_box.rd + xy(-m_perimeter_width * 6, m_perimeter_width), 2900 * speed_factor) + .extrude(fill_box.rd + xy(-m_perimeter_width * 3, m_perimeter_width)) + .extrude(fill_box.ru + xy(-m_perimeter_width * 3, -m_perimeter_width)) + .extrude(fill_box.ru + xy(-m_perimeter_width, -m_perimeter_width)); } if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) @@ -1039,7 +1094,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) ";------------------\n\n\n\n\n\n\n"); // Indicate that this wipe tower layer is fully covered. - m_idx_tool_change_in_layer = (unsigned int)m_max_color_changes; + m_current_wipe_start_y = m_wipe_tower_depth; + ///m_idx_tool_change_in_layer = (unsigned int)m_max_color_changes; + } ToolChangeResult result; @@ -1053,4 +1110,97 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) return result; } +// Appends a toolchange into m_plan and calculates neccessary depth of the corresponding box + +void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool) +{ + assert(m_plan.back().z <= z_par); // refuse to add a layer below the last one + + // volumes in mm^3 required for ramming + // hardcoded so far, in future should be calculated by integrating the speed/time curve + const std::vector ram_volumes = {22,22,22,22}; + + // volumes in mm^3 required for wipe: {{from 0 to ...},{from 1 to ...},{from 2 to ...},{from 3 to ...}}, usage [from][to] + const std::vector> wipe_volumes = {{ 0, 40, 60, 80}, + {100, 0,120,100}, + { 80,107, 0,110}, + { 60, 40, 60, 0}}; + + float depth = (wipe_volumes[old_tool][new_tool]) / (m_extrusion_flow * Filament_Area); // length of extrusion + depth = floor(depth / m_wipe_tower_width + 1); // number of lines to extrude + depth += 6; // reserved for ramming + depth += 2; // reserved for loading + depth -= 2; // we will also print borders + depth *= m_perimeter_width; // conversion to distance + + if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan along with the first toolchange + m_plan.push_back(WipeTowerInfo(z_par, layer_height_par)); + + if ( old_tool != new_tool ) { + if (!m_plan_brim_finished) { // this toolchange prints brim, we need it in m_plan, but not to count its depth + m_plan_brim_finished = true; + depth = 0.f; + } + m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool, depth)); + } + + + + // Calculate m_wipe_tower (maximum depth for all the layers) and propagate depths downwards + // Could be only called when a layer is changed, but do not forget about the last one + float this_layer_depth = m_plan.back().toolchanges_depth(); + m_plan.back().depth = this_layer_depth; + + if (this_layer_depth > m_wipe_tower_depth) + m_wipe_tower_depth = this_layer_depth; + for (int i = m_plan.size() - 2; i >= 0 && m_plan[i].depth < this_layer_depth; i-- ) { + if ( this_layer_depth - m_plan[i].depth < min_layer_difference && !m_plan[i].tool_changes.empty()) + m_plan[i].tool_changes.back().required_depth += this_layer_depth - m_plan[i].depth; + m_plan[i].depth = this_layer_depth; + } +} + + +// Processes vector m_plan and calls respective function to generate G-code for the wipe tower +// Resulting ToolChangeResults are appended into container passed by "result" reference +void WipeTowerPrusaMM::generate(std::vector> &result) +{ + std::vector layer_result; + + for (auto layer : m_plan) + { + + set_layer(layer.z,layer.height,0,layer.z == m_plan.front().z,layer.z == m_plan.back().z); + + for (const auto &toolchange : layer.tool_changes) + layer_result.emplace_back(tool_change(toolchange.new_tool, false, WipeTower::PURPOSE_EXTRUDE)); + + if (! layer_finished()) { + layer_result.emplace_back(finish_layer(WipeTower::PURPOSE_EXTRUDE)); + if (layer_result.size() > 1) { + // Merge the two last tool changes into one. + WipeTower::ToolChangeResult &tc1 = layer_result[layer_result.size() - 2]; + WipeTower::ToolChangeResult &tc2 = layer_result.back(); + if (tc1.end_pos != tc2.start_pos) { + // Add a travel move from tc1.end_pos to tc2.start_pos. + char buf[2048]; + sprintf(buf, "G1 X%.3f Y%.3f F7200\n", tc2.start_pos.x, tc2.start_pos.y); + tc1.gcode += buf; + } + tc1.gcode += tc2.gcode; + tc1.extrusions.insert(tc1.extrusions.end(), tc2.extrusions.begin(), tc2.extrusions.end()); + tc1.end_pos = tc2.end_pos; + layer_result.pop_back(); + } + } + else + m_last_infill_tan = 1000.f; //if the layer was dense, no worries about infill continuity on the next + + result.emplace_back(std::move(layer_result)); + m_is_first_layer = false; + } +} + + + }; // namespace Slic3r diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 80ccb7ee9..275b2f237 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -9,15 +9,19 @@ #include "WipeTower.hpp" // Following is used to calculate extrusion flow - should be taken from config in future -constexpr float Filament_Diameter = 1.75f; // filament diameter in mm +constexpr float Filament_Area = M_PI * 1.75f * 1.75f / 4.f; // filament diameter in mm constexpr float Nozzle_Diameter = 0.4f; // nozzle diameter in mm // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust constexpr float Width_To_Nozzle_Ratio = 1.f; // m_perimeter_width was hardcoded until now as 0.5 (for 0.4 nozzle and 0.2 layer height) // Konst = 1.25 implies same result constexpr float Konst = 1.25f; + +// m_perimeter_width is used in plan_toolchange - take care of proper initialization value when changing to variable constexpr float m_perimeter_width = Nozzle_Diameter * Width_To_Nozzle_Ratio * Konst; +constexpr float WT_EPSILON = 1e-3f; +constexpr float min_layer_difference = 2.f; @@ -75,7 +79,8 @@ public: // _zHop - z hop value in mm void set_zhop(float zhop) { m_zhop = zhop; } - + + // Set the extruder properties. void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp) { @@ -84,32 +89,39 @@ public: m_first_layer_temperature[idx] = first_layer_temp; } + + // Setter for internal structure m_plan containing info about the future wipe tower + // to be used before building begins. The entries must be added ordered in z. + void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool); + + void generate(std::vector> &result); + // Switch to a next layer. virtual void set_layer( // Print height of this layer. - float print_z, - // Layer height, used to calculate extrusion the rate. - float layer_height, + float print_z, + // Layer height, used to calculate extrusion the rate. + float layer_height, // Maximum number of tool changes on this layer or the layers below. - size_t max_tool_changes, + size_t max_tool_changes, // Is this the first layer of the print? In that case print the brim first. - bool is_first_layer, + bool is_first_layer, // Is this the last layer of the waste tower? - bool is_last_layer) + bool is_last_layer) { - if (is_first_layer) - m_wipe_tower_depth = m_wipe_area * max_tool_changes; // tower depth (y-range) of the bottom - m_z_pos = print_z; m_layer_height = layer_height; - m_max_color_changes = max_tool_changes; m_is_first_layer = is_first_layer; - m_is_last_layer = is_last_layer; // Start counting the color changes from zero. Special case: -1 - extrude a brim first. - m_idx_tool_change_in_layer = is_first_layer ? (unsigned int)(-1) : 0; + ///m_idx_tool_change_in_layer = is_first_layer ? (unsigned int)(-1) : 0; + m_print_brim = is_first_layer; m_current_wipe_start_y = 0.f; m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL; ++ m_num_layer_changes; + + + ///m_max_color_changes = max_tool_changes; + ///m_is_last_layer = is_last_layer; // Extrusion rate for an extrusion aka perimeter width 0.35mm. // Clamp the extrusion height to a 0.2mm layer height, independent of the nozzle diameter. // m_extrusion_flow = std::min(0.2f, layer_height) * 0.145f; @@ -117,8 +129,14 @@ public: //m_extrusion_flow = layer_height * 0.145f; // Calculates extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height - m_extrusion_flow = 4.f * layer_height * ( Width_To_Nozzle_Ratio * Nozzle_Diameter - layer_height * (1-M_PI/4.f)) / - (M_PI * pow(Filament_Diameter,2.f)); + m_extrusion_flow = extrusion_flow(layer_height); + + m_layer_info = nullptr; + for (auto &a : m_plan) + if ( a.z > print_z - WT_EPSILON && a.z < print_z + WT_EPSILON ) { + m_layer_info = &a; + break; + } } // Return the wipe tower position. @@ -151,8 +169,15 @@ public: // Is the current layer finished? A layer is finished if either the wipe tower is finished, or // the wipe tower has been completely covered by the tool change extrusions, // or the rest of the tower has been filled by a sparse infill with the finish_layer() method. - virtual bool layer_finished() const - { return m_idx_tool_change_in_layer == m_max_color_changes; } + virtual bool layer_finished() const { + + if (m_is_first_layer) { + return (m_wipe_tower_depth - WT_EPSILON < m_current_wipe_start_y); + } + else + return (m_layer_info->depth - WT_EPSILON < m_current_wipe_start_y); + } + private: WipeTowerPrusaMM(); @@ -169,7 +194,7 @@ private: // Width of the wipe tower. float m_wipe_tower_width; // Depth of the wipe tower (wipe_area * max_color_changes at the base) - float m_wipe_tower_depth; + float m_wipe_tower_depth = 0.f; // Per color Y span. float m_wipe_area; // Wipe tower rotation angle in degrees (with respect to x axis @@ -205,7 +230,8 @@ private: // Tool change change counter for the output statistics. unsigned int m_num_tool_changes = 0; // Layer change counter in this layer. Counting up to m_max_color_changes. - unsigned int m_idx_tool_change_in_layer = 0; + ///unsigned int m_idx_tool_change_in_layer = 0; + bool m_print_brim = true; // A fill-in direction (positive Y, negative Y) alternates with each layer. wipe_shape m_current_shape = SHAPE_NORMAL; unsigned int m_current_tool = 0; @@ -214,7 +240,18 @@ private: // How much to wipe the 1st extruder over the wipe tower at the 1st layer // after the wipe tower brim has been extruded? float m_initial_extra_wipe = 0.f; + float m_last_infill_tan = 1000.f; // impossibly high value + bool m_plan_brim_finished = false; + float + extrusion_flow(float layer_height = -1.f) + { + if ( layer_height < 0 ) + return m_extrusion_flow; + return layer_height * ( Width_To_Nozzle_Ratio * Nozzle_Diameter - layer_height * (1-M_PI/4.f)) / (Filament_Area); + } + + struct box_coordinates { box_coordinates(float left, float bottom, float width, float height) : @@ -246,8 +283,34 @@ private: xy rd; // right lower }; + + // to store information about tool changes for a given layer + struct WipeTowerInfo{ + struct ToolChange { + unsigned int old_tool; + unsigned int new_tool; + float required_depth; + ToolChange(unsigned int old,unsigned int newtool,float depth) : old_tool{old}, new_tool{newtool}, required_depth{depth} {} + }; + float z; // z position of the layer + float height; // layer height + float depth; // depth of the layer based on all layers above + float toolchanges_depth() const { float sum = 0.f; for (const auto &a : tool_changes) sum += a.required_depth; return sum; } + + std::vector tool_changes; + + WipeTowerInfo(float z_par, float layer_height_par) + : z{z_par}, height{layer_height_par} { } + }; + + // Stores information about all layers and toolchanges for the future wipe tower (filled by plan_toolchange(...)) + std::vector m_plan; + + WipeTowerInfo* m_layer_info; + + // Returns gcode for wipe tower brim - // sideOnly -- set to false -- experimental, draw brim on sides of wipe tower + // sideOnly -- set to false -- experimental, draw brim on sides of wipe tower // offset -- set to 0 -- experimental, offset to replace brim in front / rear of wipe tower ToolChangeResult toolchange_Brim(Purpose purpose, bool sideOnly = false, float y_offset = 0.f); @@ -269,9 +332,7 @@ private: void toolchange_Wipe( PrusaMultiMaterial::Writer &writer, const box_coordinates &cleaning_box, - bool skip_initial_y_move); - - void toolchange_Perimeter(); + bool skip_initial_y_move); }; }; // namespace Slic3r diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 3bd07d3eb..cfc26eeac 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1005,9 +1005,33 @@ void Print::_make_wipe_tower() m_wipe_tower_priming = Slic3r::make_unique( wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full, WipeTower::PURPOSE_EXTRUDE)); + + // Lets go through the wipe tower layers and determine pairs of extruder changes for each + // to pass to wipe_tower (so that it can use it for planning the layout of the tower) + { + unsigned int current_extruder_id = initial_extruder_id; + for (const auto &layer_tools : m_tool_ordering.layer_tools()) { // for all layers + if (!layer_tools.has_wipe_tower) continue; + bool first_layer = &layer_tools == &m_tool_ordering.front(); + wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id); + for (const auto extruder_id : layer_tools.extruders) { + if ((first_layer && extruder_id == initial_extruder_id) || extruder_id != current_extruder_id) { + wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id); + current_extruder_id = extruder_id; + } + } + if (&layer_tools == &m_tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0) + break; + } + } + + + // Generate the wipe tower layers. m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size()); - unsigned int current_extruder_id = initial_extruder_id; + wipe_tower.generate(m_wipe_tower_tool_changes); + + /*unsigned int current_extruder_id = initial_extruder_id; for (const ToolOrdering::LayerTools &layer_tools : m_tool_ordering.layer_tools()) { if (! layer_tools.has_wipe_tower) // This is a support only layer, or the wipe tower does not reach to this height. @@ -1047,7 +1071,7 @@ void Print::_make_wipe_tower() m_wipe_tower_tool_changes.emplace_back(std::move(tool_changes)); if (last_layer) break; - } + }*/ // Unload the current filament over the purge tower. coordf_t layer_height = this->objects.front()->config.layer_height.value; From c6718c94bf4cca861fd22fdf854e2103a5779324 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 21 Dec 2017 14:24:47 +0100 Subject: [PATCH 09/81] Merge fix --- xs/src/libslic3r/Print.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 3cb2e481b..8b7f9805c 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1044,14 +1044,15 @@ void Print::_make_wipe_tower() // Lets go through the wipe tower layers and determine pairs of extruder changes for each // to pass to wipe_tower (so that it can use it for planning the layout of the tower) + { - unsigned int current_extruder_id = initial_extruder_id; + unsigned int current_extruder_id = m_tool_ordering.all_extruders().back(); for (const auto &layer_tools : m_tool_ordering.layer_tools()) { // for all layers if (!layer_tools.has_wipe_tower) continue; bool first_layer = &layer_tools == &m_tool_ordering.front(); wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id); for (const auto extruder_id : layer_tools.extruders) { - if ((first_layer && extruder_id == initial_extruder_id) || extruder_id != current_extruder_id) { + if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) { wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id); current_extruder_id = extruder_id; } @@ -1069,7 +1070,7 @@ void Print::_make_wipe_tower() wipe_tower.generate(m_wipe_tower_tool_changes); // Set current_extruder_id to the last extruder primed. - unsigned int current_extruder_id = m_tool_ordering.all_extruders().back(); + /*unsigned int current_extruder_id = m_tool_ordering.all_extruders().back(); for (const ToolOrdering::LayerTools &layer_tools : m_tool_ordering.layer_tools()) { if (! layer_tools.has_wipe_tower) From 180967484e15d529a132a59f2ac760354cf87298 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 22 Dec 2017 11:26:43 +0100 Subject: [PATCH 10/81] Correction of wipe tower brim generation --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 42 +++++++++++++++------ xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 14 ++----- xs/src/libslic3r/Print.cpp | 7 ++-- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 0b3a023a4..e51b43430 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -92,7 +92,7 @@ public: if (! m_preview_suppressed && e > 0.f && len > 0.) { // Width of a squished extrusion, corrected for the roundings of the squished extrusions. // This is left zero if it is a travel move. - float width = float(double(e) * m_filament_area / (len * m_layer_height)); + float width = float(double(e) * Filament_Area / (len * m_layer_height)); // Correct for the roundings of a squished extrusion. width += m_layer_height * float(1. - M_PI / 4.); if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos) @@ -258,6 +258,25 @@ public: return *this; }; + + Writer& set_fan(unsigned int speed) + { + if (speed == m_last_fan_speed) + return *this; + + if (speed == 0) + m_gcode += "M107\n"; + else + { + m_gcode += "M106 S"; + char buf[128]; + sprintf(buf,"%u\n",(unsigned int)(255.0 * speed / 100.0)); + m_gcode += buf; + } + m_last_fan_speed = speed; + return *this; + } + Writer& comment_material(WipeTowerPrusaMM::material_type material) { m_gcode += "; material : "; @@ -294,13 +313,15 @@ private: std::string m_gcode; std::vector m_extrusions; float m_elapsed_time; - const double m_filament_area = 0.25*M_PI*1.75*1.75; float m_angle_deg = 0; WipeTower::xy m_wipe_tower_pos; float m_wipe_tower_width; float m_wipe_tower_depth; + float m_last_fan_speed = 0.f; - std::string set_format_X(float x) { + std::string + set_format_X(float x) + { char buf[64]; sprintf(buf, " X%.3f", x); m_current_pos.x = x; @@ -1116,7 +1137,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) // Appends a toolchange into m_plan and calculates neccessary depth of the corresponding box -void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool) +void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool,bool brim) { assert(m_plan.back().z <= z_par); // refuse to add a layer below the last one @@ -1131,20 +1152,18 @@ void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsi { 60, 40, 60, 0}}; float depth = (wipe_volumes[old_tool][new_tool]) / (m_extrusion_flow * Filament_Area); // length of extrusion + depth += 6 * 59; // reserved for ramming + depth += 2 * 59; // reserved for loading + depth -= 2 * 59; // we will also print borders depth = floor(depth / m_wipe_tower_width + 1); // number of lines to extrude - depth += 6; // reserved for ramming - depth += 2; // reserved for loading - depth -= 2; // we will also print borders depth *= m_perimeter_width; // conversion to distance if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan along with the first toolchange m_plan.push_back(WipeTowerInfo(z_par, layer_height_par)); - if ( old_tool != new_tool ) { - if (!m_plan_brim_finished) { // this toolchange prints brim, we need it in m_plan, but not to count its depth - m_plan_brim_finished = true; + if ( brim || old_tool != new_tool ) { + if (brim) // this toolchange prints brim, we need it in m_plan, but not to count its depth depth = 0.f; - } m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool, depth)); } @@ -1173,7 +1192,6 @@ void WipeTowerPrusaMM::generate(std::vector> &result); @@ -131,6 +131,7 @@ public: // Calculates extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height m_extrusion_flow = extrusion_flow(layer_height); + // FIXME - ideally get rid of set_layer altogether and iterate through m_plan in generate(...) m_layer_info = nullptr; for (auto &a : m_plan) if ( a.z > print_z - WT_EPSILON && a.z < print_z + WT_EPSILON ) { @@ -170,12 +171,7 @@ public: // the wipe tower has been completely covered by the tool change extrusions, // or the rest of the tower has been filled by a sparse infill with the finish_layer() method. virtual bool layer_finished() const { - - if (m_is_first_layer) { - return (m_wipe_tower_depth - WT_EPSILON < m_current_wipe_start_y); - } - else - return (m_layer_info->depth - WT_EPSILON < m_current_wipe_start_y); + return ( (m_is_first_layer ? m_wipe_tower_depth : m_layer_info->depth) - WT_EPSILON < m_current_wipe_start_y); } @@ -241,10 +237,8 @@ private: // after the wipe tower brim has been extruded? float m_initial_extra_wipe = 0.f; float m_last_infill_tan = 1000.f; // impossibly high value - bool m_plan_brim_finished = false; - float - extrusion_flow(float layer_height = -1.f) + float extrusion_flow(float layer_height = -1.f) const { if ( layer_height < 0 ) return m_extrusion_flow; diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 8b7f9805c..64f4d6046 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1050,10 +1050,10 @@ void Print::_make_wipe_tower() for (const auto &layer_tools : m_tool_ordering.layer_tools()) { // for all layers if (!layer_tools.has_wipe_tower) continue; bool first_layer = &layer_tools == &m_tool_ordering.front(); - wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id); + wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id,false); for (const auto extruder_id : layer_tools.extruders) { - if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) { - wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id); + if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) { + wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id, first_layer && extruder_id == m_tool_ordering.all_extruders().back()); current_extruder_id = extruder_id; } } @@ -1066,7 +1066,6 @@ void Print::_make_wipe_tower() // Generate the wipe tower layers. m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size()); - wipe_tower.generate(m_wipe_tower_tool_changes); // Set current_extruder_id to the last extruder primed. From 37bbeeb9d0db258dd0d4a7cf95dd723579e12a3f Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 4 Jan 2018 12:03:06 +0100 Subject: [PATCH 11/81] Parametrization of ramming and loading sequence - first steps --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 190 +++++++++++++++----- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 1 + 2 files changed, 142 insertions(+), 49 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index e51b43430..ce9b8883a 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -15,6 +15,14 @@ #endif +// experimental: ramming speed (mm^3/s) sampled in 0.25s intervals (one filament so far) +const std::vector ramming_speed = {7.6, 7.6, 7.6, 7.6, 9.0, 9.0, 9.0, 10.7, 10.7, 10.7}; +// experimental: time requested for cooling in seconds (common for all materials so far) +const float cooling_time = 14; // PVA: 20; SCAFF: 17 +const float loading_volume = 20; + + + namespace Slic3r { @@ -562,6 +570,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo } }*/ + // Finds this toolchange info if (tool != (unsigned int)(-1)) { for (const auto &b : m_layer_info->tool_changes) if ( b.new_tool == tool ) @@ -779,15 +788,51 @@ void WipeTowerPrusaMM::toolchange_Unload( { float xl = cleaning_box.ld.x + 0.5f * m_perimeter_width; float xr = cleaning_box.rd.x - 0.5f * m_perimeter_width; - float y_step = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width; - + writer.append("; CP TOOLCHANGE UNLOAD\n"); - + // Ram the hot material out of the extruder melt zone. // Current extruder position is on the left, one perimeter inside the cleaning box in both X and Y. - float e0 = m_perimeter_width * m_extrusion_flow; - float e = (xr - xl) * m_extrusion_flow; - switch (current_material) + //float e0 = m_perimeter_width * m_extrusion_flow; + //float e = (xr - xl) * m_extrusion_flow; + //float y_step = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width * ramming_step_multiplicator; + + constexpr float ramming_step_multiplicator = 1.f; // extra spacing needed for some materials + const float line_width = m_line_width * 1.5f; // desired ramming line thickness + + float y_step = (m_current_shape == SHAPE_NORMAL ? 1.f : -1.f) * // spacing between lines in mm + line_width * ramming_step_multiplicator; + + + int i = 0; // iterates through ramming_speed + m_left_to_right = true; // current direction of ramming + float remaining = xr - xl - 2 * m_perimeter_width; // keeps track of distance to the next turnaround + float e_done = 0; // measures E move done from each segment + + writer.travel(xl + m_perimeter_width, writer.y() + y_step * 0.2); // move to starting position + + while (i < ramming_speed.size()) { + const float x = (ramming_speed[i] * 0.25f) / // extrusion length to get desired line_width + (m_layer_height * (line_width - m_layer_height * (1. - M_PI / 4.))); + const float e = ramming_speed[i] * 0.25f / Filament_Area; // transform volume per sec to E move; + const float dist = std::min(x - e_done, remaining); // distance to travel for the next 0.25s + writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), std::hypot(dist, e * (dist / x)) / (0.25 / 60.)); + remaining -= dist; + + if ( remaining < WT_EPSILON ) { // we reached a turning point + writer.travel(writer.x(), writer.y() + y_step); + m_left_to_right = !m_left_to_right; + remaining = xr - xl - 2 * m_perimeter_width; + } + e_done += dist; // subtract what was actually transversed + if (e_done > x - WT_EPSILON) { // current segment finished + ++i; + e_done = 0; + } + } + + + /*switch (current_material) { case ABS: // ramming start end y increment amount feedrate @@ -803,7 +848,7 @@ void WipeTowerPrusaMM::toolchange_Unload( .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.5f, 0, 1.75f * e, 4800) .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.5f, 0, 1.75f * e, 5000); break; - case SCAFF: + case PET: //!!! SCAFF (PET only used for testing): writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 2.f, 0, 1.75f * e, 4000) .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 3.f, 0, 2.34f * e, 4600) .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 3.f, 0, 2.63f * e, 5200); @@ -814,7 +859,7 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 0.2f, 0, 1.60f * e, 4000) .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.2f, e0, 1.65f * e, 4600) .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.2f, e0, 1.74f * e, 5200); - } + }*/ // Pull the filament end into a cooling tube. writer.retract(15, 5000).retract(50, 5400).retract(15, 3000).retract(12, 2000); @@ -827,9 +872,45 @@ void WipeTowerPrusaMM::toolchange_Unload( if (std::abs(writer.x() - xl) < std::abs(writer.x() - xr)) std::swap(xl, xr); // Horizontal cooling moves will be performed at the following Y coordinate: - writer.travel(xr, writer.y() + y_step * 0.8f, 7200) + /*writer.travel(xr, writer.y() + y_step * 0.8f, 7200) + .suppress_preview();*/ + + /*constexpr float min_cool_speed = 1600; + constexpr float max_cool_speed = 2400; + + const int num_of_intervals = 4; + + writer.travel(writer.x(), writer.y() + y_step) + .retract(-3,min_cool_speed) .suppress_preview(); - switch (current_material) + + int filament_direction = -1; // retract first + float cool_speed = min_cool_speed; + // Numbers 12 (24) below fix velocity in E to 12 times less than in X (total move in X assumed to be >> move in E) + + for (int counter=0 ; counter < num_of_intervals ; ++counter) { + float needed_e_move = cool_speed * (cooling_time / num_of_intervals) / 12.f; // distance yet to move in E axis + do { + remaining = ( left_to_right ? xr-m_perimeter_width-writer.x() : -xl-m_perimeter_width+writer.x()); // distance to the turning point + float xmove = std::min( std::fabs(needed_e_move) * 12.f, remaining * 2.f); // distance to travel + printf("posun z %f na %f",writer.x(),writer.x()+xmove / 2.f * (left_to_right ? 1 : -1)); + writer.cool(writer.x() + xmove / 2.f * (left_to_right ? 1 : -1), writer.x(), filament_direction * xmove / 24.f, filament_direction * xmove / 24.f, cool_speed); + printf(", E %f, rychlost %f\n\n",filament_direction * xmove /12.f,cool_speed); + needed_e_move -= xmove/12.f; + if (needed_e_move > WT_EPSILON) + filament_direction *= -1; + else + left_to_right = !left_to_right; + + } while (needed_e_move > WT_EPSILON); + if (filament_direction==-1) + cool_speed += (max_cool_speed - min_cool_speed) / num_of_intervals; + } + + writer.retract(3, max_cool_speed);*/ + + + /*switch (current_material) { case PVA: writer.cool(xl, xr, 3, -5, 1600) @@ -851,7 +932,7 @@ void WipeTowerPrusaMM::toolchange_Unload( .cool(xl, xr, 5, -5, 2000) .cool(xl, xr, 5, -5, 2400) .cool(xl, xr, 5, -3, 2400); - } + }*/ writer.resume_preview() .flush_planner_queue(); @@ -881,13 +962,13 @@ void WipeTowerPrusaMM::toolchange_Load( PrusaMultiMaterial::Writer &writer, const box_coordinates &cleaning_box) { - float xl = cleaning_box.ld.x + m_perimeter_width; - float xr = cleaning_box.rd.x - m_perimeter_width; + float xl = cleaning_box.ld.x + m_perimeter_width * 0.75f; + float xr = cleaning_box.rd.x - m_perimeter_width * 0.75f; //FIXME flipping left / right side, so that the following toolchange_Wipe will start // where toolchange_Load ends. - std::swap(xl, xr); + //std::swap(xl, xr); - writer.append("; CP TOOLCHANGE LOAD\n") + /*writer.append("; CP TOOLCHANGE LOAD\n") // Load the filament while moving left / right, // so the excess material will not create a blob at a single position. .suppress_preview() @@ -899,9 +980,9 @@ void WipeTowerPrusaMM::toolchange_Load( .load_move_x(xr, 20, 1600) .load_move_x(xl, 10, 1000) .resume_preview(); - +*/ // Extrude first five lines (just three lines if colorInit is set). - writer.extrude(xr, writer.y(), 1600); + /*writer.extrude(xr, writer.y(), 1600); bool colorInit = false; size_t pass = colorInit ? 1 : 2; float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_line_width; @@ -910,12 +991,31 @@ void WipeTowerPrusaMM::toolchange_Load( writer.extrude(xl, writer.y(), 2200); writer.travel (xl, writer.y() + dy, 7200); writer.extrude(xr, writer.y(), 2200); + }*/ + + float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_line_width; + float x = (loading_volume) / (Filament_Area * m_extrusion_flow); // extrusion length to extrude desired volume + while (x > WT_EPSILON) { + float remaining = (m_left_to_right ? xr - writer.x() : writer.x() - xl ); + float dist = std::min(x, remaining); + writer.extrude(writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, writer.y(), 2200); + x -= dist; + + if (x > WT_EPSILON) { // don't switch it for the last (unfinished) line + m_left_to_right = !m_left_to_right; + writer.travel(writer.x(), writer.y() + dy, 7200); + } + else // advance just a fraction for debugging (to see where the load ends) (FIXME - HAS to be deleted, can pass the edge) + writer.travel(writer.x()+(m_left_to_right ? 0.1f : -0.1f),writer.y()); } // Reset the extruder current to the normal value. 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, @@ -926,8 +1026,8 @@ void WipeTowerPrusaMM::toolchange_Wipe( writer.set_extrusion_flow(m_extrusion_flow * (m_is_first_layer ? 1.18f : 1.f)) .append("; CP TOOLCHANGE WIPE\n"); float wipe_coeff = m_is_first_layer ? 0.5f : 1.f; - float xl = cleaning_box.ld.x + 2.f * m_perimeter_width; - float xr = cleaning_box.rd.x - 2.f * m_perimeter_width; + const float& xl = cleaning_box.ld.x; // + 2.f * m_perimeter_width; + const float& xr = cleaning_box.rd.x; // - 2.f * m_perimeter_width; // Wipe speed will increase up to 4800. float wipe_speed = 4200.f; float wipe_speed_inc = 50.f; @@ -935,27 +1035,22 @@ void WipeTowerPrusaMM::toolchange_Wipe( // Y increment per wipe line. float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_line_width; - for (bool p = true; - // Next wipe line fits the cleaning box (and not forgetting about border) - ((m_current_shape == SHAPE_NORMAL) ? - (writer.y() <= cleaning_box.lu.y - 1.5f * m_perimeter_width) : - (writer.y() >= cleaning_box.ld.y + 1.5f * m_perimeter_width)); - p = ! p) + for ( int i = 0 ; true ; ++i ) { wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc); - if (skip_initial_y_move) - skip_initial_y_move = false; + if (m_left_to_right) + writer.extrude(xr - (i % 4 == 0 ? 0 : m_perimeter_width), writer.y(), wipe_speed * wipe_coeff); else - writer.extrude(xl - (p ? m_perimeter_width / 2 : m_perimeter_width), writer.y() + dy, wipe_speed * wipe_coeff); - writer.extrude(xr + (p ? m_perimeter_width : m_perimeter_width * 2), writer.y(), wipe_speed * wipe_coeff); - // Next wipe line fits the cleaning box. - if ((m_current_shape == SHAPE_NORMAL) ? - (writer.y() > cleaning_box.lu.y - m_perimeter_width) : - (writer.y() < cleaning_box.ld.y + m_perimeter_width)) + writer.extrude(xl + (i % 4 == 1 ? 0 : m_perimeter_width), writer.y(), wipe_speed * wipe_coeff); + + if ((m_current_shape == SHAPE_NORMAL) ? // in case next line would not fit + (writer.y() > cleaning_box.lu.y - m_perimeter_width * 1.5f) : + (writer.y() < cleaning_box.ld.y + m_perimeter_width * 1.5f)) break; - wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc); - writer.extrude(xr + m_perimeter_width, writer.y() + dy, wipe_speed * wipe_coeff); - writer.extrude(xl - m_perimeter_width, writer.y()); + + // stepping to the next line: + writer.extrude(writer.x() + (i % 4 == 0 ? -1.f : (i % 4 == 1 ? 1.f : 0.f)) * m_perimeter_width, writer.y() + dy); + m_left_to_right = !m_left_to_right; } // Reset the extrusion flow. writer.set_extrusion_flow(m_extrusion_flow); @@ -1081,10 +1176,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) const size_t zig_zags_num = (fill_box.rd.x - fill_box.ld.x - m_perimeter_width * 12.f) / max_bridge_distance; const float step = (fill_box.rd.x - fill_box.ld.x - m_perimeter_width * 12.f) / (float)zig_zags_num; - float offsety = std::max(0.f, dy - m_last_infill_tan * (step - m_perimeter_width)); + float offsetx = std::max(0.f, dy / m_last_infill_tan > step / 2.f ? step - dy / m_last_infill_tan : 0.f); + float offsety = ( offsetx != 0 ? 0 : std::max(0.f, dy - m_last_infill_tan * (step - m_perimeter_width)) ); if (offsety < m_last_infill_tan * m_perimeter_width + WT_EPSILON || offsety > dy / 2.f) offsety = 0.f; - float offsetx = ( offsety != 0 ? 0 : std::max(0.f, dy / m_last_infill_tan > step / 2.f ? step - dy / m_last_infill_tan : 0.f ) ); + for (size_t i = 0; i < zig_zags_num; ++i) { @@ -1140,23 +1236,19 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool,bool brim) { assert(m_plan.back().z <= z_par); // refuse to add a layer below the last one - - // volumes in mm^3 required for ramming - // hardcoded so far, in future should be calculated by integrating the speed/time curve - const std::vector ram_volumes = {22,22,22,22}; - + // volumes in mm^3 required for wipe: {{from 0 to ...},{from 1 to ...},{from 2 to ...},{from 3 to ...}}, usage [from][to] - const std::vector> wipe_volumes = {{ 0, 40, 60, 80}, - {100, 0,120,100}, - { 80,107, 0,110}, - { 60, 40, 60, 0}}; + const std::vector> wipe_volumes = {{ 0, 40, 60,100}, + {100, 0,130,100}, + { 80, 90, 0,110}, + { 50, 40, 60, 0}}; - float depth = (wipe_volumes[old_tool][new_tool]) / (m_extrusion_flow * Filament_Area); // length of extrusion + float depth = (wipe_volumes[old_tool][new_tool]) / (extrusion_flow(layer_height_par) * Filament_Area); // length of extrusion depth += 6 * 59; // reserved for ramming depth += 2 * 59; // reserved for loading depth -= 2 * 59; // we will also print borders depth = floor(depth / m_wipe_tower_width + 1); // number of lines to extrude - depth *= m_perimeter_width; // conversion to distance + depth *= m_line_width; // conversion to distance if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan along with the first toolchange m_plan.push_back(WipeTowerInfo(z_par, layer_height_par)); diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 04e0b004a..6ca807528 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -237,6 +237,7 @@ private: // after the wipe tower brim has been extruded? float m_initial_extra_wipe = 0.f; float m_last_infill_tan = 1000.f; // impossibly high value + bool m_left_to_right = true; float extrusion_flow(float layer_height = -1.f) const { From 5ca0a2f37dc69aed796d84db6a82f99bdbc50d8c Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 21 Feb 2018 13:07:32 +0100 Subject: [PATCH 12/81] Parametrized toolchanges, experiments with sparse wipe tower, etc --- xs/src/libslic3r/GCode/WipeTower.hpp | 1 + xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 792 ++++++++++---------- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 105 ++- 3 files changed, 441 insertions(+), 457 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index 28549ae64..289e8e122 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -17,6 +17,7 @@ public: struct xy { xy(float x = 0.f, float y = 0.f) : x(x), y(y) {} + xy(xy& pos,float xp,float yp) : x(pos.x+xp), y(pos.y+yp) {} xy operator+(const xy &rhs) const { xy out(*this); out.x += rhs.x; out.y += rhs.y; return out; } xy operator-(const xy &rhs) const { xy out(*this); out.x -= rhs.x; out.y -= rhs.y; return out; } xy& operator+=(const xy &rhs) { x += rhs.x; y += rhs.y; return *this; } diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index ce9b8883a..c409b5f20 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -1,3 +1,18 @@ +/* + +TODO LIST +--------- + +1. cooling moves - DONE +2. priming extrusions - DONE (fixed wiping volume so far) +3. account for perimeter and finish_layer extrusions and subtract it from last wipe +4. Peter's wipe tower - layer's are not exactly square +5. Peter's wipe tower - variable width for higher levels +6. Peter's wipe tower - make sure it is not too sparse (apply max_bridge_distance and make last wipe longer) +7. Peter's wipe tower - enable enhanced first layer adhesion + +*/ + #include "WipeTowerPrusaMM.hpp" #include @@ -14,14 +29,35 @@ #define strcasecmp _stricmp #endif - +constexpr bool peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet +constexpr float min_layer_difference = 2*m_perimeter_width; +constexpr float max_bridge_distance = 10.f; // in mm +constexpr bool improve_first_layer_adhesion = true; // experimental: ramming speed (mm^3/s) sampled in 0.25s intervals (one filament so far) const std::vector ramming_speed = {7.6, 7.6, 7.6, 7.6, 9.0, 9.0, 9.0, 10.7, 10.7, 10.7}; +constexpr float ramming_step_multiplicator = 1.2f; // extra spacing may be needed for some materials +constexpr float ramming_line_width_multiplicator = 1.5f; + // experimental: time requested for cooling in seconds (common for all materials so far) -const float cooling_time = 14; // PVA: 20; SCAFF: 17 -const float loading_volume = 20; +constexpr float cooling_time = 14; // PVA: 20; SCAFF: 17; PLA+others: 14 +// volumes in mm^3 required for wipe: {{from 0 to ...},{from 1 to ...},{from 2 to ...},{from 3 to ...}}, usage [from][to] +const std::vector> wipe_volumes = {{ 0,120, 10, 50}, + { 20, 0, 30, 40}, + { 90, 20, 0, 85}, + {100,140, 30, 0}}; + +/*const std::vector> wipe_volumes = {{0, 67, 67, 67}, + {67, 0, 67, 67}, + {67, 67, 0, 67}, + {67, 67, 67, 0}}; +*/ +/*const std::vector> wipe_volumes = {{0, 10, 10, 10}, + {10, 0, 10, 10}, + {10, 10, 0, 10}, + {10, 10, 10, 0}}; +*/ namespace Slic3r { @@ -35,8 +71,8 @@ public: m_current_pos(std::numeric_limits::max(), std::numeric_limits::max()), m_current_z(0.f), m_current_feedrate(0.f), - m_extrusion_flow(0.f), m_layer_height(0.f), + m_extrusion_flow(0.f), m_preview_suppressed(false), m_elapsed_time(0.f) {} @@ -60,6 +96,9 @@ public: Writer& set_rotation(WipeTower::xy& pos, float width, float depth, float angle) { m_wipe_tower_pos = pos; m_wipe_tower_width = width; m_wipe_tower_depth=depth; m_angle_deg = angle; return (*this); } + Writer& set_y_shift(float shift) + { m_y_shift = shift; return (*this); } + // Suppress / resume G-code preview in Slic3r. Slic3r will have difficulty to differentiate the various // filament loading and cooling moves from normal extrusion moves. Therefore the writer // is asked to suppres output of some lines, which look like extrusions. @@ -79,7 +118,7 @@ public: float y() const { return m_current_pos.y; } const WipeTower::xy& pos() const { return m_current_pos; } const WipeTower::xy start_pos_rotated() const { return m_start_pos.rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } - const WipeTower::xy pos_rotated() const { return m_current_pos.rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } + const WipeTower::xy pos_rotated() const { return m_current_pos.rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } float elapsed_time() const { return m_elapsed_time; } // Extrude with an explicitely provided amount of extrusion. @@ -92,10 +131,11 @@ public: float dx = x - m_current_pos.x; float dy = y - m_current_pos.y; double len = sqrt(dx*dx+dy*dy); - + + // For rotated wipe tower, transform position to printer coordinates - WipeTower::xy rotated_current_pos(m_current_pos.rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); - WipeTower::xy rot(WipeTower::xy(x,y).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); + WipeTower::xy rotated_current_pos(WipeTower::xy(m_current_pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); + WipeTower::xy rot(WipeTower::xy(x,y+m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); if (! m_preview_suppressed && e > 0.f && len > 0.) { // Width of a squished extrusion, corrected for the roundings of the squished extrusions. @@ -321,7 +361,8 @@ private: std::string m_gcode; std::vector m_extrusions; float m_elapsed_time; - float m_angle_deg = 0; + float m_angle_deg = 0.f; + float m_y_shift = 0.f; WipeTower::xy m_wipe_tower_pos; float m_wipe_tower_width; float m_wipe_tower_depth; @@ -427,7 +468,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( { this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false); - float wipe_area = m_wipe_area; // Calculate the amount of wipe over the wipe tower brim following the prime, decrease wipe_area // with the amount of material extruded over the brim. // DOESN'T MAKE SENSE NOW, wipe tower dimensions are still unknown at this point @@ -454,7 +494,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // box_coordinates cleaning_box(xy(0.5f, - 1.5f), m_wipe_tower_width, wipe_area); //FIXME: set the width properly constexpr float prime_section_width = 60.f; - box_coordinates cleaning_box(xy(5.f, 0.f), prime_section_width, wipe_area); + box_coordinates cleaning_box(xy(5.f, 0.f), prime_section_width, 15.f); PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow) @@ -466,37 +506,26 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( .append(";--------------------\n") .speed_override(100); - // Always move to the starting position. - writer.set_initial_position(xy(0.f, 0.f)) - .travel(cleaning_box.ld, 7200) - // Increase the extruder driver current to allow fast ramming. - .set_extruder_trimpot(750); + 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. if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { - float y_end = 0.f; for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) { unsigned int tool = tools[idx_tool]; - // Select the tool, set a speed override for soluble and flex materials. - toolchange_Change(writer, tool, m_material[tool]); - // Prime the tool. - toolchange_Load(writer, cleaning_box); + m_left_to_right = true; + toolchange_Change(writer, tool, m_material[tool]); // Select the tool, set a speed override for soluble and flex materials. + toolchange_Load(writer, cleaning_box); // Prime the tool. if (idx_tool + 1 == tools.size()) { // Last tool should not be unloaded, but it should be wiped enough to become of a pure color. - if (last_wipe_inside_wipe_tower) { - // Shrink the last wipe area to the area of the other purge areas, - // remember the last initial wipe width to be purged into the 1st layer of the wipe tower. - this->m_initial_extra_wipe = std::max(0.f, wipe_area - (y_end + 0.5f * m_line_width - cleaning_box.ld.y)); - cleaning_box.lu.y -= this->m_initial_extra_wipe; - cleaning_box.ru.y -= this->m_initial_extra_wipe; - } - toolchange_Wipe(writer, cleaning_box, false); + toolchange_Wipe(writer, cleaning_box, 20.f); } else { // Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool. - writer.travel(writer.x(), writer.y() + m_perimeter_width, 7200); - // Change the extruder temperature to the temperature of the next filament before starting the cooling moves. - toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], m_first_layer_temperature[tools[idx_tool+1]]); - // Save the y end of the non-last priming area. - y_end = writer.y(); + //writer.travel(writer.x(), writer.y() + m_perimeter_width, 7200); + toolchange_Wipe(writer, cleaning_box , 5.f); + box_coordinates box = cleaning_box; + box.translate(0.f, writer.y() - cleaning_box.ld.y + m_perimeter_width); + toolchange_Unload(writer, box , m_material[m_current_tool], m_first_layer_temperature[tools[idx_tool + 1]]); cleaning_box.translate(prime_section_width, 0.f); writer.travel(cleaning_box.ld, 7200); } @@ -541,7 +570,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo } float wipe_area = 0.f; - /*if (++ m_idx_tool_change_in_layer < (unsigned int)m_max_color_changes && last_in_layer) { + {/*if (++ m_idx_tool_change_in_layer < (unsigned int)m_max_color_changes && last_in_layer) { // This tool_change() call will be followed by a finish_layer() call. // Try to shrink the wipe_area to save material, as less than usual wipe is required // if this step is foolowed by finish_layer() extrusions wiping the same extruder. @@ -568,29 +597,39 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo break; } } - }*/ + }*/} + bool last_change_in_layer = false; + float wipe_volume = 0.f; + // Finds this toolchange info - if (tool != (unsigned int)(-1)) { + if (tool != (unsigned int)(-1)) + { for (const auto &b : m_layer_info->tool_changes) - if ( b.new_tool == tool ) - wipe_area = b.required_depth; + if ( b.new_tool == tool ) { + wipe_volume = wipe_volumes[b.old_tool][b.new_tool]; + if (tool == m_layer_info->tool_changes.back().new_tool) + last_change_in_layer = true; + wipe_area = b.required_depth * m_layer_info->extra_spacing; + break; + } } else { // Otherwise we are going to Unload only. And m_layer_info would be invalid. } - + box_coordinates cleaning_box( - m_wipe_tower_pos + xy(0.f, m_current_wipe_start_y + 0.5f * m_perimeter_width), - m_wipe_tower_width, - wipe_area - m_perimeter_width); + m_wipe_tower_pos + xy(m_perimeter_width / 2.f, m_perimeter_width / 2.f), + m_wipe_tower_width - m_perimeter_width, + (tool != (unsigned int)(-1) ? m_layer_info->depth : m_wipe_tower_depth-m_perimeter_width)); PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow) .set_z(m_z_pos) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) - .set_rotation(m_wipe_tower_pos,m_wipe_tower_width,m_wipe_tower_depth,m_wipe_tower_rotation_angle) + .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) + .set_y_shift(m_y_shift) .append(";--------------------\n" "; CP TOOLCHANGE START\n") .comment_with_value(" toolchange #", m_num_tool_changes) @@ -598,8 +637,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .append(";--------------------\n") .speed_override(100); - xy initial_position = ((m_current_shape == SHAPE_NORMAL) ? cleaning_box.ld : cleaning_box.lu) + - xy(m_perimeter_width, ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width); + xy initial_position = cleaning_box.ld + WipeTower::xy(0.f,m_depth_traversed); if (purpose == PURPOSE_MOVE_TO_TOWER || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { // Scaffold leaks terribly, reduce leaking by a full retract when going to the wipe tower. @@ -623,35 +661,29 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { // Increase the extruder driver current to allow fast ramming. writer.set_extruder_trimpot(750); + // 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) { + if (tool != (unsigned int)-1){ // This is not the last change. toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], - m_is_first_layer ? m_first_layer_temperature[tool] : m_temperature[tool]); - // This is not the last change. - // Change the tool, set a speed override for soluble and flex materials. - toolchange_Change(writer, tool, m_material[tool]); - toolchange_Load(writer, cleaning_box); - // Wipe the newly loaded filament until the end of the assigned wipe area. - toolchange_Wipe(writer, cleaning_box, false); - // Draw a perimeter around cleaning_box and wipe. - box_coordinates box = cleaning_box; - if (m_current_shape == SHAPE_REVERSED) { - std::swap(box.lu, box.ld); - std::swap(box.ru, box.rd); - } - // Draw a perimeter around cleaning_box. - writer.travel(box.lu, 7000) - .extrude(box.ld, 3200).extrude(box.rd) - .extrude(box.ru).extrude(box.lu); - // Wipe the nozzle. - //if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) + m_is_first_layer ? m_first_layer_temperature[tool] : m_temperature[tool]); + toolchange_Change(writer, tool, m_material[tool]); // Change the tool, set a speed override for soluble and flex materials. + toolchange_Load(writer, cleaning_box); + toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area. + // Always wipe the nozzle with a long wipe to reduce stringing when moving away from the wipe tower. - writer.travel(box.ru, 7200) - .travel(box.lu); + /*box_coordinates box = cleaning_box; + writer.travel(box.ru, 7200) + .travel(box.lu);*/ } else toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], m_temperature[m_current_tool]); + if (last_change_in_layer) // draw perimeter line + writer.travel(m_wipe_tower_pos, 7000) + .extrude(m_wipe_tower_pos + xy(0, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width), 3200) + .extrude(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width)) + .extrude(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, 0)) + .extrude(m_wipe_tower_pos); + // Reset the extruder current to a normal value. writer.set_extruder_trimpot(550) .feedrate(6000) @@ -662,7 +694,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo "\n\n"); ++ m_num_tool_changes; - m_current_wipe_start_y += wipe_area; + //m_current_wipe_start_y += wipe_area; + m_depth_traversed += wipe_area; } ToolChangeResult result; @@ -681,18 +714,16 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b const box_coordinates wipeTower_box( m_wipe_tower_pos, m_wipe_tower_width, - m_wipe_tower_depth - m_perimeter_width / 2); + m_wipe_tower_depth); PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow * 1.1f) - // Let the writer know the current Z position as a base for Z-hop. - .set_z(m_z_pos) - .set_layer_height(m_layer_height) - .set_initial_tool(m_current_tool) - .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) - .append( - ";-------------------------------------\n" - "; CP WIPE TOWER FIRST LAYER BRIM START\n"); + .set_z(m_z_pos) // Let the writer know the current Z position as a base for Z-hop. + .set_layer_height(m_layer_height) + .set_initial_tool(m_current_tool) + .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) + .append(";-------------------------------------\n" + "; CP WIPE TOWER FIRST LAYER BRIM START\n"); xy initial_position = wipeTower_box.lu - xy(m_perimeter_width * 6.f, 0); @@ -705,66 +736,29 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b writer.set_initial_position(initial_position); if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { - // Prime the extruder 10*m_perimeter_width left along the vertical edge of the wipe tower. - writer.extrude_explicit(wipeTower_box.ld - xy(m_perimeter_width * 6.f, 0), - 1.5f * m_extrusion_flow * (wipeTower_box.lu.y - wipeTower_box.ld.y), 2400); + + writer.extrude_explicit(wipeTower_box.ld - xy(m_perimeter_width * 6.f, 0), // Prime the extruder left of the wipe tower. + 1.5f * m_extrusion_flow * (wipeTower_box.lu.y - wipeTower_box.ld.y), 2400); // The tool is supposed to be active and primed at the time when the wipe tower brim is extruded. // toolchange_Change(writer, int(tool), m_material[tool]); + + // Extrude 4 rounds of a brim around the future wipe tower. + box_coordinates box(wipeTower_box); + box.expand(m_perimeter_width); + for (size_t i = 0; i < 4; ++ i) { + writer.travel (box.ld, 7000) + .extrude(box.lu, 2100).extrude(box.ru) + .extrude(box.rd ).extrude(box.ld); + box.expand(m_perimeter_width); + } - if (sideOnly) { - float x_offset = m_perimeter_width; - for (size_t i = 0; i < 4; ++ i, x_offset += m_perimeter_width) - writer.travel (wipeTower_box.ld + xy(- x_offset, y_offset), 7000) - .extrude(wipeTower_box.lu + xy(- x_offset, - y_offset), 2100); - writer.travel(wipeTower_box.rd + xy(x_offset, y_offset), 7000); - x_offset = m_perimeter_width; - for (size_t i = 0; i < 4; ++ i, x_offset += m_perimeter_width) - writer.travel (wipeTower_box.rd + xy(x_offset, y_offset), 7000) - .extrude(wipeTower_box.ru + xy(x_offset, - y_offset), 2100); - } else { - // Extrude 4 rounds of a brim around the future wipe tower. - box_coordinates box(wipeTower_box); - //FIXME why is the box shifted in +Y by 0.5f * m_perimeter_width? - box.translate(0.f, 0.5f * m_perimeter_width); - box.expand(0.5f * m_perimeter_width); - for (size_t i = 0; i < 4; ++ i) { - writer.travel (box.ld, 7000) - .extrude(box.lu, 2100).extrude(box.ru) - .extrude(box.rd ).extrude(box.ld); - box.expand(m_perimeter_width); - } - } - - if (m_initial_extra_wipe > m_perimeter_width * 1.9f) { - box_coordinates cleaning_box( - m_wipe_tower_pos + xy(0.f, 0.5f * m_perimeter_width), - m_wipe_tower_width, - m_initial_extra_wipe - m_perimeter_width); - writer.travel(cleaning_box.ld + xy(m_perimeter_width, 0.5f * m_perimeter_width), 6000); - // Wipe the newly loaded filament until the end of the assigned wipe area. - toolchange_Wipe(writer, cleaning_box, true); - // Draw a perimeter around cleaning_box. - writer.travel(cleaning_box.lu, 7000) - .extrude(cleaning_box.ld, 3200).extrude(cleaning_box.rd) - .extrude(cleaning_box.ru).extrude(cleaning_box.lu); - m_current_wipe_start_y = m_initial_extra_wipe; - } - - // Move to the front left corner. - writer.travel(wipeTower_box.ld, 7000); - - //if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) - // Wipe along the front edge. - // Always wipe the nozzle with a long wipe to reduce stringing when moving away from the wipe tower. - writer.travel(wipeTower_box.rd) - .travel(wipeTower_box.ld); - - writer.append("; CP WIPE TOWER FIRST LAYER BRIM END\n" + writer.travel(wipeTower_box.ld, 7000); // Move to the front left corner. + writer.travel(wipeTower_box.rd) // Always wipe the nozzle with a long wipe to reduce stringing when moving away from the wipe tower. + .travel(wipeTower_box.ld); + writer.append("; CP WIPE TOWER FIRST LAYER BRIM END\n" ";-----------------------------------\n"); - // Mark the brim as extruded. - ///m_idx_tool_change_in_layer = 0; m_print_brim = false; } @@ -779,6 +773,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b return result; } + + // Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool. void WipeTowerPrusaMM::toolchange_Unload( PrusaMultiMaterial::Writer &writer, @@ -786,53 +782,46 @@ void WipeTowerPrusaMM::toolchange_Unload( const material_type current_material, const int new_temperature) { - float xl = cleaning_box.ld.x + 0.5f * m_perimeter_width; - float xr = cleaning_box.rd.x - 0.5f * m_perimeter_width; + float xl = cleaning_box.ld.x + 1.f * m_perimeter_width; + float xr = cleaning_box.rd.x - 1.f * m_perimeter_width; writer.append("; CP TOOLCHANGE UNLOAD\n"); - // Ram the hot material out of the extruder melt zone. - // Current extruder position is on the left, one perimeter inside the cleaning box in both X and Y. - //float e0 = m_perimeter_width * m_extrusion_flow; - //float e = (xr - xl) * m_extrusion_flow; - //float y_step = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width * ramming_step_multiplicator; + const float line_width = m_line_width * ramming_line_width_multiplicator; // desired ramming line thickness + const float y_step = line_width * ramming_step_multiplicator * m_extra_spacing; // spacing between lines in mm - constexpr float ramming_step_multiplicator = 1.f; // extra spacing needed for some materials - const float line_width = m_line_width * 1.5f; // desired ramming line thickness - - float y_step = (m_current_shape == SHAPE_NORMAL ? 1.f : -1.f) * // spacing between lines in mm - line_width * ramming_step_multiplicator; - - - int i = 0; // iterates through ramming_speed + unsigned i = 0; // iterates through ramming_speed m_left_to_right = true; // current direction of ramming - float remaining = xr - xl - 2 * m_perimeter_width; // keeps track of distance to the next turnaround + float remaining = xr - xl ; // keeps track of distance to the next turnaround float e_done = 0; // measures E move done from each segment + + writer.travel(xl, cleaning_box.ld.y + m_depth_traversed + y_step/2.f ); // move to starting position - writer.travel(xl + m_perimeter_width, writer.y() + y_step * 0.2); // move to starting position - - while (i < ramming_speed.size()) { - const float x = (ramming_speed[i] * 0.25f) / // extrusion length to get desired line_width - (m_layer_height * (line_width - m_layer_height * (1. - M_PI / 4.))); - const float e = ramming_speed[i] * 0.25f / Filament_Area; // transform volume per sec to E move; - const float dist = std::min(x - e_done, remaining); // distance to travel for the next 0.25s - writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), std::hypot(dist, e * (dist / x)) / (0.25 / 60.)); + while (i < ramming_speed.size()) + { + const float x = volume_to_length(ramming_speed[i] * 0.25f, line_width, m_layer_height); + const float e = ramming_speed[i] * 0.25f / Filament_Area; // transform volume per sec to E move; + const float dist = std::min(x - e_done, remaining); // distance to travel for either the next 0.25s, or to the next turnaround + const float actual_time = dist/x * 0.25; + writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), std::hypot(dist, e * (dist / x)) / (actual_time / 60.)); remaining -= dist; - if ( remaining < WT_EPSILON ) { // we reached a turning point - writer.travel(writer.x(), writer.y() + y_step); + if (remaining < WT_EPSILON) { // we reached a turning point + writer.travel(writer.x(), writer.y() + y_step, 7200); m_left_to_right = !m_left_to_right; - remaining = xr - xl - 2 * m_perimeter_width; + remaining = xr - xl; } - e_done += dist; // subtract what was actually transversed - if (e_done > x - WT_EPSILON) { // current segment finished + e_done += dist; // subtract what was actually done + if (e_done > x - WT_EPSILON) { // current segment finished ++i; e_done = 0; } } + WipeTower::xy end_of_ramming(writer.x(),writer.y()); - - /*switch (current_material) +// Alex's old ramming: +{ + /*switch (current_material) { case ABS: // ramming start end y increment amount feedrate @@ -848,7 +837,7 @@ void WipeTowerPrusaMM::toolchange_Unload( .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.5f, 0, 1.75f * e, 4800) .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.5f, 0, 1.75f * e, 5000); break; - case PET: //!!! SCAFF (PET only used for testing): + case SCAFF: writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 2.f, 0, 1.75f * e, 4000) .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 3.f, 0, 2.34f * e, 4600) .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 3.f, 0, 2.63f * e, 5200); @@ -860,85 +849,83 @@ void WipeTowerPrusaMM::toolchange_Unload( .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.2f, e0, 1.65f * e, 4600) .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.2f, e0, 1.74f * e, 5200); }*/ - +} // Pull the filament end into a cooling tube. writer.retract(15, 5000).retract(50, 5400).retract(15, 3000).retract(12, 2000); - if (new_temperature != 0) - // Set the extruder temperature, but don't wait. + if (new_temperature != 0) // Set the extruder temperature, but don't wait. writer.set_extruder_temp(new_temperature, false); - // In case the current print head position is closer to the left edge, reverse the direction. - if (std::abs(writer.x() - xl) < std::abs(writer.x() - xr)) - std::swap(xl, xr); - // Horizontal cooling moves will be performed at the following Y coordinate: - /*writer.travel(xr, writer.y() + y_step * 0.8f, 7200) - .suppress_preview();*/ - - /*constexpr float min_cool_speed = 1600; - constexpr float max_cool_speed = 2400; - - const int num_of_intervals = 4; - - writer.travel(writer.x(), writer.y() + y_step) - .retract(-3,min_cool_speed) - .suppress_preview(); - - int filament_direction = -1; // retract first - float cool_speed = min_cool_speed; - // Numbers 12 (24) below fix velocity in E to 12 times less than in X (total move in X assumed to be >> move in E) +// cooling: + writer.retract(2, 2000); + writer.suppress_preview(); + writer.travel(writer.x(), writer.y() + y_step); + const float start_x = writer.x(); + const float turning_point = ( xr-start_x > start_x-xl ? xr : xl ); + const float max_x_dist = 2*std::abs(start_x-turning_point); + const int N = 4 + (cooling_time-14)/3; + float time = cooling_time / N; - for (int counter=0 ; counter < num_of_intervals ; ++counter) { - float needed_e_move = cool_speed * (cooling_time / num_of_intervals) / 12.f; // distance yet to move in E axis - do { - remaining = ( left_to_right ? xr-m_perimeter_width-writer.x() : -xl-m_perimeter_width+writer.x()); // distance to the turning point - float xmove = std::min( std::fabs(needed_e_move) * 12.f, remaining * 2.f); // distance to travel - printf("posun z %f na %f",writer.x(),writer.x()+xmove / 2.f * (left_to_right ? 1 : -1)); - writer.cool(writer.x() + xmove / 2.f * (left_to_right ? 1 : -1), writer.x(), filament_direction * xmove / 24.f, filament_direction * xmove / 24.f, cool_speed); - printf(", E %f, rychlost %f\n\n",filament_direction * xmove /12.f,cool_speed); - needed_e_move -= xmove/12.f; - if (needed_e_move > WT_EPSILON) - filament_direction *= -1; - else - left_to_right = !left_to_right; - - } while (needed_e_move > WT_EPSILON); - if (filament_direction==-1) - cool_speed += (max_cool_speed - min_cool_speed) / num_of_intervals; + i = 0; + while (i WT_EPSILON) { - float remaining = (m_left_to_right ? xr - writer.x() : writer.x() - xl ); - float dist = std::min(x, remaining); - writer.extrude(writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, writer.y(), 2200); - x -= dist; - - if (x > WT_EPSILON) { // don't switch it for the last (unfinished) line - m_left_to_right = !m_left_to_right; - writer.travel(writer.x(), writer.y() + dy, 7200); - } - else // advance just a fraction for debugging (to see where the load ends) (FIXME - HAS to be deleted, can pass the edge) - writer.travel(writer.x()+(m_left_to_right ? 0.1f : -0.1f),writer.y()); - } - + }*/ +} // Reset the extruder current to the normal value. writer.set_extruder_trimpot(550); } @@ -1020,40 +995,55 @@ void WipeTowerPrusaMM::toolchange_Load( void WipeTowerPrusaMM::toolchange_Wipe( PrusaMultiMaterial::Writer &writer, const box_coordinates &cleaning_box, - bool skip_initial_y_move) + float wipe_volume) { // Increase flow on first layer, slow down print. writer.set_extrusion_flow(m_extrusion_flow * (m_is_first_layer ? 1.18f : 1.f)) .append("; CP TOOLCHANGE WIPE\n"); float wipe_coeff = m_is_first_layer ? 0.5f : 1.f; - const float& xl = cleaning_box.ld.x; // + 2.f * m_perimeter_width; - const float& xr = cleaning_box.rd.x; // - 2.f * m_perimeter_width; - // Wipe speed will increase up to 4800. - float wipe_speed = 4200.f; - float wipe_speed_inc = 50.f; - float wipe_speed_max = 4800.f; - // Y increment per wipe line. - float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_line_width; + const float& xl = cleaning_box.ld.x; + const float& xr = cleaning_box.rd.x; + + // DEBUGGING: The function makes sure it always wipes at least the ordered volume, even if it means violating + // the perimeter. This can later be removed and simply wipe until the end of the assigned area. + // (Variables x_to_wipe and traversed_x) - for ( int i = 0 ; true ; ++i ) - { - wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc); - if (m_left_to_right) - writer.extrude(xr - (i % 4 == 0 ? 0 : m_perimeter_width), writer.y(), wipe_speed * wipe_coeff); - else - writer.extrude(xl + (i % 4 == 1 ? 0 : m_perimeter_width), writer.y(), wipe_speed * wipe_coeff); + float x_to_wipe = volume_to_length(wipe_volume, m_line_width, m_layer_height); + float dy = m_extra_spacing*m_line_width; + float wipe_speed = 1600.f; + + for (int i = 0; true; ++i) { + if (i!=0) { + if (wipe_speed < 1610.f) wipe_speed = 1800.f; + else if (wipe_speed < 1810.f) wipe_speed = 2200.f; + else if (wipe_speed < 2210.f) wipe_speed = 4200.f; + else wipe_speed = std::min(4800.f, wipe_speed + 50.f); + } - if ((m_current_shape == SHAPE_NORMAL) ? // in case next line would not fit + float traversed_x = writer.x(); + if (m_left_to_right) + writer.extrude(xr - (i % 4 == 0 ? 0 : 1.5*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff); + else + writer.extrude(xl + (i % 4 == 1 ? 0 : 1.5*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff); + + /*if ((m_current_shape == SHAPE_NORMAL) ? // in case next line would not fit (writer.y() > cleaning_box.lu.y - m_perimeter_width * 1.5f) : (writer.y() < cleaning_box.ld.y + m_perimeter_width * 1.5f)) + break;*/ + traversed_x -= writer.x(); + x_to_wipe -= fabs(traversed_x); + if (x_to_wipe < WT_EPSILON) { + writer.travel(m_left_to_right ? xl + 1.5*m_perimeter_width : xr - 1.5*m_perimeter_width, writer.y(), 7200); break; - + } // stepping to the next line: - writer.extrude(writer.x() + (i % 4 == 0 ? -1.f : (i % 4 == 1 ? 1.f : 0.f)) * m_perimeter_width, writer.y() + dy); + writer.extrude(writer.x() + (i % 4 == 0 ? -1.f : (i % 4 == 1 ? 1.f : 0.f)) * 1.5*m_perimeter_width, writer.y() + dy); m_left_to_right = !m_left_to_right; } - // Reset the extrusion flow. - writer.set_extrusion_flow(m_extrusion_flow); + writer.set_extrusion_flow(m_extrusion_flow); // Reset the extrusion flow. + + // Wipe the nozzle + } @@ -1071,6 +1061,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) + .set_y_shift(m_y_shift) .append(";--------------------\n" "; CP EMPTY GRID START\n") // m_num_layer_changes is incremented by set_z, so it is 1 based. @@ -1078,18 +1069,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) // Slow down on the 1st layer. float speed_factor = m_is_first_layer ? 0.5f : 1.f; - - float current_depth = m_wipe_tower_depth; - if (m_is_first_layer) - current_depth = m_wipe_tower_depth; - else - current_depth = m_layer_info->depth; - - - box_coordinates fill_box(m_wipe_tower_pos + xy(0.f, m_current_wipe_start_y), - m_wipe_tower_width, current_depth - m_current_wipe_start_y); - fill_box.expand(0.f, - 0.5f * m_perimeter_width); - + float current_depth = m_layer_info->depth - m_layer_info->toolchanges_depth(); + box_coordinates fill_box(m_wipe_tower_pos + xy(m_perimeter_width, m_depth_traversed + m_perimeter_width), + m_wipe_tower_width - 2 * m_perimeter_width, current_depth-m_perimeter_width); if (purpose == PURPOSE_MOVE_TO_TOWER || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { if ( m_layer_info->tool_changes.size() == 0) { @@ -1106,102 +1088,62 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) } } else { // The print head is inside the wipe tower. Rather move to the start of the following extrusion. - // writer.set_initial_position(fill_box.ld); writer.set_initial_position(fill_box.ld); } if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { - // Extrude the first perimeter. box_coordinates box = fill_box; - writer.extrude(box.lu, 2400 * speed_factor) - .extrude(box.ru) - .extrude(box.rd) - .extrude(box.ld + xy(m_perimeter_width / 2, 0)); + for (int i=0;i<2;++i) { + if (m_layer_info->toolchanges_depth() < WT_EPSILON) { // there were no toolchanges on this layer + if (i==0) box.expand(m_perimeter_width); + else box.expand(-m_perimeter_width); + } + else i=2; // only draw the inner perimeter - // Extrude second perimeter. - box.expand(- m_perimeter_width / 2); - writer.extrude(box.lu, 3200 * speed_factor) - .extrude(box.ru) - .extrude(box.rd) - .extrude(box.ld + xy(m_perimeter_width / 2, 0)); + writer.travel(box.ld,7200) + .extrude(box.lu, 2400 * speed_factor) + .extrude(box.ru) + .extrude(box.rd) + .extrude(box.ld); + } - if (m_is_first_layer) { + if (m_is_first_layer && improve_first_layer_adhesion) { // Extrude a dense infill at the 1st layer to improve 1st layer adhesion of the wipe tower. - box.expand(- m_perimeter_width / 2); - box.ld.y -= 0.5f * m_perimeter_width; - box.rd.y = box.ld.y; - int nsteps = int(floor((box.lu.y - box.ld.y) / (2. * (1.0 * m_perimeter_width)))); + box.expand(-m_perimeter_width/2.f); + unsigned nsteps = int(floor((box.lu.y - box.ld.y) / (2*m_perimeter_width))); float step = (box.lu.y - box.ld.y) / nsteps; - //FIXME: + writer.travel(box.ld-xy(m_perimeter_width/2.f,m_perimeter_width/2.f)); if (nsteps >= 0) for (size_t i = 0; i < nsteps; ++i) { - writer.extrude(box.ld.x, writer.y() + 0.5f * step); - writer.extrude(box.rd.x, writer.y()); - writer.extrude(box.rd.x, writer.y() + 0.5f * step); - writer.extrude(box.ld.x, writer.y()); + writer.extrude(box.ld.x+m_perimeter_width/2.f, writer.y() + 0.5f * step); + writer.extrude(box.rd.x - m_perimeter_width / 2.f, writer.y()); + writer.extrude(box.rd.x - m_perimeter_width / 2.f, writer.y() + 0.5f * step); + writer.extrude(box.ld.x + m_perimeter_width / 2.f, writer.y()); } + writer.travel(box.rd.x-m_perimeter_width/2.f,writer.y()); // wipe the nozzle } else { // Extrude a sparse infill to support the material to be printed above. - // Extrude an inverse U at the left of the region. - writer.extrude(box.ld + xy(m_perimeter_width / 2, m_perimeter_width / 2)) - .extrude(fill_box.ld + xy(m_perimeter_width * 3, m_perimeter_width), 2900 * speed_factor) - .extrude(fill_box.lu + xy(m_perimeter_width * 3, - m_perimeter_width)) - .extrude(fill_box.lu + xy(m_perimeter_width * 6, - m_perimeter_width)) - .extrude(fill_box.ld + xy(m_perimeter_width * 6, m_perimeter_width)); - - /*if (fill_box.lu.y - fill_box.ld.y > 4.f) { - const float max_bridge_distance = 10.f; // in mm - size_t zig_zags_num = int((m_wipe_tower_width - m_perimeter_width * 12.f) / ( max_bridge_distance * 2.f ) ) + 1 ; - float step = (m_wipe_tower_width - m_perimeter_width * 12.f) / (zig_zags_num * 4); - for (size_t i = 0; i < zig_zags_num; ++ i) { - writer.extrude(writer.x() + step, fill_box.ld.y + m_perimeter_width * 8, 3200 * speed_factor); - writer.extrude(writer.x() , fill_box.lu.y - m_perimeter_width * 8); - writer.extrude(writer.x() + step, fill_box.lu.y - m_perimeter_width ); - writer.extrude(writer.x() + step, fill_box.lu.y - m_perimeter_width * 8); - writer.extrude(writer.x() , fill_box.ld.y + m_perimeter_width * 8); - writer.extrude(writer.x() + step, fill_box.ld.y + m_perimeter_width ); - } - } - // Extrude an inverse U at the left of the region. - writer.extrude(fill_box.ru + xy(-m_perimeter_width * 6, -m_perimeter_width), 2900 * speed_factor) - .extrude(fill_box.ru + xy(-m_perimeter_width * 3, -m_perimeter_width)) - .extrude(fill_box.rd + xy(-m_perimeter_width * 3, m_perimeter_width)) - .extrude(fill_box.rd + xy(-m_perimeter_width, m_perimeter_width));*/ - - const float dy = (fill_box.lu.y - fill_box.ld.y - 2.f * m_perimeter_width); + const float dy = (fill_box.lu.y - fill_box.ld.y - m_perimeter_width); if (dy > m_perimeter_width) - { - const float max_bridge_distance = 10.f; // in mm - const size_t zig_zags_num = (fill_box.rd.x - fill_box.ld.x - m_perimeter_width * 12.f) / max_bridge_distance; - const float step = (fill_box.rd.x - fill_box.ld.x - m_perimeter_width * 12.f) / (float)zig_zags_num; + { + // Extrude an inverse U at the left of the region. + writer.travel(fill_box.ld + xy(m_perimeter_width * 2, 0.f)) + .extrude(fill_box.lu + xy(m_perimeter_width * 2, 0.f), 2900 * speed_factor); - float offsetx = std::max(0.f, dy / m_last_infill_tan > step / 2.f ? step - dy / m_last_infill_tan : 0.f); - float offsety = ( offsetx != 0 ? 0 : std::max(0.f, dy - m_last_infill_tan * (step - m_perimeter_width)) ); - if (offsety < m_last_infill_tan * m_perimeter_width + WT_EPSILON || offsety > dy / 2.f) - offsety = 0.f; - - - for (size_t i = 0; i < zig_zags_num; ++i) - { - writer.extrude(writer.x() + offsetx, writer.y(), 3200 * speed_factor); - if ( offsety != 0 ) { - writer.extrude(writer.x() + m_perimeter_width, writer.y()); - writer.extrude(writer.x(), writer.y() + offsety); - } - writer.extrude(writer.x() + step - offsetx - (offsety==0 ? 0 : m_perimeter_width), fill_box.lu.y - m_perimeter_width); - writer.extrude(writer.x() , fill_box.ld.y + m_perimeter_width); + const float left = fill_box.lu.x+2*m_perimeter_width; + const float right = fill_box.ru.x - 2 * m_perimeter_width; + const int n = 1+(right-left)/max_bridge_distance; + const float dx = (right-left)/n; + for (int i=1;i<=n;++i) { + float x=left+dx*i; + writer.travel(x,writer.y()); + writer.extrude(x,i%2 ? fill_box.rd.y : fill_box.ru.y); } - m_last_infill_tan = (dy - offsety) / (step - offsetx - (offsety==0 ? 0 : m_perimeter_width)); + writer.travel(left,writer.y(),7200); // wipes the nozzle before moving away from the wipe tower } - - // Extrude an inverse U at the left of the region. - writer.extrude(fill_box.rd + xy(-m_perimeter_width * 6, m_perimeter_width), 2900 * speed_factor) - .extrude(fill_box.rd + xy(-m_perimeter_width * 3, m_perimeter_width)) - .extrude(fill_box.ru + xy(-m_perimeter_width * 3, -m_perimeter_width)) - .extrude(fill_box.ru + xy(-m_perimeter_width, -m_perimeter_width)); } - +/* // if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) if (true) // Wipe along the front side of the current wiping box. @@ -1210,16 +1152,14 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) .travel(fill_box.rd + xy(- m_perimeter_width, m_perimeter_width / 2)); else writer.feedrate(7200); - +*/ writer.append("; CP EMPTY GRID END\n" ";------------------\n\n\n\n\n\n\n"); // Indicate that this wipe tower layer is fully covered. - m_current_wipe_start_y = m_wipe_tower_depth; - ///m_idx_tool_change_in_layer = (unsigned int)m_max_color_changes; - + m_depth_traversed = m_wipe_tower_depth-m_perimeter_width; + ///m_idx_tool_change_in_layer = (unsigned int)m_max_color_changes; } - ToolChangeResult result; result.print_z = this->m_z_pos; result.layer_height = this->m_layer_height; @@ -1232,23 +1172,20 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) } // Appends a toolchange into m_plan and calculates neccessary depth of the corresponding box - void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool,bool brim) -{ - assert(m_plan.back().z <= z_par); // refuse to add a layer below the last one - - // volumes in mm^3 required for wipe: {{from 0 to ...},{from 1 to ...},{from 2 to ...},{from 3 to ...}}, usage [from][to] - const std::vector> wipe_volumes = {{ 0, 40, 60,100}, - {100, 0,130,100}, - { 80, 90, 0,110}, - { 50, 40, 60, 0}}; +{ + assert(m_plan.back().z <= z_par + WT_EPSILON ); // refuses to add a layer below the last one - float depth = (wipe_volumes[old_tool][new_tool]) / (extrusion_flow(layer_height_par) * Filament_Area); // length of extrusion - depth += 6 * 59; // reserved for ramming - depth += 2 * 59; // reserved for loading - depth -= 2 * 59; // we will also print borders - depth = floor(depth / m_wipe_tower_width + 1); // number of lines to extrude - depth *= m_line_width; // conversion to distance + float width = m_wipe_tower_width - 3*m_perimeter_width; + float length_to_extrude = volume_to_length(0.25f * std::accumulate(ramming_speed.begin(), ramming_speed.end(), 0.f), + m_line_width * ramming_line_width_multiplicator, + layer_height_par); + float depth = (int(length_to_extrude / width) + 1) * (m_line_width * ramming_line_width_multiplicator * ramming_step_multiplicator); + length_to_extrude = width*((length_to_extrude / width)-int(length_to_extrude / width)) - width; + length_to_extrude += volume_to_length(wipe_volumes[old_tool][new_tool], m_line_width, layer_height_par); + length_to_extrude = std::max(length_to_extrude,0.f); + depth += (int(length_to_extrude / width) + 1) * m_line_width; + depth *= m_extra_spacing; if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan along with the first toolchange m_plan.push_back(WipeTowerInfo(z_par, layer_height_par)); @@ -1259,33 +1196,97 @@ void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsi m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool, depth)); } - - - // Calculate m_wipe_tower (maximum depth for all the layers) and propagate depths downwards - // Could be only called when a layer is changed, but do not forget about the last one - float this_layer_depth = m_plan.back().toolchanges_depth(); + // Calculate m_wipe_tower_depth (maximum depth for all the layers) and propagate depths downwards + /*float this_layer_depth = m_plan.back().toolchanges_depth(); m_plan.back().depth = this_layer_depth; - if (this_layer_depth > m_wipe_tower_depth) - m_wipe_tower_depth = this_layer_depth; + if (this_layer_depth > m_wipe_tower_depth - m_perimeter_width) + m_wipe_tower_depth = this_layer_depth + m_perimeter_width; for (int i = m_plan.size() - 2; i >= 0 && m_plan[i].depth < this_layer_depth; i-- ) { if ( this_layer_depth - m_plan[i].depth < min_layer_difference && !m_plan[i].tool_changes.empty()) - m_plan[i].tool_changes.back().required_depth += this_layer_depth - m_plan[i].depth; + m_plan[i].depth += this_layer_depth - m_plan[i].depth; m_plan[i].depth = this_layer_depth; + }*/ +} + + + +void WipeTowerPrusaMM::plan_tower() +{ + // Calculate m_wipe_tower_depth (maximum depth for all the layers) and propagate depths downwards + m_wipe_tower_depth = 0.f; + for (auto& layer : m_plan) + layer.depth = 0.f; + + for (int layer_index = m_plan.size() - 1; layer_index >= 0; --layer_index) + { + float this_layer_depth = std::max(m_plan[layer_index].depth, m_plan[layer_index].toolchanges_depth()); + m_plan[layer_index].depth = this_layer_depth; + + if (this_layer_depth > m_wipe_tower_depth - m_perimeter_width) + m_wipe_tower_depth = this_layer_depth + m_perimeter_width; + + for (int i = layer_index - 1; i >= 0 /*&& m_plan[i].depth < this_layer_depth*/; i--) + { + if (m_plan[i].depth - this_layer_depth < min_layer_difference ) + m_plan[i].depth = this_layer_depth; + } } } -// Processes vector m_plan and calls respective function to generate G-code for the wipe tower -// Resulting ToolChangeResults are appended into container passed by "result" reference +void WipeTowerPrusaMM::make_wipe_tower_square() +{ + const float width = m_wipe_tower_width - 3 * m_perimeter_width; + const float depth = m_wipe_tower_depth - m_perimeter_width; + // area that we actually print into is width*depth + float side = sqrt(depth * width); + + m_wipe_tower_width = side + 3 * m_perimeter_width; + m_wipe_tower_depth = side + 2 * m_perimeter_width; + // For all layers, find how depth changed and update all toolchange depths + for (auto &lay : m_plan) + { + side = sqrt(lay.depth * width); + float width_ratio = width / side; + + //lay.extra_spacing = width_ratio; + for (auto &tch : lay.tool_changes) + tch.required_depth *= width_ratio; + } + + plan_tower(); // propagates depth downwards again (width has changed) + for (auto& lay : m_plan) // depths set, now the spacing + lay.extra_spacing = lay.depth / lay.toolchanges_depth(); + +} + + +// Processes vector m_plan and calls respective functions to generate G-code for the wipe tower +// Resulting ToolChangeResults are appended into vector "result" void WipeTowerPrusaMM::generate(std::vector> &result) { + m_extra_spacing = 1.f; + + plan_tower(); + if (peters_wipe_tower) + make_wipe_tower_square(); + std::vector layer_result; - for (auto layer : m_plan) { set_layer(layer.z,layer.height,0,layer.z == m_plan.front().z,layer.z == m_plan.back().z); + + if (peters_wipe_tower) + m_wipe_tower_rotation_angle += 90.f; + else + m_wipe_tower_rotation_angle += 180.f; + if (!peters_wipe_tower && m_layer_info->depth < m_wipe_tower_depth - m_perimeter_width) + m_y_shift = (m_wipe_tower_depth-m_layer_info->depth-m_perimeter_width)/2.f; + + + for (const auto &toolchange : layer.tool_changes) layer_result.emplace_back(tool_change(toolchange.new_tool, false, WipeTower::PURPOSE_EXTRUDE)); @@ -1307,8 +1308,6 @@ void WipeTowerPrusaMM::generate(std::vector> &result); + void plan_tower(); + + void make_wipe_tower_square(); + // Switch to a next layer. virtual void set_layer( // Print height of this layer. @@ -115,18 +118,10 @@ public: // Start counting the color changes from zero. Special case: -1 - extrude a brim first. ///m_idx_tool_change_in_layer = is_first_layer ? (unsigned int)(-1) : 0; m_print_brim = is_first_layer; - m_current_wipe_start_y = 0.f; + m_depth_traversed = 0.f; // to make room for perimeter line m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL; + ++ m_num_layer_changes; - - - ///m_max_color_changes = max_tool_changes; - ///m_is_last_layer = is_last_layer; - // Extrusion rate for an extrusion aka perimeter width 0.35mm. - // Clamp the extrusion height to a 0.2mm layer height, independent of the nozzle diameter. -// m_extrusion_flow = std::min(0.2f, layer_height) * 0.145f; - // Use a strictly - //m_extrusion_flow = layer_height * 0.145f; // Calculates extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height m_extrusion_flow = extrusion_flow(layer_height); @@ -135,6 +130,7 @@ public: m_layer_info = nullptr; for (auto &a : m_plan) if ( a.z > print_z - WT_EPSILON && a.z < print_z + WT_EPSILON ) { + m_extra_spacing = a.extra_spacing; m_layer_info = &a; break; } @@ -171,49 +167,36 @@ public: // the wipe tower has been completely covered by the tool change extrusions, // or the rest of the tower has been filled by a sparse infill with the finish_layer() method. virtual bool layer_finished() const { - return ( (m_is_first_layer ? m_wipe_tower_depth : m_layer_info->depth) - WT_EPSILON < m_current_wipe_start_y); + return ( (m_is_first_layer ? m_wipe_tower_depth - m_perimeter_width : m_layer_info->depth) - WT_EPSILON < m_depth_traversed); } private: WipeTowerPrusaMM(); - // A fill-in direction (positive Y, negative Y) alternates with each layer. - enum wipe_shape + enum wipe_shape // A fill-in direction (positive Y, negative Y) alternates with each layer. { - SHAPE_NORMAL = 1, + SHAPE_NORMAL = 1, SHAPE_REVERSED = -1 }; - // Left front corner of the wipe tower in mm. - xy m_wipe_tower_pos; - // Width of the wipe tower. - float m_wipe_tower_width; - // Depth of the wipe tower (wipe_area * max_color_changes at the base) - float m_wipe_tower_depth = 0.f; - // Per color Y span. - float m_wipe_area; - // Wipe tower rotation angle in degrees (with respect to x axis - float m_wipe_tower_rotation_angle; - // Current Z position. - float m_z_pos = 0.f; - // Current layer height. - float m_layer_height = 0.f; - // Maximum number of color changes per layer. - size_t m_max_color_changes = 0; - // Is this the 1st layer of the print? If so, print the brim around the waste tower. - bool m_is_first_layer = false; - // Is this the last layer of this waste tower? - bool m_is_last_layer = false; + xy m_wipe_tower_pos; // Left front corner of the wipe tower in mm. + float m_wipe_tower_width; // Width of the wipe tower. + float m_wipe_tower_depth = 0.f; // Depth of the wipe tower + float m_wipe_tower_rotation_angle; // Wipe tower rotation angle in degrees (with respect to x axis + float m_y_shift = 0.f; // y shift passed to writer + float m_z_pos = 0.f; // Current Z position. + float m_layer_height = 0.f; // Current layer height. + size_t m_max_color_changes = 0; // Maximum number of color changes per layer. + bool m_is_first_layer = false;// Is this the 1st layer of the print? If so, print the brim around the waste tower. + bool m_is_last_layer = false;// Is this the last layer of this waste tower? // G-code generator parameters. float m_zhop = 0.5f; float m_retract = 4.f; - // Width of an extrusion line, also a perimeter spacing for 100% infill. - float m_line_width = Nozzle_Diameter * Width_To_Nozzle_Ratio; - // Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. - float m_extrusion_flow = 0.029f; + float m_line_width = Nozzle_Diameter * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. + float m_extrusion_flow = 0.038; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. // Extruder specific parameters. material_type m_material[4]; @@ -221,23 +204,20 @@ private: int m_first_layer_temperature[4]; // State of the wiper tower generator. - // Layer change counter for the output statistics. - unsigned int m_num_layer_changes = 0; - // Tool change change counter for the output statistics. - unsigned int m_num_tool_changes = 0; - // Layer change counter in this layer. Counting up to m_max_color_changes. - ///unsigned int m_idx_tool_change_in_layer = 0; + unsigned int m_num_layer_changes = 0; // Layer change counter for the output statistics. + unsigned int m_num_tool_changes = 0; // Tool change change counter for the output statistics. + ///unsigned int m_idx_tool_change_in_layer = 0; // Layer change counter in this layer. Counting up to m_max_color_changes. bool m_print_brim = true; // A fill-in direction (positive Y, negative Y) alternates with each layer. wipe_shape m_current_shape = SHAPE_NORMAL; unsigned int m_current_tool = 0; - // Current y position at the wipe tower. - float m_current_wipe_start_y = 0.f; + + float m_depth_traversed = 0.f; // Current y position at the wipe tower. // How much to wipe the 1st extruder over the wipe tower at the 1st layer // after the wipe tower brim has been extruded? float m_initial_extra_wipe = 0.f; - float m_last_infill_tan = 1000.f; // impossibly high value bool m_left_to_right = true; + float m_extra_spacing = 1.f; float extrusion_flow(float layer_height = -1.f) const { @@ -246,7 +226,11 @@ private: return layer_height * ( Width_To_Nozzle_Ratio * Nozzle_Diameter - layer_height * (1-M_PI/4.f)) / (Filament_Area); } - + float volume_to_length(float volume, float line_width, float layer_height) const { + return volume / (layer_height * (line_width - layer_height * (1. - M_PI / 4.))); + } + + struct box_coordinates { box_coordinates(float left, float bottom, float width, float height) : @@ -274,8 +258,8 @@ private: } xy ld; // left down xy lu; // left upper - xy ru; // right upper xy rd; // right lower + xy ru; // right upper }; @@ -290,12 +274,13 @@ private: float z; // z position of the layer float height; // layer height float depth; // depth of the layer based on all layers above + float extra_spacing; float toolchanges_depth() const { float sum = 0.f; for (const auto &a : tool_changes) sum += a.required_depth; return sum; } std::vector tool_changes; WipeTowerInfo(float z_par, float layer_height_par) - : z{z_par}, height{layer_height_par} { } + : z{z_par}, height{layer_height_par}, depth{0}, extra_spacing{1.f} {} }; // Stores information about all layers and toolchanges for the future wipe tower (filled by plan_toolchange(...)) @@ -327,7 +312,7 @@ private: void toolchange_Wipe( PrusaMultiMaterial::Writer &writer, const box_coordinates &cleaning_box, - bool skip_initial_y_move); + float wipe_volume); }; }; // namespace Slic3r From 5a02bde1705bb86674e651288af3616e3f194566 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 22 Feb 2018 09:28:31 +0100 Subject: [PATCH 13/81] Fix of merge conflict and uninitialized variables in writer class --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 4 ++-- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 2 +- xs/src/slic3r/GUI/3DScene.cpp | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index adb19eba9..c5b0d6044 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -366,8 +366,8 @@ private: float m_angle_deg = 0.f; float m_y_shift = 0.f; WipeTower::xy m_wipe_tower_pos; - float m_wipe_tower_width; - float m_wipe_tower_depth; + float m_wipe_tower_width = 0.f; + float m_wipe_tower_depth = 0.f; float m_last_fan_speed = 0.f; std::string diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 9ed7ae128..ea704694a 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -183,7 +183,7 @@ private: xy m_wipe_tower_pos; // Left front corner of the wipe tower in mm. float m_wipe_tower_width; // Width of the wipe tower. float m_wipe_tower_depth = 0.f; // Depth of the wipe tower - float m_wipe_tower_rotation_angle; // Wipe tower rotation angle in degrees (with respect to x axis + float m_wipe_tower_rotation_angle = 0.f; // Wipe tower rotation angle in degrees (with respect to x axis float m_y_shift = 0.f; // y shift passed to writer float m_z_pos = 0.f; // Current Z position. float m_layer_height = 0.f; // Current layer height. diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index cfc0947fe..74ec515c1 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -321,11 +321,11 @@ int GLVolumeCollection::load_wipe_tower_preview( Point origin_of_rotation(0.f,0.f); mesh.rotate(rotation_angle,&origin_of_rotation); - v.indexed_vertex_array.load_mesh_flat_shading(mesh); - v.origin = Pointf3(pos_x, pos_y, 0.); + v.indexed_vertex_array.load_mesh_flat_shading(mesh); + v.origin = Pointf3(pos_x, pos_y, 0.); // finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry(). v.bounding_box = v.indexed_vertex_array.bounding_box(); - v.indexed_vertex_array.finalize_geometry(use_VBOs); + v.indexed_vertex_array.finalize_geometry(use_VBOs); v.composite_id = obj_idx * 1000000; v.select_group_id = obj_idx * 1000000; v.drag_group_id = obj_idx * 1000; @@ -2291,7 +2291,7 @@ void _3DScene::_load_shells(const Print& print, GLVolumeCollection& volumes, boo const PrintConfig& config = print.config; unsigned int extruders_count = config.nozzle_diameter.size(); if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects) - volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, config.wipe_tower_per_color_wipe * (extruders_count - 1), max_z, use_VBOs); + volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, config.wipe_tower_per_color_wipe * (extruders_count - 1), max_z, config.wipe_tower_rotation_angle, use_VBOs); } } From 5f5a59328b243e25439a7241ab8403e8570352f6 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 22 Feb 2018 11:03:29 +0100 Subject: [PATCH 14/81] Minor refactoring, actualized comments, etc. --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 35 +++++++++++++-------- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 33 +++++++++---------- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index c5b0d6044..2a78ed6f1 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -1193,26 +1193,32 @@ void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsi { assert(m_plan.back().z <= z_par + WT_EPSILON ); // refuses to add a layer below the last one + if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan first + m_plan.push_back(WipeTowerInfo(z_par, layer_height_par)); + + if (brim) { // this toolchange prints brim - we must add it to m_plan, but not to count its depth + m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool)); + return; + } + + if (old_tool==new_tool) // new layer without toolchanges - we are done + return; + + // this is an actual toolchange - let's calculate depth to reserve on the wipe tower + float depth = 0.f; float width = m_wipe_tower_width - 3*m_perimeter_width; float length_to_extrude = volume_to_length(0.25f * std::accumulate(ramming_speed.begin(), ramming_speed.end(), 0.f), - m_line_width * ramming_line_width_multiplicator, - layer_height_par); - float depth = (int(length_to_extrude / width) + 1) * (m_line_width * ramming_line_width_multiplicator * ramming_step_multiplicator); + m_line_width * ramming_line_width_multiplicator, + layer_height_par); + depth = (int(length_to_extrude / width) + 1) * (m_line_width * ramming_line_width_multiplicator * ramming_step_multiplicator); length_to_extrude = width*((length_to_extrude / width)-int(length_to_extrude / width)) - width; length_to_extrude += volume_to_length(wipe_volumes[old_tool][new_tool], m_line_width, layer_height_par); length_to_extrude = std::max(length_to_extrude,0.f); depth += (int(length_to_extrude / width) + 1) * m_line_width; - depth *= m_extra_spacing; - - if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan along with the first toolchange - m_plan.push_back(WipeTowerInfo(z_par, layer_height_par)); - - if ( brim || old_tool != new_tool ) { - if (brim) // this toolchange prints brim, we need it in m_plan, but not to count its depth - depth = 0.f; - m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool, depth)); - } + depth *= m_extra_spacing; + m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool, depth)); + // Calculate m_wipe_tower_depth (maximum depth for all the layers) and propagate depths downwards /*float this_layer_depth = m_plan.back().toolchanges_depth(); m_plan.back().depth = this_layer_depth; @@ -1283,6 +1289,9 @@ void WipeTowerPrusaMM::make_wipe_tower_square() // Resulting ToolChangeResults are appended into vector "result" void WipeTowerPrusaMM::generate(std::vector> &result) { + if (m_plan.empty()) return; + else m_layer_info = m_plan.begin(); + m_extra_spacing = 1.f; plan_tower(); diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index ea704694a..f5fc2985e 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -93,10 +93,13 @@ public: // to be used before building begins. The entries must be added ordered in z. void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, bool brim); + // Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result" void generate(std::vector> &result); + // Calculates depth for all layers and propagates them downwards void plan_tower(); + // Goes through m_plan and recalculates depths and width of the WT to make it exactly square - experimental void make_wipe_tower_square(); // Switch to a next layer. @@ -115,7 +118,7 @@ public: m_z_pos = print_z; m_layer_height = layer_height; m_is_first_layer = is_first_layer; - // Start counting the color changes from zero. Special case: -1 - extrude a brim first. + // Start counting the color changes from zero. Special case -1: extrude a brim first. ///m_idx_tool_change_in_layer = is_first_layer ? (unsigned int)(-1) : 0; m_print_brim = is_first_layer; m_depth_traversed = 0.f; // to make room for perimeter line @@ -126,14 +129,8 @@ public: // Calculates extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height m_extrusion_flow = extrusion_flow(layer_height); - // FIXME - ideally get rid of set_layer altogether and iterate through m_plan in generate(...) - m_layer_info = nullptr; - for (auto &a : m_plan) - if ( a.z > print_z - WT_EPSILON && a.z < print_z + WT_EPSILON ) { - m_extra_spacing = a.extra_spacing; - m_layer_info = &a; - break; - } + while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1!=m_plan.end()) + ++m_layer_info; } // Return the wipe tower position. @@ -159,13 +156,11 @@ public: // On the first layer, extrude a brim around the future wipe tower first. virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer, Purpose purpose); - // Close the current wipe tower layer with a perimeter and possibly fill the unfilled space with a zig-zag. + // Fill the unfilled space with a zig-zag. // Call this method only if layer_finished() is false. virtual ToolChangeResult finish_layer(Purpose purpose); - // Is the current layer finished? A layer is finished if either the wipe tower is finished, or - // the wipe tower has been completely covered by the tool change extrusions, - // or the rest of the tower has been filled by a sparse infill with the finish_layer() method. + // Is the current layer finished? virtual bool layer_finished() const { return ( (m_is_first_layer ? m_wipe_tower_depth - m_perimeter_width : m_layer_info->depth) - WT_EPSILON < m_depth_traversed); } @@ -219,13 +214,15 @@ private: bool m_left_to_right = true; float m_extra_spacing = 1.f; - float extrusion_flow(float layer_height = -1.f) const + // Calculates extrusion flow needed to produce required line width for given layer height + float extrusion_flow(float layer_height = -1.f) const // negative layer_height - return current m_extrusion_flow { if ( layer_height < 0 ) return m_extrusion_flow; return layer_height * ( Width_To_Nozzle_Ratio * Nozzle_Diameter - layer_height * (1-M_PI/4.f)) / (Filament_Area); } + // Calculates length of extrusion line to extrude given volume float volume_to_length(float volume, float line_width, float layer_height) const { return volume / (layer_height * (line_width - layer_height * (1. - M_PI / 4.))); } @@ -269,7 +266,7 @@ private: unsigned int old_tool; unsigned int new_tool; float required_depth; - ToolChange(unsigned int old,unsigned int newtool,float depth) : old_tool{old}, new_tool{newtool}, required_depth{depth} {} + ToolChange(unsigned int old,unsigned int newtool,float depth=0.f) : old_tool{old}, new_tool{newtool}, required_depth{depth} {} }; float z; // z position of the layer float height; // layer height @@ -283,10 +280,8 @@ private: : z{z_par}, height{layer_height_par}, depth{0}, extra_spacing{1.f} {} }; - // Stores information about all layers and toolchanges for the future wipe tower (filled by plan_toolchange(...)) - std::vector m_plan; - - WipeTowerInfo* m_layer_info; + std::vector m_plan; // Stores information about all layers and toolchanges for the future wipe tower (filled by plan_toolchange(...)) + std::vector::iterator m_layer_info; // Returns gcode for wipe tower brim From 3099c32d0805a6fff26929e9be3dcb27e50f9bfa Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 27 Feb 2018 08:56:11 +0100 Subject: [PATCH 15/81] GUI - reenabling rotation angle settings for the wipe tower (was disabled by the merge with master) --- xs/src/libslic3r/PrintConfig.cpp | 6 +++--- xs/src/slic3r/GUI/Tab.cpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index bc5d115c3..995dcee99 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1732,9 +1732,9 @@ PrintConfigDef::PrintConfigDef() def->default_value = new ConfigOptionFloat(15.); def = this->add("wipe_tower_rotation_angle", coFloat); - def->label = "Wipe tower rotation angle"; - def->tooltip = "Wipe tower rotation angle with respect to x-axis "; - def->sidetext = "degrees"; + def->label = _L("Wipe tower rotation angle"); + def->tooltip = _L("Wipe tower rotation angle with respect to x-axis "); + def->sidetext = _L("degrees"); def->cli = "wipe-tower-rotation-angle=f"; def->default_value = new ConfigOptionFloat(0.); diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index b27e7b838..ebfa69eb5 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -446,6 +446,7 @@ void TabPrint::build() optgroup->append_single_option_line("wipe_tower_y"); optgroup->append_single_option_line("wipe_tower_width"); optgroup->append_single_option_line("wipe_tower_per_color_wipe"); + optgroup->append_single_option_line("wipe_tower_rotation_angle"); optgroup = page->new_optgroup(_L("Advanced")); optgroup->append_single_option_line("interface_shells"); @@ -762,7 +763,7 @@ void TabPrint::update() bool have_wipe_tower = m_config->opt_bool("wipe_tower"); vec_enable.resize(0); - vec_enable = { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe"}; + vec_enable = { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle"}; for (auto el : vec_enable) get_field(el)->toggle(have_wipe_tower); From a62ad3323f389e3ce93915b7fea92bd1eccf321e Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 28 Feb 2018 16:04:56 +0100 Subject: [PATCH 16/81] First naive implementation of wipe tower settings dialog --- xs/CMakeLists.txt | 5 + xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 65 ++--- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 152 ++++++++++- xs/src/libslic3r/Print.cpp | 4 +- xs/src/libslic3r/PrintConfig.cpp | 9 +- xs/src/libslic3r/PrintConfig.hpp | 2 + xs/src/slic3r/GUI/BedShapeDialog.cpp | 2 +- xs/src/slic3r/GUI/Preset.cpp | 6 +- xs/src/slic3r/GUI/RammingChart.cpp | 273 ++++++++++++++++++++ xs/src/slic3r/GUI/RammingChart.hpp | 129 +++++++++ xs/src/slic3r/GUI/Tab.cpp | 24 ++ xs/src/slic3r/GUI/Tab.hpp | 1 + xs/src/slic3r/GUI/WipeTowerDialog.cpp | 264 +++++++++++++++++++ xs/src/slic3r/GUI/WipeTowerDialog.hpp | 115 +++++++++ 14 files changed, 996 insertions(+), 55 deletions(-) create mode 100644 xs/src/slic3r/GUI/RammingChart.cpp create mode 100644 xs/src/slic3r/GUI/RammingChart.hpp create mode 100644 xs/src/slic3r/GUI/WipeTowerDialog.cpp create mode 100644 xs/src/slic3r/GUI/WipeTowerDialog.hpp diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 41bf9de26..4e217d148 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -195,6 +195,11 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/2DBed.hpp ${LIBDIR}/slic3r/GUI/wxExtensions.cpp ${LIBDIR}/slic3r/GUI/wxExtensions.hpp + ${LIBDIR}/slic3r/GUI/WipeTowerDialog.cpp + ${LIBDIR}/slic3r/GUI/WipeTowerDialog.hpp + ${LIBDIR}/slic3r/GUI/RammingChart.cpp + ${LIBDIR}/slic3r/GUI/RammingChart.hpp + ) add_library(admesh STATIC diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 2a78ed6f1..d7492fdbb 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -33,33 +33,6 @@ TODO LIST constexpr bool peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet constexpr float min_layer_difference = 2*m_perimeter_width; -constexpr float max_bridge_distance = 10.f; // in mm -constexpr bool improve_first_layer_adhesion = true; -// experimental: ramming speed (mm^3/s) sampled in 0.25s intervals (one filament so far) -const std::vector ramming_speed = {7.6, 7.6, 7.6, 7.6, 9.0, 9.0, 9.0, 10.7, 10.7, 10.7}; -constexpr float ramming_step_multiplicator = 1.2f; // extra spacing may be needed for some materials -constexpr float ramming_line_width_multiplicator = 1.5f; - -// experimental: time requested for cooling in seconds (common for all materials so far) -constexpr float cooling_time = 14; // PVA: 20; SCAFF: 17; PLA+others: 14 - - -// volumes in mm^3 required for wipe: {{from 0 to ...},{from 1 to ...},{from 2 to ...},{from 3 to ...}}, usage [from][to] -const std::vector> wipe_volumes = {{ 0,120, 10, 50}, - { 20, 0, 30, 40}, - { 90, 20, 0, 85}, - {100,140, 30, 0}}; - -/*const std::vector> wipe_volumes = {{0, 67, 67, 67}, - {67, 0, 67, 67}, - {67, 67, 0, 67}, - {67, 67, 67, 0}}; -*/ -/*const std::vector> wipe_volumes = {{0, 10, 10, 10}, - {10, 0, 10, 10}, - {10, 10, 0, 10}, - {10, 10, 10, 0}}; -*/ namespace Slic3r { @@ -614,7 +587,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo { for (const auto &b : m_layer_info->tool_changes) if ( b.new_tool == tool ) { - wipe_volume = wipe_volumes[b.old_tool][b.new_tool]; + wipe_volume = m_par.wipe_volumes[b.old_tool][b.new_tool]; if (tool == m_layer_info->tool_changes.back().new_tool) last_change_in_layer = true; wipe_area = b.required_depth * m_layer_info->extra_spacing; @@ -804,20 +777,20 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.append("; CP TOOLCHANGE UNLOAD\n"); - const float line_width = m_line_width * ramming_line_width_multiplicator; // desired ramming line thickness - const float y_step = line_width * ramming_step_multiplicator * m_extra_spacing; // spacing between lines in mm + const float line_width = m_line_width * m_par.ramming_line_width_multiplicator[m_current_tool]; // desired ramming line thickness + const float y_step = line_width * m_par.ramming_step_multiplicator[m_current_tool] * m_extra_spacing; // spacing between lines in mm unsigned i = 0; // iterates through ramming_speed m_left_to_right = true; // current direction of ramming float remaining = xr - xl ; // keeps track of distance to the next turnaround float e_done = 0; // measures E move done from each segment - + writer.travel(xl, cleaning_box.ld.y + m_depth_traversed + y_step/2.f ); // move to starting position - while (i < ramming_speed.size()) + while (i < m_par.ramming_speed[m_current_tool].size()) { - const float x = volume_to_length(ramming_speed[i] * 0.25f, line_width, m_layer_height); - const float e = ramming_speed[i] * 0.25f / Filament_Area; // transform volume per sec to E move; + const float x = volume_to_length(m_par.ramming_speed[m_current_tool][i] * 0.25f, line_width, m_layer_height); + const float e = m_par.ramming_speed[m_current_tool][i] * 0.25f / Filament_Area; // transform volume per sec to E move; const float dist = std::min(x - e_done, remaining); // distance to travel for either the next 0.25s, or to the next turnaround const float actual_time = dist/x * 0.25; writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), std::hypot(dist, e * (dist / x)) / (actual_time / 60.)); @@ -880,21 +853,21 @@ void WipeTowerPrusaMM::toolchange_Unload( const float start_x = writer.x(); const float turning_point = ( xr-start_x > start_x-xl ? xr : xl ); const float max_x_dist = 2*std::abs(start_x-turning_point); - const int N = 4 + (cooling_time-14)/3; - float time = cooling_time / N; - + const unsigned int N = 4 + std::max(0,(m_par.cooling_time[m_current_tool]-14)/3); + float time = m_par.cooling_time[m_current_tool] / N; + i = 0; - while (i #include #include +#include #include #include "WipeTower.hpp" @@ -22,6 +23,11 @@ constexpr float m_perimeter_width = Nozzle_Diameter * Width_To_Nozzle_Ratio * Ko constexpr float WT_EPSILON = 1e-3f; + + + + + namespace Slic3r { @@ -29,6 +35,141 @@ namespace PrusaMultiMaterial { class Writer; }; + + +// Operator overload to output std::pairs +template +std::ostream& operator<<(std::ostream& stream,const std::pair& pair) { + return stream << pair.first << " " << pair.second; +} + +// Operator overload to output elements of a vector to std::ofstream easily: +template +std::ostream& operator<<(std::ostream& stream,const std::vector& vect) { + for (const auto& element : vect) + stream << element << " "; + return stream; +} + +// Operator overload to input elements of a vector from std::ifstream easily (reads until a fail) +template +std::istream& operator>>(std::istream& stream, std::vector& vect) { + vect.clear(); + T value{}; + bool we_read_something = false; + while (stream >> value) { + vect.push_back(value); + we_read_something = true; + } + if (!stream.eof() && we_read_something) { // if this is not eof, we might be at separator - let's get rid of it + stream.clear(); // if we failed on very first line or reached eof, return stream in !good() state + stream.get(); // get() whatever we are stuck at + } + return stream; +} + + +// This struct is used to store parameters and to pass it to wipe tower generator +struct WipeTowerParameters { + WipeTowerParameters() { } // create new empty object + WipeTowerParameters(const std::string& init_data) { // create object and initialize from std::string + std::istringstream in(init_data); // validation of input is left to the caller + in >> bridging >> adhesion >> sampling; + for (std::vector vect{} ; in >> vect ;) { // until we get to fail state ("**")... + if (vect.size()>=3) { + cooling_time.push_back(vect[0]); + ramming_line_width_multiplicator.push_back(vect[1]); + ramming_step_multiplicator.push_back(vect[2]); + vect.erase(vect.begin(),vect.begin()+3); + } + else vect.clear(); // something's not right, we will restore defaults anyway + ramming_speed.push_back(vect); + + if (in.good()) { + in >> vect; + std::vector> pairs; + for (unsigned int i=0;i vect{} ; in >> vect ;) { // let's keep reading + wipe_volumes.push_back(vect); + } + in.clear(); + in.get(); + + std::vector vect{}; + in >> vect; + for (unsigned int i=0;i{7.6, 7.6, 7.6, 7.6, 9.0, 9.0, 9.0, 10.7, 10.7, 10.7}); + ramming_buttons.push_back(std::vector>{{0.05, 6.6},{0.45, 6.8},{0.95, 7.8},{1.45, 8.3},{1.95, 9.7},{2.45,10},{2.95, 7.6},{3.45, 7.6},{3.95, 7.6},{4.45, 7.6},{4.95, 7.6}}); + } + wipe_volumes = {{ 0, 60, 60, 60}, + { 60, 0, 60, 60}, + { 60, 60, 0, 60}, + { 60, 60, 60, 0}}; + filament_wipe_volumes = {{30,30},{30,30},{30,30},{30,30}}; + } + + int bridging = 0.f; + bool adhesion = false; + float sampling = 0.25f; // this does not quite work yet, keep it fixed to 0.25f + std::vector cooling_time; + std::vector ramming_line_width_multiplicator; + std::vector ramming_step_multiplicator; + std::vector> ramming_speed; + std::vector>> ramming_buttons; + std::vector> wipe_volumes; + std::vector> filament_wipe_volumes; +}; + + class WipeTowerPrusaMM : public WipeTower { public: @@ -53,15 +194,16 @@ public: // y -- y coordinates of wipe tower in mm ( left bottom corner ) // 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 wipe_area, float rotation_angle, unsigned int initial_tool) : + WipeTowerPrusaMM(float x, float y, float width, float wipe_area, float rotation_angle, unsigned int initial_tool,std::string& parameters) : m_wipe_tower_pos(x, y), m_wipe_tower_width(width), m_wipe_tower_rotation_angle(rotation_angle), m_y_shift(0.f), m_z_pos(0.f), m_is_first_layer(false), - m_is_last_layer(false), - m_current_tool(initial_tool) + m_is_last_layer(false), + m_current_tool(initial_tool), + m_par(parameters) { for (size_t i = 0; i < 4; ++ i) { // Extruder specific parameters. @@ -206,6 +348,7 @@ private: // A fill-in direction (positive Y, negative Y) alternates with each layer. wipe_shape m_current_shape = SHAPE_NORMAL; unsigned int m_current_tool = 0; + WipeTowerParameters m_par; float m_depth_traversed = 0.f; // Current y position at the wipe tower. // How much to wipe the 1st extruder over the wipe tower at the 1st layer @@ -310,6 +453,9 @@ private: float wipe_volume); }; + + + }; // namespace Slic3r #endif /* WipeTowerPrusaMM_hpp_ */ diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 1c63dbf60..fe98612cf 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -187,6 +187,7 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.wipe_tower_x.value), float(this->config.wipe_tower_y.value), float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value), - float(this->config.wipe_tower_rotation_angle.value), m_tool_ordering.first_extruder()); + float(this->config.wipe_tower_rotation_angle.value), m_tool_ordering.first_extruder(), + this->config.wipe_tower_advanced.value); //wipe_tower.set_retract(); //wipe_tower.set_zhop(); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 995dcee99..7a48b3a32 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1701,6 +1701,13 @@ PrintConfigDef::PrintConfigDef() def->cli = "wipe-tower!"; def->default_value = new ConfigOptionBool(false); + def = this->add("wipe_tower_advanced", coString); + def->label = _L("Advanced string"); + def->tooltip = _L("Advanced tooltip "); + def->sidetext = _L("advanced sidetext"); + def->cli = "wipe-tower-advanced=s"; + def->default_value = new ConfigOptionString(""); + def = this->add("wipe_tower_x", coFloat); def->label = _L("Position X"); def->tooltip = _L("X coordinate of the left front corner of a wipe tower"); @@ -1723,7 +1730,7 @@ PrintConfigDef::PrintConfigDef() def->default_value = new ConfigOptionFloat(60.); def = this->add("wipe_tower_per_color_wipe", coFloat); - def->label = _L("Per color change depth"); + def->label = "(Unused and will be likely removed)";//_L("Per color change depth"); def->tooltip = _L("Depth of a wipe color per color change. For N colors, there will be " "maximum (N-1) tool switches performed, therefore the total depth " "of the wipe tower will be (N-1) times this value."); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 7c2d40458..d55aafed6 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -605,6 +605,7 @@ public: ConfigOptionInt threads; ConfigOptionBools wipe; ConfigOptionBool wipe_tower; + ConfigOptionString wipe_tower_advanced; ConfigOptionFloat wipe_tower_x; ConfigOptionFloat wipe_tower_y; ConfigOptionFloat wipe_tower_width; @@ -670,6 +671,7 @@ protected: OPT_PTR(threads); OPT_PTR(wipe); OPT_PTR(wipe_tower); + OPT_PTR(wipe_tower_advanced); OPT_PTR(wipe_tower_x); OPT_PTR(wipe_tower_y); OPT_PTR(wipe_tower_width); diff --git a/xs/src/slic3r/GUI/BedShapeDialog.cpp b/xs/src/slic3r/GUI/BedShapeDialog.cpp index 5ee0c1f8b..8e7f57241 100644 --- a/xs/src/slic3r/GUI/BedShapeDialog.cpp +++ b/xs/src/slic3r/GUI/BedShapeDialog.cpp @@ -34,7 +34,7 @@ void BedShapeDialog::build_dialog(ConfigOptionPoints* default_pt) void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) { -// on_change(nullptr); +// on_change(nullptr); auto box = new wxStaticBox(this, wxID_ANY, _L("Shape")); auto sbsizer = new wxStaticBoxSizer(box, wxVERTICAL); diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 4d55f347a..be31c1bd1 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -198,9 +198,9 @@ const std::vector& Preset::print_options() "ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width", "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", - "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", - "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", - "compatible_printers", "compatible_printers_condition" + "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower_advanced", "wipe_tower", "wipe_tower_x", + "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "compatible_printers", + "compatible_printers_condition" }; return s_opts; diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/xs/src/slic3r/GUI/RammingChart.cpp new file mode 100644 index 000000000..3b5f4e41e --- /dev/null +++ b/xs/src/slic3r/GUI/RammingChart.cpp @@ -0,0 +1,273 @@ +#include +#include "RammingChart.hpp" + + +wxDEFINE_EVENT(EVT_WIPE_TOWER_CHART_CHANGED, wxCommandEvent); + + +void Chart::draw(wxDC& dc) { + dc.SetPen(*wxBLACK_PEN); + dc.SetBrush(*wxWHITE_BRUSH); + dc.DrawRectangle(m_rect); + + if (visible_area->m_width < 0.499) { + dc.DrawText("NO RAMMING AT ALL",wxPoint(m_rect.GetLeft()+m_rect.GetWidth()/2-50,m_rect.GetBottom()-m_rect.GetHeight()/2)); + return; + } + + + if (!m_line_to_draw->empty()) { + for (uint i=0;isize()-2;++i) { + int color = 510*((m_rect.GetBottom()-(*m_line_to_draw)[i])/double(m_rect.GetHeight())); + dc.SetPen( wxPen( wxColor(std::min(255,color),255-std::max(color-255,0),0), 1 ) ); + dc.DrawLine(m_rect.GetLeft()+1+i,(*m_line_to_draw)[i],m_rect.GetLeft()+1+i,m_rect.GetBottom()); + } + dc.SetPen( wxPen( wxColor(0,0,0), 1 ) ); + for (uint i=0;isize()-2;++i) { + if (splines) + dc.DrawLine(m_rect.GetLeft()+i,(*m_line_to_draw)[i],m_rect.GetLeft()+i+1,(*m_line_to_draw)[i+1]); + else { + dc.DrawLine(m_rect.GetLeft()+i,(*m_line_to_draw)[i],m_rect.GetLeft()+i+1,(*m_line_to_draw)[i]); + dc.DrawLine(m_rect.GetLeft()+i+1,(*m_line_to_draw)[i],m_rect.GetLeft()+i+1,(*m_line_to_draw)[i+1]); + } + } + } + + // draw draggable buttons + dc.SetBrush(*wxBLUE_BRUSH); + dc.SetPen( wxPen( wxColor(0,0,0), 1 ) ); + for (auto& button : m_buttons[m_current_extruder]) + //dc.DrawRectangle(math_to_screen(button.get_pos())-wxPoint(side/2.,side/2.), wxSize(side,side)); + dc.DrawCircle(math_to_screen(button.get_pos()),side/2.); + //dc.DrawRectangle(math_to_screen(button.get_pos()-wxPoint2DDouble(0.125,0))-wxPoint(0,5),wxSize(50,10)); + + // draw x-axis: + float last_mark = -10000; + for (float math_x=int(visible_area->m_x*10)/10 ; math_x <= (visible_area->m_x+visible_area->m_width) ; math_x+=0.1) { + int x = math_to_screen(wxPoint2DDouble(math_x,visible_area->m_y)).x; + int y = m_rect.GetBottom(); + if (x-last_mark < 50) continue; + dc.DrawLine(x,y+3,x,y-3); + dc.DrawText(wxString().Format(wxT("%.1f"), math_x),wxPoint(x-10,y+7)); + last_mark = x; + } + + // draw y-axis: + last_mark=10000; + for (int math_y=visible_area->m_y ; math_y <= (visible_area->m_y+visible_area->m_height) ; math_y+=1) { + int y = math_to_screen(wxPoint2DDouble(visible_area->m_x,math_y)).y; + int x = m_rect.GetLeft(); + if (last_mark-y < 50) continue; + dc.DrawLine(x-3,y,x+3,y); + dc.DrawText(wxString()<2) { + m_buttons[m_current_extruder].erase(m_buttons[m_current_extruder].begin()+button_index); + recalculate_line(); + } +} + + + +void Chart::mouse_clicked(wxMouseEvent& event) { + wxPoint point = event.GetPosition(); + int button_index = which_button_is_clicked(point); + if ( button_index != -1) { + m_dragged = &m_buttons[m_current_extruder][button_index]; + m_previous_mouse = point; + } +} + + + +void Chart::mouse_moved(wxMouseEvent& event) { + if (!event.Dragging() || !m_dragged) return; + wxPoint pos = event.GetPosition(); + wxRect rect = m_rect; + rect.Deflate(side/2.); + if (!(rect.Contains(pos))) { // the mouse left chart area + mouse_left_window(event); + return; + } + int delta_x = pos.x - m_previous_mouse.x; + int delta_y = pos.y - m_previous_mouse.y; + m_dragged->move(fixed_x?0:double(delta_x)/m_rect.GetWidth() * visible_area->m_width,-double(delta_y)/m_rect.GetHeight() * visible_area->m_height); + m_previous_mouse = pos; + recalculate_line(); +} + + + +void Chart::mouse_double_clicked(wxMouseEvent& event) { + if (!manual_points_manipulation) + return; + wxPoint point = event.GetPosition(); + if (!m_rect.Contains(point)) // the click is outside the chart + return; + m_buttons[m_current_extruder].push_back(screen_to_math(point)); + std::sort(m_buttons[m_current_extruder].begin(),m_buttons[m_current_extruder].end()); + recalculate_line(); + return; +} + + + + +void Chart::recalculate_line() { + std::vector points; + for (auto& but : m_buttons[m_current_extruder]) { + points.push_back(wxPoint(math_to_screen(but.get_pos()))); + if (points.size()>1 && points.back().x==points[points.size()-2].x) points.pop_back(); + if (points.size()>1 && points.back().x > m_rect.GetRight()) { + points.pop_back(); + break; + } + } + std::sort(points.begin(),points.end(),[](wxPoint& a,wxPoint& b) { return a.x < b.x; }); + + m_line_to_draw->clear(); + m_total_volume = 0.f; + + + // Cubic spline interpolation: see https://en.wikiversity.org/wiki/Cubic_Spline_Interpolation#Methods + const bool boundary_first_derivative = true; // true - first derivative is 0 at the leftmost and rightmost point + // false - second ---- || ------- + const int N = points.size()-1; // last point can be accessed as N, we have N+1 total points + std::vector diag(N+1); + std::vector mu(N+1); + std::vector lambda(N+1); + std::vector h(N+1); + std::vector rhs(N+1); + + // let's fill in inner equations + for (int i=1;i<=N;++i) h[i] = points[i].x-points[i-1].x; + std::fill(diag.begin(),diag.end(),2.f); + for (int i=1;i<=N-1;++i) { + mu[i] = h[i]/(h[i]+h[i+1]); + lambda[i] = 1.f - mu[i]; + rhs[i] = 6 * ( float(points[i+1].y-points[i].y )/(h[i+1]*(points[i+1].x-points[i-1].x)) - + float(points[i].y -points[i-1].y)/(h[i] *(points[i+1].x-points[i-1].x)) ); + } + + // now fill in the first and last equations, according to boundary conditions: + if (boundary_first_derivative) { + const float endpoints_derivative = 0; + lambda[0] = 1; + mu[N] = 1; + rhs[0] = (6.f/h[1]) * (float(points[0].y-points[1].y)/(points[0].x-points[1].x) - endpoints_derivative); + rhs[N] = (6.f/h[N]) * (endpoints_derivative - float(points[N-1].y-points[N].y)/(points[N-1].x-points[N].x)); + } + else { + lambda[0] = 0; + mu[N] = 0; + rhs[0] = 0; + rhs[N] = 0; + } + + // the trilinear system is ready to be solved: + for (int i=1;i<=N;++i) { + float multiple = mu[i]/diag[i-1]; // let's subtract proper multiple of above equation + diag[i]-= multiple * lambda[i-1]; + rhs[i] -= multiple * rhs[i-1]; + } + // now the back substitution (vector mu contains invalid values from now on): + rhs[N] = rhs[N]/diag[N]; + for (int i=N-1;i>=0;--i) + rhs[i] = (rhs[i]-lambda[i]*rhs[i+1])/diag[i]; + + + + + unsigned int i=1; + float y=0.f; + for (int x=m_rect.GetLeft(); x<=m_rect.GetRight() ; ++x) { + if (splines) { + if (i x) + y = points[0].y; + else + if (points[N].x < x) + y = points[N].y; + else + y = (rhs[i-1]*pow(points[i].x-x,3)+rhs[i]*pow(x-points[i-1].x,3)) / (6*h[i]) + + (points[i-1].y-rhs[i-1]*h[i]*h[i]/6.f) * (points[i].x-x)/h[i] + + (points[i].y -rhs[i] *h[i]*h[i]/6.f) * (x-points[i-1].x)/h[i]; + m_line_to_draw->push_back(y); + } + else { + float x_math = screen_to_math(wxPoint(x,0)).m_x; + if (i+2<=points.size() && m_buttons[m_current_extruder][i+1].get_pos().m_x-0.125 < x_math) + ++i; + m_line_to_draw->push_back(math_to_screen(wxPoint2DDouble(x_math,m_buttons[m_current_extruder][i].get_pos().m_y)).y); + } + + + m_line_to_draw->back() = std::max(m_line_to_draw->back(), m_rect.GetTop()-1); + m_line_to_draw->back() = std::min(m_line_to_draw->back(), m_rect.GetBottom()-1); + m_total_volume += (m_rect.GetBottom() - m_line_to_draw->back()) * (visible_area->m_width / m_rect.GetWidth()) * (visible_area->m_height / m_rect.GetHeight()); + } + + wxPostEvent(this->GetParent(), wxCommandEvent(EVT_WIPE_TOWER_CHART_CHANGED)); + Refresh(); +} + + + +std::vector> Chart::get_ramming_speeds(float sampling) const { + std::vector> speeds_out; + for (unsigned int extruder_id = 0;extruder_id this_extruder; + const int number_of_samples = std::round( visible_areas[extruder_id].m_width / sampling); + if (number_of_samples>0) { + const int dx = (m_lines_to_draw[extruder_id].size()-1) / number_of_samples; + for (int j=0;j>> Chart::get_buttons() const { + std::vector>> buttons_out; + for (const auto& ext : m_buttons) { + std::vector> this_extruder; + for (const auto& button : ext) + this_extruder.push_back(std::make_pair(button.get_pos().m_x,button.get_pos().m_y)); + buttons_out.push_back(std::move(this_extruder)); + } + return buttons_out; +} + + + + +BEGIN_EVENT_TABLE(Chart, wxWindow) +EVT_MOTION(Chart::mouse_moved) +EVT_LEFT_DOWN(Chart::mouse_clicked) +EVT_LEFT_UP(Chart::mouse_released) +EVT_LEFT_DCLICK(Chart::mouse_double_clicked) +EVT_RIGHT_DOWN(Chart::mouse_right_button_clicked) +EVT_LEAVE_WINDOW(Chart::mouse_left_window) +EVT_PAINT(Chart::paint_event) +END_EVENT_TABLE() diff --git a/xs/src/slic3r/GUI/RammingChart.hpp b/xs/src/slic3r/GUI/RammingChart.hpp new file mode 100644 index 000000000..5443e957a --- /dev/null +++ b/xs/src/slic3r/GUI/RammingChart.hpp @@ -0,0 +1,129 @@ +#ifndef RAMMING_CHART_H_ +#define RAMMING_CHART_H_ + +#include +#include +#ifndef WX_PRECOMP + #include +#endif + +wxDECLARE_EVENT(EVT_WIPE_TOWER_CHART_CHANGED, wxCommandEvent); + + +class Chart : public wxWindow { + +public: + Chart(wxWindow* parent, wxRect rect,const std::vector>>& initial_buttons,std::vector> ramming_speed, float sampling) : + wxWindow(parent,wxID_ANY,rect.GetTopLeft(),rect.GetSize()) + { + m_rect=wxRect(wxPoint(30,0),rect.GetSize()-wxSize(30,30)); + for (int i=0;i<4;++i) { + visible_areas.push_back(wxRect2DDouble(0.0, 0.0, sampling*ramming_speed[i].size(), 20.)); + m_buttons.push_back(std::vector()); + m_lines_to_draw.push_back(std::vector()); + if (initial_buttons.size()>0) + for (const auto& pair : initial_buttons[i]) + m_buttons.back().push_back(wxPoint2DDouble(pair.first,pair.second)); + set_extruder(i); // to calculate all interpolating splines + } + set_extruder(0); + } + void set_extruder(unsigned ext) { + if (ext>=4) return; + m_current_extruder = ext; + visible_area = &(visible_areas[ext]); + m_line_to_draw = &(m_lines_to_draw[ext]); + recalculate_line(); + } + void set_xy_range(float x,float y) { + x = int(x/0.5) * 0.5; + if (x>=0) visible_area->SetRight(x); + if (y>=0) visible_area->SetBottom(y); + recalculate_line(); + } + float get_volume() const { return m_total_volume; } + float get_time() const { return visible_area->m_width; } + std::vector> get_ramming_speeds(float sampling) const; //returns sampled ramming speed for all extruders + std::vector>> get_buttons() const; // returns buttons position for all extruders + + + void draw(wxDC& dc); + + void mouse_clicked(wxMouseEvent& event); + void mouse_right_button_clicked(wxMouseEvent& event); + void mouse_moved(wxMouseEvent& event); + void mouse_double_clicked(wxMouseEvent& event); + void mouse_left_window(wxMouseEvent&) { m_dragged = nullptr; } + void mouse_released(wxMouseEvent&) { m_dragged = nullptr; } + void paint_event(wxPaintEvent&) { wxPaintDC dc(this); draw(dc); } + DECLARE_EVENT_TABLE() + + + +private: + static const bool fixed_x = true; + static const bool splines = true; + static const bool manual_points_manipulation = false; + static const int side = 10; // side of draggable button + + class ButtonToDrag { + public: + bool operator<(ButtonToDrag& a) { return m_pos.m_x < a.m_pos.m_x; } + ButtonToDrag(wxPoint2DDouble pos) : m_pos{pos} {}; + wxPoint2DDouble get_pos() const { return m_pos; } + void move(double x,double y) { m_pos.m_x+=x; m_pos.m_y+=y; } + private: + wxPoint2DDouble m_pos; // position in math coordinates + }; + + + + wxPoint math_to_screen(const wxPoint2DDouble& math) const { + wxPoint screen; + screen.x = (math.m_x-visible_area->m_x) * (m_rect.GetWidth() / visible_area->m_width ); + screen.y = (math.m_y-visible_area->m_y) * (m_rect.GetHeight() / visible_area->m_height ); + screen.y *= -1; + screen += m_rect.GetLeftBottom(); + return screen; + } + wxPoint2DDouble screen_to_math(const wxPoint& screen) const { + wxPoint2DDouble math = screen; + math -= m_rect.GetLeftBottom(); + math.m_y *= -1; + math.m_x *= visible_area->m_width / m_rect.GetWidth(); // scales to [0;1]x[0,1] + math.m_y *= visible_area->m_height / m_rect.GetHeight(); + return (math+visible_area->GetLeftTop()); + } + + int which_button_is_clicked(const wxPoint& point) const { + if (!m_rect.Contains(point)) + return -1; + for (uint i=0;i > m_buttons; + std::vector< std::vector > m_lines_to_draw; + std::vector< wxRect2DDouble > visible_areas; + wxRect2DDouble* visible_area = nullptr; + std::vector* m_line_to_draw = nullptr; + ButtonToDrag* m_dragged = nullptr; + float m_total_volume = 0.f; + + +}; + + +#endif // RAMMING_CHART_H_ \ No newline at end of file diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index ebfa69eb5..7e1ad5dc5 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -3,6 +3,7 @@ #include "PresetBundle.hpp" #include "PresetHints.hpp" #include "../../libslic3r/Utils.hpp" +#include "WipeTowerDialog.hpp" #include #include @@ -440,6 +441,7 @@ void TabPrint::build() optgroup->append_single_option_line("ooze_prevention"); optgroup->append_single_option_line("standby_temperature_delta"); + if (true) { optgroup = page->new_optgroup(_L("Wipe tower")); optgroup->append_single_option_line("wipe_tower"); optgroup->append_single_option_line("wipe_tower_x"); @@ -447,6 +449,27 @@ void TabPrint::build() optgroup->append_single_option_line("wipe_tower_width"); optgroup->append_single_option_line("wipe_tower_per_color_wipe"); optgroup->append_single_option_line("wipe_tower_rotation_angle"); + Line line{ _L("Advanced"), "" }; + line.widget = [this](wxWindow* parent){ + m_wipe_tower_btn = new wxButton(parent, wxID_ANY, _L("Advanced settings")+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(m_wipe_tower_btn); + m_wipe_tower_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) + { + std::string init_data = (m_config->option("wipe_tower_advanced"))->value; + std::cout << "dialog init: " << init_data << std::endl; + WipeTowerDialog dlg(this,init_data); // dlg lives on stack, no need to call Destroy + + if (dlg.ShowModal() == wxID_OK) { + load_key_value("wipe_tower_advanced", dlg.GetValue()); + std::cout << std::endl << "dialog returned: " << dlg.GetValue() << std::endl; + } + })); + return sizer; + }; + optgroup->append_line(line); + } + optgroup = page->new_optgroup(_L("Advanced")); optgroup->append_single_option_line("interface_shells"); @@ -766,6 +789,7 @@ void TabPrint::update() vec_enable = { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle"}; for (auto el : vec_enable) get_field(el)->toggle(have_wipe_tower); + m_wipe_tower_btn->Enable(have_wipe_tower); m_recommended_thin_wall_thickness_description_line->SetText( PresetHints::recommended_thin_wall_thickness(*m_preset_bundle)); diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp index 4f3a15736..b6d273e38 100644 --- a/xs/src/slic3r/GUI/Tab.hpp +++ b/xs/src/slic3r/GUI/Tab.hpp @@ -90,6 +90,7 @@ protected: wxImageList* m_icons; wxCheckBox* m_compatible_printers_checkbox; wxButton* m_compatible_printers_btn; + wxButton* m_wipe_tower_btn; int m_icon_count; std::map m_icon_index; // Map from an icon file name to its index in $self->{icons}. diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp new file mode 100644 index 000000000..5b188e6d1 --- /dev/null +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -0,0 +1,264 @@ +#include "WipeTowerDialog.hpp" + +// Human-readable output of Parameters structure +std::ostream& operator<<(std::ostream& str,Slic3r::WipeTowerParameters& par) { + str << "bridging: " << par.bridging << "\n"; + str << "adhesion: " << par.adhesion << "\n"; + str << "sampling: " << par.sampling << "\n"; + + str << "cooling times: "; + for (const auto& a : par.cooling_time) str << a << " "; + + str << "line widths: "; + for (const auto& a : par.ramming_line_width_multiplicator) str << a << " "; + + str << "line spacing: "; + for (const auto& a : par.ramming_step_multiplicator) str << a << " "; + + str<<"\n\nramming_speeds:\n"; + for (const auto& a : par.ramming_speed) { + for (const auto& b : a) + str << b << " "; + str<<"\n"; + } + str<<"\n\nramming_buttons:\n"; + for (const auto& a : par.ramming_buttons) { + for (const auto& b : a) { + Slic3r::operator <<(str,b); // temporary hack (this << is in the namespace Slic3r) + str << " | "; // the function will be deleted after everything is debugged, anyway + } + str<<"\n"; + } + str<<"\n\nwipe volumes:\n"; + for (const auto& a : par.wipe_volumes) { + for (const auto& b : a) + str << b << " "; + str<<"\n"; + } + str<<"\n\nfilament wipe volumes:\n"; + for (const auto& a : par.filament_wipe_volumes) { + Slic3r::operator <<(str,a); + str << " "; + } + str<<"\n"; + + return str; +} + + + + +RammingPanel::RammingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) +: wxPanel(parent,wxID_ANY,wxPoint(0,0),wxSize(0,0),wxBORDER_RAISED) +{ + new wxStaticText(this,wxID_ANY,wxString("Total ramming time (s):"), wxPoint(500,105), wxSize(200,25),wxALIGN_LEFT); + m_widget_time = new wxSpinCtrlDouble(this,wxID_ANY,wxEmptyString, wxPoint(700,100), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,0.,5.0,3.,0.5); + new wxStaticText(this,wxID_ANY,wxString("Total rammed volume (mm3):"), wxPoint(500,135), wxSize(200,25),wxALIGN_LEFT); + m_widget_volume = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,130), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,0,10000,0); + new wxStaticText(this,wxID_ANY,wxString("Ramming line width (%):"), wxPoint(500,205), wxSize(200,25),wxALIGN_LEFT); + m_widget_ramming_line_width_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,200), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,10,200,100); + new wxStaticText(this,wxID_ANY,wxString("Ramming line spacing (%):"), wxPoint(500,235), wxSize(200,25),wxALIGN_LEFT); + m_widget_ramming_step_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,230), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,10,200,100); + new wxStaticText(this,wxID_ANY,wxString("Extruder #:"), wxPoint(500,12), wxSize(200,25),wxALIGN_LEFT); + + wxArrayString choices; + for (unsigned int i=0;iset_extruder(0); + m_widget_time->SetValue(m_chart->get_time()); + m_widget_time->SetDigits(2); + m_widget_volume->SetValue(m_chart->get_volume()); + m_widget_volume->Disable(); + m_widget_extruder->SetSelection(0); + extruder_selection_changed(); // tell everyone to redraw + + m_widget_ramming_step_multiplicator->Bind(wxEVT_TEXT,[this](wxCommandEvent&) { line_parameters_changed(); }); + m_widget_ramming_line_width_multiplicator->Bind(wxEVT_TEXT,[this](wxCommandEvent&) { line_parameters_changed(); }); + m_widget_extruder->Bind(wxEVT_CHOICE,[this](wxCommandEvent&) { extruder_selection_changed(); }); + m_widget_time->Bind(wxEVT_TEXT,[this](wxCommandEvent&) {m_chart->set_xy_range(m_widget_time->GetValue(),-1);}); + m_widget_time->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value + m_widget_volume->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value + Bind(EVT_WIPE_TOWER_CHART_CHANGED,[this](wxCommandEvent&) {m_widget_volume->SetValue(m_chart->get_volume()); m_widget_time->SetValue(m_chart->get_time());} ); +} + +void RammingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) +{ + if (!m_chart) return; + p.ramming_buttons = m_chart->get_buttons(); + p.ramming_speed = m_chart->get_ramming_speeds(p.sampling); + for (unsigned int i=0;iGetSelection(); + m_chart->set_extruder(m_current_extruder); // tell our chart to redraw + m_widget_ramming_line_width_multiplicator ->SetValue(m_ramming_line_width_multiplicators[m_current_extruder]); + m_widget_ramming_step_multiplicator->SetValue(m_ramming_step_multiplicators[m_current_extruder]); +} + +void RammingPanel::line_parameters_changed() { + m_ramming_line_width_multiplicators[m_current_extruder]=m_widget_ramming_line_width_multiplicator->GetValue(); + m_ramming_step_multiplicators[m_current_extruder]=m_widget_ramming_step_multiplicator->GetValue(); +} + + + + + + +CoolingPanel::CoolingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) +: wxPanel(parent,wxID_ANY,wxPoint(0,0),wxSize(0,0),wxBORDER_RAISED) +{ + new wxStaticText(this,wxID_ANY,wxString("Time (in seconds) reserved for cooling after unload:"),wxPoint(220,50) ,wxSize(400,25),wxALIGN_LEFT); + for (int i=0;i<4;++i) { + new wxStaticText(this,wxID_ANY,wxString("Filament #")<=m_widget_edits.size()) + break; // so we don't initialize non-existent widget + m_widget_edits[i]->SetValue(p.cooling_time[i]); + } +} + +void CoolingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { + p.cooling_time.clear(); + for (int i=0;i<4;++i) + p.cooling_time.push_back(m_widget_edits[i]->GetValue()); +} + + + +WipingPanel::WipingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) +: wxPanel(parent,wxID_ANY,wxPoint(0,0),wxSize(0,0),wxBORDER_RAISED) +{ + const int N = 4; // number of extruders + new wxStaticText(this,wxID_ANY,wxString("Volume to wipe when the filament is being"),wxPoint(40,55) ,wxSize(500,25)); + new wxStaticText(this,wxID_ANY,wxString("unloaded"),wxPoint(110,75) ,wxSize(500,25)); + new wxStaticText(this,wxID_ANY,wxString("loaded"),wxPoint(195,75) ,wxSize(500,25)); + m_widget_button = new wxButton(this,wxID_ANY,"-> Fill in the matrix ->",wxPoint(300,130),wxSize(175,50)); + for (int i=0;i(0)); + new wxStaticText(this,wxID_ANY,wxString("")<Disable(); + else + edit_boxes[i][j]->SetValue(wxString("")<Bind(wxEVT_BUTTON,[this](wxCommandEvent&){fill_in_matrix();}); +} + +void WipingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { + p.wipe_volumes.clear(); + p.filament_wipe_volumes.clear(); + for (int i=0;i<4;++i) { + // first go through the full matrix: + p.wipe_volumes.push_back(std::vector()); + for (int j=0;j<4;++j) { + double val = 0.; + edit_boxes[j][i]->GetValue().ToDouble(&val); + p.wipe_volumes[i].push_back((float)val); + } + + // now the filament volumes: + p.filament_wipe_volumes.push_back(std::make_pair(m_old[i]->GetValue(),m_new[i]->GetValue())); + } +} + +void WipingPanel::fill_in_matrix() { + wxArrayString choices; + choices.Add("sum"); + choices.Add("maximum"); + wxSingleChoiceDialog dialog(this,"How shall I calculate volume for any given pair?\n\nI can either sum volumes for old and new filament, or just use the higher value.","DEBUGGING",choices); + if (dialog.ShowModal() == wxID_CANCEL) + return; + for (unsigned i=0;i<4;++i) { + for (unsigned j=0;j<4;++j) { + if (i==j) continue; + if (!dialog.GetSelection()) edit_boxes[j][i]->SetValue(wxString("")<< (m_old[i]->GetValue() + m_new[j]->GetValue())); + else + edit_boxes[j][i]->SetValue(wxString("")<< (std::max(m_old[i]->GetValue(), m_new[j]->GetValue()))); + } + } +} + + + +GeneralPanel::GeneralPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) : wxPanel(parent,wxID_ANY,wxPoint(0,0),wxSize(0,0),wxBORDER_RAISED) { + new wxStaticText(this,wxID_ANY,wxString("Maximum bridging over sparse infill (mm):"),wxPoint(100,105) ,wxSize(280,25),wxALIGN_LEFT); + m_widget_bridge = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxPoint(380,100),wxSize(50,25),wxALIGN_RIGHT|wxSP_ARROW_KEYS,1,50,10); + m_widget_adhesion = new wxCheckBox(this,wxID_ANY,"Increased adhesion of first layer",wxPoint(100,150),wxSize(330,25),wxALIGN_RIGHT); + m_widget_bridge->SetValue(p.bridging); + m_widget_adhesion->SetValue(p.adhesion); +} + +void GeneralPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { + p.bridging = m_widget_bridge->GetValue(); + p.adhesion = m_widget_adhesion->GetValue(); +} + + + + + +WipeTowerDialog::WipeTowerDialog(wxWindow* parent,const std::string& init_data) +: wxDialog(parent, -1, wxT("Wipe tower advanced settings"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +{ + this->Centre(); + + Slic3r::WipeTowerParameters parameters(init_data); + if (!parameters.validate()) { + wxMessageDialog(this,"Wipe tower parameters not parsed correctly!\nRestoring default settings.","Error",wxICON_ERROR); + parameters.set_defaults(); + } + + wxNotebook* notebook = new wxNotebook(this,wxID_ANY,wxPoint(0,0),wxSize(800,450)); + + m_panel_general = new GeneralPanel(notebook,parameters); + m_panel_ramming = new RammingPanel(notebook,parameters); + m_panel_cooling = new CoolingPanel(notebook,parameters); + m_panel_wiping = new WipingPanel(notebook,parameters); + notebook->AddPage(m_panel_general,"General"); + notebook->AddPage(m_panel_ramming,"Ramming"); + notebook->AddPage(m_panel_cooling,"Cooling"); + notebook->AddPage(m_panel_wiping,"Wiping"); + this->Show(); + + auto main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->Add(notebook, 1, wxEXPAND); + main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); + SetSizer(main_sizer); + SetMinSize(GetSize()); + main_sizer->SetSizeHints(this); + + this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); + + this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { + m_output_data=read_dialog_values(); + EndModal(wxID_OK); + },wxID_OK); +} + diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/xs/src/slic3r/GUI/WipeTowerDialog.hpp new file mode 100644 index 000000000..452886bc3 --- /dev/null +++ b/xs/src/slic3r/GUI/WipeTowerDialog.hpp @@ -0,0 +1,115 @@ +#ifndef _WIPE_TOWER_DIALOG_H_ +#define _WIPE_TOWER_DIALOG_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "../../libslic3r/GCode/WipeTowerPrusaMM.hpp" +#include "RammingChart.hpp" + + +// Human-readable output of Parameters structure +std::ostream& operator<<(std::ostream& str,Slic3r::WipeTowerParameters& par); + + +class RammingPanel : public wxPanel { +public: + RammingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p); + void fill_parameters(Slic3r::WipeTowerParameters& p); + +private: + Chart* m_chart = nullptr; + wxSpinCtrl* m_widget_volume = nullptr; + wxSpinCtrl* m_widget_ramming_line_width_multiplicator = nullptr; + wxSpinCtrl* m_widget_ramming_step_multiplicator = nullptr; + wxSpinCtrlDouble* m_widget_time = nullptr; + wxChoice* m_widget_extruder = nullptr; + std::vector m_ramming_step_multiplicators; + std::vector m_ramming_line_width_multiplicators; + int m_current_extruder = 0; // zero-based index + + void extruder_selection_changed(); + + void line_parameters_changed(); +}; + + + + + + +class CoolingPanel : public wxPanel { +public: + CoolingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p); + void fill_parameters(Slic3r::WipeTowerParameters& p); + +private: + std::vector m_widget_edits; +}; + + + + + + +class WipingPanel : public wxPanel { +public: + WipingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p); + void fill_parameters(Slic3r::WipeTowerParameters& p); + +private: + void fill_in_matrix(); + + std::vector m_old; + std::vector m_new; + std::vector> edit_boxes; + wxButton* m_widget_button=nullptr; +}; + + + + +class GeneralPanel : public wxPanel { +public: + GeneralPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p); + void fill_parameters(Slic3r::WipeTowerParameters& p); + +private: + wxSpinCtrl* m_widget_bridge; + wxCheckBox* m_widget_adhesion; +}; + + + + +class WipeTowerDialog : public wxDialog { +public: + WipeTowerDialog(wxWindow* parent,const std::string& init_data); + + std::string GetValue() const { return m_output_data; } + + +private: + std::string m_file_name="config_wipe_tower"; + GeneralPanel* m_panel_general = nullptr; + RammingPanel* m_panel_ramming = nullptr; + CoolingPanel* m_panel_cooling = nullptr; + WipingPanel* m_panel_wiping = nullptr; + std::string m_output_data = ""; + + std::string read_dialog_values() { + Slic3r::WipeTowerParameters p; + m_panel_general->fill_parameters(p); + m_panel_ramming->fill_parameters(p); + m_panel_cooling->fill_parameters(p); + m_panel_wiping ->fill_parameters(p); + return p.to_string(); + } +}; + +#endif // _WIPE_TOWER_DIALOG_H_ \ No newline at end of file From 9ea803b000c6de4a4ccfb0d39e88ef69555cb1c1 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 28 Feb 2018 19:53:32 +0100 Subject: [PATCH 17/81] Attempts to fix OSX and Win builds --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 19 ++----------- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 31 +++++++++------------ xs/src/slic3r/GUI/RammingChart.hpp | 2 +- 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index d7492fdbb..004aaf0de 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -31,8 +31,7 @@ TODO LIST #define strcasecmp _stricmp #endif -constexpr bool peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet -constexpr float min_layer_difference = 2*m_perimeter_width; +const bool peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet namespace Slic3r { @@ -468,7 +467,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // therefore the homing position is shifted inside the bed by 0.2 in the firmware to [0.2, -2.0]. // box_coordinates cleaning_box(xy(0.5f, - 1.5f), m_wipe_tower_width, wipe_area); //FIXME: set the width properly - constexpr float prime_section_width = 60.f; + const float prime_section_width = 60.f; box_coordinates cleaning_box(xy(5.f, 0.f), prime_section_width, 15.f); PrusaMultiMaterial::Writer writer; @@ -1191,18 +1190,6 @@ void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsi depth *= m_extra_spacing; m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool, depth)); - - // Calculate m_wipe_tower_depth (maximum depth for all the layers) and propagate depths downwards - /*float this_layer_depth = m_plan.back().toolchanges_depth(); - m_plan.back().depth = this_layer_depth; - - if (this_layer_depth > m_wipe_tower_depth - m_perimeter_width) - m_wipe_tower_depth = this_layer_depth + m_perimeter_width; - for (int i = m_plan.size() - 2; i >= 0 && m_plan[i].depth < this_layer_depth; i-- ) { - if ( this_layer_depth - m_plan[i].depth < min_layer_difference && !m_plan[i].tool_changes.empty()) - m_plan[i].depth += this_layer_depth - m_plan[i].depth; - m_plan[i].depth = this_layer_depth; - }*/ } @@ -1224,7 +1211,7 @@ void WipeTowerPrusaMM::plan_tower() for (int i = layer_index - 1; i >= 0 /*&& m_plan[i].depth < this_layer_depth*/; i--) { - if (m_plan[i].depth - this_layer_depth < min_layer_difference ) + if (m_plan[i].depth - this_layer_depth < 2*m_perimeter_width ) m_plan[i].depth = this_layer_depth; } } diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 43163a73a..ef58f6c56 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -10,22 +10,17 @@ #include "WipeTower.hpp" // Following is used to calculate extrusion flow - should be taken from config in future -constexpr float Filament_Area = M_PI * 1.75f * 1.75f / 4.f; // filament area in mm^3 -constexpr float Nozzle_Diameter = 0.4f; // nozzle diameter in mm +const float Filament_Area = M_PI * 1.75f * 1.75f / 4.f; // filament area in mm^3 +const float Nozzle_Diameter = 0.4f; // nozzle diameter in mm // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust -constexpr float Width_To_Nozzle_Ratio = 1.25f; +const float Width_To_Nozzle_Ratio = 1.25f; // m_perimeter_width was hardcoded until now as 0.5 (for 0.4 nozzle and 0.2 layer height) // FIXME m_perimeter_width is used in plan_toolchange - take care of proper initialization value when changing to variable -constexpr float Konst = 1.f; -constexpr float m_perimeter_width = Nozzle_Diameter * Width_To_Nozzle_Ratio * Konst; - -constexpr float WT_EPSILON = 1e-3f; - - - - +const float Konst = 1.f; +const float m_perimeter_width = Nozzle_Diameter * Width_To_Nozzle_Ratio * Konst; +const float WT_EPSILON = 1e-3f; namespace Slic3r @@ -147,14 +142,14 @@ struct WipeTowerParameters { ramming_speed.clear(); ramming_buttons.clear(); for (unsigned int i=0;i<4;++i) { - ramming_speed.push_back(std::vector{7.6, 7.6, 7.6, 7.6, 9.0, 9.0, 9.0, 10.7, 10.7, 10.7}); - ramming_buttons.push_back(std::vector>{{0.05, 6.6},{0.45, 6.8},{0.95, 7.8},{1.45, 8.3},{1.95, 9.7},{2.45,10},{2.95, 7.6},{3.45, 7.6},{3.95, 7.6},{4.45, 7.6},{4.95, 7.6}}); + ramming_speed.push_back(std::vector{7.6f, 7.6f, 7.6f, 7.6f, 9.f, 9.f, 9.f, 10.7f, 10.7f, 10.7f}); + ramming_buttons.push_back(std::vector>{{0.05f, 6.6f},{0.45f, 6.8f},{0.95f, 7.8f},{1.45f, 8.3f},{1.95f, 9.7f},{2.45f,10.f},{2.95f, 7.6f},{3.45f, 7.6f},{3.95f, 7.6f},{4.45f, 7.6f},{4.95f, 7.6f}}); } - wipe_volumes = {{ 0, 60, 60, 60}, - { 60, 0, 60, 60}, - { 60, 60, 0, 60}, - { 60, 60, 60, 0}}; - filament_wipe_volumes = {{30,30},{30,30},{30,30},{30,30}}; + wipe_volumes = {{ 0.f, 60.f, 60.f, 60.f}, + { 60.f, 0.f, 60.f, 60.f}, + { 60.f, 60.f, 0.f, 60.f}, + { 60.f, 60.f, 60.f, 0.f}}; + filament_wipe_volumes = {{30.f,30.f},{30.f,30.f},{30.f,30.f},{30.f,30.f}}; } int bridging = 0.f; diff --git a/xs/src/slic3r/GUI/RammingChart.hpp b/xs/src/slic3r/GUI/RammingChart.hpp index 5443e957a..5b7f6daf8 100644 --- a/xs/src/slic3r/GUI/RammingChart.hpp +++ b/xs/src/slic3r/GUI/RammingChart.hpp @@ -68,7 +68,7 @@ private: class ButtonToDrag { public: - bool operator<(ButtonToDrag& a) { return m_pos.m_x < a.m_pos.m_x; } + bool operator<(const ButtonToDrag& a) const { return m_pos.m_x < a.m_pos.m_x; } ButtonToDrag(wxPoint2DDouble pos) : m_pos{pos} {}; wxPoint2DDouble get_pos() const { return m_pos; } void move(double x,double y) { m_pos.m_x+=x; m_pos.m_y+=y; } From b1b16359d9b54d225742233ebb45d67bb6243094 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 1 Mar 2018 08:43:43 +0100 Subject: [PATCH 18/81] Changes in includes in order to fix Win builds --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 2 ++ xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 004aaf0de..fdfd8752f 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -20,6 +20,8 @@ TODO LIST #include #include #include +#include +#include #include "Analyzer.hpp" diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index ef58f6c56..58e5c0ee6 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -1,7 +1,6 @@ #ifndef WipeTowerPrusaMM_hpp_ #define WipeTowerPrusaMM_hpp_ -#include #include #include #include From c76c075569effe7b20f28c3217f8fd5c568b890d Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 1 Mar 2018 09:19:34 +0100 Subject: [PATCH 19/81] Yet another attempt to fix Win builds --- xs/src/slic3r/GUI/RammingChart.hpp | 2 +- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/xs/src/slic3r/GUI/RammingChart.hpp b/xs/src/slic3r/GUI/RammingChart.hpp index 5b7f6daf8..e04f4b52e 100644 --- a/xs/src/slic3r/GUI/RammingChart.hpp +++ b/xs/src/slic3r/GUI/RammingChart.hpp @@ -98,7 +98,7 @@ private: int which_button_is_clicked(const wxPoint& point) const { if (!m_rect.Contains(point)) return -1; - for (uint i=0;i #include "WipeTowerDialog.hpp" // Human-readable output of Parameters structure From 1d787a15a0cc3ef798bf993b8c1202d3c747bdd1 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 1 Mar 2018 09:57:51 +0100 Subject: [PATCH 20/81] Fix for win builds --- xs/src/slic3r/GUI/RammingChart.cpp | 4 ++-- xs/src/slic3r/GUI/RammingChart.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/xs/src/slic3r/GUI/RammingChart.cpp index 3b5f4e41e..3b535aacf 100644 --- a/xs/src/slic3r/GUI/RammingChart.cpp +++ b/xs/src/slic3r/GUI/RammingChart.cpp @@ -17,13 +17,13 @@ void Chart::draw(wxDC& dc) { if (!m_line_to_draw->empty()) { - for (uint i=0;isize()-2;++i) { + for (unsigned int i=0;isize()-2;++i) { int color = 510*((m_rect.GetBottom()-(*m_line_to_draw)[i])/double(m_rect.GetHeight())); dc.SetPen( wxPen( wxColor(std::min(255,color),255-std::max(color-255,0),0), 1 ) ); dc.DrawLine(m_rect.GetLeft()+1+i,(*m_line_to_draw)[i],m_rect.GetLeft()+1+i,m_rect.GetBottom()); } dc.SetPen( wxPen( wxColor(0,0,0), 1 ) ); - for (uint i=0;isize()-2;++i) { + for (unsigned int i=0;isize()-2;++i) { if (splines) dc.DrawLine(m_rect.GetLeft()+i,(*m_line_to_draw)[i],m_rect.GetLeft()+i+1,(*m_line_to_draw)[i+1]); else { diff --git a/xs/src/slic3r/GUI/RammingChart.hpp b/xs/src/slic3r/GUI/RammingChart.hpp index e04f4b52e..8274b96e6 100644 --- a/xs/src/slic3r/GUI/RammingChart.hpp +++ b/xs/src/slic3r/GUI/RammingChart.hpp @@ -111,7 +111,7 @@ private: void recalculate_volume(); - unsigned m_current_extruder = 0; + unsigned int m_current_extruder = 0; wxRect m_rect; // rectangle on screen the chart is mapped into (screen coordinates) wxPoint m_previous_mouse; std::vector< std::vector > m_buttons; From d2006c8d8ec32735fb8518855bc7df18cf502047 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 1 Mar 2018 16:15:00 +0100 Subject: [PATCH 21/81] Cooling tubes parameters added into GUI and configuration layer (not yet into wipe tower generator) --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 8 ++++++- xs/src/libslic3r/Print.cpp | 8 +++++-- xs/src/libslic3r/PrintConfig.cpp | 25 +++++++++++++++++++++ xs/src/libslic3r/PrintConfig.hpp | 6 +++++ xs/src/slic3r/GUI/Preset.cpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 3 +++ 6 files changed, 48 insertions(+), 4 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 58e5c0ee6..c05f2aebe 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -188,7 +188,9 @@ public: // y -- y coordinates of wipe tower in mm ( left bottom corner ) // 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 wipe_area, float rotation_angle, unsigned int initial_tool,std::string& parameters) : + WipeTowerPrusaMM(float x, float y, float width, float wipe_area, float rotation_angle, float cooling_tube_retraction, + float cooling_tube_length, float parking_pos_retraction, std::string& parameters, + unsigned int initial_tool) : m_wipe_tower_pos(x, y), m_wipe_tower_width(width), m_wipe_tower_rotation_angle(rotation_angle), @@ -199,6 +201,7 @@ public: m_current_tool(initial_tool), m_par(parameters) { + printf("Jsem konstruktor WT a vidim cisla %f,%f,%f\n",cooling_tube_retraction,cooling_tube_length,parking_pos_retraction); for (size_t i = 0; i < 4; ++ i) { // Extruder specific parameters. m_material[i] = PLA; @@ -325,6 +328,9 @@ private: // G-code generator parameters. float m_zhop = 0.5f; float m_retract = 4.f; + float m_cooling_tube_retraction = 0.f; + float m_cooling_tube_length = 0.f; + float m_parking_pos_retraction = 0.f; float m_line_width = Nozzle_Diameter * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. float m_extrusion_flow = 0.038; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index fe98612cf..020af7610 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -90,6 +90,8 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.wipe_tower_x.value), float(this->config.wipe_tower_y.value), float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value), - float(this->config.wipe_tower_rotation_angle.value), m_tool_ordering.first_extruder(), - this->config.wipe_tower_advanced.value); + float(this->config.wipe_tower_rotation_angle.value), float(this->config.cooling_tube_retraction.value), + float(this->config.cooling_tube_length.value), float(this->config.parking_pos_retraction.value), + this->config.wipe_tower_advanced.value,m_tool_ordering.first_extruder()); //wipe_tower.set_retract(); //wipe_tower.set_zhop(); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 7a48b3a32..a5fbb844b 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -171,6 +171,22 @@ PrintConfigDef::PrintConfigDef() def->cli = "cooling!"; def->default_value = new ConfigOptionBools { true }; + def = this->add("cooling_tube_retraction", coFloat); + def->label = _L("Cooling tube position"); + def->tooltip = _L("Distance of the center-point of the cooling tube from the extruder tip "); + def->sidetext = _L("mm"); + def->cli = "cooling_tube_retraction=f"; + def->min = 0; + def->default_value = new ConfigOptionFloat(0); + + def = this->add("cooling_tube_length", coFloat); + def->label = _L("Cooling tube length"); + def->tooltip = _L("Length of the cooling tube to limit space for cooling moves inside it "); + def->sidetext = _L("mm"); + def->cli = "cooling_tube_length=f"; + def->min = 0; + def->default_value = new ConfigOptionFloat(0); + def = this->add("default_acceleration", coFloat); def->label = _L("Default"); def->tooltip = _L("This is the acceleration your printer will be reset to after " @@ -947,6 +963,15 @@ PrintConfigDef::PrintConfigDef() def->cli = "overhangs!"; def->default_value = new ConfigOptionBool(true); + def = this->add("parking_pos_retraction", coFloat); + def->label = _L("Filament parking position"); + def->tooltip = _L("Distance of the extruder tip from the position where the filament is parked" + "when unloaded. This should match the value in printer firmware. "); + def->sidetext = _L("mm"); + def->cli = "parking_pos_retraction=f"; + def->min = 0; + def->default_value = new ConfigOptionFloat(0); + def = this->add("perimeter_acceleration", coFloat); def->label = _L("Perimeters"); def->tooltip = _L("This is the acceleration your printer will use for perimeters. " diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index d55aafed6..c556a2d69 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -491,6 +491,9 @@ public: ConfigOptionBool use_relative_e_distances; ConfigOptionBool use_volumetric_e; ConfigOptionBool variable_layer_height; + ConfigOptionFloat cooling_tube_retraction; + ConfigOptionFloat cooling_tube_length; + ConfigOptionFloat parking_pos_retraction; std::string get_extrusion_axis() const { @@ -540,6 +543,9 @@ protected: OPT_PTR(use_relative_e_distances); OPT_PTR(use_volumetric_e); OPT_PTR(variable_layer_height); + OPT_PTR(cooling_tube_retraction); + OPT_PTR(cooling_tube_length); + OPT_PTR(parking_pos_retraction); } }; diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index be31c1bd1..c363647cb 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -227,7 +227,7 @@ const std::vector& Preset::printer_options() "bed_shape", "z_offset", "gcode_flavor", "use_relative_e_distances", "serial_port", "serial_speed", "octoprint_host", "octoprint_apikey", "use_firmware_retraction", "use_volumetric_e", "variable_layer_height", "single_extruder_multi_material", "start_gcode", "end_gcode", "before_layer_gcode", "layer_gcode", "toolchange_gcode", - "between_objects_gcode", "printer_notes" + "between_objects_gcode", "printer_notes", "cooling_tube_retraction", "cooling_tube_length", "parking_pos_retraction" }; s_opts.insert(s_opts.end(), Preset::nozzle_options().begin(), Preset::nozzle_options().end()); } diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 7e1ad5dc5..790f5dc4b 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -1139,6 +1139,9 @@ void TabPrinter::build() optgroup->append_single_option_line("use_firmware_retraction"); optgroup->append_single_option_line("use_volumetric_e"); optgroup->append_single_option_line("variable_layer_height"); + optgroup->append_single_option_line("cooling_tube_retraction"); + optgroup->append_single_option_line("cooling_tube_length"); + optgroup->append_single_option_line("parking_pos_retraction"); page = add_options_page(_L("Custom G-code"), "cog.png"); optgroup = page->new_optgroup(_L("Start G-code"), 0); From e1421da5e82936bf66cdee7802c1e78481b9983e Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 2 Mar 2018 13:26:16 +0100 Subject: [PATCH 22/81] Integrating cooling tube parameters into wipe tower generator --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 25 +++++++++++++-------- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 7 +++++- xs/src/libslic3r/PrintConfig.cpp | 6 ++--- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index fdfd8752f..2e3e7c0a7 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -841,14 +841,17 @@ void WipeTowerPrusaMM::toolchange_Unload( .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.2f, e0, 1.74f * e, 5200); }*/ } - // Pull the filament end into a cooling tube. - writer.retract(15, 5000).retract(50, 5400).retract(15, 3000).retract(12, 2000); + // Pull the filament end into a cooling tube (Alex) + //writer.retract(15, 5000).retract(50, 5400).retract(15, 3000).retract(12, 2000); + + // Pull the filament end to the BEGINNING of the cooling tube + writer.retract(15, 5000).retract(m_cooling_tube_retraction+m_cooling_tube_length/2.f-42, 5400).retract(15, 3000).retract(12, 2000); + if (new_temperature != 0) // Set the extruder temperature, but don't wait. writer.set_extruder_temp(new_temperature, false); // cooling: - writer.retract(2, 2000); writer.suppress_preview(); writer.travel(writer.x(), writer.y() + y_step); const float start_x = writer.x(); @@ -860,9 +863,10 @@ void WipeTowerPrusaMM::toolchange_Unload( i = 0; while (isidetext = _L("mm"); def->cli = "cooling_tube_retraction=f"; def->min = 0; - def->default_value = new ConfigOptionFloat(0); + def->default_value = new ConfigOptionFloat(91.5f); def = this->add("cooling_tube_length", coFloat); def->label = _L("Cooling tube length"); @@ -185,7 +185,7 @@ PrintConfigDef::PrintConfigDef() def->sidetext = _L("mm"); def->cli = "cooling_tube_length=f"; def->min = 0; - def->default_value = new ConfigOptionFloat(0); + def->default_value = new ConfigOptionFloat(5.f); def = this->add("default_acceleration", coFloat); def->label = _L("Default"); @@ -970,7 +970,7 @@ PrintConfigDef::PrintConfigDef() def->sidetext = _L("mm"); def->cli = "parking_pos_retraction=f"; def->min = 0; - def->default_value = new ConfigOptionFloat(0); + def->default_value = new ConfigOptionFloat(92.f); def = this->add("perimeter_acceleration", coFloat); def->label = _L("Perimeters"); From b3e9b82280557c9803c270854edb4935287a840e Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 2 Mar 2018 15:52:16 +0100 Subject: [PATCH 23/81] (Un)loading speed and time delay parameters introduced into GUI and conf. layer (not yet into wipe tower generator) --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 21 ++++++++-------- xs/src/libslic3r/PrintConfig.cpp | 27 +++++++++++++++++++++ xs/src/libslic3r/PrintConfig.hpp | 6 +++++ xs/src/slic3r/GUI/Preset.cpp | 9 +++---- xs/src/slic3r/GUI/Tab.cpp | 12 +++++---- 5 files changed, 55 insertions(+), 20 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 2e3e7c0a7..c146f6030 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -845,7 +845,11 @@ void WipeTowerPrusaMM::toolchange_Unload( //writer.retract(15, 5000).retract(50, 5400).retract(15, 3000).retract(12, 2000); // Pull the filament end to the BEGINNING of the cooling tube - writer.retract(15, 5000).retract(m_cooling_tube_retraction+m_cooling_tube_length/2.f-42, 5400).retract(15, 3000).retract(12, 2000); + float unloading_feedrate = 5400.f; // Alex's original feedrate was 5400 + writer.retract(15, 5000) // just after ramming - fixed speed + .retract(m_cooling_tube_retraction+m_cooling_tube_length/2.f-42, unloading_feedrate) + .retract(15, unloading_feedrate*0.55f) + .retract(12, unloading_feedrate*0.35f); if (new_temperature != 0) // Set the extruder temperature, but don't wait. @@ -953,17 +957,14 @@ void WipeTowerPrusaMM::toolchange_Load( float oldx = writer.x(); // the nozzle is in place to do the first wiping moves, we will remember the position float oldy = writer.y(); - writer.append("; CP TOOLCHANGE LOAD\n") - // Load the filament while moving left / right, + // Load the filament while moving left / right, // so the excess material will not create a blob at a single position. + float loading_feedrate = 3000.f; + writer.append("; CP TOOLCHANGE LOAD\n") .suppress_preview() - // Accelerate the filament loading - .load_move_x(xr, 20, 1400) - // Fast loading phase - //.load_move_x(xl, 40, 3000) - Alex - .load_move_x(xl,m_parking_pos_retraction-50-2,3000) // loading is 2mm shorter that previous retraction - // Slowing down - .load_move_x(xr, 20, 1600) + .load_move_x(xr, 20, 1400) // Accelerate the filament loading + .load_move_x(xl,m_parking_pos_retraction-50-2,3000) // Fast phase - loading is 2mm shorter that previous retraction + .load_move_x(xr, 20, 1600) // Slowing down .load_move_x(xl, 10, 1000) .travel(oldx,oldy) .resume_preview(); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 1886d52b8..cebb0832b 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -448,6 +448,33 @@ PrintConfigDef::PrintConfigDef() def->min = 0; def->default_value = new ConfigOptionFloats { 0. }; + def = this->add("filament_loading_speed", coFloats); + def->label = _L("Loading speed"); + def->tooltip = _L("Speed used for loading the filament on the wipe tower. "); + def->sidetext = _L("mm\u00B3/s"); + def->cli = "filament-loading-speed=f@"; + def->min = 0; + def->default_value = new ConfigOptionFloats { 0. }; + + def = this->add("filament_unloading_speed", coFloats); + def->label = _L("Unloading speed"); + def->tooltip = _L("Speed used for unloading the filament on the wipe tower (does not affect " + " initial part of unloading just after ramming). "); + def->sidetext = _L("mm\u00B3/s"); + def->cli = "filament-unloading-speed=f@"; + def->min = 0; + def->default_value = new ConfigOptionFloats { 0. }; + + def = this->add("filament_toolchange_delay", coFloats); + def->label = _L("Delay after unloading"); + def->tooltip = _L("Time to wait after the filament is unloaded. " + "May help to get reliable toolchanges with flexible materials " + "that may need more time to shrink to original dimensions. "); + def->sidetext = _L("s"); + def->cli = "filament-toolchange-delay=f@"; + def->min = 0; + def->default_value = new ConfigOptionFloats { 0. }; + def = this->add("filament_diameter", coFloats); def->label = _L("Diameter"); def->tooltip = _L("Enter your filament diameter here. Good precision is required, so use a caliper " diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index c556a2d69..407832419 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -466,6 +466,9 @@ public: ConfigOptionBools filament_soluble; ConfigOptionFloats filament_cost; ConfigOptionFloats filament_max_volumetric_speed; + ConfigOptionFloats filament_loading_speed; + ConfigOptionFloats filament_unloading_speed; + ConfigOptionFloats filament_toolchange_delay; ConfigOptionBool gcode_comments; ConfigOptionEnum gcode_flavor; ConfigOptionString layer_gcode; @@ -518,6 +521,9 @@ protected: OPT_PTR(filament_soluble); OPT_PTR(filament_cost); OPT_PTR(filament_max_volumetric_speed); + OPT_PTR(filament_loading_speed); + OPT_PTR(filament_unloading_speed); + OPT_PTR(filament_toolchange_delay); OPT_PTR(gcode_comments); OPT_PTR(gcode_flavor); OPT_PTR(layer_gcode); diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index c363647cb..1cfd73bab 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -210,11 +210,10 @@ const std::vector& Preset::filament_options() { static std::vector s_opts { "filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed", - "extrusion_multiplier", "filament_density", "filament_cost", "temperature", "first_layer_temperature", "bed_temperature", - "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", - "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", - "end_filament_gcode", - "compatible_printers", "compatible_printers_condition" + "extrusion_multiplier", "filament_density", "filament_cost", "filament_loading_speed", "filament_unloading_speed", "filament_toolchange_delay", + "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", + "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", + "min_print_speed", "start_filament_gcode", "end_filament_gcode","compatible_printers", "compatible_printers_condition" }; return s_opts; } diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 790f5dc4b..92504f714 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -441,7 +441,6 @@ void TabPrint::build() optgroup->append_single_option_line("ooze_prevention"); optgroup->append_single_option_line("standby_temperature_delta"); - if (true) { optgroup = page->new_optgroup(_L("Wipe tower")); optgroup->append_single_option_line("wipe_tower"); optgroup->append_single_option_line("wipe_tower_x"); @@ -449,8 +448,8 @@ void TabPrint::build() optgroup->append_single_option_line("wipe_tower_width"); optgroup->append_single_option_line("wipe_tower_per_color_wipe"); optgroup->append_single_option_line("wipe_tower_rotation_angle"); - Line line{ _L("Advanced"), "" }; - line.widget = [this](wxWindow* parent){ + line = { _L("Advanced"), "" }; + line.widget = [this](wxWindow* parent){ m_wipe_tower_btn = new wxButton(parent, wxID_ANY, _L("Advanced settings")+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(m_wipe_tower_btn); @@ -468,8 +467,6 @@ void TabPrint::build() return sizer; }; optgroup->append_line(line); - } - optgroup = page->new_optgroup(_L("Advanced")); optgroup->append_single_option_line("interface_shells"); @@ -867,6 +864,11 @@ void TabFilament::build() }; optgroup->append_line(line); + optgroup = page->new_optgroup(_L("Toolchange behaviour")); + optgroup->append_single_option_line("filament_loading_speed"); + optgroup->append_single_option_line("filament_unloading_speed"); + optgroup->append_single_option_line("filament_toolchange_delay"); + page = add_options_page(_L("Custom G-code"), "cog.png"); optgroup = page->new_optgroup(_L("Start G-code"), 0); Option option = optgroup->get_option("start_filament_gcode"); From 5aca3045b9619903ade59fa0da22435ee21ea4e6 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 5 Mar 2018 10:45:35 +0100 Subject: [PATCH 24/81] (Un)loading speed and delay introduced into wipe tower generator --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 50 ++++++++++++++------- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 35 ++++++++++----- xs/src/libslic3r/Print.cpp | 8 +++- xs/src/libslic3r/PrintConfig.cpp | 8 ++-- 4 files changed, 68 insertions(+), 33 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index c146f6030..bc93a938e 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -243,6 +243,17 @@ public: return *this; }; + // Wait for a period of time (seconds). + Writer& wait(float time) + { + if (time==0) + return *this; + char buf[128]; + sprintf(buf, "G4 S%.3f\n", time); + m_gcode += buf; + return *this; + }; + // Set speed factor override percentage. Writer& speed_override(int speed) { @@ -495,7 +506,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) { unsigned int tool = tools[idx_tool]; m_left_to_right = true; - toolchange_Change(writer, tool, m_material[tool]); // Select the tool, set a speed override for soluble and flex materials. + toolchange_Change(writer, tool, m_filpar[tool].material); // Select the tool, set a speed override for soluble and flex materials. toolchange_Load(writer, cleaning_box); // Prime the tool. if (idx_tool + 1 == tools.size()) { // Last tool should not be unloaded, but it should be wiped enough to become of a pure color. @@ -506,7 +517,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( toolchange_Wipe(writer, cleaning_box , 5.f); box_coordinates box = cleaning_box; box.translate(0.f, writer.y() - cleaning_box.ld.y + m_perimeter_width); - toolchange_Unload(writer, box , m_material[m_current_tool], m_first_layer_temperature[tools[idx_tool + 1]]); + toolchange_Unload(writer, box , m_filpar[m_current_tool].material, m_filpar[tools[idx_tool + 1]].first_layer_temperature); cleaning_box.translate(prime_section_width, 0.f); writer.travel(cleaning_box.ld, 7200); } @@ -614,7 +625,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .append(";--------------------\n" "; CP TOOLCHANGE START\n") .comment_with_value(" toolchange #", m_num_tool_changes) - .comment_material(m_material[m_current_tool]) + .comment_material(m_filpar[m_current_tool].material) .append(";--------------------\n") .speed_override(100); @@ -622,7 +633,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo if (purpose == PURPOSE_MOVE_TO_TOWER || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { // Scaffold leaks terribly, reduce leaking by a full retract when going to the wipe tower. - float initial_retract = ((m_material[m_current_tool] == SCAFF) ? 1.f : 0.5f) * m_retract; + float initial_retract = ((m_filpar[m_current_tool].material == SCAFF) ? 1.f : 0.5f) * m_retract; writer // Lift for a Z hop. .z_hop(m_zhop, 7200) // Additional retract on move to tower. @@ -650,9 +661,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo // 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. - toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], - m_is_first_layer ? m_first_layer_temperature[tool] : m_temperature[tool]); - toolchange_Change(writer, tool, m_material[tool]); // Change the tool, set a speed override for soluble and flex materials. + toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, + m_is_first_layer ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature); + toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials. toolchange_Load(writer, cleaning_box); toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area. @@ -661,7 +672,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo writer.travel(box.ru, 7200) .travel(box.lu);*/ } else - toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], m_temperature[m_current_tool]); + toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, m_filpar[m_current_tool].temperature); if (last_change_in_layer) // draw perimeter line writer.travel(m_wipe_tower_pos, 7000) @@ -845,8 +856,8 @@ void WipeTowerPrusaMM::toolchange_Unload( //writer.retract(15, 5000).retract(50, 5400).retract(15, 3000).retract(12, 2000); // Pull the filament end to the BEGINNING of the cooling tube - float unloading_feedrate = 5400.f; // Alex's original feedrate was 5400 - writer.retract(15, 5000) // just after ramming - fixed speed + float unloading_feedrate = 60.f * m_filpar[m_current_tool].unloading_speed; + writer.retract(15, 5000) // just after ramming - always the same speed .retract(m_cooling_tube_retraction+m_cooling_tube_length/2.f-42, unloading_feedrate) .retract(15, unloading_feedrate*0.55f) .retract(12, unloading_feedrate*0.35f); @@ -882,6 +893,9 @@ void WipeTowerPrusaMM::toolchange_Unload( const float feedrate = std::hypot(e_dist, x_dist) / ((e_dist / speed) / 60.f); writer.cool(start_x+x_dist/2.f,start_x,e_dist/2.f,-e_dist/2.f, feedrate); } + + // let's wait is necessary + writer.wait(m_filpar[m_current_tool].delay); // we should be at the beginning of the cooling tube again - let's move to parking position: writer.retract(-m_cooling_tube_length/2.f+m_parking_pos_retraction-m_cooling_tube_retraction, 2000); @@ -957,15 +971,17 @@ void WipeTowerPrusaMM::toolchange_Load( float oldx = writer.x(); // the nozzle is in place to do the first wiping moves, we will remember the position float oldy = writer.y(); - // Load the filament while moving left / right, - // so the excess material will not create a blob at a single position. - float loading_feedrate = 3000.f; + // Load the filament while moving left / right, so the excess material will not create a blob at a single position. + float loading_speed = m_filpar[m_current_tool].loading_speed; // mm/s in e axis + float turning_point = ( oldx-xl < xr-oldx ? xr : xl ); + float dist = std::abs(oldx-turning_point); + float edist = m_parking_pos_retraction-50-2; // loading is 2mm shorter that previous retraction, 50mm reserved for acceleration/deceleration writer.append("; CP TOOLCHANGE LOAD\n") .suppress_preview() - .load_move_x(xr, 20, 1400) // Accelerate the filament loading - .load_move_x(xl,m_parking_pos_retraction-50-2,3000) // Fast phase - loading is 2mm shorter that previous retraction - .load_move_x(xr, 20, 1600) // Slowing down - .load_move_x(xl, 10, 1000) + .load_move_x(turning_point, 20, 60*std::hypot(dist,20.f)/20.f * loading_speed*0.3f) // Acceleration + .load_move_x(oldx,edist,60*std::hypot(dist,edist)/edist * loading_speed) // Fast phase + .load_move_x(turning_point, 20, 60*std::hypot(dist,20.f)/20.f * loading_speed*0.3f) // Slowing down + .load_move_x(oldx, 10, 60*std::hypot(dist,10.f)/10.f * loading_speed*0.1f) // Super slow .travel(oldx,oldy) .resume_preview(); diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 7f4cc8a30..893e4a125 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -209,9 +209,9 @@ public: { for (size_t i = 0; i < 4; ++ i) { // Extruder specific parameters. - m_material[i] = PLA; - m_temperature[i] = 0; - m_first_layer_temperature[i] = 0; + m_filpar[i].material = PLA; + m_filpar[i].temperature = 0; + m_filpar[i].first_layer_temperature = 0; } } @@ -225,11 +225,15 @@ public: // Set the extruder properties. - void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp) + void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed, + float unloading_speed, float delay) { - m_material[idx] = material; - m_temperature[idx] = temp; - m_first_layer_temperature[idx] = first_layer_temp; + m_filpar[idx].material = material; + m_filpar[idx].temperature = temp; + m_filpar[idx].first_layer_temperature = first_layer_temp; + m_filpar[idx].loading_speed = loading_speed; + m_filpar[idx].unloading_speed = unloading_speed; + m_filpar[idx].delay = delay; } @@ -336,14 +340,23 @@ private: float m_cooling_tube_retraction = 0.f; float m_cooling_tube_length = 0.f; float m_parking_pos_retraction = 0.f; - + float m_line_width = Nozzle_Diameter * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. float m_extrusion_flow = 0.038; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. + + struct FilamentParameters { + material_type material; + int temperature; + int first_layer_temperature; + float loading_speed; + float unloading_speed; + float delay; + }; + // Extruder specific parameters. - material_type m_material[4]; - int m_temperature[4]; - int m_first_layer_temperature[4]; + FilamentParameters m_filpar[4]; + // State of the wiper tower generator. unsigned int m_num_layer_changes = 0; // Layer change counter for the output statistics. diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 020af7610..447aec750 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -185,6 +185,9 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.filament_type.get_at(i).c_str()), this->config.temperature.get_at(i), - this->config.first_layer_temperature.get_at(i)); + this->config.first_layer_temperature.get_at(i), + this->config.filament_loading_speed.get_at(i), + this->config.filament_unloading_speed.get_at(i), + this->config.filament_toolchange_delay.get_at(i)); // When printing the first layer's wipe tower, the first extruder is expected to be active and primed. // Therefore the number of wipe sections at the wipe tower will be (m_tool_ordering.front().extruders-1) at the 1st layer. diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index cebb0832b..40b348fb8 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -451,19 +451,19 @@ PrintConfigDef::PrintConfigDef() def = this->add("filament_loading_speed", coFloats); def->label = _L("Loading speed"); def->tooltip = _L("Speed used for loading the filament on the wipe tower. "); - def->sidetext = _L("mm\u00B3/s"); + def->sidetext = _L("mm/s"); def->cli = "filament-loading-speed=f@"; def->min = 0; - def->default_value = new ConfigOptionFloats { 0. }; + def->default_value = new ConfigOptionFloats { 28. }; def = this->add("filament_unloading_speed", coFloats); def->label = _L("Unloading speed"); def->tooltip = _L("Speed used for unloading the filament on the wipe tower (does not affect " " initial part of unloading just after ramming). "); - def->sidetext = _L("mm\u00B3/s"); + def->sidetext = _L("mm/s"); def->cli = "filament-unloading-speed=f@"; def->min = 0; - def->default_value = new ConfigOptionFloats { 0. }; + def->default_value = new ConfigOptionFloats { 90. }; def = this->add("filament_toolchange_delay", coFloats); def->label = _L("Delay after unloading"); From 4058f002751477b677d4f547eed1af459d7ea7ee Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 5 Mar 2018 13:53:49 +0100 Subject: [PATCH 25/81] Added print head moves after ramming and removed one unnecessary diagonal move --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 25 ++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index bc93a938e..f87db98a7 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -675,11 +675,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, m_filpar[m_current_tool].temperature); if (last_change_in_layer) // draw perimeter line - writer.travel(m_wipe_tower_pos, 7000) - .extrude(m_wipe_tower_pos + xy(0, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width), 3200) - .extrude(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width)) - .extrude(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, 0)) - .extrude(m_wipe_tower_pos); + writer.travel(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width), 7000) + .extrude(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, 0), 3200) + .extrude(m_wipe_tower_pos) + .extrude(m_wipe_tower_pos + xy(0, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width)) + .extrude(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width)); // Reset the extruder current to a normal value. writer.set_extruder_trimpot(550) @@ -856,12 +856,21 @@ void WipeTowerPrusaMM::toolchange_Unload( //writer.retract(15, 5000).retract(50, 5400).retract(15, 3000).retract(12, 2000); // Pull the filament end to the BEGINNING of the cooling tube - float unloading_feedrate = 60.f * m_filpar[m_current_tool].unloading_speed; + /*float unloading_feedrate = 60.f * m_filpar[m_current_tool].unloading_speed; writer.retract(15, 5000) // just after ramming - always the same speed .retract(m_cooling_tube_retraction+m_cooling_tube_length/2.f-42, unloading_feedrate) .retract(15, unloading_feedrate*0.55f) - .retract(12, unloading_feedrate*0.35f); + .retract(12, unloading_feedrate*0.35f);*/ + // Pull the filament end to the BEGINNING of the cooling tube while still moving the print head + float oldx = writer.x(); + float turning_point = (!m_left_to_right ? std::max(xl,oldx-15.f) : std::min(xr,oldx+15.f) ); // so it's not too far + float xdist = std::abs(oldx-turning_point); + float edist = -(m_cooling_tube_retraction+m_cooling_tube_length/2.f-42); + writer.load_move_x(turning_point,-15 , 60.f * std::hypot(xdist,15)/15 * 83 ) // fixed speed after ramming + .load_move_x(oldx ,edist , 60.f * std::hypot(xdist,edist)/edist * m_filpar[m_current_tool].unloading_speed ) + .load_move_x(turning_point,-15 , 60.f * std::hypot(xdist,15)/15 * m_filpar[m_current_tool].unloading_speed*0.55f ) + .load_move_x(oldx ,-12 , 60.f * std::hypot(xdist,12)/12 * m_filpar[m_current_tool].unloading_speed*0.35f ); if (new_temperature != 0) // Set the extruder temperature, but don't wait. writer.set_extruder_temp(new_temperature, false); @@ -870,7 +879,7 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.suppress_preview(); writer.travel(writer.x(), writer.y() + y_step); const float start_x = writer.x(); - const float turning_point = ( xr-start_x > start_x-xl ? xr : xl ); + turning_point = ( xr-start_x > start_x-xl ? xr : xl ); const float max_x_dist = 2*std::abs(start_x-turning_point); const unsigned int N = 4 + std::max(0,(m_par.cooling_time[m_current_tool]-14)/3); float time = m_par.cooling_time[m_current_tool] / N; From 6c223c2f8464f92462bdaadc70dbee822b69560f Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 5 Mar 2018 16:51:31 +0100 Subject: [PATCH 26/81] Fixed cooling time calculation, removed unnecessary diagonal moves, fixed 'stringing' on start and end of narrower wipe tower layers --- xs/src/libslic3r/GCode/WipeTower.hpp | 2 +- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index 289e8e122..e193fd972 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -17,7 +17,7 @@ public: struct xy { xy(float x = 0.f, float y = 0.f) : x(x), y(y) {} - xy(xy& pos,float xp,float yp) : x(pos.x+xp), y(pos.y+yp) {} + xy(const xy& pos,float xp,float yp) : x(pos.x+xp), y(pos.y+yp) {} xy operator+(const xy &rhs) const { xy out(*this); out.x += rhs.x; out.y += rhs.y; return out; } xy operator-(const xy &rhs) const { xy out(*this); out.x -= rhs.x; out.y -= rhs.y; return out; } xy& operator+=(const xy &rhs) { x += rhs.x; y += rhs.y; return *this; } diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index f87db98a7..8e548a4a4 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -93,8 +93,8 @@ public: float x() const { return m_current_pos.x; } float y() const { return m_current_pos.y; } const WipeTower::xy& pos() const { return m_current_pos; } - const WipeTower::xy start_pos_rotated() const { return m_start_pos.rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } - const WipeTower::xy pos_rotated() const { return m_current_pos.rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } + const WipeTower::xy start_pos_rotated() const { return WipeTower::xy(m_start_pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } + const WipeTower::xy pos_rotated() const { return WipeTower::xy(m_current_pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } float elapsed_time() const { return m_elapsed_time; } // Extrude with an explicitely provided amount of extrusion. @@ -882,7 +882,7 @@ void WipeTowerPrusaMM::toolchange_Unload( turning_point = ( xr-start_x > start_x-xl ? xr : xl ); const float max_x_dist = 2*std::abs(start_x-turning_point); const unsigned int N = 4 + std::max(0,(m_par.cooling_time[m_current_tool]-14)/3); - float time = m_par.cooling_time[m_current_tool] / N; + float time = m_par.cooling_time[m_current_tool] / float(N); i = 0; while (i Date: Tue, 6 Mar 2018 19:14:12 +0100 Subject: [PATCH 27/81] Last wipe on layer accounts of border and sparse infill (ugly, yet working) --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 105 +++++++++++++------- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 8 +- 2 files changed, 76 insertions(+), 37 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 8e548a4a4..d6e3013e2 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -613,7 +613,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo box_coordinates cleaning_box( m_wipe_tower_pos + xy(m_perimeter_width / 2.f, m_perimeter_width / 2.f), m_wipe_tower_width - m_perimeter_width, - (tool != (unsigned int)(-1) ? m_layer_info->depth : m_wipe_tower_depth-m_perimeter_width)); + (tool != (unsigned int)(-1) ? /*m_layer_info->depth*/wipe_area+m_depth_traversed-0.5*m_perimeter_width + : m_wipe_tower_depth-m_perimeter_width)); PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow) @@ -1049,11 +1050,10 @@ void WipeTowerPrusaMM::toolchange_Wipe( writer.extrude(xr - (i % 4 == 0 ? 0 : 1.5*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff); else writer.extrude(xl + (i % 4 == 1 ? 0 : 1.5*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff); - - /*if ((m_current_shape == SHAPE_NORMAL) ? // in case next line would not fit - (writer.y() > cleaning_box.lu.y - m_perimeter_width * 1.5f) : - (writer.y() < cleaning_box.ld.y + m_perimeter_width * 1.5f)) - break;*/ + + if (writer.y()+EPSILON > cleaning_box.lu.y-0.5f*m_perimeter_width) + break; // in case next line would not fit + traversed_x -= writer.x(); x_to_wipe -= fabs(traversed_x); if (x_to_wipe < WT_EPSILON) { @@ -1218,13 +1218,16 @@ void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsi m_line_width * m_par.ramming_line_width_multiplicator[old_tool], layer_height_par); depth = (int(length_to_extrude / width) + 1) * (m_line_width * m_par.ramming_line_width_multiplicator[old_tool] * m_par.ramming_step_multiplicator[old_tool]); - length_to_extrude = width*((length_to_extrude / width)-int(length_to_extrude / width)) - width; - length_to_extrude += volume_to_length(m_par.wipe_volumes[old_tool][new_tool], m_line_width, layer_height_par); - length_to_extrude = std::max(length_to_extrude,0.f); - depth += (int(length_to_extrude / width) + 1) * m_line_width; - depth *= m_extra_spacing; + float ramming_depth = depth; + length_to_extrude = width*((length_to_extrude / width)-int(length_to_extrude / width)) - width; + float first_wipe_line = -length_to_extrude; + length_to_extrude += volume_to_length(m_par.wipe_volumes[old_tool][new_tool], m_line_width, layer_height_par); + length_to_extrude = std::max(length_to_extrude,0.f); - m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool, depth)); + depth += (int(length_to_extrude / width) + 1) * m_line_width; + depth *= m_extra_spacing; + + m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool, depth, ramming_depth,first_wipe_line)); } @@ -1252,31 +1255,27 @@ void WipeTowerPrusaMM::plan_tower() } } - -void WipeTowerPrusaMM::make_wipe_tower_square() +void WipeTowerPrusaMM::save_on_last_wipe() { - const float width = m_wipe_tower_width - 3 * m_perimeter_width; - const float depth = m_wipe_tower_depth - m_perimeter_width; - // area that we actually print into is width*depth - float side = sqrt(depth * width); + for (m_layer_info=m_plan.begin();m_layer_infoz, m_layer_info->height, 0, m_layer_info->z == m_plan.front().z, m_layer_info->z == m_plan.back().z); + if (m_layer_info->tool_changes.size()==0) // we have no way to save anything on an empty layer + continue; - m_wipe_tower_width = side + 3 * m_perimeter_width; - m_wipe_tower_depth = side + 2 * m_perimeter_width; - // For all layers, find how depth changed and update all toolchange depths - for (auto &lay : m_plan) - { - side = sqrt(lay.depth * width); - float width_ratio = width / side; + for (const auto &toolchange : m_layer_info->tool_changes) + tool_change(toolchange.new_tool, false, PURPOSE_EXTRUDE); - //lay.extra_spacing = width_ratio; - for (auto &tch : lay.tool_changes) - tch.required_depth *= width_ratio; - } + float width = m_wipe_tower_width - 3*m_perimeter_width; // width we draw into + float length_to_save = 2*(m_wipe_tower_width+m_wipe_tower_depth) + (!layer_finished() ? finish_layer(PURPOSE_EXTRUDE).total_extrusion_length_in_plane() : 0.f); + float length_to_wipe = volume_to_length(m_par.wipe_volumes[m_layer_info->tool_changes.back().old_tool][m_layer_info->tool_changes.back().new_tool], + m_line_width,m_layer_info->height) - m_layer_info->tool_changes.back().first_wipe_line - length_to_save; - plan_tower(); // propagates depth downwards again (width has changed) - for (auto& lay : m_plan) // depths set, now the spacing - lay.extra_spacing = lay.depth / lay.toolchanges_depth(); + length_to_wipe = std::max(length_to_wipe,0.f); + float depth_to_wipe = m_line_width * (std::floor(length_to_wipe/width) + ( length_to_wipe > 0.f ? 1.f : 0.f ) ) * m_extra_spacing; + //depth += (int(length_to_extrude / width) + 1) * m_line_width; + m_layer_info->tool_changes.back().required_depth = m_layer_info->tool_changes.back().ramming_depth + depth_to_wipe; + } } @@ -1285,14 +1284,20 @@ void WipeTowerPrusaMM::make_wipe_tower_square() void WipeTowerPrusaMM::generate(std::vector> &result) { if (m_plan.empty()) return; - else m_layer_info = m_plan.begin(); - m_extra_spacing = 1.f; + m_extra_spacing = 1.f; plan_tower(); + for (int i=0;i<5;++i) { + save_on_last_wipe(); + plan_tower(); + } + if (peters_wipe_tower) make_wipe_tower_square(); + m_layer_info = m_plan.begin(); + std::vector layer_result; for (auto layer : m_plan) { @@ -1306,8 +1311,6 @@ void WipeTowerPrusaMM::generate(std::vectordepth < m_wipe_tower_depth - m_perimeter_width) m_y_shift = (m_wipe_tower_depth-m_layer_info->depth-m_perimeter_width)/2.f; - - for (const auto &toolchange : layer.tool_changes) layer_result.emplace_back(tool_change(toolchange.new_tool, false, WipeTower::PURPOSE_EXTRUDE)); @@ -1336,4 +1339,34 @@ void WipeTowerPrusaMM::generate(std::vector Date: Wed, 7 Mar 2018 08:55:53 +0100 Subject: [PATCH 28/81] Supressed preview on unloadingmoves --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index d6e3013e2..57135475a 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -868,10 +868,12 @@ void WipeTowerPrusaMM::toolchange_Unload( float turning_point = (!m_left_to_right ? std::max(xl,oldx-15.f) : std::min(xr,oldx+15.f) ); // so it's not too far float xdist = std::abs(oldx-turning_point); float edist = -(m_cooling_tube_retraction+m_cooling_tube_length/2.f-42); - writer.load_move_x(turning_point,-15 , 60.f * std::hypot(xdist,15)/15 * 83 ) // fixed speed after ramming + writer.suppress_preview() + .load_move_x(turning_point,-15 , 60.f * std::hypot(xdist,15)/15 * 83 ) // fixed speed after ramming .load_move_x(oldx ,edist , 60.f * std::hypot(xdist,edist)/edist * m_filpar[m_current_tool].unloading_speed ) .load_move_x(turning_point,-15 , 60.f * std::hypot(xdist,15)/15 * m_filpar[m_current_tool].unloading_speed*0.55f ) - .load_move_x(oldx ,-12 , 60.f * std::hypot(xdist,12)/12 * m_filpar[m_current_tool].unloading_speed*0.35f ); + .load_move_x(oldx ,-12 , 60.f * std::hypot(xdist,12)/12 * m_filpar[m_current_tool].unloading_speed*0.35f ) + .resume_preview(); if (new_temperature != 0) // Set the extruder temperature, but don't wait. writer.set_extruder_temp(new_temperature, false); From 76aa134f662ba760d01105d4dc15dbf097cf259a Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 7 Mar 2018 11:44:47 +0100 Subject: [PATCH 29/81] Ramming lines that would end unsupported are made longer to reach to the edge --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 79 ++++++++++++++++----- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 2 +- 2 files changed, 63 insertions(+), 18 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 57135475a..250bad1d2 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -790,8 +790,8 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.append("; CP TOOLCHANGE UNLOAD\n"); - const float line_width = m_line_width * m_par.ramming_line_width_multiplicator[m_current_tool]; // desired ramming line thickness - const float y_step = line_width * m_par.ramming_step_multiplicator[m_current_tool] * m_extra_spacing; // spacing between lines in mm + const float line_width = m_line_width * m_par.ramming_line_width_multiplicator[m_current_tool]; // desired ramming line thickness + const float y_step = line_width * m_par.ramming_step_multiplicator[m_current_tool] * m_extra_spacing; // spacing between lines in mm unsigned i = 0; // iterates through ramming_speed m_left_to_right = true; // current direction of ramming @@ -800,14 +800,54 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.travel(xl, cleaning_box.ld.y + m_depth_traversed + y_step/2.f ); // move to starting position - while (i < m_par.ramming_speed[m_current_tool].size()) - { - const float x = volume_to_length(m_par.ramming_speed[m_current_tool][i] * 0.25f, line_width, m_layer_height); - const float e = m_par.ramming_speed[m_current_tool][i] * 0.25f / Filament_Area; // transform volume per sec to E move; - const float dist = std::min(x - e_done, remaining); // distance to travel for either the next 0.25s, or to the next turnaround - const float actual_time = dist/x * 0.25; - writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), std::hypot(dist, e * (dist / x)) / (actual_time / 60.)); - remaining -= dist; + // if the ending point of the ram would end up in mid air, align it with the end of the wipe tower: + if (m_layer_info > m_plan.begin() && m_layer_info < m_plan.end()) { + + // this is y of the center of first supported line + float sparse_beginning_y = m_wipe_tower_pos.y + + ((m_layer_info-1)->depth - (m_layer_info-1)->toolchanges_depth()); + + //debugging: + /* float oldx = writer.x(); + float oldy = writer.y(); + writer.travel(xr,sparse_beginning_y); + writer.extrude(xr+5,writer.y()); + writer.travel(oldx,oldy);*/ + + float sum_of_depths = 0.f; + for (const auto& tch : m_layer_info->tool_changes) { // let's find this toolchange + if (tch.old_tool == m_current_tool) { + sum_of_depths += tch.ramming_depth; + float ramming_end_y = m_wipe_tower_pos.y + sum_of_depths; + ramming_end_y -= (y_step/m_extra_spacing-m_line_width) / 2.f; // center of final ramming line + + // debugging: + /*float oldx = writer.x(); + float oldy = writer.y(); + writer.travel(xl,ramming_end_y); + writer.extrude(xl-15,writer.y()); + writer.travel(oldx,oldy);*/ + + if (ramming_end_y < sparse_beginning_y) { + writer.extrude(xl + tch.first_wipe_line-1.f*m_perimeter_width-0.1f,writer.y()); + writer.travel(xl + tch.first_wipe_line-1.f*m_perimeter_width,writer.y()); + remaining -= tch.first_wipe_line-1.f*m_perimeter_width; + } + break; + } + sum_of_depths += tch.required_depth; + } + } + + // now the ramming itself: + while (i < m_par.ramming_speed[m_current_tool].size()) + { + const float x = volume_to_length(m_par.ramming_speed[m_current_tool][i] * 0.25f, line_width, m_layer_height); + const float e = m_par.ramming_speed[m_current_tool][i] * 0.25f / Filament_Area; // transform volume per sec to E move; + const float dist = std::min(x - e_done, remaining); // distance to travel for either the next 0.25s, or to the next turnaround + const float actual_time = dist/x * 0.25; + writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), std::hypot(dist, e * (dist / x)) / (actual_time / 60.)); + remaining -= dist; if (remaining < WT_EPSILON) { // we reached a turning point writer.travel(writer.x(), writer.y() + y_step, 7200); @@ -1030,15 +1070,23 @@ void WipeTowerPrusaMM::toolchange_Wipe( float wipe_coeff = m_is_first_layer ? 0.5f : 1.f; const float& xl = cleaning_box.ld.x; const float& xr = cleaning_box.rd.x; - - // DEBUGGING: The function makes sure it always wipes at least the ordered volume, even if it means violating - // the perimeter. This can later be removed and simply wipe until the end of the assigned area. - // (Variables x_to_wipe and traversed_x) + + + // Variables x_to_wipe and traversed_x are here to be able to make sure it always wipes at least + // the ordered volume, even if it means violating the box. This can later be removed and simply + // wipe until the end of the assigned area. float x_to_wipe = volume_to_length(wipe_volume, m_line_width, m_layer_height); float dy = m_extra_spacing*m_line_width; float wipe_speed = 1600.f; + // if there is less than 2.5*m_perimeter_width to the edge, advance straightaway (there is likely a blob anyway) + if ((m_left_to_right ? xr-writer.x() : writer.x()-xl) < 2.5f*m_perimeter_width) { + writer.travel((m_left_to_right ? xr-m_perimeter_width : xl+m_perimeter_width),writer.y()+dy); + m_left_to_right = !m_left_to_right; + } + + // now the wiping itself: for (int i = 0; true; ++i) { if (i!=0) { if (wipe_speed < 1610.f) wipe_speed = 1800.f; @@ -1067,9 +1115,6 @@ void WipeTowerPrusaMM::toolchange_Wipe( m_left_to_right = !m_left_to_right; } writer.set_extrusion_flow(m_extrusion_flow); // Reset the extrusion flow. - - // Wipe the nozzle - } diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 16baa2b37..1b6b94308 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -448,7 +448,7 @@ private: }; std::vector m_plan; // Stores information about all layers and toolchanges for the future wipe tower (filled by plan_toolchange(...)) - std::vector::iterator m_layer_info; + std::vector::iterator m_layer_info = m_plan.end(); // Returns gcode for wipe tower brim From f5cf181372116857524511ec22b8d770cbf45e50 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 7 Mar 2018 15:34:12 +0100 Subject: [PATCH 30/81] Sparse infill repositioned always to the same side --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 33 +++++++++++++-------- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 1 + 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 250bad1d2..fcb651423 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -622,7 +622,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) - .set_y_shift(m_y_shift) + .set_y_shift(m_y_shift + (tool!=(unsigned int)(-1) && (m_layer_parity && !peters_wipe_tower) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f)) .append(";--------------------\n" "; CP TOOLCHANGE START\n") .comment_with_value(" toolchange #", m_num_tool_changes) @@ -676,7 +676,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, m_filpar[m_current_tool].temperature); if (last_change_in_layer) // draw perimeter line - writer.travel(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width), 7000) + writer.set_y_shift(m_y_shift) + .travel(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width), 7000) .extrude(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, 0), 3200) .extrude(m_wipe_tower_pos) .extrude(m_wipe_tower_pos + xy(0, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width)) @@ -801,11 +802,15 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.travel(xl, cleaning_box.ld.y + m_depth_traversed + y_step/2.f ); // move to starting position // if the ending point of the ram would end up in mid air, align it with the end of the wipe tower: - if (m_layer_info > m_plan.begin() && m_layer_info < m_plan.end()) { + if (m_layer_info > m_plan.begin() && m_layer_info < m_plan.end() && (m_layer_info-1!=m_plan.begin() || !m_par.adhesion )) { - // this is y of the center of first supported line - float sparse_beginning_y = m_wipe_tower_pos.y - + ((m_layer_info-1)->depth - (m_layer_info-1)->toolchanges_depth()); + // this is y of the center of previous sparse infill border + float sparse_beginning_y = m_wipe_tower_pos.y; + if (m_layer_parity) + sparse_beginning_y += ((m_layer_info-1)->depth - (m_layer_info-1)->toolchanges_depth()) + - ((m_layer_info)->depth-(m_layer_info)->toolchanges_depth()) ; + else + sparse_beginning_y += (m_layer_info-1)->toolchanges_depth() + m_perimeter_width; //debugging: /* float oldx = writer.x(); @@ -828,9 +833,10 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.extrude(xl-15,writer.y()); writer.travel(oldx,oldy);*/ - if (ramming_end_y < sparse_beginning_y) { - writer.extrude(xl + tch.first_wipe_line-1.f*m_perimeter_width-0.1f,writer.y()); - writer.travel(xl + tch.first_wipe_line-1.f*m_perimeter_width,writer.y()); + if ( (m_layer_parity && ramming_end_y < sparse_beginning_y - 0.5f*m_perimeter_width ) || + (!m_layer_parity && ramming_end_y > sparse_beginning_y + 0.5f*m_perimeter_width ) ) + { + writer.extrude(xl + tch.first_wipe_line-1.f*m_perimeter_width,writer.y()); remaining -= tch.first_wipe_line-1.f*m_perimeter_width; } break; @@ -1132,7 +1138,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) - .set_y_shift(m_y_shift) + .set_y_shift(m_y_shift - (m_layer_parity && !peters_wipe_tower ? m_layer_info->toolchanges_depth() : 0.f)) .append(";--------------------\n" "; CP EMPTY GRID START\n") // m_num_layer_changes is incremented by set_z, so it is 1 based. @@ -1353,8 +1359,11 @@ void WipeTowerPrusaMM::generate(std::vectordepth < m_wipe_tower_depth - m_perimeter_width) m_y_shift = (m_wipe_tower_depth-m_layer_info->depth-m_perimeter_width)/2.f; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 1b6b94308..0906d334e 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -336,6 +336,7 @@ private: size_t m_max_color_changes = 0; // Maximum number of color changes per layer. bool m_is_first_layer = false;// Is this the 1st layer of the print? If so, print the brim around the waste tower. bool m_is_last_layer = false;// Is this the last layer of this waste tower? + bool m_layer_parity = false; // G-code generator parameters. float m_zhop = 0.5f; From 8340a71f885eba943b45a0e08ba5182061353ed6 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 8 Mar 2018 16:44:52 +0100 Subject: [PATCH 31/81] Lots of unnecessary code removed, minor refactoring changes --- xs/src/libslic3r/GCode/WipeTower.hpp | 8 +- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 533 +++++++------------- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 12 +- xs/src/libslic3r/Print.cpp | 4 +- 4 files changed, 180 insertions(+), 377 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index e193fd972..36cebeb84 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -126,17 +126,15 @@ public: const std::vector &tools, // If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower. // If false, the last priming are will be large enough to wipe the last extruder sufficiently. - bool last_wipe_inside_wipe_tower, - // May be used by a stand alone post processor. - Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0; + bool last_wipe_inside_wipe_tower) = 0; // Returns gcode for toolchange and the end position. // if new_tool == -1, just unload the current filament over the wipe tower. - virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0; + virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer) = 0; // Close the current wipe tower layer with a perimeter and possibly fill the unfilled space with a zig-zag. // Call this method only if layer_finished() is false. - virtual ToolChangeResult finish_layer(Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0; + virtual ToolChangeResult finish_layer() = 0; // Is the current layer finished? A layer is finished if either the wipe tower is finished, or // the wipe tower has been completely covered by the tool change extrusions, diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index fcb651423..39ccc7155 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -4,8 +4,8 @@ TODO LIST --------- 1. cooling moves - DONE -2. priming extrusions - DONE (fixed wiping volume so far) -3. account for perimeter and finish_layer extrusions and subtract it from last wipe +2. account for perimeter and finish_layer extrusions and subtract it from last wipe - DONE +3. priming extrusions (last wipe must clear the color) 4. Peter's wipe tower - layer's are not exactly square 5. Peter's wipe tower - variable width for higher levels 6. Peter's wipe tower - make sure it is not too sparse (apply max_bridge_distance and make last wipe longer) @@ -53,7 +53,7 @@ public: m_elapsed_time(0.f) {} Writer& set_initial_position(const WipeTower::xy &pos) { - m_start_pos = pos; + m_start_pos = WipeTower::xy(pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); m_current_pos = pos; return *this; } @@ -93,7 +93,7 @@ public: float x() const { return m_current_pos.x; } float y() const { return m_current_pos.y; } const WipeTower::xy& pos() const { return m_current_pos; } - const WipeTower::xy start_pos_rotated() const { return WipeTower::xy(m_start_pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } + const WipeTower::xy start_pos_rotated() const { return m_start_pos; } const WipeTower::xy pos_rotated() const { return WipeTower::xy(m_current_pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); } float elapsed_time() const { return m_elapsed_time; } @@ -169,6 +169,27 @@ public: Writer& extrude(const WipeTower::xy &dest, const float f = 0.f) { return extrude(dest.x, dest.y, f); } + + Writer& rectangle(const WipeTower::xy& ld,float width,float height,const float f = 0.f) + { + WipeTower::xy corners[4]; + corners[0] = ld; + corners[1] = WipeTower::xy(ld,width,0.f); + corners[2] = WipeTower::xy(ld,width,height); + corners[3] = WipeTower::xy(ld,0.f,height); + int index_of_closest = (x()-ld.x < ld.x+width-x() ? 0 : 1); + if (y()-ld.y > ld.y+height-x()) // closer to the top + index_of_closest += (index_of_closest==0 ? 3 : 1); + travel(corners[index_of_closest].x,y(),f); // travel to the closest corner + travel(x(),corners[index_of_closest].y,f); + int i = index_of_closest; + do { + ++i; + if (i==4) i=0; + this->extrude(corners[i]); + } while (i != index_of_closest); + return (*this); + } Writer& load(float e, float f = 0.f) { @@ -449,29 +470,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( const std::vector &tools, // If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower. // If false, the last priming are will be large enough to wipe the last extruder sufficiently. - bool last_wipe_inside_wipe_tower, - // May be used by a stand alone post processor. - Purpose purpose) + bool last_wipe_inside_wipe_tower) { this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false); - - // Calculate the amount of wipe over the wipe tower brim following the prime, decrease wipe_area - // with the amount of material extruded over the brim. - // DOESN'T MAKE SENSE NOW, wipe tower dimensions are still unknown at this point - /*{ - // Simulate the brim extrusions, summ the length of the extrusion. - float e_length = this->tool_change(0, false, PURPOSE_EXTRUDE).total_extrusion_length_in_plane(); - // Shrink wipe_area by the amount of extrusion extruded by the finish_layer(). - // Y stepping of the wipe extrusions. - float dy = m_line_width; - // Number of whole wipe lines, that would be extruded to wipe as much material as the finish_layer(). - // Minimum wipe area is 5mm wide. - //FIXME calculate the purge_lines_width precisely. - float purge_lines_width = 1.3f; - wipe_area = std::max(5.f, m_wipe_area - float(floor(e_length / m_wipe_tower_width)) * dy - purge_lines_width); - } - - this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false);*/ this->m_num_layer_changes = 0; this->m_current_tool = tools.front(); @@ -502,28 +503,26 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower); writer.append(buf); - if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { - for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) { - unsigned int tool = tools[idx_tool]; - m_left_to_right = true; - toolchange_Change(writer, tool, m_filpar[tool].material); // Select the tool, set a speed override for soluble and flex materials. - toolchange_Load(writer, cleaning_box); // Prime the tool. - if (idx_tool + 1 == tools.size()) { - // Last tool should not be unloaded, but it should be wiped enough to become of a pure color. - toolchange_Wipe(writer, cleaning_box, 20.f); - } else { - // Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool. - //writer.travel(writer.x(), writer.y() + m_perimeter_width, 7200); - toolchange_Wipe(writer, cleaning_box , 5.f); - box_coordinates box = cleaning_box; - box.translate(0.f, writer.y() - cleaning_box.ld.y + m_perimeter_width); - toolchange_Unload(writer, box , m_filpar[m_current_tool].material, m_filpar[tools[idx_tool + 1]].first_layer_temperature); - cleaning_box.translate(prime_section_width, 0.f); - writer.travel(cleaning_box.ld, 7200); - } - ++ m_num_tool_changes; - } - } + for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) { + unsigned int tool = tools[idx_tool]; + m_left_to_right = true; + toolchange_Change(writer, tool, m_filpar[tool].material); // Select the tool, set a speed override for soluble and flex materials. + toolchange_Load(writer, cleaning_box); // Prime the tool. + if (idx_tool + 1 == tools.size()) { + // Last tool should not be unloaded, but it should be wiped enough to become of a pure color. + toolchange_Wipe(writer, cleaning_box, 20.f); + } else { + // Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool. + //writer.travel(writer.x(), writer.y() + m_perimeter_width, 7200); + toolchange_Wipe(writer, cleaning_box , 5.f); + box_coordinates box = cleaning_box; + box.translate(0.f, writer.y() - cleaning_box.ld.y + m_perimeter_width); + toolchange_Unload(writer, box , m_filpar[m_current_tool].material, m_filpar[tools[idx_tool + 1]].first_layer_temperature); + cleaning_box.translate(prime_section_width, 0.f); + writer.travel(cleaning_box.ld, 7200); + } + ++ m_num_tool_changes; + } // Reset the extruder current to a normal value. writer.set_extruder_trimpot(550) @@ -534,8 +533,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( ";------------------\n" "\n\n"); - // Force m_idx_tool_change_in_layer to -1, so that tool_change() will know to extrude the wipe tower brim. - ///m_idx_tool_change_in_layer = (unsigned int)(-1); + // so that tool_change() will know to extrude the wipe tower brim: m_print_brim = true; ToolChangeResult result; @@ -549,48 +547,13 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( return result; } -WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, bool last_in_layer, Purpose purpose) +WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, bool last_in_layer) { - // Either it is the last tool unload, - // or there must be a nonzero wipe tower partitions available. -// assert(tool < 0 || it_layer_tools->wipe_tower_partitions > 0); + if ( m_print_brim ) + return toolchange_Brim(); - if ( m_print_brim ) { - ///if (m_idx_tool_change_in_layer == (unsigned int)(-1)) { - // First layer, prime the extruder. - return toolchange_Brim(purpose); - } float wipe_area = 0.f; - {/*if (++ m_idx_tool_change_in_layer < (unsigned int)m_max_color_changes && last_in_layer) { - // This tool_change() call will be followed by a finish_layer() call. - // Try to shrink the wipe_area to save material, as less than usual wipe is required - // if this step is foolowed by finish_layer() extrusions wiping the same extruder. - for (size_t iter = 0; iter < 3; ++ iter) { - // Simulate the finish_layer() extrusions, summ the length of the extrusion. - float e_length = 0.f; - { - unsigned int old_idx_tool_change = m_idx_tool_change_in_layer; - float old_wipe_start_y = m_current_wipe_start_y; - m_current_wipe_start_y += wipe_area; - e_length = this->finish_layer(PURPOSE_EXTRUDE).total_extrusion_length_in_plane(); - m_idx_tool_change_in_layer = old_idx_tool_change; - m_current_wipe_start_y = old_wipe_start_y; - } - // Shrink wipe_area by the amount of extrusion extruded by the finish_layer(). - // Y stepping of the wipe extrusions. - float dy = m_line_width; - // Number of whole wipe lines, that would be extruded to wipe as much material as the finish_layer(). - float num_lines_extruded = floor(e_length / m_wipe_tower_width); - // Minimum wipe area is 5mm wide. - wipe_area = m_wipe_area - num_lines_extruded * dy; - if (wipe_area < 5.) { - wipe_area = 5.; - break; - } - } - }*/} - bool last_change_in_layer = false; float wipe_volume = 0.f; @@ -622,7 +585,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) - .set_y_shift(m_y_shift + (tool!=(unsigned int)(-1) && (m_layer_parity && !peters_wipe_tower) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f)) + .set_y_shift(m_y_shift + (tool!=(unsigned int)(-1) && (m_current_shape == SHAPE_REVERSED && !peters_wipe_tower) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f)) .append(";--------------------\n" "; CP TOOLCHANGE START\n") .comment_with_value(" toolchange #", m_num_tool_changes) @@ -631,71 +594,46 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .speed_override(100); xy initial_position = cleaning_box.ld + WipeTower::xy(0.f,m_depth_traversed); + writer.set_initial_position(initial_position); - if (purpose == PURPOSE_MOVE_TO_TOWER || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { - // Scaffold leaks terribly, reduce leaking by a full retract when going to the wipe tower. - float initial_retract = ((m_filpar[m_current_tool].material == SCAFF) ? 1.f : 0.5f) * m_retract; - writer // Lift for a Z hop. - .z_hop(m_zhop, 7200) - // Additional retract on move to tower. - .retract(initial_retract, 3600) - // Move to a starting position, one perimeter width inside the cleaning box. - .travel(initial_position, 7200) - // Unlift for a Z hop. - .z_hop_reset(7200) - // Additional retract on move to tower. - .load(initial_retract, 3600) - .load(m_retract, 1500); - } else { - // Already at the initial position. - writer.set_initial_position(initial_position); - } // adds tag for analyzer char buf[32]; sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower); writer.append(buf); - if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { - // Increase the extruder driver current to allow fast ramming. - writer.set_extruder_trimpot(750); - - // 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. - toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, - m_is_first_layer ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature); - toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials. - toolchange_Load(writer, cleaning_box); - toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area. + // Increase the extruder driver current to allow fast ramming. + writer.set_extruder_trimpot(750); - // Always wipe the nozzle with a long wipe to reduce stringing when moving away from the wipe tower. - /*box_coordinates box = cleaning_box; - writer.travel(box.ru, 7200) - .travel(box.lu);*/ - } else - toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, m_filpar[m_current_tool].temperature); + // 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. + toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, + m_is_first_layer ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature); + toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials. + toolchange_Load(writer, cleaning_box); + toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area. + } else + toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, m_filpar[m_current_tool].temperature); - if (last_change_in_layer) // draw perimeter line - writer.set_y_shift(m_y_shift) - .travel(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width), 7000) - .extrude(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, 0), 3200) - .extrude(m_wipe_tower_pos) - .extrude(m_wipe_tower_pos + xy(0, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width)) - .extrude(m_wipe_tower_pos + xy(peters_wipe_tower ? m_layer_info->depth + 3*m_perimeter_width : m_wipe_tower_width, peters_wipe_tower ? m_wipe_tower_depth : m_layer_info->depth + m_perimeter_width)); + if (last_change_in_layer) {// draw perimeter line + writer.set_y_shift(m_y_shift); + if (peters_wipe_tower) + writer.rectangle(m_wipe_tower_pos,m_layer_info->depth + 3*m_perimeter_width,m_wipe_tower_depth); + else + writer.rectangle(m_wipe_tower_pos,m_wipe_tower_width, m_layer_info->depth + m_perimeter_width); + } - // Reset the extruder current to a normal value. - writer.set_extruder_trimpot(550) - .feedrate(6000) - .flush_planner_queue() - .reset_extruder() - .append("; CP TOOLCHANGE END\n" - ";------------------\n" - "\n\n"); + // Reset the extruder current to a normal value. + writer.set_extruder_trimpot(550) + .feedrate(6000) + .flush_planner_queue() + .reset_extruder() + .append("; CP TOOLCHANGE END\n" + ";------------------\n" + "\n\n"); - ++ m_num_tool_changes; - //m_current_wipe_start_y += wipe_area; - m_depth_traversed += wipe_area; - } + ++ m_num_tool_changes; + m_depth_traversed += wipe_area; ToolChangeResult result; result.print_z = this->m_z_pos; @@ -708,7 +646,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo return result; } -WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, bool sideOnly, float y_offset) +WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, float y_offset) { const box_coordinates wipeTower_box( m_wipe_tower_pos, @@ -725,46 +663,33 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b "; CP WIPE TOWER FIRST LAYER BRIM START\n"); xy initial_position = wipeTower_box.lu - xy(m_perimeter_width * 6.f, 0); - - if (purpose == PURPOSE_MOVE_TO_TOWER || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) - // Move with Z hop. - writer.z_hop(m_zhop, 7200) - .travel(initial_position, 6000) - .z_hop_reset(7200); - else - writer.set_initial_position(initial_position); + writer.set_initial_position(initial_position); // adds tag for analyzer char buf[32]; sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower); - writer.append(buf); + writer.append(buf) + .extrude_explicit(wipeTower_box.ld - xy(m_perimeter_width * 6.f, 0), // Prime the extruder left of the wipe tower. + 1.5f * m_extrusion_flow * (wipeTower_box.lu.y - wipeTower_box.ld.y), 2400); - if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { + // The tool is supposed to be active and primed at the time when the wipe tower brim is extruded. + // Extrude 4 rounds of a brim around the future wipe tower. + box_coordinates box(wipeTower_box); + box.expand(m_perimeter_width); + for (size_t i = 0; i < 4; ++ i) { + writer.travel (box.ld, 7000) + .extrude(box.lu, 2100).extrude(box.ru) + .extrude(box.rd ).extrude(box.ld); + box.expand(m_perimeter_width); + } - writer.extrude_explicit(wipeTower_box.ld - xy(m_perimeter_width * 6.f, 0), // Prime the extruder left of the wipe tower. - 1.5f * m_extrusion_flow * (wipeTower_box.lu.y - wipeTower_box.ld.y), 2400); + writer.travel(wipeTower_box.ld, 7000); // Move to the front left corner. + writer.travel(wipeTower_box.rd) // Always wipe the nozzle with a long wipe to reduce stringing when moving away from the wipe tower. + .travel(wipeTower_box.ld); + writer.append("; CP WIPE TOWER FIRST LAYER BRIM END\n" + ";-----------------------------------\n"); - // The tool is supposed to be active and primed at the time when the wipe tower brim is extruded. - // toolchange_Change(writer, int(tool), m_material[tool]); - - // Extrude 4 rounds of a brim around the future wipe tower. - box_coordinates box(wipeTower_box); - box.expand(m_perimeter_width); - for (size_t i = 0; i < 4; ++ i) { - writer.travel (box.ld, 7000) - .extrude(box.lu, 2100).extrude(box.ru) - .extrude(box.rd ).extrude(box.ld); - box.expand(m_perimeter_width); - } - - writer.travel(wipeTower_box.ld, 7000); // Move to the front left corner. - writer.travel(wipeTower_box.rd) // Always wipe the nozzle with a long wipe to reduce stringing when moving away from the wipe tower. - .travel(wipeTower_box.ld); - writer.append("; CP WIPE TOWER FIRST LAYER BRIM END\n" - ";-----------------------------------\n"); - // Mark the brim as extruded. - m_print_brim = false; - } + m_print_brim = false; // Mark the brim as extruded ToolChangeResult result; result.print_z = this->m_z_pos; @@ -806,7 +731,7 @@ void WipeTowerPrusaMM::toolchange_Unload( // this is y of the center of previous sparse infill border float sparse_beginning_y = m_wipe_tower_pos.y; - if (m_layer_parity) + if (m_current_shape == SHAPE_REVERSED) sparse_beginning_y += ((m_layer_info-1)->depth - (m_layer_info-1)->toolchanges_depth()) - ((m_layer_info)->depth-(m_layer_info)->toolchanges_depth()) ; else @@ -833,8 +758,8 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.extrude(xl-15,writer.y()); writer.travel(oldx,oldy);*/ - if ( (m_layer_parity && ramming_end_y < sparse_beginning_y - 0.5f*m_perimeter_width ) || - (!m_layer_parity && ramming_end_y > sparse_beginning_y + 0.5f*m_perimeter_width ) ) + if ( (m_current_shape == SHAPE_REVERSED && ramming_end_y < sparse_beginning_y - 0.5f*m_perimeter_width ) || + (m_current_shape == SHAPE_NORMAL && ramming_end_y > sparse_beginning_y + 0.5f*m_perimeter_width ) ) { writer.extrude(xl + tch.first_wipe_line-1.f*m_perimeter_width,writer.y()); remaining -= tch.first_wipe_line-1.f*m_perimeter_width; @@ -868,47 +793,6 @@ void WipeTowerPrusaMM::toolchange_Unload( } WipeTower::xy end_of_ramming(writer.x(),writer.y()); -// Alex's old ramming: -{ - /*switch (current_material) - { - case ABS: - // ramming start end y increment amount feedrate - writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 0.2f, 0, 1.2f * e, 4000) - .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.2f, e0, 1.6f * e, 4600) - .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.2f, e0, 1.8f * e, 5000) - .ram(xr - m_perimeter_width * 2, xl + m_perimeter_width * 2, y_step * 1.2f, e0, 1.8f * e, 5000); - break; - case PVA: - // Used for the PrimaSelect PVA - writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 0.2f, 0, 1.75f * e, 4000) - .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.5f, 0, 1.75f * e, 4500) - .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.5f, 0, 1.75f * e, 4800) - .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.5f, 0, 1.75f * e, 5000); - break; - case SCAFF: - writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 2.f, 0, 1.75f * e, 4000) - .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 3.f, 0, 2.34f * e, 4600) - .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 3.f, 0, 2.63f * e, 5200); - break; - default: - // PLA, PLA/PHA and others - // Used for the Verbatim BVOH, PET, NGEN, co-polyesters - writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 0.2f, 0, 1.60f * e, 4000) - .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.2f, e0, 1.65f * e, 4600) - .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.2f, e0, 1.74f * e, 5200); - }*/ -} - // Pull the filament end into a cooling tube (Alex) - //writer.retract(15, 5000).retract(50, 5400).retract(15, 3000).retract(12, 2000); - - // Pull the filament end to the BEGINNING of the cooling tube - /*float unloading_feedrate = 60.f * m_filpar[m_current_tool].unloading_speed; - writer.retract(15, 5000) // just after ramming - always the same speed - .retract(m_cooling_tube_retraction+m_cooling_tube_length/2.f-42, unloading_feedrate) - .retract(15, unloading_feedrate*0.55f) - .retract(12, unloading_feedrate*0.35f);*/ - // Pull the filament end to the BEGINNING of the cooling tube while still moving the print head float oldx = writer.x(); float turning_point = (!m_left_to_right ? std::max(xl,oldx-15.f) : std::min(xr,oldx+15.f) ); // so it's not too far @@ -957,42 +841,8 @@ void WipeTowerPrusaMM::toolchange_Unload( // we should be at the beginning of the cooling tube again - let's move to parking position: writer.retract(-m_cooling_tube_length/2.f+m_parking_pos_retraction-m_cooling_tube_retraction, 2000); - writer.travel(writer.x(), writer.y() - y_step,2400); - - // Alex's old cooling: - { - // In case the current print head position is closer to the left edge, reverse the direction. - /*if (std::abs(writer.x() - xl) < std::abs(writer.x() - xr)) - std::swap(xl, xr); - // Horizontal cooling moves will be performed at the following Y coordinate: - writer.travel(xr, writer.y() + y_step * 0.8f, 7200) - .suppress_preview(); - switch (current_material) - { - case PVA: - writer.cool(xl, xr, 3, -5, 1600) - .cool(xl, xr, 5, -5, 2000) - .cool(xl, xr, 5, -5, 2200) - .cool(xl, xr, 5, -5, 2400) - .cool(xl, xr, 5, -5, 2400) - .cool(xl, xr, 5, -3, 2400); - break; - case SCAFF: - writer.cool(xl, xr, 3, -5, 1600) - .cool(xl, xr, 5, -5, 2000) - .cool(xl, xr, 5, -5, 2200) - .cool(xl, xr, 5, -5, 2200) - .cool(xl, xr, 5, -3, 2400); - break; - default: - writer.cool(xl, xr, 3, -5, 1600) - .cool(xl, xr, 5, -5, 2000) - .cool(xl, xr, 5, -5, 2400) - .cool(xl, xr, 5, -3, 2400); - }*/ -} // this is to align ramming and future loading extrusions, so the future y-steps can be uniform from the start: - writer.travel(end_of_ramming.x, end_of_ramming.y + (y_step/m_extra_spacing-m_line_width) / 2.f, 2400.f); + writer.travel(end_of_ramming.x, end_of_ramming.y + (y_step/m_extra_spacing-m_line_width) / 2.f + m_perimeter_width, 2400.f); writer.resume_preview() .flush_planner_queue(); @@ -1036,6 +886,7 @@ void WipeTowerPrusaMM::toolchange_Load( float edist = m_parking_pos_retraction-50-2; // loading is 2mm shorter that previous retraction, 50mm reserved for acceleration/deceleration writer.append("; CP TOOLCHANGE LOAD\n") .suppress_preview() + .travel(writer.x(),writer.y() + m_perimeter_width) // So that we move in free space .load_move_x(turning_point, 20, 60*std::hypot(dist,20.f)/20.f * loading_speed*0.3f) // Acceleration .load_move_x(oldx,edist,60*std::hypot(dist,edist)/edist * loading_speed) // Fast phase .load_move_x(turning_point, 20, 60*std::hypot(dist,20.f)/20.f * loading_speed*0.3f) // Slowing down @@ -1043,20 +894,6 @@ void WipeTowerPrusaMM::toolchange_Load( .travel(oldx,oldy) .resume_preview(); -// Alex's old loading extrusions - this has been moved to toolchange_Wipe(...) -{ - // Extrude first five lines (just three lines if colorInit is set). - /*writer.extrude(xr, writer.y(), 1600); - bool colorInit = false; - size_t pass = colorInit ? 1 : 2; - float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_line_width; - for (int i = 0; i < pass; ++ i) { - writer.travel (xr, writer.y() + dy, 7200); - writer.extrude(xl, writer.y(), 2200); - writer.travel (xl, writer.y() + dy, 7200); - writer.extrude(xr, writer.y(), 2200); - }*/ -} // Reset the extruder current to the normal value. writer.set_extruder_trimpot(550); } @@ -1091,6 +928,8 @@ void WipeTowerPrusaMM::toolchange_Wipe( writer.travel((m_left_to_right ? xr-m_perimeter_width : xl+m_perimeter_width),writer.y()+dy); m_left_to_right = !m_left_to_right; } + + writer.travel(writer.x(),writer.y()-m_perimeter_width); // cooling & loading was done a fraction down the road // now the wiping itself: for (int i = 0; true; ++i) { @@ -1126,7 +965,7 @@ void WipeTowerPrusaMM::toolchange_Wipe( -WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) +WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() { // This should only be called if the layer is not finished yet. // Otherwise the caller would likely travel to the wipe tower in vain. @@ -1138,7 +977,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) - .set_y_shift(m_y_shift - (m_layer_parity && !peters_wipe_tower ? m_layer_info->toolchanges_depth() : 0.f)) + .set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED && !peters_wipe_tower ? m_layer_info->toolchanges_depth() : 0.f)) .append(";--------------------\n" "; CP EMPTY GRID START\n") // m_num_layer_changes is incremented by set_z, so it is 1 based. @@ -1150,93 +989,65 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) box_coordinates fill_box(m_wipe_tower_pos + xy(m_perimeter_width, m_depth_traversed + m_perimeter_width), m_wipe_tower_width - 2 * m_perimeter_width, current_depth-m_perimeter_width); - if (purpose == PURPOSE_MOVE_TO_TOWER || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { - if ( m_layer_info->tool_changes.size() == 0) { - // There were no tool changes at all in this layer. - writer.retract(m_retract * 1.5f, 3600) - // Jump with retract to fill_box.ld + a random shift in +x. - .z_hop(m_zhop, 7200) - .travel(fill_box.ld + xy(5.f + 15.f * float(rand()) / RAND_MAX, 0.f), 7000) - .z_hop_reset(7200) - // Prime the extruder. - .load_move_x(fill_box.ld.x, m_retract * 1.5f, 3600); - } else { - // Otherwise the extruder is already over the wipe tower. - } - } else { - // The print head is inside the wipe tower. Rather move to the start of the following extrusion. - writer.set_initial_position(fill_box.lu); - } + // The print head is inside the wipe tower. Rather move to the start of the following extrusion. + writer.set_initial_position(fill_box.lu); - if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { - box_coordinates box = fill_box; - for (int i=0;i<2;++i) { - if (m_layer_info->toolchanges_depth() < WT_EPSILON) { // there were no toolchanges on this layer - if (i==0) box.expand(m_perimeter_width); - else box.expand(-m_perimeter_width); - } - else i=2; // only draw the inner perimeter - - writer.travel(box.lu,7200) - .extrude(box.ru, 2400 * speed_factor) - .extrude(box.rd) - .extrude(box.ld) - .extrude(box.lu); - } - - if (m_is_first_layer && m_par.adhesion) { - // Extrude a dense infill at the 1st layer to improve 1st layer adhesion of the wipe tower. - box.expand(-m_perimeter_width/2.f); - unsigned nsteps = int(floor((box.lu.y - box.ld.y) / (2*m_perimeter_width))); - float step = (box.lu.y - box.ld.y) / nsteps; - writer.travel(box.ld-xy(m_perimeter_width/2.f,m_perimeter_width/2.f)); - if (nsteps >= 0) - for (size_t i = 0; i < nsteps; ++i) { - writer.extrude(box.ld.x+m_perimeter_width/2.f, writer.y() + 0.5f * step); - writer.extrude(box.rd.x - m_perimeter_width / 2.f, writer.y()); - writer.extrude(box.rd.x - m_perimeter_width / 2.f, writer.y() + 0.5f * step); - writer.extrude(box.ld.x + m_perimeter_width / 2.f, writer.y()); - } - writer.travel(box.rd.x-m_perimeter_width/2.f,writer.y()); // wipe the nozzle - } else { - // Extrude a sparse infill to support the material to be printed above. - - const float dy = (fill_box.lu.y - fill_box.ld.y - m_perimeter_width); - if (dy > m_perimeter_width) - { - // Extrude an inverse U at the left of the region. - writer.travel(fill_box.ld + xy(m_perimeter_width * 2, 0.f)) - .extrude(fill_box.lu + xy(m_perimeter_width * 2, 0.f), 2900 * speed_factor); - - const float left = fill_box.lu.x+2*m_perimeter_width; - const float right = fill_box.ru.x - 2 * m_perimeter_width; - const int n = 1+(right-left)/(m_par.bridging); - const float dx = (right-left)/n; - for (int i=1;i<=n;++i) { - float x=left+dx*i; - writer.travel(x,writer.y()); - writer.extrude(x,i%2 ? fill_box.rd.y : fill_box.ru.y); - } - writer.travel(left,writer.y(),7200); // wipes the nozzle before moving away from the wipe tower - } - } + box_coordinates box = fill_box; + for (int i=0;i<2;++i) { + if (m_layer_info->toolchanges_depth() < WT_EPSILON) { // there were no toolchanges on this layer + if (i==0) box.expand(m_perimeter_width); + else box.expand(-m_perimeter_width); + } + else i=2; // only draw the inner perimeter, outer has been already drawn by tool_change(...) + writer.rectangle(box.ld,box.rd.x-box.ld.x,box.ru.y-box.rd.y); /* - // if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) - if (true) - // Wipe along the front side of the current wiping box. - // Always wipe the nozzle with a long wipe to reduce stringing when moving away from the wipe tower. - writer.travel(fill_box.ld + xy( m_perimeter_width, m_perimeter_width / 2), 7200) - .travel(fill_box.rd + xy(- m_perimeter_width, m_perimeter_width / 2)); - else - writer.feedrate(7200); -*/ - writer.append("; CP EMPTY GRID END\n" - ";------------------\n\n\n\n\n\n\n"); + writer.travel(box.lu,7200) + .extrude(box.ru, 2400 * speed_factor) + .extrude(box.rd) + .extrude(box.ld) + .extrude(box.lu);*/ + } + + if (m_is_first_layer && m_par.adhesion) { + // Extrude a dense infill at the 1st layer to improve 1st layer adhesion of the wipe tower. + box.expand(-m_perimeter_width/2.f); + unsigned nsteps = int(floor((box.lu.y - box.ld.y) / (2*m_perimeter_width))); + float step = (box.lu.y - box.ld.y) / nsteps; + writer.travel(box.ld-xy(m_perimeter_width/2.f,m_perimeter_width/2.f)); + if (nsteps >= 0) + for (size_t i = 0; i < nsteps; ++i) { + writer.extrude(box.ld.x+m_perimeter_width/2.f, writer.y() + 0.5f * step); + writer.extrude(box.rd.x - m_perimeter_width / 2.f, writer.y()); + writer.extrude(box.rd.x - m_perimeter_width / 2.f, writer.y() + 0.5f * step); + writer.extrude(box.ld.x + m_perimeter_width / 2.f, writer.y()); + } + writer.travel(box.rd.x-m_perimeter_width/2.f,writer.y()); // wipe the nozzle + } + else { // Extrude a sparse infill to support the material to be printed above. + const float dy = (fill_box.lu.y - fill_box.ld.y - m_perimeter_width); + if (dy > m_perimeter_width) + { + // Extrude an inverse U at the left of the region. + writer.travel(fill_box.ld + xy(m_perimeter_width * 2, 0.f)) + .extrude(fill_box.lu + xy(m_perimeter_width * 2, 0.f), 2900 * speed_factor); + + const float left = fill_box.lu.x+2*m_perimeter_width; + const float right = fill_box.ru.x - 2 * m_perimeter_width; + const int n = 1+(right-left)/(m_par.bridging); + const float dx = (right-left)/n; + for (int i=1;i<=n;++i) { + float x=left+dx*i; + writer.travel(x,writer.y()); + writer.extrude(x,i%2 ? fill_box.rd.y : fill_box.ru.y); + } + writer.travel(left,writer.y(),7200); // wipes the nozzle before moving away from the wipe tower + } + } + writer.append("; CP EMPTY GRID END\n" + ";------------------\n\n\n\n\n\n\n"); + + m_depth_traversed = m_wipe_tower_depth-m_perimeter_width; - // Indicate that this wipe tower layer is fully covered. - m_depth_traversed = m_wipe_tower_depth-m_perimeter_width; - ///m_idx_tool_change_in_layer = (unsigned int)m_max_color_changes; - } ToolChangeResult result; result.print_z = this->m_z_pos; result.layer_height = this->m_layer_height; @@ -1316,10 +1127,10 @@ void WipeTowerPrusaMM::save_on_last_wipe() continue; for (const auto &toolchange : m_layer_info->tool_changes) - tool_change(toolchange.new_tool, false, PURPOSE_EXTRUDE); + tool_change(toolchange.new_tool, false); float width = m_wipe_tower_width - 3*m_perimeter_width; // width we draw into - float length_to_save = 2*(m_wipe_tower_width+m_wipe_tower_depth) + (!layer_finished() ? finish_layer(PURPOSE_EXTRUDE).total_extrusion_length_in_plane() : 0.f); + float length_to_save = 2*(m_wipe_tower_width+m_wipe_tower_depth) + (!layer_finished() ? finish_layer().total_extrusion_length_in_plane() : 0.f); float length_to_wipe = volume_to_length(m_par.wipe_volumes[m_layer_info->tool_changes.back().old_tool][m_layer_info->tool_changes.back().new_tool], m_line_width,m_layer_info->height) - m_layer_info->tool_changes.back().first_wipe_line - length_to_save; @@ -1359,19 +1170,17 @@ void WipeTowerPrusaMM::generate(std::vectordepth < m_wipe_tower_depth - m_perimeter_width) m_y_shift = (m_wipe_tower_depth-m_layer_info->depth-m_perimeter_width)/2.f; for (const auto &toolchange : layer.tool_changes) - layer_result.emplace_back(tool_change(toolchange.new_tool, false, WipeTower::PURPOSE_EXTRUDE)); + layer_result.emplace_back(tool_change(toolchange.new_tool, false)); if (! layer_finished()) { - layer_result.emplace_back(finish_layer(WipeTower::PURPOSE_EXTRUDE)); + layer_result.emplace_back(finish_layer()); if (layer_result.size() > 1) { // Merge the two last tool changes into one. WipeTower::ToolChangeResult &tc1 = layer_result[layer_result.size() - 2]; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 0906d334e..3a1b332fd 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -269,8 +269,6 @@ public: m_z_pos = print_z; m_layer_height = layer_height; m_is_first_layer = is_first_layer; - // Start counting the color changes from zero. Special case -1: extrude a brim first. - ///m_idx_tool_change_in_layer = is_first_layer ? (unsigned int)(-1) : 0; m_print_brim = is_first_layer; m_depth_traversed = 0.f; // to make room for perimeter line m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL; @@ -299,17 +297,15 @@ public: const std::vector &tools, // If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower. // If false, the last priming are will be large enough to wipe the last extruder sufficiently. - bool last_wipe_inside_wipe_tower, - // May be used by a stand alone post processor. - Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE); + bool last_wipe_inside_wipe_tower); // Returns gcode for a toolchange and a final print head position. // On the first layer, extrude a brim around the future wipe tower first. - virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer, Purpose purpose); + virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer); // Fill the unfilled space with a zig-zag. // Call this method only if layer_finished() is false. - virtual ToolChangeResult finish_layer(Purpose purpose); + virtual ToolChangeResult finish_layer(); // Is the current layer finished? virtual bool layer_finished() const { @@ -455,7 +451,7 @@ private: // Returns gcode for wipe tower brim // sideOnly -- set to false -- experimental, draw brim on sides of wipe tower // offset -- set to 0 -- experimental, offset to replace brim in front / rear of wipe tower - ToolChangeResult toolchange_Brim(Purpose purpose, bool sideOnly = false, float y_offset = 0.f); + ToolChangeResult toolchange_Brim(bool sideOnly = false, float y_offset = 0.f); void toolchange_Unload( PrusaMultiMaterial::Writer &writer, diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 447aec750..5affad297 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1052,7 +1052,7 @@ void Print::_make_wipe_tower() bool last_priming_wipe_full = m_tool_ordering.front().extruders.size() > m_tool_ordering.front().wipe_tower_partitions; m_wipe_tower_priming = Slic3r::make_unique( - wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full, WipeTower::PURPOSE_EXTRUDE)); + wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full)); // Lets go through the wipe tower layers and determine pairs of extruder changes for each @@ -1146,7 +1146,7 @@ void Print::_make_wipe_tower() wipe_tower.set_layer(float(m_tool_ordering.back().print_z), float(layer_height), 0, false, true); } m_wipe_tower_final_purge = Slic3r::make_unique( - wipe_tower.tool_change((unsigned int)-1, false, WipeTower::PURPOSE_EXTRUDE)); + wipe_tower.tool_change((unsigned int)-1, false)); } std::string Print::output_filename() From 6e39f61198e237a85a43b08df6c3aaa6e7fa775e Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 9 Mar 2018 12:40:39 +0100 Subject: [PATCH 32/81] Priming extrusions, nozzle-wipes when leaving tower, removed few unnecessary moves --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 71 +++++++++++++-------- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 2 +- 2 files changed, 44 insertions(+), 29 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 39ccc7155..671819286 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -72,8 +72,11 @@ public: Writer& set_rotation(WipeTower::xy& pos, float width, float depth, float angle) { m_wipe_tower_pos = pos; m_wipe_tower_width = width; m_wipe_tower_depth=depth; m_angle_deg = angle; return (*this); } - Writer& set_y_shift(float shift) - { m_y_shift = shift; return (*this); } + Writer& set_y_shift(float shift) { + m_current_pos.y += shift-m_y_shift; + m_y_shift = shift; + return (*this); + } // Suppress / resume G-code preview in Slic3r. Slic3r will have difficulty to differentiate the various // filament loading and cooling moves from normal extrusion moves. Therefore the writer @@ -481,8 +484,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // therefore the homing position is shifted inside the bed by 0.2 in the firmware to [0.2, -2.0]. // box_coordinates cleaning_box(xy(0.5f, - 1.5f), m_wipe_tower_width, wipe_area); //FIXME: set the width properly - const float prime_section_width = 60.f; - box_coordinates cleaning_box(xy(5.f, 0.f), prime_section_width, 15.f); + const float prime_section_width = 55.f; + box_coordinates cleaning_box(xy(5.f, 0.f), prime_section_width, 100.f); PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow) @@ -510,11 +513,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( toolchange_Load(writer, cleaning_box); // Prime the tool. if (idx_tool + 1 == tools.size()) { // Last tool should not be unloaded, but it should be wiped enough to become of a pure color. - toolchange_Wipe(writer, cleaning_box, 20.f); + toolchange_Wipe(writer, cleaning_box, m_par.wipe_volumes[tools[idx_tool-1]][tool]); } else { // Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool. //writer.travel(writer.x(), writer.y() + m_perimeter_width, 7200); - toolchange_Wipe(writer, cleaning_box , 5.f); + toolchange_Wipe(writer, cleaning_box , 20.f); box_coordinates box = cleaning_box; box.translate(0.f, writer.y() - cleaning_box.ld.y + m_perimeter_width); toolchange_Unload(writer, box , m_filpar[m_current_tool].material, m_filpar[tools[idx_tool + 1]].first_layer_temperature); @@ -611,20 +614,28 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo m_is_first_layer ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature); toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials. toolchange_Load(writer, cleaning_box); - toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area. + writer.travel(writer.x(),writer.y()-m_perimeter_width); // cooling and loading were done a bit down the road + toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area. } else toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, m_filpar[m_current_tool].temperature); + ++ m_num_tool_changes; + m_depth_traversed += wipe_area; + if (last_change_in_layer) {// draw perimeter line writer.set_y_shift(m_y_shift); if (peters_wipe_tower) writer.rectangle(m_wipe_tower_pos,m_layer_info->depth + 3*m_perimeter_width,m_wipe_tower_depth); - else + else { + writer.wait(2.f); writer.rectangle(m_wipe_tower_pos,m_wipe_tower_width, m_layer_info->depth + m_perimeter_width); + if (layer_finished()) { // no finish_layer will be called, we must wipe the nozzle + writer.travel(m_wipe_tower_pos.x + (writer.x()>m_wipe_tower_pos.x + EPSILON ? 0.f : m_wipe_tower_width), writer.y()); + } + } } - // Reset the extruder current to a normal value. - writer.set_extruder_trimpot(550) + writer.set_extruder_trimpot(550) // Reset the extruder current to a normal value. .feedrate(6000) .flush_planner_queue() .reset_extruder() @@ -632,9 +643,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo ";------------------\n" "\n\n"); - ++ m_num_tool_changes; - m_depth_traversed += wipe_area; - ToolChangeResult result; result.print_z = this->m_z_pos; result.layer_height = this->m_layer_height; @@ -841,7 +849,8 @@ void WipeTowerPrusaMM::toolchange_Unload( // we should be at the beginning of the cooling tube again - let's move to parking position: writer.retract(-m_cooling_tube_length/2.f+m_parking_pos_retraction-m_cooling_tube_retraction, 2000); - // this is to align ramming and future loading extrusions, so the future y-steps can be uniform from the start: + // this is to align ramming and future wiping extrusions, so the future y-steps can be uniform from the start: + // the perimeter_width will later be subtracted, it is there to not load while moving over just extruded material writer.travel(end_of_ramming.x, end_of_ramming.y + (y_step/m_extra_spacing-m_line_width) / 2.f + m_perimeter_width, 2400.f); writer.resume_preview() @@ -877,7 +886,6 @@ void WipeTowerPrusaMM::toolchange_Load( float xl = cleaning_box.ld.x + m_perimeter_width * 0.75f; float xr = cleaning_box.rd.x - m_perimeter_width * 0.75f; float oldx = writer.x(); // the nozzle is in place to do the first wiping moves, we will remember the position - float oldy = writer.y(); // Load the filament while moving left / right, so the excess material will not create a blob at a single position. float loading_speed = m_filpar[m_current_tool].loading_speed; // mm/s in e axis @@ -886,12 +894,10 @@ void WipeTowerPrusaMM::toolchange_Load( float edist = m_parking_pos_retraction-50-2; // loading is 2mm shorter that previous retraction, 50mm reserved for acceleration/deceleration writer.append("; CP TOOLCHANGE LOAD\n") .suppress_preview() - .travel(writer.x(),writer.y() + m_perimeter_width) // So that we move in free space .load_move_x(turning_point, 20, 60*std::hypot(dist,20.f)/20.f * loading_speed*0.3f) // Acceleration .load_move_x(oldx,edist,60*std::hypot(dist,edist)/edist * loading_speed) // Fast phase .load_move_x(turning_point, 20, 60*std::hypot(dist,20.f)/20.f * loading_speed*0.3f) // Slowing down .load_move_x(oldx, 10, 60*std::hypot(dist,10.f)/10.f * loading_speed*0.1f) // Super slow - .travel(oldx,oldy) .resume_preview(); // Reset the extruder current to the normal value. @@ -929,7 +935,6 @@ void WipeTowerPrusaMM::toolchange_Wipe( m_left_to_right = !m_left_to_right; } - writer.travel(writer.x(),writer.y()-m_perimeter_width); // cooling & loading was done a fraction down the road // now the wiping itself: for (int i = 0; true; ++i) { @@ -959,6 +964,14 @@ void WipeTowerPrusaMM::toolchange_Wipe( writer.extrude(writer.x() + (i % 4 == 0 ? -1.f : (i % 4 == 1 ? 1.f : 0.f)) * 1.5*m_perimeter_width, writer.y() + dy); m_left_to_right = !m_left_to_right; } + + // this is neither priming nor not the last toolchange on this layer - we are going back to the model - wipe the nozzle + if (m_layer_info != m_plan.end() && m_current_tool != m_layer_info->tool_changes.back().new_tool) { + m_left_to_right = !m_left_to_right; + writer.travel(writer.x(), writer.y() - dy) + .travel(m_wipe_tower_pos.x + (m_left_to_right ? m_wipe_tower_width : 0.f), writer.y()); + } + writer.set_extrusion_flow(m_extrusion_flow); // Reset the extrusion flow. } @@ -989,8 +1002,10 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() box_coordinates fill_box(m_wipe_tower_pos + xy(m_perimeter_width, m_depth_traversed + m_perimeter_width), m_wipe_tower_width - 2 * m_perimeter_width, current_depth-m_perimeter_width); - // The print head is inside the wipe tower. Rather move to the start of the following extrusion. - writer.set_initial_position(fill_box.lu); + if (m_left_to_right) // so there is never a diagonal travel + writer.set_initial_position(fill_box.ru); + else + writer.set_initial_position(fill_box.lu); box_coordinates box = fill_box; for (int i=0;i<2;++i) { @@ -1000,14 +1015,12 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() } else i=2; // only draw the inner perimeter, outer has been already drawn by tool_change(...) writer.rectangle(box.ld,box.rd.x-box.ld.x,box.ru.y-box.rd.y); -/* - writer.travel(box.lu,7200) - .extrude(box.ru, 2400 * speed_factor) - .extrude(box.rd) - .extrude(box.ld) - .extrude(box.lu);*/ } + // we are in one of the corners, travel to ld along the perimeter: + if (writer.x() > fill_box.ld.x+EPSILON) writer.travel(fill_box.ld.x,writer.y()); + if (writer.y() > fill_box.ld.y+EPSILON) writer.travel(writer.x(),fill_box.ld.y); + if (m_is_first_layer && m_par.adhesion) { // Extrude a dense infill at the 1st layer to improve 1st layer adhesion of the wipe tower. box.expand(-m_perimeter_width/2.f); @@ -1025,14 +1038,14 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() } else { // Extrude a sparse infill to support the material to be printed above. const float dy = (fill_box.lu.y - fill_box.ld.y - m_perimeter_width); + const float left = fill_box.lu.x+2*m_perimeter_width; + const float right = fill_box.ru.x - 2 * m_perimeter_width; if (dy > m_perimeter_width) { // Extrude an inverse U at the left of the region. writer.travel(fill_box.ld + xy(m_perimeter_width * 2, 0.f)) .extrude(fill_box.lu + xy(m_perimeter_width * 2, 0.f), 2900 * speed_factor); - const float left = fill_box.lu.x+2*m_perimeter_width; - const float right = fill_box.ru.x - 2 * m_perimeter_width; const int n = 1+(right-left)/(m_par.bridging); const float dx = (right-left)/n; for (int i=1;i<=n;++i) { @@ -1042,6 +1055,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() } writer.travel(left,writer.y(),7200); // wipes the nozzle before moving away from the wipe tower } + else + writer.travel(right,writer.y(),7200); // wipes the nozzle before moving away from the wipe tower } writer.append("; CP EMPTY GRID END\n" ";------------------\n\n\n\n\n\n\n"); diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 3a1b332fd..3182c8b8e 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -471,7 +471,7 @@ private: void toolchange_Wipe( PrusaMultiMaterial::Writer &writer, const box_coordinates &cleaning_box, - float wipe_volume); + float wipe_volume); }; From b5fd4ddb8c50908e5754df8f49d698eb16f0fd2f Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 12 Mar 2018 08:35:35 +0100 Subject: [PATCH 33/81] Removed an unnecessary wait --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 671819286..624b48903 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -627,7 +627,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo if (peters_wipe_tower) writer.rectangle(m_wipe_tower_pos,m_layer_info->depth + 3*m_perimeter_width,m_wipe_tower_depth); else { - writer.wait(2.f); writer.rectangle(m_wipe_tower_pos,m_wipe_tower_width, m_layer_info->depth + m_perimeter_width); if (layer_finished()) { // no finish_layer will be called, we must wipe the nozzle writer.travel(m_wipe_tower_pos.x + (writer.x()>m_wipe_tower_pos.x + EPSILON ? 0.f : m_wipe_tower_width), writer.y()); From 27ab8ff4e1fc9efdc5ca61ff1ae70cdfde16b4e8 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 12 Mar 2018 15:41:25 +0100 Subject: [PATCH 34/81] Configuration layer changes (cooling_time, bridging, adhesion moved from dedicated dialog to filament/print settings) --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 12 ++--- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 42 ++++++++--------- xs/src/libslic3r/Print.cpp | 5 ++ xs/src/libslic3r/PrintConfig.cpp | 23 ++++++++++ xs/src/libslic3r/PrintConfig.hpp | 6 +++ xs/src/slic3r/GUI/Preset.cpp | 6 +-- xs/src/slic3r/GUI/Tab.cpp | 23 ++++++++++ xs/src/slic3r/GUI/WipeTowerDialog.cpp | 51 ++------------------- xs/src/slic3r/GUI/WipeTowerDialog.hpp | 33 ------------- 9 files changed, 91 insertions(+), 110 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 624b48903..b94950af1 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -734,7 +734,7 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.travel(xl, cleaning_box.ld.y + m_depth_traversed + y_step/2.f ); // move to starting position // if the ending point of the ram would end up in mid air, align it with the end of the wipe tower: - if (m_layer_info > m_plan.begin() && m_layer_info < m_plan.end() && (m_layer_info-1!=m_plan.begin() || !m_par.adhesion )) { + if (m_layer_info > m_plan.begin() && m_layer_info < m_plan.end() && (m_layer_info-1!=m_plan.begin() || !m_adhesion )) { // this is y of the center of previous sparse infill border float sparse_beginning_y = m_wipe_tower_pos.y; @@ -821,8 +821,8 @@ void WipeTowerPrusaMM::toolchange_Unload( const float start_x = writer.x(); turning_point = ( xr-start_x > start_x-xl ? xr : xl ); const float max_x_dist = 2*std::abs(start_x-turning_point); - const unsigned int N = 4 + std::max(0,(m_par.cooling_time[m_current_tool]-14)/3); - float time = m_par.cooling_time[m_current_tool] / float(N); + const unsigned int N = 4 + std::max(0,(m_filpar[m_current_tool].cooling_time-14)/3); + float time = m_filpar[m_current_tool].cooling_time / float(N); i = 0; while (i fill_box.ld.x+EPSILON) writer.travel(fill_box.ld.x,writer.y()); if (writer.y() > fill_box.ld.y+EPSILON) writer.travel(writer.x(),fill_box.ld.y); - if (m_is_first_layer && m_par.adhesion) { + if (m_is_first_layer && m_adhesion) { // Extrude a dense infill at the 1st layer to improve 1st layer adhesion of the wipe tower. box.expand(-m_perimeter_width/2.f); unsigned nsteps = int(floor((box.lu.y - box.ld.y) / (2*m_perimeter_width))); @@ -1045,7 +1045,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() writer.travel(fill_box.ld + xy(m_perimeter_width * 2, 0.f)) .extrude(fill_box.lu + xy(m_perimeter_width * 2, 0.f), 2900 * speed_factor); - const int n = 1+(right-left)/(m_par.bridging); + const int n = 1+(right-left)/(m_bridging); const float dx = (right-left)/n; for (int i=1;i<=n;++i) { float x=left+dx*i; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 3182c8b8e..3c2f82ffd 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -68,13 +68,12 @@ struct WipeTowerParameters { WipeTowerParameters() { } // create new empty object WipeTowerParameters(const std::string& init_data) { // create object and initialize from std::string std::istringstream in(init_data); // validation of input is left to the caller - in >> bridging >> adhesion >> sampling; + in >> sampling; for (std::vector vect{} ; in >> vect ;) { // until we get to fail state ("**")... - if (vect.size()>=3) { - cooling_time.push_back(vect[0]); - ramming_line_width_multiplicator.push_back(vect[1]); - ramming_step_multiplicator.push_back(vect[2]); - vect.erase(vect.begin(),vect.begin()+3); + if (vect.size()>=2) { + ramming_line_width_multiplicator.push_back(vect[0]); + ramming_step_multiplicator.push_back(vect[1]); + vect.erase(vect.begin(),vect.begin()+2); } else vect.clear(); // something's not right, we will restore defaults anyway ramming_speed.push_back(vect); @@ -102,16 +101,16 @@ struct WipeTowerParameters { for (unsigned int i=0;i cooling_time; std::vector ramming_line_width_multiplicator; std::vector ramming_step_multiplicator; std::vector> ramming_speed; @@ -192,7 +185,7 @@ 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 wipe_area, float rotation_angle, float cooling_tube_retraction, - float cooling_tube_length, float parking_pos_retraction, std::string& parameters, + float cooling_tube_length, float parking_pos_retraction, float bridging, bool adhesion, std::string& parameters, unsigned int initial_tool) : m_wipe_tower_pos(x, y), m_wipe_tower_width(width), @@ -205,8 +198,11 @@ public: m_cooling_tube_length(cooling_tube_length), m_parking_pos_retraction(parking_pos_retraction), m_current_tool(initial_tool), - m_par(parameters) + m_par(parameters) { + m_bridging = bridging; + m_adhesion = adhesion; + for (size_t i = 0; i < 4; ++ i) { // Extruder specific parameters. m_filpar[i].material = PLA; @@ -226,7 +222,7 @@ public: // Set the extruder properties. void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed, - float unloading_speed, float delay) + float unloading_speed, float delay, int cooling_time) { m_filpar[idx].material = material; m_filpar[idx].temperature = temp; @@ -234,6 +230,7 @@ public: m_filpar[idx].loading_speed = loading_speed; m_filpar[idx].unloading_speed = unloading_speed; m_filpar[idx].delay = delay; + m_filpar[idx].cooling_time = cooling_time; } @@ -340,6 +337,8 @@ private: float m_cooling_tube_retraction = 0.f; float m_cooling_tube_length = 0.f; float m_parking_pos_retraction = 0.f; + float m_bridging = 0.f; + bool m_adhesion = true; float m_line_width = Nozzle_Diameter * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. float m_extrusion_flow = 0.038; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. @@ -352,6 +351,7 @@ private: float loading_speed; float unloading_speed; float delay; + int cooling_time; }; // Extruder specific parameters. diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 5affad297..95c57339a 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -188,6 +188,7 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value), float(this->config.wipe_tower_rotation_angle.value), float(this->config.cooling_tube_retraction.value), float(this->config.cooling_tube_length.value), float(this->config.parking_pos_retraction.value), + float(this->config.wipe_tower_bridging), bool(this->config.wipe_tower_adhesion), this->config.wipe_tower_advanced.value,m_tool_ordering.first_extruder()); //wipe_tower.set_retract(); @@ -1044,6 +1048,7 @@ void Print::_make_wipe_tower() this->config.first_layer_temperature.get_at(i), this->config.filament_loading_speed.get_at(i), this->config.filament_unloading_speed.get_at(i), + this->config.filament_toolchange_delay.get_at(i), this->config.filament_toolchange_delay.get_at(i)); // When printing the first layer's wipe tower, the first extruder is expected to be active and primed. diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index f31e5de3b..b0b1c4e99 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -469,6 +469,15 @@ PrintConfigDef::PrintConfigDef() def->cli = "filament-toolchange-delay=f@"; def->min = 0; def->default_value = new ConfigOptionFloats { 0. }; + + def = this->add("filament_cooling_time", coInts); + def->label = L("Cooling time"); + def->tooltip = L("The filament is slowly moved back and forth after retraction into the cooling tube " + "for this amount of time."); + def->cli = "filament_cooling_time=i@"; + def->sidetext = L("s"); + def->min = 0; + def->default_value = new ConfigOptionInts { 14 }; def = this->add("filament_diameter", coFloats); def->label = L("Diameter"); @@ -1800,6 +1809,20 @@ PrintConfigDef::PrintConfigDef() def->sidetext = L("degrees"); def->cli = "wipe-tower-rotation-angle=f"; def->default_value = new ConfigOptionFloat(0.); + + def = this->add("wipe_tower_bridging", coFloat); + def->label = L("Maximal bridging distance"); + def->tooltip = L("Maximal distance between supports on sparse infill sections. "); + def->sidetext = L("mm"); + def->cli = "wipe-tower-bridging=f"; + def->default_value = new ConfigOptionFloat(10.); + + def = this->add("wipe_tower_adhesion", coBool); + def->label = L("Increase first layer adhesion"); + def->tooltip = L("This prevents using sparse infill on the first layer, if it would be " + "normally applied. Dense infill is used instead. "); + def->cli = "wipe-tower_adhesion!"; + def->default_value = new ConfigOptionBool(true); def = this->add("xy_size_compensation", coFloat); def->label = L("XY Size Compensation"); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 06aa343b8..501a8ac36 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -470,6 +470,7 @@ public: ConfigOptionFloats filament_loading_speed; ConfigOptionFloats filament_unloading_speed; ConfigOptionFloats filament_toolchange_delay; + ConfigOptionInts filament_cooling_time; ConfigOptionBool gcode_comments; ConfigOptionEnum gcode_flavor; ConfigOptionString layer_gcode; @@ -525,6 +526,7 @@ protected: OPT_PTR(filament_loading_speed); OPT_PTR(filament_unloading_speed); OPT_PTR(filament_toolchange_delay); + OPT_PTR(filament_cooling_time); OPT_PTR(gcode_comments); OPT_PTR(gcode_flavor); OPT_PTR(layer_gcode); @@ -624,6 +626,8 @@ public: ConfigOptionFloat wipe_tower_width; ConfigOptionFloat wipe_tower_per_color_wipe; ConfigOptionFloat wipe_tower_rotation_angle; + ConfigOptionFloat wipe_tower_bridging; + ConfigOptionBool wipe_tower_adhesion; ConfigOptionFloat z_offset; protected: @@ -690,6 +694,8 @@ protected: OPT_PTR(wipe_tower_width); OPT_PTR(wipe_tower_per_color_wipe); OPT_PTR(wipe_tower_rotation_angle); + OPT_PTR(wipe_tower_bridging); + OPT_PTR(wipe_tower_adhesion); OPT_PTR(z_offset); } }; diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index a8b6a514c..92bfef416 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -199,8 +199,8 @@ const std::vector& Preset::print_options() "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower_advanced", "wipe_tower", "wipe_tower_x", - "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "compatible_printers", - "compatible_printers_condition" + "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "wipe_tower_adhesion", "wipe_tower_bridging", + "compatible_printers", "compatible_printers_condition" }; return s_opts; @@ -211,7 +211,7 @@ const std::vector& Preset::filament_options() static std::vector s_opts { "filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed", "extrusion_multiplier", "filament_density", "filament_cost", "filament_loading_speed", "filament_unloading_speed", "filament_toolchange_delay", - "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", + "filament_cooling_time", "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", "end_filament_gcode","compatible_printers", "compatible_printers_condition" }; diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 177fccc59..ea80e2ece 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -458,6 +458,8 @@ void TabPrint::build() optgroup->append_single_option_line("wipe_tower_width"); optgroup->append_single_option_line("wipe_tower_per_color_wipe"); optgroup->append_single_option_line("wipe_tower_rotation_angle"); + optgroup->append_single_option_line("wipe_tower_bridging"); + optgroup->append_single_option_line("wipe_tower_adhesion"); line = { _(L("Advanced")), "" }; line.widget = [this](wxWindow* parent){ m_wipe_tower_btn = new wxButton(parent, wxID_ANY, _(L("Advanced settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); @@ -880,6 +882,27 @@ void TabFilament::build() optgroup->append_single_option_line("filament_loading_speed"); optgroup->append_single_option_line("filament_unloading_speed"); optgroup->append_single_option_line("filament_toolchange_delay"); + optgroup->append_single_option_line("filament_cooling_time"); + line = { _(L("Ramming")), "" }; + line.widget = [this](wxWindow* parent){ + auto ramming_dialog = new wxButton(parent, wxID_ANY, _(L("Advanced settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(ramming_dialog); + /*m_wipe_tower_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) + { + std::string init_data = (m_config->option("wipe_tower_advanced"))->value; + std::cout << "dialog init: " << init_data << std::endl; + WipeTowerDialog dlg(this,init_data); // dlg lives on stack, no need to call Destroy + + if (dlg.ShowModal() == wxID_OK) { + load_key_value("wipe_tower_advanced", dlg.GetValue()); + std::cout << std::endl << "dialog returned: " << dlg.GetValue() << std::endl; + } + }));*/ + return sizer; + }; + optgroup->append_line(line); + page = add_options_page(_(L("Custom G-code")), "cog.png"); optgroup = page->new_optgroup(_(L("Start G-code")), 0); diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index 323749b0a..1891a401c 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -3,13 +3,8 @@ // Human-readable output of Parameters structure std::ostream& operator<<(std::ostream& str,Slic3r::WipeTowerParameters& par) { - str << "bridging: " << par.bridging << "\n"; - str << "adhesion: " << par.adhesion << "\n"; str << "sampling: " << par.sampling << "\n"; - str << "cooling times: "; - for (const auto& a : par.cooling_time) str << a << " "; - str << "line widths: "; for (const auto& a : par.ramming_line_width_multiplicator) str << a << " "; @@ -116,30 +111,6 @@ void RammingPanel::line_parameters_changed() { - -CoolingPanel::CoolingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) -: wxPanel(parent,wxID_ANY,wxPoint(0,0),wxSize(0,0),wxBORDER_RAISED) -{ - new wxStaticText(this,wxID_ANY,wxString("Time (in seconds) reserved for cooling after unload:"),wxPoint(220,50) ,wxSize(400,25),wxALIGN_LEFT); - for (int i=0;i<4;++i) { - new wxStaticText(this,wxID_ANY,wxString("Filament #")<=m_widget_edits.size()) - break; // so we don't initialize non-existent widget - m_widget_edits[i]->SetValue(p.cooling_time[i]); - } -} - -void CoolingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { - p.cooling_time.clear(); - for (int i=0;i<4;++i) - p.cooling_time.push_back(m_widget_edits[i]->GetValue()); -} - - - WipingPanel::WipingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) : wxPanel(parent,wxID_ANY,wxPoint(0,0),wxSize(0,0),wxBORDER_RAISED) { @@ -208,20 +179,6 @@ void WipingPanel::fill_in_matrix() { -GeneralPanel::GeneralPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) : wxPanel(parent,wxID_ANY,wxPoint(0,0),wxSize(0,0),wxBORDER_RAISED) { - new wxStaticText(this,wxID_ANY,wxString("Maximum bridging over sparse infill (mm):"),wxPoint(100,105) ,wxSize(280,25),wxALIGN_LEFT); - m_widget_bridge = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxPoint(380,100),wxSize(50,25),wxALIGN_RIGHT|wxSP_ARROW_KEYS,1,50,10); - m_widget_adhesion = new wxCheckBox(this,wxID_ANY,"Increased adhesion of first layer",wxPoint(100,150),wxSize(330,25),wxALIGN_RIGHT); - m_widget_bridge->SetValue(p.bridging); - m_widget_adhesion->SetValue(p.adhesion); -} - -void GeneralPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { - p.bridging = m_widget_bridge->GetValue(); - p.adhesion = m_widget_adhesion->GetValue(); -} - - @@ -238,13 +195,13 @@ WipeTowerDialog::WipeTowerDialog(wxWindow* parent,const std::string& init_data) wxNotebook* notebook = new wxNotebook(this,wxID_ANY,wxPoint(0,0),wxSize(800,450)); - m_panel_general = new GeneralPanel(notebook,parameters); + //m_panel_general = new GeneralPanel(notebook,parameters); m_panel_ramming = new RammingPanel(notebook,parameters); - m_panel_cooling = new CoolingPanel(notebook,parameters); + //m_panel_cooling = new CoolingPanel(notebook,parameters); m_panel_wiping = new WipingPanel(notebook,parameters); - notebook->AddPage(m_panel_general,"General"); + //notebook->AddPage(m_panel_general,"General"); notebook->AddPage(m_panel_ramming,"Ramming"); - notebook->AddPage(m_panel_cooling,"Cooling"); + //notebook->AddPage(m_panel_cooling,"Cooling"); notebook->AddPage(m_panel_wiping,"Wiping"); this->Show(); diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/xs/src/slic3r/GUI/WipeTowerDialog.hpp index 452886bc3..8a1c88be8 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.hpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.hpp @@ -40,23 +40,6 @@ private: - - - -class CoolingPanel : public wxPanel { -public: - CoolingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p); - void fill_parameters(Slic3r::WipeTowerParameters& p); - -private: - std::vector m_widget_edits; -}; - - - - - - class WipingPanel : public wxPanel { public: WipingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p); @@ -74,18 +57,6 @@ private: -class GeneralPanel : public wxPanel { -public: - GeneralPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p); - void fill_parameters(Slic3r::WipeTowerParameters& p); - -private: - wxSpinCtrl* m_widget_bridge; - wxCheckBox* m_widget_adhesion; -}; - - - class WipeTowerDialog : public wxDialog { public: @@ -96,17 +67,13 @@ public: private: std::string m_file_name="config_wipe_tower"; - GeneralPanel* m_panel_general = nullptr; RammingPanel* m_panel_ramming = nullptr; - CoolingPanel* m_panel_cooling = nullptr; WipingPanel* m_panel_wiping = nullptr; std::string m_output_data = ""; std::string read_dialog_values() { Slic3r::WipeTowerParameters p; - m_panel_general->fill_parameters(p); m_panel_ramming->fill_parameters(p); - m_panel_cooling->fill_parameters(p); m_panel_wiping ->fill_parameters(p); return p.to_string(); } From cf5dfb9673a37203b36b9f56cf135d4d021d7f08 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 13 Mar 2018 15:54:29 +0100 Subject: [PATCH 35/81] Started to move ramming dialog into filament settings --- xs/src/slic3r/GUI/RammingChart.cpp | 98 ++++++++++++--------------- xs/src/slic3r/GUI/RammingChart.hpp | 61 +++++++---------- xs/src/slic3r/GUI/Tab.cpp | 24 +++---- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 88 ++++++++++++------------ xs/src/slic3r/GUI/WipeTowerDialog.hpp | 23 ++++--- 5 files changed, 135 insertions(+), 159 deletions(-) diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/xs/src/slic3r/GUI/RammingChart.cpp index 3b535aacf..e07b95839 100644 --- a/xs/src/slic3r/GUI/RammingChart.cpp +++ b/xs/src/slic3r/GUI/RammingChart.cpp @@ -10,41 +10,41 @@ void Chart::draw(wxDC& dc) { dc.SetBrush(*wxWHITE_BRUSH); dc.DrawRectangle(m_rect); - if (visible_area->m_width < 0.499) { + if (visible_area.m_width < 0.499) { dc.DrawText("NO RAMMING AT ALL",wxPoint(m_rect.GetLeft()+m_rect.GetWidth()/2-50,m_rect.GetBottom()-m_rect.GetHeight()/2)); return; } - if (!m_line_to_draw->empty()) { - for (unsigned int i=0;isize()-2;++i) { - int color = 510*((m_rect.GetBottom()-(*m_line_to_draw)[i])/double(m_rect.GetHeight())); + if (!m_line_to_draw.empty()) { + for (unsigned int i=0;isize()-2;++i) { + for (unsigned int i=0;im_x*10)/10 ; math_x <= (visible_area->m_x+visible_area->m_width) ; math_x+=0.1) { - int x = math_to_screen(wxPoint2DDouble(math_x,visible_area->m_y)).x; + for (float math_x=int(visible_area.m_x*10)/10 ; math_x <= (visible_area.m_x+visible_area.m_width) ; math_x+=0.1) { + int x = math_to_screen(wxPoint2DDouble(math_x,visible_area.m_y)).x; int y = m_rect.GetBottom(); if (x-last_mark < 50) continue; dc.DrawLine(x,y+3,x,y-3); @@ -54,8 +54,8 @@ void Chart::draw(wxDC& dc) { // draw y-axis: last_mark=10000; - for (int math_y=visible_area->m_y ; math_y <= (visible_area->m_y+visible_area->m_height) ; math_y+=1) { - int y = math_to_screen(wxPoint2DDouble(visible_area->m_x,math_y)).y; + for (int math_y=visible_area.m_y ; math_y <= (visible_area.m_y+visible_area.m_height) ; math_y+=1) { + int y = math_to_screen(wxPoint2DDouble(visible_area.m_x,math_y)).y; int x = m_rect.GetLeft(); if (last_mark-y < 50) continue; dc.DrawLine(x-3,y,x+3,y); @@ -72,8 +72,8 @@ void Chart::mouse_right_button_clicked(wxMouseEvent& event) { return; wxPoint point = event.GetPosition(); int button_index = which_button_is_clicked(point); - if (button_index != -1 && m_buttons[m_current_extruder].size()>2) { - m_buttons[m_current_extruder].erase(m_buttons[m_current_extruder].begin()+button_index); + if (button_index != -1 && m_buttons.size()>2) { + m_buttons.erase(m_buttons.begin()+button_index); recalculate_line(); } } @@ -84,7 +84,7 @@ void Chart::mouse_clicked(wxMouseEvent& event) { wxPoint point = event.GetPosition(); int button_index = which_button_is_clicked(point); if ( button_index != -1) { - m_dragged = &m_buttons[m_current_extruder][button_index]; + m_dragged = &m_buttons[button_index]; m_previous_mouse = point; } } @@ -102,7 +102,7 @@ void Chart::mouse_moved(wxMouseEvent& event) { } int delta_x = pos.x - m_previous_mouse.x; int delta_y = pos.y - m_previous_mouse.y; - m_dragged->move(fixed_x?0:double(delta_x)/m_rect.GetWidth() * visible_area->m_width,-double(delta_y)/m_rect.GetHeight() * visible_area->m_height); + m_dragged->move(fixed_x?0:double(delta_x)/m_rect.GetWidth() * visible_area.m_width,-double(delta_y)/m_rect.GetHeight() * visible_area.m_height); m_previous_mouse = pos; recalculate_line(); } @@ -115,8 +115,8 @@ void Chart::mouse_double_clicked(wxMouseEvent& event) { wxPoint point = event.GetPosition(); if (!m_rect.Contains(point)) // the click is outside the chart return; - m_buttons[m_current_extruder].push_back(screen_to_math(point)); - std::sort(m_buttons[m_current_extruder].begin(),m_buttons[m_current_extruder].end()); + m_buttons.push_back(screen_to_math(point)); + std::sort(m_buttons.begin(),m_buttons.end()); recalculate_line(); return; } @@ -126,7 +126,7 @@ void Chart::mouse_double_clicked(wxMouseEvent& event) { void Chart::recalculate_line() { std::vector points; - for (auto& but : m_buttons[m_current_extruder]) { + for (auto& but : m_buttons) { points.push_back(wxPoint(math_to_screen(but.get_pos()))); if (points.size()>1 && points.back().x==points[points.size()-2].x) points.pop_back(); if (points.size()>1 && points.back().x > m_rect.GetRight()) { @@ -136,7 +136,7 @@ void Chart::recalculate_line() { } std::sort(points.begin(),points.end(),[](wxPoint& a,wxPoint& b) { return a.x < b.x; }); - m_line_to_draw->clear(); + m_line_to_draw.clear(); m_total_volume = 0.f; @@ -205,19 +205,19 @@ void Chart::recalculate_line() { y = (rhs[i-1]*pow(points[i].x-x,3)+rhs[i]*pow(x-points[i-1].x,3)) / (6*h[i]) + (points[i-1].y-rhs[i-1]*h[i]*h[i]/6.f) * (points[i].x-x)/h[i] + (points[i].y -rhs[i] *h[i]*h[i]/6.f) * (x-points[i-1].x)/h[i]; - m_line_to_draw->push_back(y); + m_line_to_draw.push_back(y); } else { float x_math = screen_to_math(wxPoint(x,0)).m_x; - if (i+2<=points.size() && m_buttons[m_current_extruder][i+1].get_pos().m_x-0.125 < x_math) + if (i+2<=points.size() && m_buttons[i+1].get_pos().m_x-0.125 < x_math) ++i; - m_line_to_draw->push_back(math_to_screen(wxPoint2DDouble(x_math,m_buttons[m_current_extruder][i].get_pos().m_y)).y); + m_line_to_draw.push_back(math_to_screen(wxPoint2DDouble(x_math,m_buttons[i].get_pos().m_y)).y); } - m_line_to_draw->back() = std::max(m_line_to_draw->back(), m_rect.GetTop()-1); - m_line_to_draw->back() = std::min(m_line_to_draw->back(), m_rect.GetBottom()-1); - m_total_volume += (m_rect.GetBottom() - m_line_to_draw->back()) * (visible_area->m_width / m_rect.GetWidth()) * (visible_area->m_height / m_rect.GetHeight()); + m_line_to_draw.back() = std::max(m_line_to_draw.back(), m_rect.GetTop()-1); + m_line_to_draw.back() = std::min(m_line_to_draw.back(), m_rect.GetBottom()-1); + m_total_volume += (m_rect.GetBottom() - m_line_to_draw.back()) * (visible_area.m_width / m_rect.GetWidth()) * (visible_area.m_height / m_rect.GetHeight()); } wxPostEvent(this->GetParent(), wxCommandEvent(EVT_WIPE_TOWER_CHART_CHANGED)); @@ -226,36 +226,26 @@ void Chart::recalculate_line() { -std::vector> Chart::get_ramming_speeds(float sampling) const { - std::vector> speeds_out; - for (unsigned int extruder_id = 0;extruder_id this_extruder; - const int number_of_samples = std::round( visible_areas[extruder_id].m_width / sampling); - if (number_of_samples>0) { - const int dx = (m_lines_to_draw[extruder_id].size()-1) / number_of_samples; - for (int j=0;j Chart::get_ramming_speed(float sampling) const { + std::vector speeds_out; + const int number_of_samples = std::round( visible_area.m_width / sampling); + if (number_of_samples>0) { + const int dx = (m_line_to_draw.size()-1) / number_of_samples; + for (int j=0;j>> Chart::get_buttons() const { - std::vector>> buttons_out; - for (const auto& ext : m_buttons) { - std::vector> this_extruder; - for (const auto& button : ext) - this_extruder.push_back(std::make_pair(button.get_pos().m_x,button.get_pos().m_y)); - buttons_out.push_back(std::move(this_extruder)); - } +std::vector> Chart::get_buttons() const { + std::vector> buttons_out; + for (const auto& button : m_buttons) + buttons_out.push_back(std::make_pair(button.get_pos().m_x,button.get_pos().m_y)); return buttons_out; } diff --git a/xs/src/slic3r/GUI/RammingChart.hpp b/xs/src/slic3r/GUI/RammingChart.hpp index 8274b96e6..520b5808e 100644 --- a/xs/src/slic3r/GUI/RammingChart.hpp +++ b/xs/src/slic3r/GUI/RammingChart.hpp @@ -13,39 +13,28 @@ wxDECLARE_EVENT(EVT_WIPE_TOWER_CHART_CHANGED, wxCommandEvent); class Chart : public wxWindow { public: - Chart(wxWindow* parent, wxRect rect,const std::vector>>& initial_buttons,std::vector> ramming_speed, float sampling) : + Chart(wxWindow* parent, wxRect rect,const std::vector>& initial_buttons,std::vector ramming_speed, float sampling) : wxWindow(parent,wxID_ANY,rect.GetTopLeft(),rect.GetSize()) { m_rect=wxRect(wxPoint(30,0),rect.GetSize()-wxSize(30,30)); - for (int i=0;i<4;++i) { - visible_areas.push_back(wxRect2DDouble(0.0, 0.0, sampling*ramming_speed[i].size(), 20.)); - m_buttons.push_back(std::vector()); - m_lines_to_draw.push_back(std::vector()); - if (initial_buttons.size()>0) - for (const auto& pair : initial_buttons[i]) - m_buttons.back().push_back(wxPoint2DDouble(pair.first,pair.second)); - set_extruder(i); // to calculate all interpolating splines - } - set_extruder(0); - } - void set_extruder(unsigned ext) { - if (ext>=4) return; - m_current_extruder = ext; - visible_area = &(visible_areas[ext]); - m_line_to_draw = &(m_lines_to_draw[ext]); + visible_area = wxRect2DDouble(0.0, 0.0, sampling*ramming_speed.size(), 20.); + m_buttons.clear(); + if (initial_buttons.size()>0) + for (const auto& pair : initial_buttons) + m_buttons.push_back(wxPoint2DDouble(pair.first,pair.second)); recalculate_line(); } void set_xy_range(float x,float y) { x = int(x/0.5) * 0.5; - if (x>=0) visible_area->SetRight(x); - if (y>=0) visible_area->SetBottom(y); + if (x>=0) visible_area.SetRight(x); + if (y>=0) visible_area.SetBottom(y); recalculate_line(); } float get_volume() const { return m_total_volume; } - float get_time() const { return visible_area->m_width; } - std::vector> get_ramming_speeds(float sampling) const; //returns sampled ramming speed for all extruders - std::vector>> get_buttons() const; // returns buttons position for all extruders - + float get_time() const { return visible_area.m_width; } + + std::vector get_ramming_speed(float sampling) const; //returns sampled ramming speed + std::vector> get_buttons() const; // returns buttons position void draw(wxDC& dc); @@ -80,8 +69,8 @@ private: wxPoint math_to_screen(const wxPoint2DDouble& math) const { wxPoint screen; - screen.x = (math.m_x-visible_area->m_x) * (m_rect.GetWidth() / visible_area->m_width ); - screen.y = (math.m_y-visible_area->m_y) * (m_rect.GetHeight() / visible_area->m_height ); + screen.x = (math.m_x-visible_area.m_x) * (m_rect.GetWidth() / visible_area.m_width ); + screen.y = (math.m_y-visible_area.m_y) * (m_rect.GetHeight() / visible_area.m_height ); screen.y *= -1; screen += m_rect.GetLeftBottom(); return screen; @@ -90,16 +79,16 @@ private: wxPoint2DDouble math = screen; math -= m_rect.GetLeftBottom(); math.m_y *= -1; - math.m_x *= visible_area->m_width / m_rect.GetWidth(); // scales to [0;1]x[0,1] - math.m_y *= visible_area->m_height / m_rect.GetHeight(); - return (math+visible_area->GetLeftTop()); + math.m_x *= visible_area.m_width / m_rect.GetWidth(); // scales to [0;1]x[0,1] + math.m_y *= visible_area.m_height / m_rect.GetHeight(); + return (math+visible_area.GetLeftTop()); } int which_button_is_clicked(const wxPoint& point) const { if (!m_rect.Contains(point)) return -1; - for (unsigned int i=0;i > m_buttons; - std::vector< std::vector > m_lines_to_draw; - std::vector< wxRect2DDouble > visible_areas; - wxRect2DDouble* visible_area = nullptr; - std::vector* m_line_to_draw = nullptr; + std::vector m_buttons; + std::vector m_line_to_draw; + wxRect2DDouble visible_area; ButtonToDrag* m_dragged = nullptr; - float m_total_volume = 0.f; - + float m_total_volume = 0.f; }; diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index ea80e2ece..58d714fc7 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -796,7 +796,7 @@ void TabPrint::update() bool have_wipe_tower = m_config->opt_bool("wipe_tower"); vec_enable.resize(0); - vec_enable = { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle"}; + vec_enable = { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "wipe_tower_bridging"}; for (auto el : vec_enable) get_field(el)->toggle(have_wipe_tower); m_wipe_tower_btn->Enable(have_wipe_tower); @@ -885,20 +885,18 @@ void TabFilament::build() optgroup->append_single_option_line("filament_cooling_time"); line = { _(L("Ramming")), "" }; line.widget = [this](wxWindow* parent){ - auto ramming_dialog = new wxButton(parent, wxID_ANY, _(L("Advanced settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(ramming_dialog); - /*m_wipe_tower_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) + auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(ramming_dialog_btn); + + ramming_dialog_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) { - std::string init_data = (m_config->option("wipe_tower_advanced"))->value; - std::cout << "dialog init: " << init_data << std::endl; - WipeTowerDialog dlg(this,init_data); // dlg lives on stack, no need to call Destroy - - if (dlg.ShowModal() == wxID_OK) { - load_key_value("wipe_tower_advanced", dlg.GetValue()); - std::cout << std::endl << "dialog returned: " << dlg.GetValue() << std::endl; + //std::string init_data = (m_config->option("wipe_tower_advanced"))->value; + RammingDialog dlg(this,std::string()); + if (dlg.ShowModal() == wxID_OK) { + //load_key_value("wipe_tower_advanced", dlg.GetValue()); } - }));*/ + })); return sizer; }; optgroup->append_line(line); diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index 1891a401c..8bf51e4e5 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -40,12 +40,37 @@ std::ostream& operator<<(std::ostream& str,Slic3r::WipeTowerParameters& par) { return str; } + + +RammingDialog::RammingDialog(wxWindow* parent,const std::string& init_data) +: wxDialog(parent, -1, wxT("Ramming customization"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +{ + this->Centre(); + m_panel_ramming = new RammingPanel(this,Slic3r::WipeTowerParameters(std::string())); + m_panel_ramming->Show(true); + this->Show(); + + auto main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->Add(m_panel_ramming, 1, wxEXPAND); + main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); + SetSizer(main_sizer); + SetMinSize(GetSize()); + main_sizer->SetSizeHints(this); + + this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); + this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { + // m_output_data=read_dialog_values(); + EndModal(wxID_OK); + },wxID_OK); +} + + RammingPanel::RammingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) -: wxPanel(parent,wxID_ANY,wxPoint(0,0),wxSize(0,0),wxBORDER_RAISED) +: wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(800,350),wxBORDER_RAISED) { new wxStaticText(this,wxID_ANY,wxString("Total ramming time (s):"), wxPoint(500,105), wxSize(200,25),wxALIGN_LEFT); m_widget_time = new wxSpinCtrlDouble(this,wxID_ANY,wxEmptyString, wxPoint(700,100), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,0.,5.0,3.,0.5); @@ -55,56 +80,40 @@ RammingPanel::RammingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p m_widget_ramming_line_width_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,200), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,10,200,100); new wxStaticText(this,wxID_ANY,wxString("Ramming line spacing (%):"), wxPoint(500,235), wxSize(200,25),wxALIGN_LEFT); m_widget_ramming_step_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,230), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,10,200,100); - new wxStaticText(this,wxID_ANY,wxString("Extruder #:"), wxPoint(500,12), wxSize(200,25),wxALIGN_LEFT); - wxArrayString choices; - for (unsigned int i=0;iset_extruder(0); m_widget_time->SetValue(m_chart->get_time()); m_widget_time->SetDigits(2); m_widget_volume->SetValue(m_chart->get_volume()); m_widget_volume->Disable(); - m_widget_extruder->SetSelection(0); - extruder_selection_changed(); // tell everyone to redraw + m_widget_ramming_line_width_multiplicator->SetValue(m_ramming_line_width_multiplicator); + m_widget_ramming_step_multiplicator->SetValue(m_ramming_step_multiplicator); m_widget_ramming_step_multiplicator->Bind(wxEVT_TEXT,[this](wxCommandEvent&) { line_parameters_changed(); }); m_widget_ramming_line_width_multiplicator->Bind(wxEVT_TEXT,[this](wxCommandEvent&) { line_parameters_changed(); }); - m_widget_extruder->Bind(wxEVT_CHOICE,[this](wxCommandEvent&) { extruder_selection_changed(); }); m_widget_time->Bind(wxEVT_TEXT,[this](wxCommandEvent&) {m_chart->set_xy_range(m_widget_time->GetValue(),-1);}); m_widget_time->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value m_widget_volume->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value - Bind(EVT_WIPE_TOWER_CHART_CHANGED,[this](wxCommandEvent&) {m_widget_volume->SetValue(m_chart->get_volume()); m_widget_time->SetValue(m_chart->get_time());} ); + Bind(EVT_WIPE_TOWER_CHART_CHANGED,[this](wxCommandEvent&) {m_widget_volume->SetValue(m_chart->get_volume()); m_widget_time->SetValue(m_chart->get_time());} ); + Refresh(this); } + void RammingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { if (!m_chart) return; - p.ramming_buttons = m_chart->get_buttons(); - p.ramming_speed = m_chart->get_ramming_speeds(p.sampling); - for (unsigned int i=0;iGetSelection(); - m_chart->set_extruder(m_current_extruder); // tell our chart to redraw - m_widget_ramming_line_width_multiplicator ->SetValue(m_ramming_line_width_multiplicators[m_current_extruder]); - m_widget_ramming_step_multiplicator->SetValue(m_ramming_step_multiplicators[m_current_extruder]); + p.ramming_buttons[0] = m_chart->get_buttons(); + p.ramming_speed[0] = m_chart->get_ramming_speed(p.sampling); + p.ramming_line_width_multiplicator.push_back(m_ramming_line_width_multiplicator/100.f); + p.ramming_step_multiplicator.push_back(m_ramming_step_multiplicator/100.f); } + void RammingPanel::line_parameters_changed() { - m_ramming_line_width_multiplicators[m_current_extruder]=m_widget_ramming_line_width_multiplicator->GetValue(); - m_ramming_step_multiplicators[m_current_extruder]=m_widget_ramming_step_multiplicator->GetValue(); + m_ramming_line_width_multiplicator = m_widget_ramming_line_width_multiplicator->GetValue(); + m_ramming_step_multiplicator = m_widget_ramming_step_multiplicator->GetValue(); } @@ -112,7 +121,7 @@ void RammingPanel::line_parameters_changed() { WipingPanel::WipingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) -: wxPanel(parent,wxID_ANY,wxPoint(0,0),wxSize(0,0),wxBORDER_RAISED) +: wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(800,350),wxBORDER_RAISED) { const int N = 4; // number of extruders new wxStaticText(this,wxID_ANY,wxString("Volume to wipe when the filament is being"),wxPoint(40,55) ,wxSize(500,25)); @@ -141,6 +150,7 @@ WipingPanel::WipingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) } m_widget_button->Bind(wxEVT_BUTTON,[this](wxCommandEvent&){fill_in_matrix();}); + Refresh(this); } void WipingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { @@ -183,7 +193,7 @@ void WipingPanel::fill_in_matrix() { WipeTowerDialog::WipeTowerDialog(wxWindow* parent,const std::string& init_data) -: wxDialog(parent, -1, wxT("Wipe tower advanced settings"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +: wxDialog(parent, -1, wxT("Wiping customization"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { this->Centre(); @@ -192,21 +202,11 @@ WipeTowerDialog::WipeTowerDialog(wxWindow* parent,const std::string& init_data) wxMessageDialog(this,"Wipe tower parameters not parsed correctly!\nRestoring default settings.","Error",wxICON_ERROR); parameters.set_defaults(); } - - wxNotebook* notebook = new wxNotebook(this,wxID_ANY,wxPoint(0,0),wxSize(800,450)); - - //m_panel_general = new GeneralPanel(notebook,parameters); - m_panel_ramming = new RammingPanel(notebook,parameters); - //m_panel_cooling = new CoolingPanel(notebook,parameters); - m_panel_wiping = new WipingPanel(notebook,parameters); - //notebook->AddPage(m_panel_general,"General"); - notebook->AddPage(m_panel_ramming,"Ramming"); - //notebook->AddPage(m_panel_cooling,"Cooling"); - notebook->AddPage(m_panel_wiping,"Wiping"); + m_panel_wiping = new WipingPanel(this,parameters); this->Show(); auto main_sizer = new wxBoxSizer(wxVERTICAL); - main_sizer->Add(notebook, 1, wxEXPAND); + main_sizer->Add(m_panel_wiping, 1, wxEXPAND); main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); SetSizer(main_sizer); SetMinSize(GetSize()); diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/xs/src/slic3r/GUI/WipeTowerDialog.hpp index 8a1c88be8..f9a9f9524 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.hpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.hpp @@ -15,10 +15,10 @@ // Human-readable output of Parameters structure std::ostream& operator<<(std::ostream& str,Slic3r::WipeTowerParameters& par); - class RammingPanel : public wxPanel { public: + RammingPanel(wxWindow* parent); RammingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p); void fill_parameters(Slic3r::WipeTowerParameters& p); @@ -28,17 +28,22 @@ private: wxSpinCtrl* m_widget_ramming_line_width_multiplicator = nullptr; wxSpinCtrl* m_widget_ramming_step_multiplicator = nullptr; wxSpinCtrlDouble* m_widget_time = nullptr; - wxChoice* m_widget_extruder = nullptr; - std::vector m_ramming_step_multiplicators; - std::vector m_ramming_line_width_multiplicators; - int m_current_extruder = 0; // zero-based index - - void extruder_selection_changed(); - + int m_ramming_step_multiplicator; + int m_ramming_line_width_multiplicator; + void line_parameters_changed(); }; +class RammingDialog : public wxDialog { +public: + RammingDialog(wxWindow* parent,const std::string& init_data); +private: + RammingPanel* m_panel_ramming = nullptr; +}; + + + class WipingPanel : public wxPanel { public: @@ -67,13 +72,11 @@ public: private: std::string m_file_name="config_wipe_tower"; - RammingPanel* m_panel_ramming = nullptr; WipingPanel* m_panel_wiping = nullptr; std::string m_output_data = ""; std::string read_dialog_values() { Slic3r::WipeTowerParameters p; - m_panel_ramming->fill_parameters(p); m_panel_wiping ->fill_parameters(p); return p.to_string(); } From 5f28b89ae02a873080a229f76debd2e5f406ef0e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 14 Mar 2018 11:54:11 +0100 Subject: [PATCH 36/81] Added a project specific config to the PresetBundle class. This project specific config will be stored into the config.ini, into .3mf and .amf and .gcode, and recover it from the same files. --- xs/src/slic3r/GUI/PresetBundle.cpp | 9 +++++++++ xs/src/slic3r/GUI/PresetBundle.hpp | 5 +++++ xs/xsp/GUI_Preset.xsp | 2 ++ 3 files changed, 16 insertions(+) diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index bf79c6562..7d2501a65 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -32,6 +32,9 @@ namespace Slic3r { +static std::vector s_project_options { +}; + PresetBundle::PresetBundle() : prints(Preset::TYPE_PRINT, Preset::print_options()), filaments(Preset::TYPE_FILAMENT, Preset::filament_options()), @@ -56,6 +59,8 @@ PresetBundle::PresetBundle() : this->filaments.load_bitmap_default("spool.png"); this->printers .load_bitmap_default("printer_empty.png"); this->load_compatible_bitmaps(); + + this->project_config.apply_only(FullPrintConfig::defaults(), s_project_options); } PresetBundle::~PresetBundle() @@ -223,6 +228,7 @@ DynamicPrintConfig PresetBundle::full_config() const out.apply(FullPrintConfig()); out.apply(this->prints.get_edited_preset().config); out.apply(this->printers.get_edited_preset().config); + out.apply(this->project_config); auto *nozzle_diameter = dynamic_cast(out.option("nozzle_diameter")); size_t num_extruders = nozzle_diameter->values.size(); @@ -412,6 +418,9 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool } } + // 4) Load the project config values (the per extruder wipe matrix etc). + this->project_config.apply_only(config, s_project_options); + this->update_compatible_with_printer(false); } diff --git a/xs/src/slic3r/GUI/PresetBundle.hpp b/xs/src/slic3r/GUI/PresetBundle.hpp index e6aea206d..6840df75e 100644 --- a/xs/src/slic3r/GUI/PresetBundle.hpp +++ b/xs/src/slic3r/GUI/PresetBundle.hpp @@ -39,6 +39,11 @@ public: // extruders.size() should be the same as printers.get_edited_preset().config.nozzle_diameter.size() std::vector filament_presets; + // The project configuration values are kept separated from the print/filament/printer preset, + // they are being serialized / deserialized from / to the .amf, .3mf, .config, .gcode, + // and they are being used by slicing core. + DynamicPrintConfig project_config; + bool has_defauls_only() const { return prints.size() <= 1 && filaments.size() <= 1 && printers.size() <= 1; } diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index 0033ebd0e..dc8ebf41c 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -161,6 +161,8 @@ PresetCollection::arrayref() Ref print() %code%{ RETVAL = &THIS->prints; %}; Ref filament() %code%{ RETVAL = &THIS->filaments; %}; Ref printer() %code%{ RETVAL = &THIS->printers; %}; + Ref project_config() %code%{ RETVAL = &THIS->project_config; %}; + bool has_defauls_only(); std::vector filament_presets() %code%{ RETVAL = THIS->filament_presets; %}; From 9f18b639a84e43f4f0f783b6023a4fd896269973 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 14 Mar 2018 15:48:37 +0100 Subject: [PATCH 37/81] Added filament_ramming_parameters and filament_ramming_buttons into configuration layer --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 2 +- xs/src/libslic3r/PrintConfig.cpp | 12 ++++++++++++ xs/src/libslic3r/PrintConfig.hpp | 4 ++++ xs/src/slic3r/GUI/Preset.cpp | 7 ++++--- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 3c2f82ffd..160848a47 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -56,7 +56,7 @@ std::istream& operator>>(std::istream& stream, std::vector& vect) { we_read_something = true; } if (!stream.eof() && we_read_something) { // if this is not eof, we might be at separator - let's get rid of it - stream.clear(); // if we failed on very first line or reached eof, return stream in !good() state + stream.clear(); // if we failed on very first line or reached eof, return stream in good() state stream.get(); // get() whatever we are stuck at } return stream; diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index b0b1c4e99..198d78ad3 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -479,6 +479,18 @@ PrintConfigDef::PrintConfigDef() def->min = 0; def->default_value = new ConfigOptionInts { 14 }; + def = this->add("filament_ramming_parameters", coStrings); + def->label = L("Ramming parameters"); + def->tooltip = L("This string is edited by RammingDialog and contains ramming specific parameters "); + def->cli = "filament-ramming-parameters=s@"; + def->default_value = new ConfigOptionStrings { "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0" }; + + def = this->add("filament_ramming_buttons", coStrings); + def->label = L("Draggable button in RammingDialog"); + def->tooltip = L("This string is edited by RammingDialog and contains position of draggable buttons "); + def->cli = "filament-ramming-buttons=s@"; + def->default_value = new ConfigOptionStrings { "0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" }; + def = this->add("filament_diameter", coFloats); def->label = L("Diameter"); def->tooltip = L("Enter your filament diameter here. Good precision is required, so use a caliper " diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 501a8ac36..c6d7ce277 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -471,6 +471,8 @@ public: ConfigOptionFloats filament_unloading_speed; ConfigOptionFloats filament_toolchange_delay; ConfigOptionInts filament_cooling_time; + ConfigOptionStrings filament_ramming_parameters; + ConfigOptionStrings filament_ramming_buttons; ConfigOptionBool gcode_comments; ConfigOptionEnum gcode_flavor; ConfigOptionString layer_gcode; @@ -527,6 +529,8 @@ protected: OPT_PTR(filament_unloading_speed); OPT_PTR(filament_toolchange_delay); OPT_PTR(filament_cooling_time); + OPT_PTR(filament_ramming_parameters); + OPT_PTR(filament_ramming_buttons); OPT_PTR(gcode_comments); OPT_PTR(gcode_flavor); OPT_PTR(layer_gcode); diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 92bfef416..c3a988e65 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -211,9 +211,10 @@ const std::vector& Preset::filament_options() static std::vector s_opts { "filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed", "extrusion_multiplier", "filament_density", "filament_cost", "filament_loading_speed", "filament_unloading_speed", "filament_toolchange_delay", - "filament_cooling_time", "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", - "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", - "min_print_speed", "start_filament_gcode", "end_filament_gcode","compatible_printers", "compatible_printers_condition" + "filament_cooling_time", "filament_ramming_buttons", "filament_ramming_parameters", "temperature", "first_layer_temperature", "bed_temperature", + "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", + "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", "end_filament_gcode","compatible_printers", + "compatible_printers_condition" }; return s_opts; } From 67009d80fd83d5bb3951e9e4b4cc73824e0cad6f Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 15 Mar 2018 14:04:12 +0100 Subject: [PATCH 38/81] Ramming parameters reduced to one and connected to the wipe tower generator again --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 19 +- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 106 +++-------- xs/src/libslic3r/Print.cpp | 4 +- xs/src/libslic3r/PrintConfig.cpp | 9 +- xs/src/libslic3r/PrintConfig.hpp | 2 - xs/src/slic3r/GUI/Preset.cpp | 2 +- xs/src/slic3r/GUI/RammingChart.hpp | 4 +- xs/src/slic3r/GUI/Tab.cpp | 8 +- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 187 +++++++++----------- xs/src/slic3r/GUI/WipeTowerDialog.hpp | 15 +- 10 files changed, 139 insertions(+), 217 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index b94950af1..ab5429615 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -465,6 +465,7 @@ WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *nam return INVALID; } + // Returns gcode to prime the nozzles at the front edge of the print bed. WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // print_z of the first layer. @@ -478,7 +479,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false); this->m_num_layer_changes = 0; this->m_current_tool = tools.front(); - + // The Prusa i3 MK2 has a working space of [0, -2.2] to [250, 210]. // Due to the XYZ calibration, this working space may shrink slightly from all directions, // therefore the homing position is shifted inside the bed by 0.2 in the firmware to [0.2, -2.0]. @@ -723,8 +724,8 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.append("; CP TOOLCHANGE UNLOAD\n"); - const float line_width = m_line_width * m_par.ramming_line_width_multiplicator[m_current_tool]; // desired ramming line thickness - const float y_step = line_width * m_par.ramming_step_multiplicator[m_current_tool] * m_extra_spacing; // spacing between lines in mm + const float line_width = m_line_width * m_filpar[m_current_tool].ramming_line_width_multiplicator; // desired ramming line thickness + const float y_step = line_width * m_filpar[m_current_tool].ramming_step_multiplicator * m_extra_spacing; // spacing between lines in mm unsigned i = 0; // iterates through ramming_speed m_left_to_right = true; // current direction of ramming @@ -778,10 +779,10 @@ void WipeTowerPrusaMM::toolchange_Unload( } // now the ramming itself: - while (i < m_par.ramming_speed[m_current_tool].size()) + while (i < m_filpar[m_current_tool].ramming_speed.size()) { - const float x = volume_to_length(m_par.ramming_speed[m_current_tool][i] * 0.25f, line_width, m_layer_height); - const float e = m_par.ramming_speed[m_current_tool][i] * 0.25f / Filament_Area; // transform volume per sec to E move; + const float x = volume_to_length(m_filpar[m_current_tool].ramming_speed[i] * 0.25f, line_width, m_layer_height); + const float e = m_filpar[m_current_tool].ramming_speed[i] * 0.25f / Filament_Area; // transform volume per sec to E move; const float dist = std::min(x - e_done, remaining); // distance to travel for either the next 0.25s, or to the next turnaround const float actual_time = dist/x * 0.25; writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), std::hypot(dist, e * (dist / x)) / (actual_time / 60.)); @@ -1092,10 +1093,10 @@ void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsi // this is an actual toolchange - let's calculate depth to reserve on the wipe tower float depth = 0.f; float width = m_wipe_tower_width - 3*m_perimeter_width; - float length_to_extrude = volume_to_length(0.25f * std::accumulate(m_par.ramming_speed[old_tool].begin(), m_par.ramming_speed[old_tool].end(), 0.f), - m_line_width * m_par.ramming_line_width_multiplicator[old_tool], + float length_to_extrude = volume_to_length(0.25f * std::accumulate(m_filpar[old_tool].ramming_speed.begin(), m_filpar[old_tool].ramming_speed.end(), 0.f), + m_line_width * m_filpar[old_tool].ramming_line_width_multiplicator, layer_height_par); - depth = (int(length_to_extrude / width) + 1) * (m_line_width * m_par.ramming_line_width_multiplicator[old_tool] * m_par.ramming_step_multiplicator[old_tool]); + depth = (int(length_to_extrude / width) + 1) * (m_line_width * m_filpar[old_tool].ramming_line_width_multiplicator * m_filpar[old_tool].ramming_step_multiplicator); float ramming_depth = depth; length_to_extrude = width*((length_to_extrude / width)-int(length_to_extrude / width)) - width; float first_wipe_line = -length_to_extrude; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 160848a47..4ecdb5f42 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -67,82 +67,11 @@ std::istream& operator>>(std::istream& stream, std::vector& vect) { struct WipeTowerParameters { WipeTowerParameters() { } // create new empty object WipeTowerParameters(const std::string& init_data) { // create object and initialize from std::string - std::istringstream in(init_data); // validation of input is left to the caller - in >> sampling; - for (std::vector vect{} ; in >> vect ;) { // until we get to fail state ("**")... - if (vect.size()>=2) { - ramming_line_width_multiplicator.push_back(vect[0]); - ramming_step_multiplicator.push_back(vect[1]); - vect.erase(vect.begin(),vect.begin()+2); - } - else vect.clear(); // something's not right, we will restore defaults anyway - ramming_speed.push_back(vect); - - if (in.good()) { - in >> vect; - std::vector> pairs; - for (unsigned int i=0;i vect{} ; in >> vect ;) { // let's keep reading - wipe_volumes.push_back(vect); - } - in.clear(); - in.get(); - - std::vector vect{}; - in >> vect; - for (unsigned int i=0;i{7.6f, 7.6f, 7.6f, 7.6f, 9.f, 9.f, 9.f, 10.7f, 10.7f, 10.7f}); - ramming_buttons.push_back(std::vector>{{0.05f, 6.6f},{0.45f, 6.8f},{0.95f, 7.8f},{1.45f, 8.3f},{1.95f, 9.7f},{2.45f,10.f},{2.95f, 7.6f},{3.45f, 7.6f},{3.95f, 7.6f},{4.45f, 7.6f},{4.95f, 7.6f}}); - } wipe_volumes = {{ 0.f, 60.f, 60.f, 60.f}, { 60.f, 0.f, 60.f, 60.f}, { 60.f, 60.f, 0.f, 60.f}, @@ -151,10 +80,6 @@ struct WipeTowerParameters { } float sampling = 0.25f; // this does not quite work yet, keep it fixed to 0.25f - std::vector ramming_line_width_multiplicator; - std::vector ramming_step_multiplicator; - std::vector> ramming_speed; - std::vector>> ramming_buttons; std::vector> wipe_volumes; std::vector> filament_wipe_volumes; }; @@ -222,7 +147,7 @@ public: // Set the extruder properties. void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed, - float unloading_speed, float delay, int cooling_time) + float unloading_speed, float delay, int cooling_time, std::string ramming_parameters) { m_filpar[idx].material = material; m_filpar[idx].temperature = temp; @@ -231,6 +156,14 @@ public: m_filpar[idx].unloading_speed = unloading_speed; m_filpar[idx].delay = delay; m_filpar[idx].cooling_time = cooling_time; + + std::stringstream stream{ramming_parameters}; + float speed = 0.f; + stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator; + m_filpar[idx].ramming_line_width_multiplicator /= 100; + m_filpar[idx].ramming_step_multiplicator /= 100; + while (stream >> speed) + m_filpar[idx].ramming_speed.push_back(speed); } @@ -345,13 +278,16 @@ private: struct FilamentParameters { - material_type material; - int temperature; - int first_layer_temperature; - float loading_speed; - float unloading_speed; - float delay; - int cooling_time; + material_type material; + int temperature; + int first_layer_temperature; + float loading_speed; + float unloading_speed; + float delay; + int cooling_time; + float ramming_line_width_multiplicator; + float ramming_step_multiplicator; + std::vector ramming_speed; }; // Extruder specific parameters. diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 95c57339a..ae34b47d8 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -189,6 +189,7 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.filament_loading_speed.get_at(i), this->config.filament_unloading_speed.get_at(i), this->config.filament_toolchange_delay.get_at(i), - this->config.filament_toolchange_delay.get_at(i)); + this->config.filament_cooling_time.get_at(i), + this->config.filament_ramming_parameters.get_at(i)); // When printing the first layer's wipe tower, the first extruder is expected to be active and primed. // Therefore the number of wipe sections at the wipe tower will be (m_tool_ordering.front().extruders-1) at the 1st layer. diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 198d78ad3..081c05b2d 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -483,13 +483,8 @@ PrintConfigDef::PrintConfigDef() def->label = L("Ramming parameters"); def->tooltip = L("This string is edited by RammingDialog and contains ramming specific parameters "); def->cli = "filament-ramming-parameters=s@"; - def->default_value = new ConfigOptionStrings { "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0" }; - - def = this->add("filament_ramming_buttons", coStrings); - def->label = L("Draggable button in RammingDialog"); - def->tooltip = L("This string is edited by RammingDialog and contains position of draggable buttons "); - def->cli = "filament-ramming-buttons=s@"; - def->default_value = new ConfigOptionStrings { "0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" }; + def->default_value = new ConfigOptionStrings { "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0|" + " 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" }; def = this->add("filament_diameter", coFloats); def->label = L("Diameter"); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index c6d7ce277..ecec43ae1 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -472,7 +472,6 @@ public: ConfigOptionFloats filament_toolchange_delay; ConfigOptionInts filament_cooling_time; ConfigOptionStrings filament_ramming_parameters; - ConfigOptionStrings filament_ramming_buttons; ConfigOptionBool gcode_comments; ConfigOptionEnum gcode_flavor; ConfigOptionString layer_gcode; @@ -530,7 +529,6 @@ protected: OPT_PTR(filament_toolchange_delay); OPT_PTR(filament_cooling_time); OPT_PTR(filament_ramming_parameters); - OPT_PTR(filament_ramming_buttons); OPT_PTR(gcode_comments); OPT_PTR(gcode_flavor); OPT_PTR(layer_gcode); diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index c3a988e65..5049c9cf6 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -211,7 +211,7 @@ const std::vector& Preset::filament_options() static std::vector s_opts { "filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed", "extrusion_multiplier", "filament_density", "filament_cost", "filament_loading_speed", "filament_unloading_speed", "filament_toolchange_delay", - "filament_cooling_time", "filament_ramming_buttons", "filament_ramming_parameters", "temperature", "first_layer_temperature", "bed_temperature", + "filament_cooling_time", "filament_ramming_parameters", "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", "end_filament_gcode","compatible_printers", "compatible_printers_condition" diff --git a/xs/src/slic3r/GUI/RammingChart.hpp b/xs/src/slic3r/GUI/RammingChart.hpp index 520b5808e..5ec8b33ee 100644 --- a/xs/src/slic3r/GUI/RammingChart.hpp +++ b/xs/src/slic3r/GUI/RammingChart.hpp @@ -13,11 +13,11 @@ wxDECLARE_EVENT(EVT_WIPE_TOWER_CHART_CHANGED, wxCommandEvent); class Chart : public wxWindow { public: - Chart(wxWindow* parent, wxRect rect,const std::vector>& initial_buttons,std::vector ramming_speed, float sampling) : + Chart(wxWindow* parent, wxRect rect,const std::vector>& initial_buttons,int ramming_speed_size, float sampling) : wxWindow(parent,wxID_ANY,rect.GetTopLeft(),rect.GetSize()) { m_rect=wxRect(wxPoint(30,0),rect.GetSize()-wxSize(30,30)); - visible_area = wxRect2DDouble(0.0, 0.0, sampling*ramming_speed.size(), 20.); + visible_area = wxRect2DDouble(0.0, 0.0, sampling*ramming_speed_size, 20.); m_buttons.clear(); if (initial_buttons.size()>0) for (const auto& pair : initial_buttons) diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 58d714fc7..ef95da90b 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -469,7 +469,7 @@ void TabPrint::build() { std::string init_data = (m_config->option("wipe_tower_advanced"))->value; std::cout << "dialog init: " << init_data << std::endl; - WipeTowerDialog dlg(this,init_data); // dlg lives on stack, no need to call Destroy + WipingDialog dlg(this,init_data); // dlg lives on stack, no need to call Destroy if (dlg.ShowModal() == wxID_OK) { load_key_value("wipe_tower_advanced", dlg.GetValue()); @@ -891,10 +891,10 @@ void TabFilament::build() ramming_dialog_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) { - //std::string init_data = (m_config->option("wipe_tower_advanced"))->value; - RammingDialog dlg(this,std::string()); + RammingDialog dlg(this,(m_config->option("filament_ramming_parameters"))->get_at(0)); if (dlg.ShowModal() == wxID_OK) { - //load_key_value("wipe_tower_advanced", dlg.GetValue()); + wxMessageBox("DIALOG OK:\n"+dlg.get_parameters()); + //load_key_value("wipe_tower_advanced", dlg.get_parameters()); } })); return sizer; diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index 8bf51e4e5..8e2746329 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -1,52 +1,13 @@ #include +#include #include "WipeTowerDialog.hpp" -// Human-readable output of Parameters structure -std::ostream& operator<<(std::ostream& str,Slic3r::WipeTowerParameters& par) { - str << "sampling: " << par.sampling << "\n"; - - str << "line widths: "; - for (const auto& a : par.ramming_line_width_multiplicator) str << a << " "; - - str << "line spacing: "; - for (const auto& a : par.ramming_step_multiplicator) str << a << " "; - - str<<"\n\nramming_speeds:\n"; - for (const auto& a : par.ramming_speed) { - for (const auto& b : a) - str << b << " "; - str<<"\n"; - } - str<<"\n\nramming_buttons:\n"; - for (const auto& a : par.ramming_buttons) { - for (const auto& b : a) { - Slic3r::operator <<(str,b); // temporary hack (this << is in the namespace Slic3r) - str << " | "; // the function will be deleted after everything is debugged, anyway - } - str<<"\n"; - } - str<<"\n\nwipe volumes:\n"; - for (const auto& a : par.wipe_volumes) { - for (const auto& b : a) - str << b << " "; - str<<"\n"; - } - str<<"\n\nfilament wipe volumes:\n"; - for (const auto& a : par.filament_wipe_volumes) { - Slic3r::operator <<(str,a); - str << " "; - } - str<<"\n"; - - return str; -} - -RammingDialog::RammingDialog(wxWindow* parent,const std::string& init_data) +RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) : wxDialog(parent, -1, wxT("Ramming customization"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { this->Centre(); - m_panel_ramming = new RammingPanel(this,Slic3r::WipeTowerParameters(std::string())); + m_panel_ramming = new RammingPanel(this,parameters); m_panel_ramming->Show(true); this->Show(); @@ -60,7 +21,7 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& init_data) this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { - // m_output_data=read_dialog_values(); + m_output_data = m_panel_ramming->get_parameters(); EndModal(wxID_OK); },wxID_OK); } @@ -69,7 +30,7 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& init_data) -RammingPanel::RammingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) +RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters) : wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(800,350),wxBORDER_RAISED) { new wxStaticText(this,wxID_ANY,wxString("Total ramming time (s):"), wxPoint(500,105), wxSize(200,25),wxALIGN_LEFT); @@ -81,8 +42,22 @@ RammingPanel::RammingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p new wxStaticText(this,wxID_ANY,wxString("Ramming line spacing (%):"), wxPoint(500,235), wxSize(200,25),wxALIGN_LEFT); m_widget_ramming_step_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,230), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,10,200,100); + std::stringstream stream{parameters}; + stream >> m_ramming_line_width_multiplicator >> m_ramming_step_multiplicator; + int ramming_speed_size = 0; + float dummy = 0.f; + while (stream >> dummy) + ++ramming_speed_size; + stream.clear(); + stream.get(); - m_chart = new Chart(this,wxRect(10,10,480,360),p.ramming_buttons[0],p.ramming_speed[0],p.sampling); + std::vector> buttons; + float x = 0.f; + float y = 0.f; + while (stream >> x >> y) + buttons.push_back(std::make_pair(x,y)); + + m_chart = new Chart(this,wxRect(10,10,480,360),buttons,ramming_speed_size,0.25f); m_widget_time->SetValue(m_chart->get_time()); m_widget_time->SetDigits(2); @@ -100,26 +75,83 @@ RammingPanel::RammingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p Refresh(this); } - -void RammingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) -{ - if (!m_chart) return; - p.ramming_buttons[0] = m_chart->get_buttons(); - p.ramming_speed[0] = m_chart->get_ramming_speed(p.sampling); - p.ramming_line_width_multiplicator.push_back(m_ramming_line_width_multiplicator/100.f); - p.ramming_step_multiplicator.push_back(m_ramming_step_multiplicator/100.f); -} - - void RammingPanel::line_parameters_changed() { m_ramming_line_width_multiplicator = m_widget_ramming_line_width_multiplicator->GetValue(); m_ramming_step_multiplicator = m_widget_ramming_step_multiplicator->GetValue(); } +std::string RammingPanel::get_parameters() +{ + std::vector speeds = m_chart->get_ramming_speed(0.25f); + std::vector> buttons = m_chart->get_buttons(); + std::stringstream stream; + stream << m_ramming_line_width_multiplicator << " " << m_ramming_step_multiplicator; + for (const float& speed_value : speeds) + stream << " " << speed_value; + stream << "|"; + for (const auto& button : buttons) + stream << " " << button.first << " " << button.second; + return stream.str(); +} + + + + +/* +void WipingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { + p.wipe_volumes.clear(); + p.filament_wipe_volumes.clear(); + for (int i=0;i<4;++i) { + // first go through the full matrix: + p.wipe_volumes.push_back(std::vector()); + for (int j=0;j<4;++j) { + double val = 0.; + edit_boxes[j][i]->GetValue().ToDouble(&val); + p.wipe_volumes[i].push_back((float)val); + } + + // now the filament volumes: + p.filament_wipe_volumes.push_back(std::make_pair(m_old[i]->GetValue(),m_new[i]->GetValue())); + } +} +*/ + + + +WipingDialog::WipingDialog(wxWindow* parent,const std::string& init_data) +: wxDialog(parent, -1, wxT("Wiping customization"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +{ + this->Centre(); + + Slic3r::WipeTowerParameters parameters(init_data); + /*if (!parameters.validate()) { + wxMessageDialog(this,"Wipe tower parameters not parsed correctly!\nRestoring default settings.","Error",wxICON_ERROR); + parameters.set_defaults(); + }*/ + m_panel_wiping = new WipingPanel(this,parameters); + this->Show(); + + auto main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->Add(m_panel_wiping, 1, wxEXPAND); + main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); + SetSizer(main_sizer); + SetMinSize(GetSize()); + main_sizer->SetSizeHints(this); + + this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); + + this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { + m_output_data=read_dialog_values(); + EndModal(wxID_OK); + },wxID_OK); +} + + + WipingPanel::WipingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) : wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(800,350),wxBORDER_RAISED) { @@ -153,23 +185,6 @@ WipingPanel::WipingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) Refresh(this); } -void WipingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { - p.wipe_volumes.clear(); - p.filament_wipe_volumes.clear(); - for (int i=0;i<4;++i) { - // first go through the full matrix: - p.wipe_volumes.push_back(std::vector()); - for (int j=0;j<4;++j) { - double val = 0.; - edit_boxes[j][i]->GetValue().ToDouble(&val); - p.wipe_volumes[i].push_back((float)val); - } - - // now the filament volumes: - p.filament_wipe_volumes.push_back(std::make_pair(m_old[i]->GetValue(),m_new[i]->GetValue())); - } -} - void WipingPanel::fill_in_matrix() { wxArrayString choices; choices.Add("sum"); @@ -192,31 +207,5 @@ void WipingPanel::fill_in_matrix() { -WipeTowerDialog::WipeTowerDialog(wxWindow* parent,const std::string& init_data) -: wxDialog(parent, -1, wxT("Wiping customization"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) -{ - this->Centre(); - - Slic3r::WipeTowerParameters parameters(init_data); - if (!parameters.validate()) { - wxMessageDialog(this,"Wipe tower parameters not parsed correctly!\nRestoring default settings.","Error",wxICON_ERROR); - parameters.set_defaults(); - } - m_panel_wiping = new WipingPanel(this,parameters); - this->Show(); - auto main_sizer = new wxBoxSizer(wxVERTICAL); - main_sizer->Add(m_panel_wiping, 1, wxEXPAND); - main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); - SetSizer(main_sizer); - SetMinSize(GetSize()); - main_sizer->SetSizeHints(this); - - this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); - - this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { - m_output_data=read_dialog_values(); - EndModal(wxID_OK); - },wxID_OK); -} diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/xs/src/slic3r/GUI/WipeTowerDialog.hpp index f9a9f9524..92624037b 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.hpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.hpp @@ -13,14 +13,13 @@ #include "RammingChart.hpp" -// Human-readable output of Parameters structure std::ostream& operator<<(std::ostream& str,Slic3r::WipeTowerParameters& par); class RammingPanel : public wxPanel { public: RammingPanel(wxWindow* parent); - RammingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p); - void fill_parameters(Slic3r::WipeTowerParameters& p); + RammingPanel(wxWindow* parent,const std::string& data); + std::string get_parameters(); private: Chart* m_chart = nullptr; @@ -37,9 +36,11 @@ private: class RammingDialog : public wxDialog { public: - RammingDialog(wxWindow* parent,const std::string& init_data); + RammingDialog(wxWindow* parent,const std::string& parameters); + std::string get_parameters() { return m_output_data; } private: RammingPanel* m_panel_ramming = nullptr; + std::string m_output_data; }; @@ -63,9 +64,9 @@ private: -class WipeTowerDialog : public wxDialog { +class WipingDialog : public wxDialog { public: - WipeTowerDialog(wxWindow* parent,const std::string& init_data); + WipingDialog(wxWindow* parent,const std::string& init_data); std::string GetValue() const { return m_output_data; } @@ -78,7 +79,7 @@ private: std::string read_dialog_values() { Slic3r::WipeTowerParameters p; m_panel_wiping ->fill_parameters(p); - return p.to_string(); + //return p.to_string(); } }; From b556cec42d25291fa167da745c9b985490b0a8ac Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 16 Mar 2018 13:58:58 +0100 Subject: [PATCH 39/81] Got rid of wipe_tower_advanced option --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 2 +- xs/src/libslic3r/Print.cpp | 3 +-- xs/src/libslic3r/PrintConfig.cpp | 24 +++++++++++++++------ xs/src/libslic3r/PrintConfig.hpp | 6 +++--- xs/src/slic3r/GUI/Preset.cpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 9 ++++---- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 21 +++++++----------- xs/src/slic3r/GUI/WipeTowerDialog.hpp | 10 ++++----- 8 files changed, 40 insertions(+), 37 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 4ecdb5f42..d5dc4f962 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -110,7 +110,7 @@ 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 wipe_area, float rotation_angle, float cooling_tube_retraction, - float cooling_tube_length, float parking_pos_retraction, float bridging, bool adhesion, std::string& parameters, + float cooling_tube_length, float parking_pos_retraction, float bridging, bool adhesion, const std::string& parameters, unsigned int initial_tool) : m_wipe_tower_pos(x, y), m_wipe_tower_width(width), diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index ae34b47d8..6a804c10d 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -195,7 +195,6 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.wipe_tower_rotation_angle.value), float(this->config.cooling_tube_retraction.value), float(this->config.cooling_tube_length.value), float(this->config.parking_pos_retraction.value), float(this->config.wipe_tower_bridging), bool(this->config.wipe_tower_adhesion), - this->config.wipe_tower_advanced.value,m_tool_ordering.first_extruder()); + /*this->config.wipe_tower_advanced.value*/std::string(""),m_tool_ordering.first_extruder()); //wipe_tower.set_retract(); //wipe_tower.set_zhop(); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 081c05b2d..6d40b8582 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1773,12 +1773,24 @@ PrintConfigDef::PrintConfigDef() def->cli = "wipe-tower!"; def->default_value = new ConfigOptionBool(false); - def = this->add("wipe_tower_advanced", coString); - def->label = L("Advanced string"); - def->tooltip = L("Advanced tooltip "); - def->sidetext = L("advanced sidetext"); - def->cli = "wipe-tower-advanced=s"; - def->default_value = new ConfigOptionString(""); + def = this->add("wiping_volumes_extruders", coFloats); + def->label = L("Extrusion multiplier"); + def->tooltip = L("This vector saves required volumes to change from/to each tool used on the " + "wipe tower. These values are used to simplify creation of the full purging " + "volumes below. "); + def->cli = "wiping-volumes-extruders=f@"; + def->default_value = new ConfigOptionFloats { 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f }; + + def = this->add("wiping_volumes_matrix", coFloats); + def->label = L("Extrusion multiplier"); + def->tooltip = L("This matrix describes volumes (in cubic milimetres) required to purge the" + " new filament on the wipe tower for any given pair of tools. "); + def->cli = "wiping-volumes-matrix=f@"; + def->default_value = new ConfigOptionFloats { 0.f, 100.f, 100.f, 100.f, 100.f, + 100.f, 0.f, 100.f, 100.f, 100.f, + 100.f, 100.f, 0.f, 100.f, 100.f, + 100.f, 100.f, 100.f, 0.f, 100.f, + 100.f, 100.f, 100.f, 100.f, 0.f }; def = this->add("wipe_tower_x", coFloat); def->label = L("Position X"); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index ecec43ae1..af0c814e1 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -500,7 +500,8 @@ public: ConfigOptionFloat cooling_tube_retraction; ConfigOptionFloat cooling_tube_length; ConfigOptionFloat parking_pos_retraction; - + + std::string get_extrusion_axis() const { return @@ -622,7 +623,6 @@ public: ConfigOptionInt threads; ConfigOptionBools wipe; ConfigOptionBool wipe_tower; - ConfigOptionString wipe_tower_advanced; ConfigOptionFloat wipe_tower_x; ConfigOptionFloat wipe_tower_y; ConfigOptionFloat wipe_tower_width; @@ -690,7 +690,6 @@ protected: OPT_PTR(threads); OPT_PTR(wipe); OPT_PTR(wipe_tower); - OPT_PTR(wipe_tower_advanced); OPT_PTR(wipe_tower_x); OPT_PTR(wipe_tower_y); OPT_PTR(wipe_tower_width); @@ -736,6 +735,7 @@ class FullPrintConfig : public: // Validate the FullPrintConfig. Returns an empty string on success, otherwise an error message is returned. std::string validate(); + protected: // Protected constructor to be called to initialize ConfigCache::m_default. FullPrintConfig(int) : PrintObjectConfig(0), PrintRegionConfig(0), PrintConfig(0), HostConfig(0) {} diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 5049c9cf6..e2706c5db 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -198,7 +198,7 @@ const std::vector& Preset::print_options() "ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width", "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", - "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower_advanced", "wipe_tower", "wipe_tower_x", + "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "wipe_tower_adhesion", "wipe_tower_bridging", "compatible_printers", "compatible_printers_condition" diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index ef95da90b..473e0b13c 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -467,13 +467,12 @@ void TabPrint::build() sizer->Add(m_wipe_tower_btn); m_wipe_tower_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) { - std::string init_data = (m_config->option("wipe_tower_advanced"))->value; - std::cout << "dialog init: " << init_data << std::endl; - WipingDialog dlg(this,init_data); // dlg lives on stack, no need to call Destroy + //auto init_data = (m_config->option("wiping_volumes_matrix"))->values; + //WipingDialog dlg(this,std::vector(init_data.begin(), init_data.end())); // dlg lives on stack, no need to call Destroy if (dlg.ShowModal() == wxID_OK) { - load_key_value("wipe_tower_advanced", dlg.GetValue()); - std::cout << std::endl << "dialog returned: " << dlg.GetValue() << std::endl; + //load_key_value("wipe_tower_advanced", dlg.GetValue()); + //std::cout << std::endl << "dialog returned: " << dlg.GetValue() << std::endl; } })); return sizer; diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index 8e2746329..1c69285b7 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -122,17 +122,12 @@ void WipingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { -WipingDialog::WipingDialog(wxWindow* parent,const std::string& init_data) +WipingDialog::WipingDialog(wxWindow* parent,const std::vector& init_data) : wxDialog(parent, -1, wxT("Wiping customization"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { this->Centre(); - - Slic3r::WipeTowerParameters parameters(init_data); - /*if (!parameters.validate()) { - wxMessageDialog(this,"Wipe tower parameters not parsed correctly!\nRestoring default settings.","Error",wxICON_ERROR); - parameters.set_defaults(); - }*/ - m_panel_wiping = new WipingPanel(this,parameters); + + m_panel_wiping = new WipingPanel(this,init_data); this->Show(); auto main_sizer = new wxBoxSizer(wxVERTICAL); @@ -145,14 +140,14 @@ WipingDialog::WipingDialog(wxWindow* parent,const std::string& init_data) this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { - m_output_data=read_dialog_values(); + //m_output_data=read_dialog_values(); EndModal(wxID_OK); },wxID_OK); } -WipingPanel::WipingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) +WipingPanel::WipingPanel(wxWindow* parent,const std::vector& data) : wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(800,350),wxBORDER_RAISED) { const int N = 4; // number of extruders @@ -162,8 +157,8 @@ WipingPanel::WipingPanel(wxWindow* parent,const Slic3r::WipeTowerParameters& p) m_widget_button = new wxButton(this,wxID_ANY,"-> Fill in the matrix ->",wxPoint(300,130),wxSize(175,50)); for (int i=0;iDisable(); else - edit_boxes[i][j]->SetValue(wxString("")<SetValue(wxString("")<& data); void fill_parameters(Slic3r::WipeTowerParameters& p); private: @@ -66,15 +66,13 @@ private: class WipingDialog : public wxDialog { public: - WipingDialog(wxWindow* parent,const std::string& init_data); - - std::string GetValue() const { return m_output_data; } + WipingDialog(wxWindow* parent,const std::vector& init_data); + std::vector get_value() const { return m_output_data; } private: - std::string m_file_name="config_wipe_tower"; WipingPanel* m_panel_wiping = nullptr; - std::string m_output_data = ""; + std::vector m_output_data; std::string read_dialog_values() { Slic3r::WipeTowerParameters p; From e41eff91868063326fc4e163c33a6201d0fe8149 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 19 Mar 2018 15:30:54 +0100 Subject: [PATCH 40/81] Wiping volumes options temporarily added to Print Settings --- xs/src/libslic3r/PrintConfig.hpp | 4 ++++ xs/src/slic3r/GUI/Preset.cpp | 2 +- xs/src/slic3r/GUI/PresetBundle.cpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 7 ++++--- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 3488b5c4f..b35cf9cf1 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -630,6 +630,8 @@ public: ConfigOptionFloat wipe_tower_rotation_angle; ConfigOptionFloat wipe_tower_bridging; ConfigOptionBool wipe_tower_adhesion; + ConfigOptionFloats wiping_volumes_matrix; + ConfigOptionFloats wiping_volumes_extruders; ConfigOptionFloat z_offset; protected: @@ -698,6 +700,8 @@ protected: OPT_PTR(wipe_tower_rotation_angle); OPT_PTR(wipe_tower_bridging); OPT_PTR(wipe_tower_adhesion); + OPT_PTR(wiping_volumes_matrix); + OPT_PTR(wiping_volumes_extruders); OPT_PTR(z_offset); } }; diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 57fa97774..847c7e523 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -200,7 +200,7 @@ const std::vector& Preset::print_options() "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "wipe_tower_adhesion", "wipe_tower_bridging", - "compatible_printers", "compatible_printers_condition" + "wiping_volumes_matrix", "wiping_volumes_extruders", "compatible_printers", "compatible_printers_condition" }; return s_opts; diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 7d2501a65..668b9ee12 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -32,7 +32,7 @@ namespace Slic3r { -static std::vector s_project_options { +static std::vector s_project_options { }; PresetBundle::PresetBundle() : diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 8cec658b3..6e978f083 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -528,11 +528,12 @@ void TabPrint::build() sizer->Add(m_wipe_tower_btn); m_wipe_tower_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) { - //auto init_data = (m_config->option("wiping_volumes_matrix"))->values; - //WipingDialog dlg(this,std::vector(init_data.begin(), init_data.end())); // dlg lives on stack, no need to call Destroy + std::vector init_data = (m_config->option("wiping_volumes_matrix"))->values; + load_key_value("wiping_volumes_matrix", a); + WipingDialog dlg(this,std::vector(init_data.begin(), init_data.end())); // dlg lives on stack, no need to call Destroy if (dlg.ShowModal() == wxID_OK) { - //load_key_value("wipe_tower_advanced", dlg.GetValue()); + //load_key_value("wiping_volumes_matrix", dlg.GetValue()); //std::cout << std::endl << "dialog returned: " << dlg.GetValue() << std::endl; } })); From 349a8a88aec920c0970fe384f6ee94cab5e8a9a9 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 19 Mar 2018 15:35:31 +0100 Subject: [PATCH 41/81] Bug fix: speed for finish_layer was not properly set --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index ab5429615..59fa7dced 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -1014,7 +1014,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() else box.expand(-m_perimeter_width); } else i=2; // only draw the inner perimeter, outer has been already drawn by tool_change(...) - writer.rectangle(box.ld,box.rd.x-box.ld.x,box.ru.y-box.rd.y); + writer.rectangle(box.ld,box.rd.x-box.ld.x,box.ru.y-box.rd.y,2900*speed_factor); } // we are in one of the corners, travel to ld along the perimeter: diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 6e978f083..d220130fd 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -529,7 +529,6 @@ void TabPrint::build() m_wipe_tower_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) { std::vector init_data = (m_config->option("wiping_volumes_matrix"))->values; - load_key_value("wiping_volumes_matrix", a); WipingDialog dlg(this,std::vector(init_data.begin(), init_data.end())); // dlg lives on stack, no need to call Destroy if (dlg.ShowModal() == wxID_OK) { From 76b280c64caab570c5b3e3fb6704cfa9a767797d Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 19 Mar 2018 15:53:49 +0100 Subject: [PATCH 42/81] Removed parameter 'wipe_tower_adhesion', it will always be true --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 3 +-- xs/src/libslic3r/Print.cpp | 3 +-- xs/src/libslic3r/PrintConfig.cpp | 7 ------- xs/src/libslic3r/PrintConfig.hpp | 2 -- xs/src/slic3r/GUI/Preset.cpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 1 - 6 files changed, 3 insertions(+), 15 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index d5dc4f962..8cfc5872c 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -110,7 +110,7 @@ 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 wipe_area, float rotation_angle, float cooling_tube_retraction, - float cooling_tube_length, float parking_pos_retraction, float bridging, bool adhesion, const std::string& parameters, + float cooling_tube_length, float parking_pos_retraction, float bridging, const std::string& parameters, unsigned int initial_tool) : m_wipe_tower_pos(x, y), m_wipe_tower_width(width), @@ -126,7 +126,6 @@ public: m_par(parameters) { m_bridging = bridging; - m_adhesion = adhesion; for (size_t i = 0; i < 4; ++ i) { // Extruder specific parameters. diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index a126d84b7..0167b8ba7 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -202,7 +202,6 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value), float(this->config.wipe_tower_rotation_angle.value), float(this->config.cooling_tube_retraction.value), float(this->config.cooling_tube_length.value), float(this->config.parking_pos_retraction.value), - float(this->config.wipe_tower_bridging), bool(this->config.wipe_tower_adhesion), + float(this->config.wipe_tower_bridging), /*this->config.wipe_tower_advanced.value*/std::string(""),m_tool_ordering.first_extruder()); //wipe_tower.set_retract(); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index a09b896c9..ff426c9a2 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1840,13 +1840,6 @@ PrintConfigDef::PrintConfigDef() def->sidetext = L("mm"); def->cli = "wipe-tower-bridging=f"; def->default_value = new ConfigOptionFloat(10.); - - def = this->add("wipe_tower_adhesion", coBool); - def->label = L("Increase first layer adhesion"); - def->tooltip = L("This prevents using sparse infill on the first layer, if it would be " - "normally applied. Dense infill is used instead. "); - def->cli = "wipe-tower_adhesion!"; - def->default_value = new ConfigOptionBool(true); def = this->add("xy_size_compensation", coFloat); def->label = L("XY Size Compensation"); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index b35cf9cf1..d184a2161 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -629,7 +629,6 @@ public: ConfigOptionFloat wipe_tower_per_color_wipe; ConfigOptionFloat wipe_tower_rotation_angle; ConfigOptionFloat wipe_tower_bridging; - ConfigOptionBool wipe_tower_adhesion; ConfigOptionFloats wiping_volumes_matrix; ConfigOptionFloats wiping_volumes_extruders; ConfigOptionFloat z_offset; @@ -699,7 +698,6 @@ protected: OPT_PTR(wipe_tower_per_color_wipe); OPT_PTR(wipe_tower_rotation_angle); OPT_PTR(wipe_tower_bridging); - OPT_PTR(wipe_tower_adhesion); OPT_PTR(wiping_volumes_matrix); OPT_PTR(wiping_volumes_extruders); OPT_PTR(z_offset); diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 847c7e523..99d003f7a 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -199,7 +199,7 @@ const std::vector& Preset::print_options() "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", - "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "wipe_tower_adhesion", "wipe_tower_bridging", + "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "wipe_tower_bridging", "wiping_volumes_matrix", "wiping_volumes_extruders", "compatible_printers", "compatible_printers_condition" }; diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index d220130fd..e3e773f7d 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -520,7 +520,6 @@ void TabPrint::build() optgroup->append_single_option_line("wipe_tower_per_color_wipe"); optgroup->append_single_option_line("wipe_tower_rotation_angle"); optgroup->append_single_option_line("wipe_tower_bridging"); - optgroup->append_single_option_line("wipe_tower_adhesion"); line = { _(L("Advanced")), "" }; line.widget = [this](wxWindow* parent){ m_wipe_tower_btn = new wxButton(parent, wxID_ANY, _(L("Advanced settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); From a923062167ed8f0632eda1eeca304e4aecaeec71 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 20 Mar 2018 13:50:51 +0100 Subject: [PATCH 43/81] Purging volume dialog improved and connected to configuration layer --- xs/src/slic3r/GUI/Tab.cpp | 12 +- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 175 +++++++++++++++++--------- xs/src/slic3r/GUI/WipeTowerDialog.hpp | 34 ++--- 3 files changed, 141 insertions(+), 80 deletions(-) diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index e3e773f7d..146696d1e 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -527,12 +527,16 @@ void TabPrint::build() sizer->Add(m_wipe_tower_btn); m_wipe_tower_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) { - std::vector init_data = (m_config->option("wiping_volumes_matrix"))->values; - WipingDialog dlg(this,std::vector(init_data.begin(), init_data.end())); // dlg lives on stack, no need to call Destroy + std::vector init_matrix = (m_config->option("wiping_volumes_matrix"))->values; + std::vector init_extruders = (m_config->option("wiping_volumes_extruders"))->values; + + WipingDialog dlg(this,std::vector(init_matrix.begin(),init_matrix.end()),std::vector(init_extruders.begin(),init_extruders.end())); if (dlg.ShowModal() == wxID_OK) { - //load_key_value("wiping_volumes_matrix", dlg.GetValue()); - //std::cout << std::endl << "dialog returned: " << dlg.GetValue() << std::endl; + std::vector matrix = dlg.get_matrix(); + std::vector extruders = dlg.get_extruders(); + (m_config->option("wiping_volumes_matrix"))->values = std::vector(matrix.begin(),matrix.end()); + (m_config->option("wiping_volumes_extruders"))->values = std::vector(extruders.begin(),extruders.end()); } })); return sizer; diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index 1c69285b7..fc3d30a5d 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -2,6 +2,11 @@ #include #include "WipeTowerDialog.hpp" +//! macro used to mark string used at localization, +//! return same string +#define L(s) s + + RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) : wxDialog(parent, -1, wxT("Ramming customization"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) @@ -97,37 +102,12 @@ std::string RammingPanel::get_parameters() - - - - -/* -void WipingPanel::fill_parameters(Slic3r::WipeTowerParameters& p) { - p.wipe_volumes.clear(); - p.filament_wipe_volumes.clear(); - for (int i=0;i<4;++i) { - // first go through the full matrix: - p.wipe_volumes.push_back(std::vector()); - for (int j=0;j<4;++j) { - double val = 0.; - edit_boxes[j][i]->GetValue().ToDouble(&val); - p.wipe_volumes[i].push_back((float)val); - } - - // now the filament volumes: - p.filament_wipe_volumes.push_back(std::make_pair(m_old[i]->GetValue(),m_new[i]->GetValue())); - } -} -*/ - - - -WipingDialog::WipingDialog(wxWindow* parent,const std::vector& init_data) -: wxDialog(parent, -1, wxT("Wiping customization"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +WipingDialog::WipingDialog(wxWindow* parent,const std::vector& matrix, const std::vector& extruders) +: wxDialog(parent, -1, wxT(L("Wipe tower - Purging volume adjustment")), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { this->Centre(); - m_panel_wiping = new WipingPanel(this,init_data); + m_panel_wiping = new WipingPanel(this,matrix,extruders); this->Show(); auto main_sizer = new wxBoxSizer(wxVERTICAL); @@ -140,59 +120,85 @@ WipingDialog::WipingDialog(wxWindow* parent,const std::vector& init_data) this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { - //m_output_data=read_dialog_values(); + m_output_matrix = m_panel_wiping->read_matrix_values(); + m_output_extruders = m_panel_wiping->read_extruders_values(); EndModal(wxID_OK); },wxID_OK); } -WipingPanel::WipingPanel(wxWindow* parent,const std::vector& data) -: wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(800,350),wxBORDER_RAISED) + +WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, const std::vector& extruders) +: wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(500,350),wxBORDER_RAISED) { - const int N = 4; // number of extruders - new wxStaticText(this,wxID_ANY,wxString("Volume to wipe when the filament is being"),wxPoint(40,55) ,wxSize(500,25)); - new wxStaticText(this,wxID_ANY,wxString("unloaded"),wxPoint(110,75) ,wxSize(500,25)); - new wxStaticText(this,wxID_ANY,wxString("loaded"),wxPoint(195,75) ,wxSize(500,25)); - m_widget_button = new wxButton(this,wxID_ANY,"-> Fill in the matrix ->",wxPoint(300,130),wxSize(175,50)); - for (int i=0;i(0)); - new wxStaticText(this,wxID_ANY,wxString("")<Disable(); else - edit_boxes[i][j]->SetValue(wxString("")<SetValue(wxString("")<Bind(wxEVT_BUTTON,[this](wxCommandEvent&){fill_in_matrix();}); - Refresh(this); + + m_widget_button->Bind(wxEVT_BUTTON,[this](wxCommandEvent&){toggle_advanced(true);}); + toggle_advanced(); } + + + + +std::vector WipingPanel::read_matrix_values() { + if (!m_advanced) + fill_in_matrix(); + std::vector output; + for (unsigned int i=0;iGetValue().ToDouble(&val); + output.push_back((float)val); + } + } + return output; +} + + +std::vector WipingPanel::read_extruders_values() { + std::vector output; + for (unsigned int i=0;iGetValue()); + output.push_back(m_new[i]->GetValue()); + } + return output; +} + + void WipingPanel::fill_in_matrix() { - wxArrayString choices; - choices.Add("sum"); - choices.Add("maximum"); - wxSingleChoiceDialog dialog(this,"How shall I calculate volume for any given pair?\n\nI can either sum volumes for old and new filament, or just use the higher value.","DEBUGGING",choices); - if (dialog.ShowModal() == wxID_CANCEL) - return; - for (unsigned i=0;i<4;++i) { - for (unsigned j=0;j<4;++j) { + for (unsigned i=0;iSetValue(wxString("")<< (m_old[i]->GetValue() + m_new[j]->GetValue())); - else - edit_boxes[j][i]->SetValue(wxString("")<< (std::max(m_old[i]->GetValue(), m_new[j]->GetValue()))); + edit_boxes[j][i]->SetValue(wxString("")<< (m_old[i]->GetValue() + m_new[j]->GetValue())); } } } @@ -200,7 +206,52 @@ void WipingPanel::fill_in_matrix() { +bool WipingPanel::advanced_matches_simple() { + for (unsigned i=0;iGetValue() != (wxString("")<< (m_old[i]->GetValue() + m_new[j]->GetValue()))) + return false; + } + } + return true; +} +void WipingPanel::toggle_advanced(bool user_button) { + if (m_advanced && !advanced_matches_simple() && user_button) { + if (wxMessageDialog(this,wxString(L("Switching to simple settings will discard changes done in the advanced mode!\n\nDo you want to proceed?")), + wxString(L("Warning")),wxYES_NO|wxICON_EXCLAMATION).ShowModal() != wxID_YES) + return; + } + m_advanced = !m_advanced; + + if (!user_button) { // we were called from constructor + if (advanced_matches_simple()) // advanced and simple match - let's show simple version + m_advanced = false; + else + m_advanced = true; + } + + for (unsigned i=0;iShow(m_advanced); + m_old[i]->Show(!m_advanced); + m_new[i]->Show(!m_advanced); + } + for (const auto& widget : m_advanced_widgets) // shows/hides other widgets + widget->Show(m_advanced); + for (const auto& widget : m_notadvanced_widgets) + widget->Show(!m_advanced); + + if (m_advanced) { + if (user_button) fill_in_matrix(); // otherwise keep values loaded from config + m_widget_button->SetLabel(L("Show simplified settings")); + } + else + m_widget_button->SetLabel(L("Show advanced settings")); + + this->Refresh(); +} \ No newline at end of file diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/xs/src/slic3r/GUI/WipeTowerDialog.hpp index 8e84f3dc1..0adefe5f2 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.hpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.hpp @@ -46,18 +46,28 @@ private: + + + class WipingPanel : public wxPanel { public: - WipingPanel(wxWindow* parent,const std::vector& data); - void fill_parameters(Slic3r::WipeTowerParameters& p); + WipingPanel(wxWindow* parent, const std::vector& matrix, const std::vector& extruders); + std::vector read_matrix_values(); + std::vector read_extruders_values(); private: void fill_in_matrix(); + void toggle_advanced(bool user_button = false); + bool advanced_matches_simple(); std::vector m_old; std::vector m_new; + std::vector m_advanced_widgets; + std::vector m_notadvanced_widgets; std::vector> edit_boxes; - wxButton* m_widget_button=nullptr; + wxButton* m_widget_button = nullptr; + unsigned int m_number_of_extruders = 0; + bool m_advanced = false; }; @@ -66,19 +76,15 @@ private: class WipingDialog : public wxDialog { public: - WipingDialog(wxWindow* parent,const std::vector& init_data); - std::vector get_value() const { return m_output_data; } - - + WipingDialog(wxWindow* parent,const std::vector& matrix, const std::vector& extruders); + std::vector get_matrix() const { return m_output_matrix; } + std::vector get_extruders() const { return m_output_extruders; } + + private: WipingPanel* m_panel_wiping = nullptr; - std::vector m_output_data; - - std::string read_dialog_values() { - Slic3r::WipeTowerParameters p; - m_panel_wiping ->fill_parameters(p); - //return p.to_string(); - } + std::vector m_output_matrix; + std::vector m_output_extruders; }; #endif // _WIPE_TOWER_DIALOG_H_ \ No newline at end of file From a782424d5f4ab4e34e4291af8cee965b2ad23848 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 20 Mar 2018 15:07:18 +0100 Subject: [PATCH 44/81] Wipe tower generator connected to purging volumes from the configuration layer --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 8 +-- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 63 ++------------------- xs/src/libslic3r/Print.cpp | 4 +- xs/src/slic3r/GUI/WipeTowerDialog.hpp | 5 -- 4 files changed, 13 insertions(+), 67 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 59fa7dced..2010b7ae7 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -514,7 +514,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( toolchange_Load(writer, cleaning_box); // Prime the tool. if (idx_tool + 1 == tools.size()) { // Last tool should not be unloaded, but it should be wiped enough to become of a pure color. - toolchange_Wipe(writer, cleaning_box, m_par.wipe_volumes[tools[idx_tool-1]][tool]); + toolchange_Wipe(writer, cleaning_box, wipe_volumes[tools[idx_tool-1]][tool]); } else { // Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool. //writer.travel(writer.x(), writer.y() + m_perimeter_width, 7200); @@ -566,7 +566,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo { for (const auto &b : m_layer_info->tool_changes) if ( b.new_tool == tool ) { - wipe_volume = m_par.wipe_volumes[b.old_tool][b.new_tool]; + wipe_volume = wipe_volumes[b.old_tool][b.new_tool]; if (tool == m_layer_info->tool_changes.back().new_tool) last_change_in_layer = true; wipe_area = b.required_depth * m_layer_info->extra_spacing; @@ -1100,7 +1100,7 @@ void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsi float ramming_depth = depth; length_to_extrude = width*((length_to_extrude / width)-int(length_to_extrude / width)) - width; float first_wipe_line = -length_to_extrude; - length_to_extrude += volume_to_length(m_par.wipe_volumes[old_tool][new_tool], m_line_width, layer_height_par); + length_to_extrude += volume_to_length(wipe_volumes[old_tool][new_tool], m_line_width, layer_height_par); length_to_extrude = std::max(length_to_extrude,0.f); depth += (int(length_to_extrude / width) + 1) * m_line_width; @@ -1146,7 +1146,7 @@ void WipeTowerPrusaMM::save_on_last_wipe() float width = m_wipe_tower_width - 3*m_perimeter_width; // width we draw into float length_to_save = 2*(m_wipe_tower_width+m_wipe_tower_depth) + (!layer_finished() ? finish_layer().total_extrusion_length_in_plane() : 0.f); - float length_to_wipe = volume_to_length(m_par.wipe_volumes[m_layer_info->tool_changes.back().old_tool][m_layer_info->tool_changes.back().new_tool], + float length_to_wipe = volume_to_length(wipe_volumes[m_layer_info->tool_changes.back().old_tool][m_layer_info->tool_changes.back().new_tool], m_line_width,m_layer_info->height) - m_layer_info->tool_changes.back().first_wipe_line - length_to_save; length_to_wipe = std::max(length_to_wipe,0.f); diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 8cfc5872c..acdcef8f2 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -31,59 +31,6 @@ namespace PrusaMultiMaterial { -// Operator overload to output std::pairs -template -std::ostream& operator<<(std::ostream& stream,const std::pair& pair) { - return stream << pair.first << " " << pair.second; -} - -// Operator overload to output elements of a vector to std::ofstream easily: -template -std::ostream& operator<<(std::ostream& stream,const std::vector& vect) { - for (const auto& element : vect) - stream << element << " "; - return stream; -} - -// Operator overload to input elements of a vector from std::ifstream easily (reads until a fail) -template -std::istream& operator>>(std::istream& stream, std::vector& vect) { - vect.clear(); - T value{}; - bool we_read_something = false; - while (stream >> value) { - vect.push_back(value); - we_read_something = true; - } - if (!stream.eof() && we_read_something) { // if this is not eof, we might be at separator - let's get rid of it - stream.clear(); // if we failed on very first line or reached eof, return stream in good() state - stream.get(); // get() whatever we are stuck at - } - return stream; -} - - -// This struct is used to store parameters and to pass it to wipe tower generator -struct WipeTowerParameters { - WipeTowerParameters() { } // create new empty object - WipeTowerParameters(const std::string& init_data) { // create object and initialize from std::string - set_defaults(); - } - - void set_defaults() { - sampling = 0.25f; - wipe_volumes = {{ 0.f, 60.f, 60.f, 60.f}, - { 60.f, 0.f, 60.f, 60.f}, - { 60.f, 60.f, 0.f, 60.f}, - { 60.f, 60.f, 60.f, 0.f}}; - filament_wipe_volumes = {{30.f,30.f},{30.f,30.f},{30.f,30.f},{30.f,30.f}}; - } - - float sampling = 0.25f; // this does not quite work yet, keep it fixed to 0.25f - std::vector> wipe_volumes; - std::vector> filament_wipe_volumes; -}; - class WipeTowerPrusaMM : public WipeTower { @@ -110,7 +57,7 @@ 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 wipe_area, float rotation_angle, float cooling_tube_retraction, - float cooling_tube_length, float parking_pos_retraction, float bridging, const std::string& parameters, + float cooling_tube_length, float parking_pos_retraction, float bridging, const std::vector& wiping_matrix, unsigned int initial_tool) : m_wipe_tower_pos(x, y), m_wipe_tower_width(width), @@ -123,9 +70,11 @@ public: m_cooling_tube_length(cooling_tube_length), m_parking_pos_retraction(parking_pos_retraction), m_current_tool(initial_tool), - m_par(parameters) + m_bridging(bridging) { - m_bridging = bridging; + const unsigned int number_of_extruders = int(sqrt(wiping_matrix.size())+WT_EPSILON); + for (unsigned int i = 0; i(wiping_matrix.begin()+i*number_of_extruders,wiping_matrix.begin()+(i+1)*number_of_extruders)); for (size_t i = 0; i < 4; ++ i) { // Extruder specific parameters. @@ -301,7 +250,7 @@ private: // A fill-in direction (positive Y, negative Y) alternates with each layer. wipe_shape m_current_shape = SHAPE_NORMAL; unsigned int m_current_tool = 0; - WipeTowerParameters m_par; + std::vector> wipe_volumes; float m_depth_traversed = 0.f; // Current y position at the wipe tower. // How much to wipe the 1st extruder over the wipe tower at the 1st layer diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 0167b8ba7..acff4492a 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -202,6 +202,7 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.wipe_tower_rotation_angle.value), float(this->config.cooling_tube_retraction.value), float(this->config.cooling_tube_length.value), float(this->config.parking_pos_retraction.value), float(this->config.wipe_tower_bridging), - /*this->config.wipe_tower_advanced.value*/std::string(""),m_tool_ordering.first_extruder()); + std::vector((this->config.wiping_volumes_matrix.values).begin(),(this->config.wiping_volumes_matrix.values).end()), + m_tool_ordering.first_extruder()); //wipe_tower.set_retract(); //wipe_tower.set_zhop(); diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/xs/src/slic3r/GUI/WipeTowerDialog.hpp index 0adefe5f2..54ae9596d 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.hpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.hpp @@ -5,16 +5,11 @@ #include #include #include -#include -#include #include -#include "../../libslic3r/GCode/WipeTowerPrusaMM.hpp" #include "RammingChart.hpp" -std::ostream& operator<<(std::ostream& str,Slic3r::WipeTowerParameters& par); - class RammingPanel : public wxPanel { public: RammingPanel(wxWindow* parent); From 0fc2da5a325d07252d57a6bb1a88ad1e27824df3 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 20 Mar 2018 15:45:11 +0100 Subject: [PATCH 45/81] Wipe tower generator should now work for more than 4 extruders (actual number extracted from wiping_volumes_matrix) --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 32 +++++++++++---------- xs/src/libslic3r/Print.cpp | 11 +++---- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index acdcef8f2..90317673e 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -69,19 +69,19 @@ public: m_cooling_tube_retraction(cooling_tube_retraction), m_cooling_tube_length(cooling_tube_length), m_parking_pos_retraction(parking_pos_retraction), - m_current_tool(initial_tool), - m_bridging(bridging) + m_bridging(bridging), + m_current_tool(initial_tool) { const unsigned int number_of_extruders = int(sqrt(wiping_matrix.size())+WT_EPSILON); for (unsigned int i = 0; i(wiping_matrix.begin()+i*number_of_extruders,wiping_matrix.begin()+(i+1)*number_of_extruders)); - for (size_t i = 0; i < 4; ++ i) { + /*for (size_t i = 0; i < number_of_extruders; ++ i) { // Extruder specific parameters. - m_filpar[i].material = PLA; + m_filpar[i].material = PLA; m_filpar[i].temperature = 0; m_filpar[i].first_layer_temperature = 0; - } + }*/ } virtual ~WipeTowerPrusaMM() {} @@ -97,6 +97,8 @@ public: void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed, float unloading_speed, float delay, int cooling_time, std::string ramming_parameters) { + while (m_filpar.size() < idx+1) // makes sure the required element is in the vector + m_filpar.push_back(FilamentParameters()); m_filpar[idx].material = material; m_filpar[idx].temperature = temp; m_filpar[idx].first_layer_temperature = first_layer_temp; @@ -226,20 +228,20 @@ private: struct FilamentParameters { - material_type material; - int temperature; - int first_layer_temperature; - float loading_speed; - float unloading_speed; - float delay; - int cooling_time; - float ramming_line_width_multiplicator; - float ramming_step_multiplicator; + material_type material = PLA; + int temperature = 0; + int first_layer_temperature = 0; + float loading_speed = 0.f; + float unloading_speed = 0.f; + float delay = 0.f ; + int cooling_time = 0; + float ramming_line_width_multiplicator = 0.f; + float ramming_step_multiplicator = 0.f; std::vector ramming_speed; }; // Extruder specific parameters. - FilamentParameters m_filpar[4]; + std::vector m_filpar; // State of the wiper tower generator. diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index acff4492a..cd227ed1c 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1037,21 +1037,22 @@ void Print::_make_wipe_tower() } } + // Get wiping matrix to get number of extruders and convert vector to vector: + std::vector wiping_volumes((this->config.wiping_volumes_matrix.values).begin(),(this->config.wiping_volumes_matrix.values).end()); + // Initialize the wipe tower. WipeTowerPrusaMM wipe_tower( float(this->config.wipe_tower_x.value), float(this->config.wipe_tower_y.value), float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value), float(this->config.wipe_tower_rotation_angle.value), float(this->config.cooling_tube_retraction.value), float(this->config.cooling_tube_length.value), float(this->config.parking_pos_retraction.value), - float(this->config.wipe_tower_bridging), - std::vector((this->config.wiping_volumes_matrix.values).begin(),(this->config.wiping_volumes_matrix.values).end()), - m_tool_ordering.first_extruder()); - + float(this->config.wipe_tower_bridging), wiping_volumes, m_tool_ordering.first_extruder()); + //wipe_tower.set_retract(); //wipe_tower.set_zhop(); // Set the extruder & material properties at the wipe tower object. - for (size_t i = 0; i < 4; ++ i) + for (size_t i = 0; i < (int)(sqrt(wiping_volumes.size())+EPSILON); ++ i) wipe_tower.set_extruder( i, WipeTowerPrusaMM::parse_material(this->config.filament_type.get_at(i).c_str()), From ac9db81820af7b531ea548cc8f8f2b149a87db08 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 21 Mar 2018 09:36:27 +0100 Subject: [PATCH 46/81] Normalization of purging volume parameters when number of extruders is changed --- xs/src/slic3r/GUI/PresetBundle.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 668b9ee12..d26a007bb 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -719,6 +719,35 @@ void PresetBundle::update_multi_material_filament_presets() // Append the rest of filament presets. // if (this->filament_presets.size() < num_extruders) this->filament_presets.resize(num_extruders, this->filament_presets.empty() ? this->filaments.first_visible().name : this->filament_presets.back()); + + + + // Now verify if wiping_volumes_matrix has proper size (it is used to deduce number of extruders in wipe tower generator): + std::vector old_matrix = (prints.get_edited_preset().config.option("wiping_volumes_matrix"))->values; + size_t old_number_of_extruders = int(sqrt(old_matrix.size())+EPSILON); + // First do it for the extruders presets (in-place): + std::vector& extruders = (prints.get_edited_preset().config.option("wiping_volumes_extruders"))->values; + while (extruders.size() < 2*num_extruders) { + extruders.push_back(extruders[0]); // copy the values from the first extruder + extruders.push_back(extruders[1]); + } + while (extruders.size() > 2*num_extruders) { + extruders.pop_back(); + extruders.pop_back(); + } + // Now update the purging volume matrix: + if (num_extruders != old_number_of_extruders) { + std::vector new_matrix; + for (unsigned int i=0;i("wiping_volumes_matrix"))->values = new_matrix; + } } void PresetBundle::update_compatible_with_printer(bool select_other_if_incompatible) From 1a1be94c99f99a63aab45a13f83711e8a007e8c2 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 21 Mar 2018 10:20:36 +0100 Subject: [PATCH 47/81] Purging volume parameters normalization - minor changes --- xs/src/slic3r/GUI/PresetBundle.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index d26a007bb..1d4795832 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -721,22 +721,21 @@ void PresetBundle::update_multi_material_filament_presets() this->filament_presets.resize(num_extruders, this->filament_presets.empty() ? this->filaments.first_visible().name : this->filament_presets.back()); - // Now verify if wiping_volumes_matrix has proper size (it is used to deduce number of extruders in wipe tower generator): std::vector old_matrix = (prints.get_edited_preset().config.option("wiping_volumes_matrix"))->values; size_t old_number_of_extruders = int(sqrt(old_matrix.size())+EPSILON); - // First do it for the extruders presets (in-place): + if (num_extruders != old_number_of_extruders) { + // First verify if purging volumes presets for each extruder matches number of extruders std::vector& extruders = (prints.get_edited_preset().config.option("wiping_volumes_extruders"))->values; while (extruders.size() < 2*num_extruders) { - extruders.push_back(extruders[0]); // copy the values from the first extruder - extruders.push_back(extruders[1]); + extruders.push_back(extruders.size()>1 ? extruders[0] : 50.); // copy the values from the first extruder + extruders.push_back(extruders.size()>1 ? extruders[1] : 50.); } while (extruders.size() > 2*num_extruders) { extruders.pop_back(); extruders.pop_back(); } - // Now update the purging volume matrix: - if (num_extruders != old_number_of_extruders) { + std::vector new_matrix; for (unsigned int i=0;i Date: Wed, 21 Mar 2018 15:57:17 +0100 Subject: [PATCH 48/81] Partial refactoring of wipe tower code (got rid of global constants, etc) --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 108 ++++++++------------ xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 94 +++++++---------- xs/src/libslic3r/Print.cpp | 1 - xs/src/slic3r/GUI/WipeTowerDialog.cpp | 2 +- 4 files changed, 79 insertions(+), 126 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 2010b7ae7..7c8181ff6 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -33,7 +33,6 @@ TODO LIST #define strcasecmp _stricmp #endif -const bool peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet namespace Slic3r { @@ -119,7 +118,7 @@ public: if (! m_preview_suppressed && e > 0.f && len > 0.) { // Width of a squished extrusion, corrected for the roundings of the squished extrusions. // This is left zero if it is a travel move. - float width = float(double(e) * Filament_Area / (len * m_layer_height)); + float width = float(double(e) * /*Filament_Area*/2.40528 / (len * m_layer_height)); // Correct for the roundings of a squished extrusion. width += m_layer_height * float(1. - M_PI / 4.); if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos) @@ -415,33 +414,12 @@ private: } Writer& operator=(const Writer &rhs); -}; - -/* -class Material -{ -public: - std::string name; - std::string type; - - struct RammingStep { -// float length; - float extrusion_multiplier; // sirka linky - float extrusion; - float speed; - }; - std::vector ramming_sequence; - - // Number and speed of the cooling moves. - std::vector cooling_moves; - - // Percentage of the speed overide, in pairs of - std::vector> speed_override; -}; -*/ +}; // class Writer }; // namespace PrusaMultiMaterial + + WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *name) { if (strcasecmp(name, "PLA") == 0) @@ -476,6 +454,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // If false, the last priming are will be large enough to wipe the last extruder sufficiently. bool last_wipe_inside_wipe_tower) { + this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false); this->m_num_layer_changes = 0; this->m_current_tool = tools.front(); @@ -484,8 +463,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // Due to the XYZ calibration, this working space may shrink slightly from all directions, // therefore the homing position is shifted inside the bed by 0.2 in the firmware to [0.2, -2.0]. // box_coordinates cleaning_box(xy(0.5f, - 1.5f), m_wipe_tower_width, wipe_area); - //FIXME: set the width properly - const float prime_section_width = 55.f; + + const float prime_section_width = std::min(240.f / tools.size(), 60.f); box_coordinates cleaning_box(xy(5.f, 0.f), prime_section_width, 100.f); PrusaMultiMaterial::Writer writer; @@ -556,7 +535,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo if ( m_print_brim ) return toolchange_Brim(); - float wipe_area = 0.f; bool last_change_in_layer = false; float wipe_volume = 0.f; @@ -589,7 +567,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) - .set_y_shift(m_y_shift + (tool!=(unsigned int)(-1) && (m_current_shape == SHAPE_REVERSED && !peters_wipe_tower) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f)) + .set_y_shift(m_y_shift + (tool!=(unsigned int)(-1) && (m_current_shape == SHAPE_REVERSED && !m_peters_wipe_tower) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f)) .append(";--------------------\n" "; CP TOOLCHANGE START\n") .comment_with_value(" toolchange #", m_num_tool_changes) @@ -625,7 +603,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo if (last_change_in_layer) {// draw perimeter line writer.set_y_shift(m_y_shift); - if (peters_wipe_tower) + if (m_peters_wipe_tower) writer.rectangle(m_wipe_tower_pos,m_layer_info->depth + 3*m_perimeter_width,m_wipe_tower_depth); else { writer.rectangle(m_wipe_tower_pos,m_wipe_tower_width, m_layer_info->depth + m_perimeter_width); @@ -724,7 +702,7 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.append("; CP TOOLCHANGE UNLOAD\n"); - const float line_width = m_line_width * m_filpar[m_current_tool].ramming_line_width_multiplicator; // desired ramming line thickness + const float line_width = m_perimeter_width * m_filpar[m_current_tool].ramming_line_width_multiplicator; // desired ramming line thickness const float y_step = line_width * m_filpar[m_current_tool].ramming_step_multiplicator * m_extra_spacing; // spacing between lines in mm unsigned i = 0; // iterates through ramming_speed @@ -757,7 +735,7 @@ void WipeTowerPrusaMM::toolchange_Unload( if (tch.old_tool == m_current_tool) { sum_of_depths += tch.ramming_depth; float ramming_end_y = m_wipe_tower_pos.y + sum_of_depths; - ramming_end_y -= (y_step/m_extra_spacing-m_line_width) / 2.f; // center of final ramming line + ramming_end_y -= (y_step/m_extra_spacing-m_perimeter_width) / 2.f; // center of final ramming line // debugging: /*float oldx = writer.x(); @@ -851,7 +829,7 @@ void WipeTowerPrusaMM::toolchange_Unload( // this is to align ramming and future wiping extrusions, so the future y-steps can be uniform from the start: // the perimeter_width will later be subtracted, it is there to not load while moving over just extruded material - writer.travel(end_of_ramming.x, end_of_ramming.y + (y_step/m_extra_spacing-m_line_width) / 2.f + m_perimeter_width, 2400.f); + writer.travel(end_of_ramming.x, end_of_ramming.y + (y_step/m_extra_spacing-m_perimeter_width) / 2.f + m_perimeter_width, 2400.f); writer.resume_preview() .flush_planner_queue(); @@ -925,8 +903,8 @@ void WipeTowerPrusaMM::toolchange_Wipe( // the ordered volume, even if it means violating the box. This can later be removed and simply // wipe until the end of the assigned area. - float x_to_wipe = volume_to_length(wipe_volume, m_line_width, m_layer_height); - float dy = m_extra_spacing*m_line_width; + float x_to_wipe = volume_to_length(wipe_volume, m_perimeter_width, m_layer_height); + float dy = m_extra_spacing*m_perimeter_width; float wipe_speed = 1600.f; // if there is less than 2.5*m_perimeter_width to the edge, advance straightaway (there is likely a blob anyway) @@ -990,7 +968,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() .set_layer_height(m_layer_height) .set_initial_tool(m_current_tool) .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle) - .set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED && !peters_wipe_tower ? m_layer_info->toolchanges_depth() : 0.f)) + .set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED && !m_peters_wipe_tower ? m_layer_info->toolchanges_depth() : 0.f)) .append(";--------------------\n" "; CP EMPTY GRID START\n") // m_num_layer_changes is incremented by set_z, so it is 1 based. @@ -1024,11 +1002,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() if (m_is_first_layer && m_adhesion) { // Extrude a dense infill at the 1st layer to improve 1st layer adhesion of the wipe tower. box.expand(-m_perimeter_width/2.f); - unsigned nsteps = int(floor((box.lu.y - box.ld.y) / (2*m_perimeter_width))); + int nsteps = int(floor((box.lu.y - box.ld.y) / (2*m_perimeter_width))); float step = (box.lu.y - box.ld.y) / nsteps; writer.travel(box.ld-xy(m_perimeter_width/2.f,m_perimeter_width/2.f)); if (nsteps >= 0) - for (size_t i = 0; i < nsteps; ++i) { + for (int i = 0; i < nsteps; ++i) { writer.extrude(box.ld.x+m_perimeter_width/2.f, writer.y() + 0.5f * step); writer.extrude(box.rd.x - m_perimeter_width / 2.f, writer.y()); writer.extrude(box.rd.x - m_perimeter_width / 2.f, writer.y() + 0.5f * step); @@ -1076,7 +1054,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() // Appends a toolchange into m_plan and calculates neccessary depth of the corresponding box void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool,bool brim) -{ +{ assert(m_plan.back().z <= z_par + WT_EPSILON ); // refuses to add a layer below the last one if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan first @@ -1094,16 +1072,16 @@ void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsi float depth = 0.f; float width = m_wipe_tower_width - 3*m_perimeter_width; float length_to_extrude = volume_to_length(0.25f * std::accumulate(m_filpar[old_tool].ramming_speed.begin(), m_filpar[old_tool].ramming_speed.end(), 0.f), - m_line_width * m_filpar[old_tool].ramming_line_width_multiplicator, + m_perimeter_width * m_filpar[old_tool].ramming_line_width_multiplicator, layer_height_par); - depth = (int(length_to_extrude / width) + 1) * (m_line_width * m_filpar[old_tool].ramming_line_width_multiplicator * m_filpar[old_tool].ramming_step_multiplicator); + depth = (int(length_to_extrude / width) + 1) * (m_perimeter_width * m_filpar[old_tool].ramming_line_width_multiplicator * m_filpar[old_tool].ramming_step_multiplicator); float ramming_depth = depth; length_to_extrude = width*((length_to_extrude / width)-int(length_to_extrude / width)) - width; float first_wipe_line = -length_to_extrude; - length_to_extrude += volume_to_length(wipe_volumes[old_tool][new_tool], m_line_width, layer_height_par); + length_to_extrude += volume_to_length(wipe_volumes[old_tool][new_tool], m_perimeter_width, layer_height_par); length_to_extrude = std::max(length_to_extrude,0.f); - depth += (int(length_to_extrude / width) + 1) * m_line_width; + depth += (int(length_to_extrude / width) + 1) * m_perimeter_width; depth *= m_extra_spacing; m_plan.back().tool_changes.push_back(WipeTowerInfo::ToolChange(old_tool, new_tool, depth, ramming_depth,first_wipe_line)); @@ -1147,12 +1125,12 @@ void WipeTowerPrusaMM::save_on_last_wipe() float width = m_wipe_tower_width - 3*m_perimeter_width; // width we draw into float length_to_save = 2*(m_wipe_tower_width+m_wipe_tower_depth) + (!layer_finished() ? finish_layer().total_extrusion_length_in_plane() : 0.f); float length_to_wipe = volume_to_length(wipe_volumes[m_layer_info->tool_changes.back().old_tool][m_layer_info->tool_changes.back().new_tool], - m_line_width,m_layer_info->height) - m_layer_info->tool_changes.back().first_wipe_line - length_to_save; + m_perimeter_width,m_layer_info->height) - m_layer_info->tool_changes.back().first_wipe_line - length_to_save; length_to_wipe = std::max(length_to_wipe,0.f); - float depth_to_wipe = m_line_width * (std::floor(length_to_wipe/width) + ( length_to_wipe > 0.f ? 1.f : 0.f ) ) * m_extra_spacing; + float depth_to_wipe = m_perimeter_width * (std::floor(length_to_wipe/width) + ( length_to_wipe > 0.f ? 1.f : 0.f ) ) * m_extra_spacing; - //depth += (int(length_to_extrude / width) + 1) * m_line_width; + //depth += (int(length_to_extrude / width) + 1) * m_perimeter_width; m_layer_info->tool_changes.back().required_depth = m_layer_info->tool_changes.back().ramming_depth + depth_to_wipe; } } @@ -1172,7 +1150,7 @@ void WipeTowerPrusaMM::generate(std::vectordepth < m_wipe_tower_depth - m_perimeter_width) + if (!m_peters_wipe_tower && m_layer_info->depth < m_wipe_tower_depth - m_perimeter_width) m_y_shift = (m_wipe_tower_depth-m_layer_info->depth-m_perimeter_width)/2.f; for (const auto &toolchange : layer.tool_changes) layer_result.emplace_back(tool_change(toolchange.new_tool, false)); if (! layer_finished()) { - layer_result.emplace_back(finish_layer()); - if (layer_result.size() > 1) { - // Merge the two last tool changes into one. - WipeTower::ToolChangeResult &tc1 = layer_result[layer_result.size() - 2]; - WipeTower::ToolChangeResult &tc2 = layer_result.back(); - if (tc1.end_pos != tc2.start_pos) { - // Add a travel move from tc1.end_pos to tc2.start_pos. - char buf[2048]; - sprintf(buf, "G1 X%.3f Y%.3f F7200\n", tc2.start_pos.x, tc2.start_pos.y); - tc1.gcode += buf; + auto finish_layer_toolchange = finish_layer(); + if (layer_result.size() > 1) { // we will merge it to the last toolchange + auto& last_toolchange = layer_result.back(); + if (last_toolchange.end_pos != finish_layer_toolchange.start_pos) { + char buf[2048]; // Add a travel move from tc1.end_pos to tc2.start_pos. + sprintf(buf, "G1 X%.3f Y%.3f F7200\n", finish_layer_toolchange.start_pos.x, finish_layer_toolchange.start_pos.y); + last_toolchange.gcode += buf; } - tc1.gcode += tc2.gcode; - tc1.extrusions.insert(tc1.extrusions.end(), tc2.extrusions.begin(), tc2.extrusions.end()); - tc1.end_pos = tc2.end_pos; - layer_result.pop_back(); - } - } + last_toolchange.gcode += finish_layer_toolchange.gcode; + last_toolchange.extrusions.insert(last_toolchange.extrusions.end(),finish_layer_toolchange.extrusions.begin(),finish_layer_toolchange.extrusions.end()); + last_toolchange.end_pos = finish_layer_toolchange.end_pos; + } + else + layer_result.emplace_back(std::move(finish_layer_toolchange)); + } result.emplace_back(std::move(layer_result)); m_is_first_layer = false; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 90317673e..734d61dc6 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -8,19 +8,6 @@ #include "WipeTower.hpp" -// Following is used to calculate extrusion flow - should be taken from config in future -const float Filament_Area = M_PI * 1.75f * 1.75f / 4.f; // filament area in mm^3 -const float Nozzle_Diameter = 0.4f; // nozzle diameter in mm -// desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust -const float Width_To_Nozzle_Ratio = 1.25f; - -// m_perimeter_width was hardcoded until now as 0.5 (for 0.4 nozzle and 0.2 layer height) -// FIXME m_perimeter_width is used in plan_toolchange - take care of proper initialization value when changing to variable -const float Konst = 1.f; -const float m_perimeter_width = Nozzle_Diameter * Width_To_Nozzle_Ratio * Konst; - -const float WT_EPSILON = 1e-3f; - namespace Slic3r { @@ -31,7 +18,6 @@ namespace PrusaMultiMaterial { - class WipeTowerPrusaMM : public WipeTower { public: @@ -65,40 +51,27 @@ public: m_y_shift(0.f), m_z_pos(0.f), m_is_first_layer(false), - m_is_last_layer(false), m_cooling_tube_retraction(cooling_tube_retraction), m_cooling_tube_length(cooling_tube_length), m_parking_pos_retraction(parking_pos_retraction), m_bridging(bridging), m_current_tool(initial_tool) { - const unsigned int number_of_extruders = int(sqrt(wiping_matrix.size())+WT_EPSILON); + unsigned int number_of_extruders = (unsigned int)(sqrt(wiping_matrix.size())+WT_EPSILON); for (unsigned int i = 0; i(wiping_matrix.begin()+i*number_of_extruders,wiping_matrix.begin()+(i+1)*number_of_extruders)); - - /*for (size_t i = 0; i < number_of_extruders; ++ i) { - // Extruder specific parameters. - m_filpar[i].material = PLA; - m_filpar[i].temperature = 0; - m_filpar[i].first_layer_temperature = 0; - }*/ } virtual ~WipeTowerPrusaMM() {} - // _retract - retract value in mm - void set_retract(float retract) { m_retract = retract; } - - // _zHop - z hop value in mm - void set_zhop(float zhop) { m_zhop = zhop; } - // Set the extruder properties. void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed, float unloading_speed, float delay, int cooling_time, std::string ramming_parameters) { - while (m_filpar.size() < idx+1) // makes sure the required element is in the vector - m_filpar.push_back(FilamentParameters()); + //while (m_filpar.size() < idx+1) // makes sure the required element is in the vector + m_filpar.push_back(FilamentParameters()); + m_filpar[idx].material = material; m_filpar[idx].temperature = temp; m_filpar[idx].first_layer_temperature = first_layer_temp; @@ -106,7 +79,7 @@ public: m_filpar[idx].unloading_speed = unloading_speed; m_filpar[idx].delay = delay; m_filpar[idx].cooling_time = cooling_time; - + std::stringstream stream{ramming_parameters}; float speed = 0.f; stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator; @@ -117,21 +90,14 @@ public: } - // Setter for internal structure m_plan containing info about the future wipe tower + // Appends into internal structure m_plan containing info about the future wipe tower // to be used before building begins. The entries must be added ordered in z. void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, bool brim); // Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result" void generate(std::vector> &result); - // Calculates depth for all layers and propagates them downwards - void plan_tower(); - // Goes through m_plan and recalculates depths and width of the WT to make it exactly square - experimental - void make_wipe_tower_square(); - - // Goes through m_plan, calculates border and finish_layer extrusions and subtracts them from last wipe - void save_on_last_wipe(); // Switch to a next layer. virtual void set_layer( @@ -150,15 +116,16 @@ public: m_layer_height = layer_height; m_is_first_layer = is_first_layer; m_print_brim = is_first_layer; - m_depth_traversed = 0.f; // to make room for perimeter line + m_depth_traversed = 0.f; m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL; ++ m_num_layer_changes; - // Calculates extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height + // Calculate extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height: m_extrusion_flow = extrusion_flow(layer_height); - while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1!=m_plan.end()) + // Advance m_layer_info iterator, making sure we got it right + while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1 != m_plan.end()) ++m_layer_info; } @@ -183,7 +150,7 @@ public: // On the first layer, extrude a brim around the future wipe tower first. virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer); - // Fill the unfilled space with a zig-zag. + // Fill the unfilled space with a sparse infill. // Call this method only if layer_finished() is false. virtual ToolChangeResult finish_layer(); @@ -196,34 +163,38 @@ public: private: WipeTowerPrusaMM(); - enum wipe_shape // A fill-in direction (positive Y, negative Y) alternates with each layer. + enum wipe_shape // A fill-in direction { SHAPE_NORMAL = 1, SHAPE_REVERSED = -1 }; + + const bool m_peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet + const float Filament_Area = M_PI * 1.75f * 1.75f / 4.f; // filament area in mm^3 + const float Nozzle_Diameter = 0.4f; // nozzle diameter in mm + const float Width_To_Nozzle_Ratio = 1.25f; // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust + const float WT_EPSILON = 1e-3f; + + xy m_wipe_tower_pos; // Left front corner of the wipe tower in mm. float m_wipe_tower_width; // Width of the wipe tower. float m_wipe_tower_depth = 0.f; // Depth of the wipe tower - float m_wipe_tower_rotation_angle = 0.f; // Wipe tower rotation angle in degrees (with respect to x axis + float m_wipe_tower_rotation_angle = 0.f; // Wipe tower rotation angle in degrees (with respect to x axis) float m_y_shift = 0.f; // y shift passed to writer float m_z_pos = 0.f; // Current Z position. float m_layer_height = 0.f; // Current layer height. size_t m_max_color_changes = 0; // Maximum number of color changes per layer. bool m_is_first_layer = false;// Is this the 1st layer of the print? If so, print the brim around the waste tower. - bool m_is_last_layer = false;// Is this the last layer of this waste tower? - bool m_layer_parity = false; // G-code generator parameters. - float m_zhop = 0.5f; - float m_retract = 4.f; float m_cooling_tube_retraction = 0.f; float m_cooling_tube_length = 0.f; float m_parking_pos_retraction = 0.f; float m_bridging = 0.f; bool m_adhesion = true; - float m_line_width = Nozzle_Diameter * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. + float m_perimeter_width = Nozzle_Diameter * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. float m_extrusion_flow = 0.038; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. @@ -244,7 +215,7 @@ private: std::vector m_filpar; - // State of the wiper tower generator. + // State of the wipe tower generator. unsigned int m_num_layer_changes = 0; // Layer change counter for the output statistics. unsigned int m_num_tool_changes = 0; // Tool change change counter for the output statistics. ///unsigned int m_idx_tool_change_in_layer = 0; // Layer change counter in this layer. Counting up to m_max_color_changes. @@ -254,12 +225,10 @@ private: unsigned int m_current_tool = 0; std::vector> wipe_volumes; - float m_depth_traversed = 0.f; // Current y position at the wipe tower. - // How much to wipe the 1st extruder over the wipe tower at the 1st layer - // after the wipe tower brim has been extruded? - float m_initial_extra_wipe = 0.f; - bool m_left_to_right = true; - float m_extra_spacing = 1.f; + float m_depth_traversed = 0.f; // Current y position at the wipe tower. + bool m_left_to_right = true; + float m_extra_spacing = 1.f; + // Calculates extrusion flow needed to produce required line width for given layer height float extrusion_flow(float layer_height = -1.f) const // negative layer_height - return current m_extrusion_flow @@ -274,6 +243,15 @@ private: return volume / (layer_height * (line_width - layer_height * (1. - M_PI / 4.))); } + // Calculates depth for all layers and propagates them downwards + void plan_tower(); + + // Goes through m_plan and recalculates depths and width of the WT to make it exactly square - experimental + void make_wipe_tower_square(); + + // Goes through m_plan, calculates border and finish_layer extrusions and subtracts them from last wipe + void save_on_last_wipe(); + struct box_coordinates { diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index cd227ed1c..18d2bcead 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1075,7 +1075,6 @@ void Print::_make_wipe_tower() // Lets go through the wipe tower layers and determine pairs of extruder changes for each // to pass to wipe_tower (so that it can use it for planning the layout of the tower) - { unsigned int current_extruder_id = m_tool_ordering.all_extruders().back(); for (const auto &layer_tools : m_tool_ordering.layer_tools()) { // for all layers diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index fc3d30a5d..ac35756a4 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -40,7 +40,7 @@ RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters) { new wxStaticText(this,wxID_ANY,wxString("Total ramming time (s):"), wxPoint(500,105), wxSize(200,25),wxALIGN_LEFT); m_widget_time = new wxSpinCtrlDouble(this,wxID_ANY,wxEmptyString, wxPoint(700,100), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,0.,5.0,3.,0.5); - new wxStaticText(this,wxID_ANY,wxString("Total rammed volume (mm3):"), wxPoint(500,135), wxSize(200,25),wxALIGN_LEFT); + new wxStaticText(this,wxID_ANY,wxString("Total rammed volume (mm\u00B3):"), wxPoint(500,135), wxSize(200,25),wxALIGN_LEFT); m_widget_volume = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,130), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,0,10000,0); new wxStaticText(this,wxID_ANY,wxString("Ramming line width (%):"), wxPoint(500,205), wxSize(200,25),wxALIGN_LEFT); m_widget_ramming_line_width_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,200), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,10,200,100); From e7a5bc1afefb3d051c888830e3655e8e456b6eaa Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 21 Mar 2018 16:01:31 +0100 Subject: [PATCH 49/81] Added a check that no object uses extruder the printer doesn't have --- xs/src/libslic3r/Print.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 18d2bcead..62c9c8819 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -624,7 +624,12 @@ std::string Print::validate() const for (unsigned int extruder_id : extruders) nozzle_diameters.push_back(this->config.nozzle_diameter.get_at(extruder_id)); double min_nozzle_diameter = *std::min_element(nozzle_diameters.begin(), nozzle_diameters.end()); - + + unsigned int total_extruders_count = this->config.nozzle_diameter.size(); + for (const auto& extruder_idx : extruders) + if ( extruder_idx >= total_extruders_count ) + return "One or more object have assigned an extruder that the printer does not have."; + for (PrintObject *object : this->objects) { if ((object->config.support_material_extruder == -1 || object->config.support_material_interface_extruder == -1) && (object->config.raft_layers > 0 || object->config.support_material.value)) { From 036e41ae6952b84c32b93b9a2ce21741542cf7ea Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 22 Mar 2018 13:07:45 +0100 Subject: [PATCH 50/81] Wiping dialog - first experiments with sizers --- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 138 +++++++++++++++----------- xs/src/slic3r/GUI/WipeTowerDialog.hpp | 8 +- 2 files changed, 84 insertions(+), 62 deletions(-) diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index ac35756a4..1989a82f1 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -2,6 +2,8 @@ #include #include "WipeTowerDialog.hpp" +#include + //! macro used to mark string used at localization, //! return same string #define L(s) s @@ -22,9 +24,9 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) SetSizer(main_sizer); SetMinSize(GetSize()); main_sizer->SetSizeHints(this); - + this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); - + this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { m_output_data = m_panel_ramming->get_parameters(); EndModal(wxID_OK); @@ -101,74 +103,105 @@ std::string RammingPanel::get_parameters() - +// Parent dialog for purging volume adjustments - it fathers WipingPanel widget (that contains all controls) and a button to toggle simple/advanced mode: WipingDialog::WipingDialog(wxWindow* parent,const std::vector& matrix, const std::vector& extruders) : wxDialog(parent, -1, wxT(L("Wipe tower - Purging volume adjustment")), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { this->Centre(); - - m_panel_wiping = new WipingPanel(this,matrix,extruders); - this->Show(); + + auto widget_button = new wxButton(this,wxID_ANY,"-",wxPoint(0,0),wxDefaultSize); + m_panel_wiping = new WipingPanel(this,matrix,extruders, widget_button); auto main_sizer = new wxBoxSizer(wxVERTICAL); main_sizer->Add(m_panel_wiping, 1, wxEXPAND); + + + main_sizer->Add(widget_button,0,wxALIGN_CENTER_HORIZONTAL|wxCENTER,10); main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); SetSizer(main_sizer); SetMinSize(GetSize()); main_sizer->SetSizeHints(this); - + this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); - this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { - m_output_matrix = m_panel_wiping->read_matrix_values(); - m_output_extruders = m_panel_wiping->read_extruders_values(); + this->Bind(wxEVT_BUTTON,[this](wxCommandEvent&) { // if OK button is clicked.. + m_output_matrix = m_panel_wiping->read_matrix_values(); // ..query wiping panel and save returned values + m_output_extruders = m_panel_wiping->read_extruders_values(); // so they can be recovered later by calling get_...() EndModal(wxID_OK); },wxID_OK); + + this->Show(); } - -WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, const std::vector& extruders) +// This panel contains all control widgets for both simple and advanced mode (these reside in separate sizers) +WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, const std::vector& extruders, wxButton* widget_button) : wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(500,350),wxBORDER_RAISED) { - m_number_of_extruders = (int)(sqrt(matrix.size())+0.001); // number of extruders - m_notadvanced_widgets.push_back(new wxStaticText(this,wxID_ANY,wxString(L("Total purging volume is calculated by summing two values below, depending on which tools are loaded/unloaded.")),wxPoint(40,25) ,wxSize(500,35))); - m_notadvanced_widgets.push_back(new wxStaticText(this,wxID_ANY,wxString(L("Volume to purge (mm\u00B3) when the filament is being")),wxPoint(40,85) ,wxSize(500,25))); - m_notadvanced_widgets.push_back(new wxStaticText(this,wxID_ANY,wxString(L("unloaded")),wxPoint(110,105) ,wxSize(500,25))); - m_notadvanced_widgets.push_back(new wxStaticText(this,wxID_ANY,wxString(L("loaded")),wxPoint(195,105) ,wxSize(500,25))); - m_widget_button = new wxButton(this,wxID_ANY,"-",wxPoint(0,0),wxSize(170,20)); + m_widget_button = widget_button; // pointer to the button in parent dialog + m_widget_button->Bind(wxEVT_BUTTON,[this](wxCommandEvent&){ toggle_advanced(true); }); + + m_number_of_extruders = (int)(sqrt(matrix.size())+0.001); + + m_sizer_simple = new wxBoxSizer(wxVERTICAL); + m_sizer_advanced = new wxBoxSizer(wxVERTICAL); + auto gridsizer_simple = new wxGridSizer(3,10,10); + auto gridsizer_advanced = new wxGridSizer(m_number_of_extruders+1,10,10); + + + // First create controls for simple mode and assign them to m_sizer_simple: + m_sizer_simple->Add(new wxStaticText(this,wxID_ANY,wxString(L("Total purging volume is calculated by summing two values below, depending on which tools are loaded/unloaded.")),wxPoint(40,25), wxSize(450,35)),-1,wxEXPAND,10); + m_sizer_simple->Add(new wxStaticText(this,wxID_ANY,wxString(L("Volume to purge (mm\u00B3) when the filament is being")),wxPoint(40,85) ,/*wxSize(500,25)*/wxDefaultSize,wxALIGN_LEFT),-1,wxEXPAND|wxALIGN_CENTER,10); + + gridsizer_simple->Add(0,-1,wxALL,10); + gridsizer_simple->Add(new wxStaticText(this,wxID_ANY,wxString(L("unloaded")),wxPoint(110,105) ,/*wxSize(80,25)*/wxDefaultSize,wxALIGN_CENTER),-1,wxALIGN_CENTER,10); + gridsizer_simple->Add(new wxStaticText(this,wxID_ANY,wxString(L("loaded")),wxPoint(195,105) ,/*wxSize(80,25)*/wxDefaultSize,wxALIGN_CENTER),-1,wxALIGN_CENTER,10); for (unsigned int i=0;iAdd(new wxStaticText(this,wxID_ANY,wxString(L("Tool #"))<Add(m_old.back(),-1,wxALIGN_CENTER,10); + gridsizer_simple->Add(m_new.back(),-1,wxALIGN_CENTER,10); } + // Now the same for advanced mode: wxPoint origin(50,85); - m_advanced_widgets.push_back(new wxStaticText(this,wxID_ANY,wxString(L("Here you can adjust required purging volume (mm\u00B3) for any given pair of tools.")),wxPoint(40,25) ,wxSize(500,35))); + m_sizer_advanced->Add(new wxStaticText(this,wxID_ANY,wxString(L("Here you can adjust required purging volume (mm\u00B3) for any given pair of tools.")),wxPoint(40,25) ,/*wxSize(500,35)*/wxDefaultSize),-1,wxALL,10); + m_sizer_advanced->Add(new wxStaticText(this,wxID_ANY,wxString(L("Filament changed to")),origin+wxPoint(75,0) ,/*wxSize(500,25)*/wxDefaultSize),-1,wxALL,10); + for (unsigned int i=0;i(0)); - m_advanced_widgets.push_back(new wxStaticText(this,wxID_ANY,wxString("")<Disable(); else edit_boxes[i][j]->SetValue(wxString("")<Bind(wxEVT_BUTTON,[this](wxCommandEvent&){toggle_advanced(true);}); - toggle_advanced(); + gridsizer_advanced->Add(0,-1,wxALL,10); + for (unsigned int i=0;iAdd(new wxStaticText(this,wxID_ANY,wxString("")<Add(new wxStaticText(this,wxID_ANY,wxString("")<Add(edit_boxes[j][i],-1,wxALL,10); + } + + + m_sizer_simple->Add(gridsizer_simple,-1,wxALL,10); + m_sizer_advanced->Add(gridsizer_advanced,-1,wxALL,10); + toggle_advanced(); // to show/hide what is appropriate } - +// Reads values from the (advanced) wiping matrix: std::vector WipingPanel::read_matrix_values() { if (!m_advanced) fill_in_matrix(); @@ -183,7 +216,7 @@ std::vector WipingPanel::read_matrix_values() { return output; } - +// Reads values from simple mode to save them for next time: std::vector WipingPanel::read_extruders_values() { std::vector output; for (unsigned int i=0;i WipingPanel::read_extruders_values() { return output; } - +// This updates the "advanced" matrix based on values from "simple" mode void WipingPanel::fill_in_matrix() { for (unsigned i=0;i toggle + else { + m_advanced = !advanced_matches_simple(); // if called from constructor, show what is appropriate + (m_advanced ? m_sizer_advanced : m_sizer_simple)->SetSizeHints(this); + SetSizer(m_advanced ? m_sizer_advanced : m_sizer_simple); } - for (unsigned i=0;iShow(m_advanced); - m_old[i]->Show(!m_advanced); - m_new[i]->Show(!m_advanced); - } - for (const auto& widget : m_advanced_widgets) // shows/hides other widgets - widget->Show(m_advanced); - for (const auto& widget : m_notadvanced_widgets) - widget->Show(!m_advanced); + m_sizer_simple->Show(!m_advanced); + m_sizer_advanced->Show(m_advanced); - if (m_advanced) { - if (user_button) fill_in_matrix(); // otherwise keep values loaded from config - m_widget_button->SetLabel(L("Show simplified settings")); - } - else - m_widget_button->SetLabel(L("Show advanced settings")); + m_widget_button->SetLabel(m_advanced ? L("Show simplified settings") : L("Show advanced settings")); + if (m_advanced) + if (user_action) fill_in_matrix(); // otherwise keep values loaded from config this->Refresh(); } \ No newline at end of file diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/xs/src/slic3r/GUI/WipeTowerDialog.hpp index 54ae9596d..c8e7bd480 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.hpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.hpp @@ -46,13 +46,13 @@ private: class WipingPanel : public wxPanel { public: - WipingPanel(wxWindow* parent, const std::vector& matrix, const std::vector& extruders); + WipingPanel(wxWindow* parent, const std::vector& matrix, const std::vector& extruders, wxButton* widget_button); std::vector read_matrix_values(); std::vector read_extruders_values(); + void toggle_advanced(bool user_action = false); private: void fill_in_matrix(); - void toggle_advanced(bool user_button = false); bool advanced_matches_simple(); std::vector m_old; @@ -60,9 +60,11 @@ private: std::vector m_advanced_widgets; std::vector m_notadvanced_widgets; std::vector> edit_boxes; - wxButton* m_widget_button = nullptr; unsigned int m_number_of_extruders = 0; bool m_advanced = false; + wxBoxSizer*m_sizer_simple = nullptr; + wxBoxSizer*m_sizer_advanced = nullptr; + wxButton* m_widget_button = nullptr; }; From 985b414c64ba2c86be36e60b3a3134127b6146bc Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 22 Mar 2018 13:37:01 +0100 Subject: [PATCH 51/81] Removed parameter 'wipe_tower_per_color_wipe' from UI and configuration layer --- lib/Slic3r/GUI/Plater.pm | 3 +-- lib/Slic3r/GUI/Plater/3D.pm | 5 +++-- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 2 +- xs/src/libslic3r/Print.cpp | 3 +-- xs/src/libslic3r/PrintConfig.cpp | 9 --------- xs/src/slic3r/GUI/3DScene.cpp | 8 +++++--- xs/src/slic3r/GUI/Preset.cpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 3 +-- 8 files changed, 13 insertions(+), 22 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index ad98fdf99..8a4953603 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -53,8 +53,7 @@ sub new { bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height serial_port serial_speed octoprint_host octoprint_apikey octoprint_cafile nozzle_diameter single_extruder_multi_material wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width - wipe_tower_per_color_wipe wipe_tower_rotation_angle extruder_colour filament_colour - max_print_height + wipe_tower_rotation_angle extruder_colour filament_colour max_print_height )]); # C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm $self->{model} = Slic3r::Model->new; diff --git a/lib/Slic3r/GUI/Plater/3D.pm b/lib/Slic3r/GUI/Plater/3D.pm index bd823c730..00035672f 100644 --- a/lib/Slic3r/GUI/Plater/3D.pm +++ b/lib/Slic3r/GUI/Plater/3D.pm @@ -205,8 +205,9 @@ sub reload_scene { if ($extruders_count > 1 && $self->{config}->single_extruder_multi_material && $self->{config}->wipe_tower && ! $self->{config}->complete_objects) { $self->volumes->load_wipe_tower_preview(1000, - $self->{config}->wipe_tower_x, $self->{config}->wipe_tower_y, - $self->{config}->wipe_tower_width, $self->{config}->wipe_tower_per_color_wipe * ($extruders_count - 1), + $self->{config}->wipe_tower_x, $self->{config}->wipe_tower_y, $self->{config}->wipe_tower_width, + #$self->{config}->wipe_tower_per_color_wipe# 15 * ($extruders_count - 1), # this is just a hack when the config parameter became obsolete + 15 * ($extruders_count - 1), $self->{model}->bounding_box->z_max, $self->{config}->wipe_tower_rotation_angle, $self->UseVBOs); } } diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 734d61dc6..4f97f700f 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -42,7 +42,7 @@ public: // y -- y coordinates of wipe tower in mm ( left bottom corner ) // 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 wipe_area, float rotation_angle, float cooling_tube_retraction, + WipeTowerPrusaMM(float x, float y, float width, float rotation_angle, float cooling_tube_retraction, float cooling_tube_length, float parking_pos_retraction, float bridging, const std::vector& wiping_matrix, unsigned int initial_tool) : m_wipe_tower_pos(x, y), diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 62c9c8819..cd66f6f56 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -199,7 +199,6 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.wipe_tower_x.value), float(this->config.wipe_tower_y.value), - float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value), + float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_rotation_angle.value), float(this->config.cooling_tube_retraction.value), float(this->config.cooling_tube_length.value), float(this->config.parking_pos_retraction.value), float(this->config.wipe_tower_bridging), wiping_volumes, m_tool_ordering.first_extruder()); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index ff426c9a2..cb5bcea4a 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1818,15 +1818,6 @@ PrintConfigDef::PrintConfigDef() def->cli = "wipe-tower-width=f"; def->default_value = new ConfigOptionFloat(60.); - def = this->add("wipe_tower_per_color_wipe", coFloat); - def->label = "(Unused and will be likely removed)";//L("Per color change depth"); - def->tooltip = L("Depth of a wipe color per color change. For N colors, there will be " - "maximum (N-1) tool switches performed, therefore the total depth " - "of the wipe tower will be (N-1) times this value."); - def->sidetext = L("mm"); - def->cli = "wipe-tower-per-color-wipe=f"; - def->default_value = new ConfigOptionFloat(15.); - def = this->add("wipe_tower_rotation_angle", coFloat); def->label = L("Wipe tower rotation angle"); def->tooltip = L("Wipe tower rotation angle with respect to x-axis "); diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 994c62a83..cbaa4ac90 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -2588,8 +2588,10 @@ void _3DScene::_load_shells(const Print& print, GLVolumeCollection& volumes, boo coordf_t max_z = print.objects[0]->model_object()->get_model()->bounding_box().max.z; const PrintConfig& config = print.config; unsigned int extruders_count = config.nozzle_diameter.size(); - if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects) - volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, config.wipe_tower_per_color_wipe * (extruders_count - 1), max_z, config.wipe_tower_rotation_angle, use_VBOs); + if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects) { + const float width_per_extruder = 15.f; // a simple workaround after wipe_tower_per_color_wipe got obsolete + volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, width_per_extruder * (extruders_count - 1), max_z, config.wipe_tower_rotation_angle, use_VBOs); + } } -} +} // namespace Slic3r diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 99d003f7a..a0d4fe5ff 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -199,7 +199,7 @@ const std::vector& Preset::print_options() "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", - "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "wipe_tower_bridging", + "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "wiping_volumes_matrix", "wiping_volumes_extruders", "compatible_printers", "compatible_printers_condition" }; diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 146696d1e..9716abfb4 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -517,7 +517,6 @@ void TabPrint::build() optgroup->append_single_option_line("wipe_tower_x"); optgroup->append_single_option_line("wipe_tower_y"); optgroup->append_single_option_line("wipe_tower_width"); - optgroup->append_single_option_line("wipe_tower_per_color_wipe"); optgroup->append_single_option_line("wipe_tower_rotation_angle"); optgroup->append_single_option_line("wipe_tower_bridging"); line = { _(L("Advanced")), "" }; @@ -863,7 +862,7 @@ void TabPrint::update() bool have_wipe_tower = m_config->opt_bool("wipe_tower"); vec_enable.resize(0); - vec_enable = { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", "wipe_tower_rotation_angle", "wipe_tower_bridging"}; + vec_enable = { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging"}; for (auto el : vec_enable) get_field(el)->toggle(have_wipe_tower); m_wipe_tower_btn->Enable(have_wipe_tower); From 3fdd182f0c74366f4e164d65059b516b2616dec5 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 22 Mar 2018 16:13:41 +0100 Subject: [PATCH 52/81] Parameters describing cooling tubes position etc moved to separate page in Printer Settings --- xs/src/slic3r/GUI/Tab.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 9716abfb4..267e579b6 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -1099,7 +1099,7 @@ void TabPrinter::build() optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value){ size_t extruders_count = boost::any_cast(optgroup->get_value("extruders_count")); wxTheApp->CallAfter([this, opt_key, value, extruders_count](){ - if (opt_key.compare("extruders_count")==0) { + if (opt_key.compare("extruders_count")==0 || opt_key.compare("single_extruder_multi_material")==0) { extruders_count_changed(extruders_count); update_dirty(); } @@ -1110,6 +1110,7 @@ void TabPrinter::build() }); }; + if (!m_no_controller) { optgroup = page->new_optgroup(_(L("USB/Serial connection"))); @@ -1249,9 +1250,6 @@ void TabPrinter::build() optgroup->append_single_option_line("use_firmware_retraction"); optgroup->append_single_option_line("use_volumetric_e"); optgroup->append_single_option_line("variable_layer_height"); - optgroup->append_single_option_line("cooling_tube_retraction"); - optgroup->append_single_option_line("cooling_tube_length"); - optgroup->append_single_option_line("parking_pos_retraction"); page = add_options_page(_(L("Custom G-code")), "cog.png"); optgroup = page->new_optgroup(_(L("Start G-code")), 0); @@ -1374,6 +1372,25 @@ void TabPrinter::build_extruder_pages(){ for (auto page_extruder : m_extruder_pages) m_pages.push_back(page_extruder); m_pages.push_back(page_note); + + { + // if we have a single extruder MM setup, add a page with configuration options: + for (int i=0;ititle().find(_(L("Single extruder MM setup"))) != std::string::npos) { + m_pages.erase(m_pages.begin()+i); + break; + } + if ( m_extruder_pages.size()>1 && m_config->opt_bool("single_extruder_multi_material")) { + // create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves + auto page = add_options_page(_(L("Single extruder MM setup")), "printer_empty.png",true); + auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters"))); + optgroup->append_single_option_line("cooling_tube_retraction"); + optgroup->append_single_option_line("cooling_tube_length"); + optgroup->append_single_option_line("parking_pos_retraction"); + m_pages.insert(m_pages.begin()+1,page); + } + } + rebuild_page_tree(); } From 7d9e892edccea9ee7fa3c94937b258e6d744f2f6 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 27 Mar 2018 13:44:18 +0200 Subject: [PATCH 53/81] Added a button to open purging volumes dialog directly from Plater --- xs/src/slic3r/GUI/GUI.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 0410b7969..3c8504756 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -1,4 +1,5 @@ #include "GUI.hpp" +#include "WipeTowerDialog.hpp" #include @@ -678,6 +679,32 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl option = Option(def, "brim"); m_optgroup->append_single_option_line(option); + + Line line = { _(L("")), "" }; + line.widget = [config](wxWindow* parent){ + auto wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(wiping_dialog_button); + wiping_dialog_button->Bind(wxEVT_BUTTON, ([config, parent](wxCommandEvent& e) + { + std::vector init_matrix = (config->option("wiping_volumes_matrix"))->values; + std::vector init_extruders = (config->option("wiping_volumes_extruders"))->values; + + WipingDialog dlg(parent,std::vector(init_matrix.begin(),init_matrix.end()),std::vector(init_extruders.begin(),init_extruders.end())); + + if (dlg.ShowModal() == wxID_OK) { + std::vector matrix = dlg.get_matrix(); + std::vector extruders = dlg.get_extruders(); + (config->option("wiping_volumes_matrix"))->values = std::vector(matrix.begin(),matrix.end()); + (config->option("wiping_volumes_extruders"))->values = std::vector(extruders.begin(),extruders.end()); + } + })); + return sizer; + }; + m_optgroup->append_line(line); + + + sizer->Add(m_optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxBottom, 1); } From 56fef5302cd8cdf7e2b3c1f9190887ac909d27c1 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 27 Mar 2018 14:42:47 +0200 Subject: [PATCH 54/81] Added axis-labels to RammingChart --- xs/src/slic3r/GUI/RammingChart.cpp | 23 ++++++++++++++++++----- xs/src/slic3r/GUI/RammingChart.hpp | 2 +- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/xs/src/slic3r/GUI/RammingChart.cpp index e07b95839..79a701847 100644 --- a/xs/src/slic3r/GUI/RammingChart.cpp +++ b/xs/src/slic3r/GUI/RammingChart.cpp @@ -2,6 +2,12 @@ #include "RammingChart.hpp" +//! macro used to mark string used at localization, +//! return same string +#define L(s) s + + + wxDEFINE_EVENT(EVT_WIPE_TOWER_CHART_CHANGED, wxCommandEvent); @@ -43,9 +49,9 @@ void Chart::draw(wxDC& dc) { // draw x-axis: float last_mark = -10000; - for (float math_x=int(visible_area.m_x*10)/10 ; math_x <= (visible_area.m_x+visible_area.m_width) ; math_x+=0.1) { + for (float math_x=int(visible_area.m_x*10)/10 ; math_x < (visible_area.m_x+visible_area.m_width) ; math_x+=0.1) { int x = math_to_screen(wxPoint2DDouble(math_x,visible_area.m_y)).x; - int y = m_rect.GetBottom(); + int y = m_rect.GetBottom(); if (x-last_mark < 50) continue; dc.DrawLine(x,y+3,x,y-3); dc.DrawText(wxString().Format(wxT("%.1f"), math_x),wxPoint(x-10,y+7)); @@ -54,7 +60,7 @@ void Chart::draw(wxDC& dc) { // draw y-axis: last_mark=10000; - for (int math_y=visible_area.m_y ; math_y <= (visible_area.m_y+visible_area.m_height) ; math_y+=1) { + for (int math_y=visible_area.m_y ; math_y < (visible_area.m_y+visible_area.m_height) ; math_y+=1) { int y = math_to_screen(wxPoint2DDouble(visible_area.m_x,math_y)).y; int x = m_rect.GetLeft(); if (last_mark-y < 50) continue; @@ -63,8 +69,15 @@ void Chart::draw(wxDC& dc) { last_mark = y; } - - + // axis labels: + wxString label = L("Time (s)"); + int text_width = 0; + int text_height = 0; + dc.GetTextExtent(label,&text_width,&text_height); + dc.DrawText(label,wxPoint(0.5*(m_rect.GetRight()+m_rect.GetLeft())-text_width/2.f, m_rect.GetBottom()+25)); + label = L("Volumetric speed (mm\u00B3/s)"); + dc.GetTextExtent(label,&text_width,&text_height); + dc.DrawRotatedText(label,wxPoint(0,0.5*(m_rect.GetBottom()+m_rect.GetTop())+text_width/2.f),90); } void Chart::mouse_right_button_clicked(wxMouseEvent& event) { diff --git a/xs/src/slic3r/GUI/RammingChart.hpp b/xs/src/slic3r/GUI/RammingChart.hpp index 5ec8b33ee..aa1e7acc7 100644 --- a/xs/src/slic3r/GUI/RammingChart.hpp +++ b/xs/src/slic3r/GUI/RammingChart.hpp @@ -16,7 +16,7 @@ public: Chart(wxWindow* parent, wxRect rect,const std::vector>& initial_buttons,int ramming_speed_size, float sampling) : wxWindow(parent,wxID_ANY,rect.GetTopLeft(),rect.GetSize()) { - m_rect=wxRect(wxPoint(30,0),rect.GetSize()-wxSize(30,30)); + m_rect = wxRect(wxPoint(50,0),rect.GetSize()-wxSize(50,50)); visible_area = wxRect2DDouble(0.0, 0.0, sampling*ramming_speed_size, 20.); m_buttons.clear(); if (initial_buttons.size()>0) diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index 1989a82f1..255c0d6bd 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -38,7 +38,7 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters) -: wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(800,350),wxBORDER_RAISED) +: wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(800,400),wxBORDER_RAISED) { new wxStaticText(this,wxID_ANY,wxString("Total ramming time (s):"), wxPoint(500,105), wxSize(200,25),wxALIGN_LEFT); m_widget_time = new wxSpinCtrlDouble(this,wxID_ANY,wxEmptyString, wxPoint(700,100), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,0.,5.0,3.,0.5); From 4da6085ef883a8139417f25c6650045379c4cc44 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 28 Mar 2018 02:17:51 +0200 Subject: [PATCH 55/81] Corrected UI for WipingDialog --- xs/src/slic3r/GUI/Tab.cpp | 2 +- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 135 +++++++++++++++----------- xs/src/slic3r/GUI/WipeTowerDialog.hpp | 4 + 3 files changed, 83 insertions(+), 58 deletions(-) diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 267e579b6..503ef54a4 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -521,7 +521,7 @@ void TabPrint::build() optgroup->append_single_option_line("wipe_tower_bridging"); line = { _(L("Advanced")), "" }; line.widget = [this](wxWindow* parent){ - m_wipe_tower_btn = new wxButton(parent, wxID_ANY, _(L("Advanced settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); + m_wipe_tower_btn = new wxButton(parent, wxID_ANY, _(L("Advanced settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(m_wipe_tower_btn); m_wipe_tower_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index 1989a82f1..8cd6528d9 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -11,7 +11,7 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) -: wxDialog(parent, -1, wxT("Ramming customization"), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +: wxDialog(parent, wxID_ANY, _(L("Ramming customization")), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { this->Centre(); m_panel_ramming = new RammingPanel(this,parameters); @@ -20,7 +20,7 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) auto main_sizer = new wxBoxSizer(wxVERTICAL); main_sizer->Add(m_panel_ramming, 1, wxEXPAND); - main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); + main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM | wxTOP, 10); SetSizer(main_sizer); SetMinSize(GetSize()); main_sizer->SetSizeHints(this); @@ -102,24 +102,24 @@ std::string RammingPanel::get_parameters() } - +#define ITEM_WIDTH 60 // Parent dialog for purging volume adjustments - it fathers WipingPanel widget (that contains all controls) and a button to toggle simple/advanced mode: WipingDialog::WipingDialog(wxWindow* parent,const std::vector& matrix, const std::vector& extruders) -: wxDialog(parent, -1, wxT(L("Wipe tower - Purging volume adjustment")), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +: wxDialog(parent, wxID_ANY, _(L("Wipe tower - Purging volume adjustment")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - this->Centre(); - auto widget_button = new wxButton(this,wxID_ANY,"-",wxPoint(0,0),wxDefaultSize); m_panel_wiping = new WipingPanel(this,matrix,extruders, widget_button); auto main_sizer = new wxBoxSizer(wxVERTICAL); - main_sizer->Add(m_panel_wiping, 1, wxEXPAND); + // set min sizer width according to extruders count + const auto sizer_width = (int)((sqrt(matrix.size()) + 2.8)*ITEM_WIDTH); + main_sizer->SetMinSize(wxSize(sizer_width, -1)); - main_sizer->Add(widget_button,0,wxALIGN_CENTER_HORIZONTAL|wxCENTER,10); + main_sizer->Add(m_panel_wiping, 0, wxEXPAND | wxALL, 5); + main_sizer->Add(widget_button, 0, wxALIGN_CENTER_HORIZONTAL | wxCENTER | wxBOTTOM, 5); main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); SetSizer(main_sizer); - SetMinSize(GetSize()); main_sizer->SetSizeHints(this); this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); @@ -133,68 +133,91 @@ WipingDialog::WipingDialog(wxWindow* parent,const std::vector& matrix, co this->Show(); } - +// This function allows to "play" with sizers parameters (like align or border) +void WipingPanel::format_sizer(wxSizer* sizer, wxPanel* page, wxGridSizer* grid_sizer, const wxString& info, const wxString& table_title, int table_lshift/*=0*/) +{ + sizer->Add(new wxStaticText(page, wxID_ANY, info), 0, wxEXPAND | wxLEFT, 15); + auto table_sizer = new wxBoxSizer(wxVERTICAL); + sizer->Add(table_sizer, 0, wxALIGN_LEFT | wxLEFT, table_lshift); + table_sizer->Add(new wxStaticText(page, wxID_ANY, table_title), 0, wxALIGN_CENTER | wxTOP, 50); + table_sizer->Add(grid_sizer, 0, wxALIGN_CENTER | wxTOP, 10); +} // This panel contains all control widgets for both simple and advanced mode (these reside in separate sizers) WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, const std::vector& extruders, wxButton* widget_button) -: wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(500,350),wxBORDER_RAISED) +: wxPanel(parent,wxID_ANY, wxDefaultPosition, wxDefaultSize,wxBORDER_RAISED) { m_widget_button = widget_button; // pointer to the button in parent dialog m_widget_button->Bind(wxEVT_BUTTON,[this](wxCommandEvent&){ toggle_advanced(true); }); m_number_of_extruders = (int)(sqrt(matrix.size())+0.001); + // Create two switched panels with their own sizers m_sizer_simple = new wxBoxSizer(wxVERTICAL); m_sizer_advanced = new wxBoxSizer(wxVERTICAL); - auto gridsizer_simple = new wxGridSizer(3,10,10); - auto gridsizer_advanced = new wxGridSizer(m_number_of_extruders+1,10,10); + m_page_simple = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + m_page_advanced = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + m_page_simple->SetSizer(m_sizer_simple); + m_page_advanced->SetSizer(m_sizer_advanced); + auto gridsizer_simple = new wxGridSizer(3, 5, 10); + auto gridsizer_advanced = new wxGridSizer(m_number_of_extruders+1, 5, 1); - // First create controls for simple mode and assign them to m_sizer_simple: - m_sizer_simple->Add(new wxStaticText(this,wxID_ANY,wxString(L("Total purging volume is calculated by summing two values below, depending on which tools are loaded/unloaded.")),wxPoint(40,25), wxSize(450,35)),-1,wxEXPAND,10); - m_sizer_simple->Add(new wxStaticText(this,wxID_ANY,wxString(L("Volume to purge (mm\u00B3) when the filament is being")),wxPoint(40,85) ,/*wxSize(500,25)*/wxDefaultSize,wxALIGN_LEFT),-1,wxEXPAND|wxALIGN_CENTER,10); + // First create controls for advanced mode and assign them to m_page_advanced: + for (unsigned int i = 0; i < m_number_of_extruders; ++i) { + edit_boxes.push_back(std::vector(0)); - gridsizer_simple->Add(0,-1,wxALL,10); - gridsizer_simple->Add(new wxStaticText(this,wxID_ANY,wxString(L("unloaded")),wxPoint(110,105) ,/*wxSize(80,25)*/wxDefaultSize,wxALIGN_CENTER),-1,wxALIGN_CENTER,10); - gridsizer_simple->Add(new wxStaticText(this,wxID_ANY,wxString(L("loaded")),wxPoint(195,105) ,/*wxSize(80,25)*/wxDefaultSize,wxALIGN_CENTER),-1,wxALIGN_CENTER,10); + for (unsigned int j = 0; j < m_number_of_extruders; ++j) { + edit_boxes.back().push_back(new wxTextCtrl(m_page_advanced, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(ITEM_WIDTH, -1))); + if (i == j) + edit_boxes[i][j]->Disable(); + else + edit_boxes[i][j]->SetValue(wxString("") << int(matrix[m_number_of_extruders*j + i])); + } + } + gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString(""))); + for (unsigned int i = 0; i < m_number_of_extruders; ++i) + gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("") << i + 1), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + for (unsigned int i = 0; i < m_number_of_extruders; ++i) { + gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("") << i + 1), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + for (unsigned int j = 0; j < m_number_of_extruders; ++j) + gridsizer_advanced->Add(edit_boxes[j][i], 0); + } - for (unsigned int i=0;iAdd(new wxStaticText(this,wxID_ANY,wxString(L("Tool #"))<Add(m_old.back(),-1,wxALIGN_CENTER,10); - gridsizer_simple->Add(m_new.back(),-1,wxALIGN_CENTER,10); - } + // collect and format sizer + format_sizer(m_sizer_advanced, m_page_advanced, gridsizer_advanced, + _(L("Here you can adjust required purging volume (mm\u00B3) for any given pair of tools.")), + _(L("Filament changed to"))); - // Now the same for advanced mode: - wxPoint origin(50,85); - m_sizer_advanced->Add(new wxStaticText(this,wxID_ANY,wxString(L("Here you can adjust required purging volume (mm\u00B3) for any given pair of tools.")),wxPoint(40,25) ,/*wxSize(500,35)*/wxDefaultSize),-1,wxALL,10); - m_sizer_advanced->Add(new wxStaticText(this,wxID_ANY,wxString(L("Filament changed to")),origin+wxPoint(75,0) ,/*wxSize(500,25)*/wxDefaultSize),-1,wxALL,10); + // Hide preview page before new page creating + // It allows to do that from a beginning of the main panel + m_page_advanced->Hide(); - for (unsigned int i=0;i(0)); + // Now the same for simple mode: + gridsizer_simple->Add(new wxStaticText(m_page_simple, wxID_ANY, wxString("")), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + gridsizer_simple->Add(new wxStaticText(m_page_simple, wxID_ANY, wxString(_(L("unloaded")))), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + gridsizer_simple->Add(new wxStaticText(m_page_simple,wxID_ANY,wxString(_(L("loaded")))), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - for (unsigned int j=0;jDisable(); - else - edit_boxes[i][j]->SetValue(wxString("")<Add(new wxStaticText(m_page_simple, wxID_ANY, wxString(_(L("Tool #"))) << i + 1 << ": "), 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + gridsizer_simple->Add(m_old.back(),0); + gridsizer_simple->Add(m_new.back(),0); + } - gridsizer_advanced->Add(0,-1,wxALL,10); - for (unsigned int i=0;iAdd(new wxStaticText(this,wxID_ANY,wxString("")<Add(new wxStaticText(this,wxID_ANY,wxString("")<Add(edit_boxes[j][i],-1,wxALL,10); - } + // collect and format sizer + format_sizer(m_sizer_simple, m_page_simple, gridsizer_simple, + _(L("Total purging volume is calculated by summing two values below, depending on which tools are loaded/unloaded.")), + _(L("Volume to purge (mm\u00B3) when the filament is being")), 50); + m_sizer = new wxBoxSizer(wxVERTICAL); + m_sizer->Add(m_page_simple, 0, wxEXPAND | wxALL, 25); + m_sizer->Add(m_page_advanced, 0, wxEXPAND | wxALL, 25); + + m_sizer->SetSizeHints(this); + SetSizer(m_sizer); - m_sizer_simple->Add(gridsizer_simple,-1,wxALL,10); - m_sizer_advanced->Add(gridsizer_advanced,-1,wxALL,10); toggle_advanced(); // to show/hide what is appropriate } @@ -260,18 +283,16 @@ void WipingPanel::toggle_advanced(bool user_action) { } if (user_action) m_advanced = !m_advanced; // user demands a change -> toggle - else { + else m_advanced = !advanced_matches_simple(); // if called from constructor, show what is appropriate - (m_advanced ? m_sizer_advanced : m_sizer_simple)->SetSizeHints(this); - SetSizer(m_advanced ? m_sizer_advanced : m_sizer_simple); - } - m_sizer_simple->Show(!m_advanced); - m_sizer_advanced->Show(m_advanced); + (m_advanced ? m_page_advanced : m_page_simple)->Show(); + (!m_advanced ? m_page_advanced : m_page_simple)->Hide(); m_widget_button->SetLabel(m_advanced ? L("Show simplified settings") : L("Show advanced settings")); if (m_advanced) if (user_action) fill_in_matrix(); // otherwise keep values loaded from config - this->Refresh(); + m_sizer->Layout(); + Refresh(); } \ No newline at end of file diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/xs/src/slic3r/GUI/WipeTowerDialog.hpp index c8e7bd480..7448cd1e5 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.hpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.hpp @@ -50,6 +50,7 @@ public: std::vector read_matrix_values(); std::vector read_extruders_values(); void toggle_advanced(bool user_action = false); + void format_sizer(wxSizer* sizer, wxPanel* page, wxGridSizer* grid_sizer, const wxString& info, const wxString& table_title, int table_lshift=0); private: void fill_in_matrix(); @@ -62,6 +63,9 @@ private: std::vector> edit_boxes; unsigned int m_number_of_extruders = 0; bool m_advanced = false; + wxPanel* m_page_simple = nullptr; + wxPanel* m_page_advanced = nullptr; + wxBoxSizer* m_sizer = nullptr; wxBoxSizer*m_sizer_simple = nullptr; wxBoxSizer*m_sizer_advanced = nullptr; wxButton* m_widget_button = nullptr; From 0d2637fede41b966361fbc03876a892e1d64ad56 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 28 Mar 2018 10:16:04 +0200 Subject: [PATCH 56/81] t tests changed so they don't fail on the extruder number check --- t/combineinfill.t | 2 +- t/custom_gcode.t | 4 +++- t/fill.t | 4 +++- t/multi.t | 6 ++++++ t/retraction.t | 4 +++- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/t/combineinfill.t b/t/combineinfill.t index e94cf9eb5..5402a84f5 100644 --- a/t/combineinfill.t +++ b/t/combineinfill.t @@ -57,7 +57,7 @@ plan tests => 8; my $config = Slic3r::Config::new_from_defaults; $config->set('layer_height', 0.2); $config->set('first_layer_height', 0.2); - $config->set('nozzle_diameter', [0.5]); + $config->set('nozzle_diameter', [0.5,0.5,0.5,0.5]); $config->set('infill_every_layers', 2); $config->set('perimeter_extruder', 1); $config->set('infill_extruder', 2); diff --git a/t/custom_gcode.t b/t/custom_gcode.t index bafcd4610..31d1d48e0 100644 --- a/t/custom_gcode.t +++ b/t/custom_gcode.t @@ -49,7 +49,6 @@ use Slic3r::Test; my $parser = Slic3r::GCode::PlaceholderParser->new; my $config = Slic3r::Config::new_from_defaults; $config->set('printer_notes', ' PRINTER_VENDOR_PRUSA3D PRINTER_MODEL_MK2 '); - $config->set('nozzle_diameter', [0.6, 0.6, 0.6, 0.6]); $parser->apply_config($config); $parser->set('foo' => 0); $parser->set('bar' => 2); @@ -123,6 +122,7 @@ use Slic3r::Test; { my $config = Slic3r::Config->new; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $config->set('extruder', 2); $config->set('first_layer_temperature', [200,205]); @@ -204,6 +204,7 @@ use Slic3r::Test; { my $config = Slic3r::Config->new; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6,0.6]); $config->set('start_gcode', qq! ;substitution:{if infill_extruder==1}if block {elsif infill_extruder==2}elsif block 1 @@ -228,6 +229,7 @@ use Slic3r::Test; { my $config = Slic3r::Config->new; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $config->set('start_gcode', ';substitution:{if infill_extruder==1}{if perimeter_extruder==1}block11{else}block12{endif}' . '{elsif infill_extruder==2}{if perimeter_extruder==1}block21{else}block22{endif}' . diff --git a/t/fill.t b/t/fill.t index a6fe8619c..dd9eee487 100644 --- a/t/fill.t +++ b/t/fill.t @@ -164,6 +164,7 @@ SKIP: for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) { my $config = Slic3r::Config::new_from_defaults; + $config->set('nozzle_diameter', [0.4,0.4,0.4,0.4]); $config->set('fill_pattern', $pattern); $config->set('external_fill_pattern', $pattern); $config->set('perimeters', 1); @@ -195,6 +196,7 @@ for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) { { my $config = Slic3r::Config::new_from_defaults; + $config->set('nozzle_diameter', [0.4,0.4,0.4,0.4]); $config->set('infill_only_where_needed', 1); $config->set('bottom_solid_layers', 0); $config->set('infill_extruder', 2); @@ -276,7 +278,7 @@ for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) { $config->set('fill_density', 0); $config->set('layer_height', 0.2); $config->set('first_layer_height', 0.2); - $config->set('nozzle_diameter', [0.35]); + $config->set('nozzle_diameter', [0.35,0.35,0.35,0.35]); $config->set('infill_extruder', 2); $config->set('solid_infill_extruder', 2); $config->set('infill_extrusion_width', 0.52); diff --git a/t/multi.t b/t/multi.t index 49d35d907..75ce0c286 100644 --- a/t/multi.t +++ b/t/multi.t @@ -16,6 +16,7 @@ use Slic3r::Test; { my $config = Slic3r::Config::new_from_defaults; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $config->set('raft_layers', 2); $config->set('infill_extruder', 2); $config->set('solid_infill_extruder', 3); @@ -89,6 +90,7 @@ use Slic3r::Test; { my $config = Slic3r::Config::new_from_defaults; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $config->set('support_material_extruder', 3); my $print = Slic3r::Test::init_print('20mm_cube', config => $config); @@ -97,6 +99,7 @@ use Slic3r::Test; { my $config = Slic3r::Config->new; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $config->set('extruder', 2); my $print = Slic3r::Test::init_print('20mm_cube', config => $config); @@ -105,6 +108,7 @@ use Slic3r::Test; { my $config = Slic3r::Config->new; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $config->set('perimeter_extruder', 2); $config->set('infill_extruder', 2); $config->set('support_material_extruder', 2); @@ -126,6 +130,7 @@ use Slic3r::Test; $upper_config->set('bottom_solid_layers', 1); $upper_config->set('top_solid_layers', 0); my $config = Slic3r::Config::new_from_defaults; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $config->set('fill_density', 0); $config->set('solid_infill_speed', 99); $config->set('top_solid_infill_speed', 99); @@ -172,6 +177,7 @@ use Slic3r::Test; my $object = $model->objects->[0]; my $config = Slic3r::Config::new_from_defaults; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $config->set('layer_height', 0.4); $config->set('first_layer_height', '100%'); $config->set('skirts', 0); diff --git a/t/retraction.t b/t/retraction.t index d7f1ea145..6e6a130ca 100644 --- a/t/retraction.t +++ b/t/retraction.t @@ -95,6 +95,7 @@ use Slic3r::Test qw(_eq); 1; }; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $config->set('first_layer_height', $config->layer_height); $config->set('first_layer_speed', '100%'); $config->set('start_gcode', ''); # to avoid dealing with the nozzle lift in start G-code @@ -207,6 +208,7 @@ use Slic3r::Test qw(_eq); { my $config = Slic3r::Config::new_from_defaults; + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $config->set('start_gcode', ''); $config->set('retract_lift', [3, 4]); @@ -255,4 +257,4 @@ use Slic3r::Test qw(_eq); 'Z is not lifted above the configured value for 2. extruder'; } -__END__ \ No newline at end of file +__END__ From 7951349a1f64771848ca51147c7ac0474d83fb5b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 28 Mar 2018 10:32:23 +0200 Subject: [PATCH 57/81] Another t-test change to avoid fails --- t/custom_gcode.t | 1 + 1 file changed, 1 insertion(+) diff --git a/t/custom_gcode.t b/t/custom_gcode.t index 31d1d48e0..7c2a75f29 100644 --- a/t/custom_gcode.t +++ b/t/custom_gcode.t @@ -49,6 +49,7 @@ use Slic3r::Test; my $parser = Slic3r::GCode::PlaceholderParser->new; my $config = Slic3r::Config::new_from_defaults; $config->set('printer_notes', ' PRINTER_VENDOR_PRUSA3D PRINTER_MODEL_MK2 '); + $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); $parser->apply_config($config); $parser->set('foo' => 0); $parser->set('bar' => 2); From 1b4dc685f4430a8ff1f35aea61dd920743b71c8b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 28 Mar 2018 15:37:10 +0200 Subject: [PATCH 58/81] Connected filament_ramming_parameters to respective dialog, other minor changes --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 2 +- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 4 ++-- xs/src/libslic3r/PrintConfig.cpp | 8 ++++---- xs/src/libslic3r/PrintConfig.hpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 8 +++----- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 7c8181ff6..0c8f4fe9f 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -800,7 +800,7 @@ void WipeTowerPrusaMM::toolchange_Unload( const float start_x = writer.x(); turning_point = ( xr-start_x > start_x-xl ? xr : xl ); const float max_x_dist = 2*std::abs(start_x-turning_point); - const unsigned int N = 4 + std::max(0,(m_filpar[m_current_tool].cooling_time-14)/3); + const unsigned int N = 4 + std::max(0.f, (m_filpar[m_current_tool].cooling_time-14)/3); float time = m_filpar[m_current_tool].cooling_time / float(N); i = 0; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 4f97f700f..636b4b738 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -67,7 +67,7 @@ public: // Set the extruder properties. void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed, - float unloading_speed, float delay, int cooling_time, std::string ramming_parameters) + float unloading_speed, float delay, float cooling_time, std::string ramming_parameters) { //while (m_filpar.size() < idx+1) // makes sure the required element is in the vector m_filpar.push_back(FilamentParameters()); @@ -205,7 +205,7 @@ private: float loading_speed = 0.f; float unloading_speed = 0.f; float delay = 0.f ; - int cooling_time = 0; + float cooling_time = 0.f; float ramming_line_width_multiplicator = 0.f; float ramming_step_multiplicator = 0.f; std::vector ramming_speed; diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index cb5bcea4a..aef9a8fa2 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -470,14 +470,14 @@ PrintConfigDef::PrintConfigDef() def->min = 0; def->default_value = new ConfigOptionFloats { 0. }; - def = this->add("filament_cooling_time", coInts); + def = this->add("filament_cooling_time", coFloats); def->label = L("Cooling time"); def->tooltip = L("The filament is slowly moved back and forth after retraction into the cooling tube " "for this amount of time."); def->cli = "filament_cooling_time=i@"; def->sidetext = L("s"); def->min = 0; - def->default_value = new ConfigOptionInts { 14 }; + def->default_value = new ConfigOptionFloats { 14.f }; def = this->add("filament_ramming_parameters", coStrings); def->label = L("Ramming parameters"); @@ -1779,7 +1779,7 @@ PrintConfigDef::PrintConfigDef() def->default_value = new ConfigOptionBool(false); def = this->add("wiping_volumes_extruders", coFloats); - def->label = L("Extrusion multiplier"); + def->label = L("Purging volumes - load/unload volumes"); def->tooltip = L("This vector saves required volumes to change from/to each tool used on the " "wipe tower. These values are used to simplify creation of the full purging " "volumes below. "); @@ -1787,7 +1787,7 @@ PrintConfigDef::PrintConfigDef() def->default_value = new ConfigOptionFloats { 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f }; def = this->add("wiping_volumes_matrix", coFloats); - def->label = L("Extrusion multiplier"); + def->label = L("Purging volumes - matrix"); def->tooltip = L("This matrix describes volumes (in cubic milimetres) required to purge the" " new filament on the wipe tower for any given pair of tools. "); def->cli = "wiping-volumes-matrix=f@"; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index d184a2161..be64d35bd 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -469,7 +469,7 @@ public: ConfigOptionFloats filament_loading_speed; ConfigOptionFloats filament_unloading_speed; ConfigOptionFloats filament_toolchange_delay; - ConfigOptionInts filament_cooling_time; + ConfigOptionFloats filament_cooling_time; ConfigOptionStrings filament_ramming_parameters; ConfigOptionBool gcode_comments; ConfigOptionEnum gcode_flavor; diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 267e579b6..82d4c456d 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -521,7 +521,7 @@ void TabPrint::build() optgroup->append_single_option_line("wipe_tower_bridging"); line = { _(L("Advanced")), "" }; line.widget = [this](wxWindow* parent){ - m_wipe_tower_btn = new wxButton(parent, wxID_ANY, _(L("Advanced settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); + m_wipe_tower_btn = new wxButton(parent, wxID_ANY, _(L("Purging volumes"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(m_wipe_tower_btn); m_wipe_tower_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) @@ -958,10 +958,8 @@ void TabFilament::build() ramming_dialog_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) { RammingDialog dlg(this,(m_config->option("filament_ramming_parameters"))->get_at(0)); - if (dlg.ShowModal() == wxID_OK) { - wxMessageBox("DIALOG OK:\n"+dlg.get_parameters()); - //load_key_value("wipe_tower_advanced", dlg.get_parameters()); - } + if (dlg.ShowModal() == wxID_OK) + (m_config->option("filament_ramming_parameters"))->get_at(0) = dlg.get_parameters(); })); return sizer; }; From c61ffe9f6b7a776f4bc468fbcaf0f7d794197b5e Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 28 Mar 2018 20:31:36 +0200 Subject: [PATCH 59/81] Corrected UI for RammingDialog --- xs/src/slic3r/GUI/RammingChart.cpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 2 +- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 84 +++++++++++++++++---------- 3 files changed, 54 insertions(+), 34 deletions(-) diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/xs/src/slic3r/GUI/RammingChart.cpp index e07b95839..7b6730c1b 100644 --- a/xs/src/slic3r/GUI/RammingChart.cpp +++ b/xs/src/slic3r/GUI/RammingChart.cpp @@ -59,7 +59,7 @@ void Chart::draw(wxDC& dc) { int x = m_rect.GetLeft(); if (last_mark-y < 50) continue; dc.DrawLine(x-3,y,x+3,y); - dc.DrawText(wxString()<append_single_option_line("filament_cooling_time"); line = { _(L("Ramming")), "" }; line.widget = [this](wxWindow* parent){ - auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); + auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(ramming_dialog_btn); diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index 8cd6528d9..b491415da 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -11,18 +11,16 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) -: wxDialog(parent, wxID_ANY, _(L("Ramming customization")), wxPoint(50,50), wxSize(800,550), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +: wxDialog(parent, wxID_ANY, _(L("Ramming customization")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - this->Centre(); m_panel_ramming = new RammingPanel(this,parameters); m_panel_ramming->Show(true); this->Show(); auto main_sizer = new wxBoxSizer(wxVERTICAL); - main_sizer->Add(m_panel_ramming, 1, wxEXPAND); - main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM | wxTOP, 10); + main_sizer->Add(m_panel_ramming, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5); + main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_CENTER_HORIZONTAL | wxTOP | wxBOTTOM, 10); SetSizer(main_sizer); - SetMinSize(GetSize()); main_sizer->SetSizeHints(this); this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); }); @@ -38,34 +36,48 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters) -: wxPanel(parent,wxID_ANY,wxPoint(50,50), wxSize(800,350),wxBORDER_RAISED) +: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,/*wxPoint(50,50), wxSize(800,350),*/wxBORDER_RAISED) { - new wxStaticText(this,wxID_ANY,wxString("Total ramming time (s):"), wxPoint(500,105), wxSize(200,25),wxALIGN_LEFT); - m_widget_time = new wxSpinCtrlDouble(this,wxID_ANY,wxEmptyString, wxPoint(700,100), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,0.,5.0,3.,0.5); - new wxStaticText(this,wxID_ANY,wxString("Total rammed volume (mm\u00B3):"), wxPoint(500,135), wxSize(200,25),wxALIGN_LEFT); - m_widget_volume = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,130), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,0,10000,0); - new wxStaticText(this,wxID_ANY,wxString("Ramming line width (%):"), wxPoint(500,205), wxSize(200,25),wxALIGN_LEFT); - m_widget_ramming_line_width_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,200), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,10,200,100); - new wxStaticText(this,wxID_ANY,wxString("Ramming line spacing (%):"), wxPoint(500,235), wxSize(200,25),wxALIGN_LEFT); - m_widget_ramming_step_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString, wxPoint(700,230), wxSize(75,25),wxSP_ARROW_KEYS|wxALIGN_RIGHT,10,200,100); - - std::stringstream stream{parameters}; - stream >> m_ramming_line_width_multiplicator >> m_ramming_step_multiplicator; - int ramming_speed_size = 0; - float dummy = 0.f; - while (stream >> dummy) - ++ramming_speed_size; - stream.clear(); - stream.get(); - - std::vector> buttons; - float x = 0.f; - float y = 0.f; - while (stream >> x >> y) - buttons.push_back(std::make_pair(x,y)); - - m_chart = new Chart(this,wxRect(10,10,480,360),buttons,ramming_speed_size,0.25f); - + auto sizer_chart = new wxBoxSizer(wxVERTICAL); + auto sizer_param = new wxBoxSizer(wxVERTICAL); + + std::stringstream stream{ parameters }; + stream >> m_ramming_line_width_multiplicator >> m_ramming_step_multiplicator; + int ramming_speed_size = 0; + float dummy = 0.f; + while (stream >> dummy) + ++ramming_speed_size; + stream.clear(); + stream.get(); + + std::vector> buttons; + float x = 0.f; + float y = 0.f; + while (stream >> x >> y) + buttons.push_back(std::make_pair(x, y)); + + m_chart = new Chart(this, wxRect(10, 10, 480, 360), buttons, ramming_speed_size, 0.25f); + sizer_chart->Add(m_chart, 0, wxALL, 5); + + m_widget_time = new wxSpinCtrlDouble(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(75, -1),wxSP_ARROW_KEYS,0.,5.0,3.,0.5); + m_widget_volume = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(75, -1),wxSP_ARROW_KEYS,0,10000,0); + m_widget_ramming_line_width_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(75, -1),wxSP_ARROW_KEYS,10,200,100); + m_widget_ramming_step_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(75, -1),wxSP_ARROW_KEYS,10,200,100); + + auto gsizer_param = new wxFlexGridSizer(2, 5, 15); + gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Total ramming time (s):")))), 0, wxALIGN_CENTER_VERTICAL); + gsizer_param->Add(m_widget_time); + gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Total rammed volume (mm"))+"\u00B3):")), 0, wxALIGN_CENTER_VERTICAL); + gsizer_param->Add(m_widget_volume); + gsizer_param->AddSpacer(20); + gsizer_param->AddSpacer(20); + gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Ramming line width (%):")))), 0, wxALIGN_CENTER_VERTICAL); + gsizer_param->Add(m_widget_ramming_line_width_multiplicator); + gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Ramming line spacing (%):")))), 0, wxALIGN_CENTER_VERTICAL); + gsizer_param->Add(m_widget_ramming_step_multiplicator); + + sizer_param->Add(gsizer_param, 0, wxTOP, 100); + m_widget_time->SetValue(m_chart->get_time()); m_widget_time->SetDigits(2); m_widget_volume->SetValue(m_chart->get_volume()); @@ -75,6 +87,14 @@ RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters) m_widget_ramming_step_multiplicator->Bind(wxEVT_TEXT,[this](wxCommandEvent&) { line_parameters_changed(); }); m_widget_ramming_line_width_multiplicator->Bind(wxEVT_TEXT,[this](wxCommandEvent&) { line_parameters_changed(); }); + + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(sizer_chart, 0, wxALL, 5); + sizer->Add(sizer_param, 0, wxALL, 10); + + sizer->SetSizeHints(this); + SetSizer(sizer); + m_widget_time->Bind(wxEVT_TEXT,[this](wxCommandEvent&) {m_chart->set_xy_range(m_widget_time->GetValue(),-1);}); m_widget_time->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value m_widget_volume->Bind(wxEVT_CHAR,[](wxKeyEvent&){}); // do nothing - prevents the user to change the value From 572008546d3a6758af20963dcde20846add08445 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 29 Mar 2018 12:04:09 +0200 Subject: [PATCH 60/81] Vertical label in wiping matrix dialog --- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 24 +++++++++++++++++------- xs/src/slic3r/GUI/WipeTowerDialog.hpp | 2 -- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index b69d7c6f0..05be20cd6 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -11,7 +11,7 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) -: wxDialog(parent, wxID_ANY, _(L("Ramming customization")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +: wxDialog(parent, wxID_ANY, _(L("Ramming customization")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/) { m_panel_ramming = new RammingPanel(this,parameters); m_panel_ramming->Show(true); @@ -36,7 +36,7 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters) -: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,/*wxPoint(50,50), wxSize(800,350),*/wxBORDER_RAISED). +: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize/*,wxPoint(50,50), wxSize(800,350),wxBORDER_RAISED*/) { auto sizer_chart = new wxBoxSizer(wxVERTICAL); auto sizer_param = new wxBoxSizer(wxVERTICAL); @@ -125,7 +125,7 @@ std::string RammingPanel::get_parameters() #define ITEM_WIDTH 60 // Parent dialog for purging volume adjustments - it fathers WipingPanel widget (that contains all controls) and a button to toggle simple/advanced mode: WipingDialog::WipingDialog(wxWindow* parent,const std::vector& matrix, const std::vector& extruders) -: wxDialog(parent, wxID_ANY, _(L("Wipe tower - Purging volume adjustment")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +: wxDialog(parent, wxID_ANY, _(L("Wipe tower - Purging volume adjustment")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/) { auto widget_button = new wxButton(this,wxID_ANY,"-",wxPoint(0,0),wxDefaultSize); m_panel_wiping = new WipingPanel(this,matrix,extruders, widget_button); @@ -156,16 +156,16 @@ WipingDialog::WipingDialog(wxWindow* parent,const std::vector& matrix, co // This function allows to "play" with sizers parameters (like align or border) void WipingPanel::format_sizer(wxSizer* sizer, wxPanel* page, wxGridSizer* grid_sizer, const wxString& info, const wxString& table_title, int table_lshift/*=0*/) { - sizer->Add(new wxStaticText(page, wxID_ANY, info), 0, wxEXPAND | wxLEFT, 15); + sizer->Add(new wxStaticText(page, wxID_ANY, info,wxDefaultPosition,wxSize(0,50)), 0, wxEXPAND | wxLEFT, 15); auto table_sizer = new wxBoxSizer(wxVERTICAL); - sizer->Add(table_sizer, 0, wxALIGN_LEFT | wxLEFT, table_lshift); + sizer->Add(table_sizer, 0, wxALIGN_CENTER | wxCENTER, table_lshift); table_sizer->Add(new wxStaticText(page, wxID_ANY, table_title), 0, wxALIGN_CENTER | wxTOP, 50); table_sizer->Add(grid_sizer, 0, wxALIGN_CENTER | wxTOP, 10); } // This panel contains all control widgets for both simple and advanced mode (these reside in separate sizers) WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, const std::vector& extruders, wxButton* widget_button) -: wxPanel(parent,wxID_ANY, wxDefaultPosition, wxDefaultSize,wxBORDER_RAISED) +: wxPanel(parent,wxID_ANY, wxDefaultPosition, wxDefaultSize/*,wxBORDER_RAISED*/) { m_widget_button = widget_button; // pointer to the button in parent dialog m_widget_button->Bind(wxEVT_BUTTON,[this](wxCommandEvent&){ toggle_advanced(true); }); @@ -207,7 +207,7 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con // collect and format sizer format_sizer(m_sizer_advanced, m_page_advanced, gridsizer_advanced, _(L("Here you can adjust required purging volume (mm\u00B3) for any given pair of tools.")), - _(L("Filament changed to"))); + _(L("Extruder changed to"))); // Hide preview page before new page creating // It allows to do that from a beginning of the main panel @@ -239,6 +239,16 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con SetSizer(m_sizer); toggle_advanced(); // to show/hide what is appropriate + + m_page_advanced->Bind(wxEVT_PAINT,[this](wxPaintEvent&) { + wxPaintDC dc(m_page_advanced); + int y_pos = 0.5 * (edit_boxes[0][0]->GetPosition().y + edit_boxes[0][edit_boxes.size()-1]->GetPosition().y + edit_boxes[0][edit_boxes.size()-1]->GetSize().y); + wxString label = L("From"); + int text_width = 0; + int text_height = 0; + dc.GetTextExtent(label,&text_width,&text_height); + dc.DrawRotatedText(label,5,y_pos + text_width/2.f,90); + }); } diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/xs/src/slic3r/GUI/WipeTowerDialog.hpp index 7448cd1e5..beb5c5f46 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.hpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.hpp @@ -58,8 +58,6 @@ private: std::vector m_old; std::vector m_new; - std::vector m_advanced_widgets; - std::vector m_notadvanced_widgets; std::vector> edit_boxes; unsigned int m_number_of_extruders = 0; bool m_advanced = false; From 6fd3f38717affdd552b3b218ea69768e955a7d55 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 29 Mar 2018 14:23:45 +0200 Subject: [PATCH 61/81] Warning to show before ramming adjustements, vertical text in wiping dialog positioned better --- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 21 ++++++++++++++------- xs/src/slic3r/GUI/WipeTowerDialog.hpp | 5 +++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index 05be20cd6..df0552299 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -29,6 +29,12 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) m_output_data = m_panel_ramming->get_parameters(); EndModal(wxID_OK); },wxID_OK); + this->Show(); + wxMessageDialog(this,L("Ramming denotes the rapid extrusion just before a tool change in a single-extruder MM printer. Its purpose is to " + "properly shape the end of the unloaded filament so it does not prevent insertion of the new filament and can itself " + "be reinserted later. This phase is important and different materials can require different extrusion speeds to get " + "the good shape. For this reason, the extrusion rates during ramming are adjustable.\n\nThis is an expert-level " + "setting, incorrect adjustment will likely lead to jams, extruder wheel grinding into filament etc."),L("Warning"),wxOK|wxICON_EXCLAMATION).ShowModal(); } @@ -181,7 +187,7 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con m_page_advanced->SetSizer(m_sizer_advanced); auto gridsizer_simple = new wxGridSizer(3, 5, 10); - auto gridsizer_advanced = new wxGridSizer(m_number_of_extruders+1, 5, 1); + m_gridsizer_advanced = new wxGridSizer(m_number_of_extruders+1, 5, 1); // First create controls for advanced mode and assign them to m_page_advanced: for (unsigned int i = 0; i < m_number_of_extruders; ++i) { @@ -195,17 +201,17 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con edit_boxes[i][j]->SetValue(wxString("") << int(matrix[m_number_of_extruders*j + i])); } } - gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString(""))); + m_gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString(""))); for (unsigned int i = 0; i < m_number_of_extruders; ++i) - gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("") << i + 1), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + m_gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("") << i + 1), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); for (unsigned int i = 0; i < m_number_of_extruders; ++i) { - gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("") << i + 1), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + m_gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("") << i + 1), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); for (unsigned int j = 0; j < m_number_of_extruders; ++j) - gridsizer_advanced->Add(edit_boxes[j][i], 0); + m_gridsizer_advanced->Add(edit_boxes[j][i], 0); } // collect and format sizer - format_sizer(m_sizer_advanced, m_page_advanced, gridsizer_advanced, + format_sizer(m_sizer_advanced, m_page_advanced, m_gridsizer_advanced, _(L("Here you can adjust required purging volume (mm\u00B3) for any given pair of tools.")), _(L("Extruder changed to"))); @@ -247,7 +253,8 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con int text_width = 0; int text_height = 0; dc.GetTextExtent(label,&text_width,&text_height); - dc.DrawRotatedText(label,5,y_pos + text_width/2.f,90); + int xpos = m_gridsizer_advanced->GetPosition().x; + dc.DrawRotatedText(label,xpos-text_height,y_pos + text_width/2.f,90); }); } diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/xs/src/slic3r/GUI/WipeTowerDialog.hpp index beb5c5f46..d858062da 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.hpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.hpp @@ -64,8 +64,9 @@ private: wxPanel* m_page_simple = nullptr; wxPanel* m_page_advanced = nullptr; wxBoxSizer* m_sizer = nullptr; - wxBoxSizer*m_sizer_simple = nullptr; - wxBoxSizer*m_sizer_advanced = nullptr; + wxBoxSizer* m_sizer_simple = nullptr; + wxBoxSizer* m_sizer_advanced = nullptr; + wxGridSizer* m_gridsizer_advanced = nullptr; wxButton* m_widget_button = nullptr; }; From 281732ca388909d475abd1e504add7ce06dcc196 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 29 Mar 2018 15:32:09 +0200 Subject: [PATCH 62/81] Variable layer height enabled, nozzle diameters properly passed to the wipe tower generator --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 2 +- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 13 ++++++++----- xs/src/libslic3r/Print.cpp | 13 ++++++++++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 0c8f4fe9f..889eaf2f5 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -1104,7 +1104,7 @@ void WipeTowerPrusaMM::plan_tower() if (this_layer_depth > m_wipe_tower_depth - m_perimeter_width) m_wipe_tower_depth = this_layer_depth + m_perimeter_width; - for (int i = layer_index - 1; i >= 0 /*&& m_plan[i].depth < this_layer_depth*/; i--) + for (int i = layer_index - 1; i >= 0 ; i--) { if (m_plan[i].depth - this_layer_depth < 2*m_perimeter_width ) m_plan[i].depth = this_layer_depth; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 636b4b738..26c40fbc9 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -67,7 +67,7 @@ public: // Set the extruder properties. void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed, - float unloading_speed, float delay, float cooling_time, std::string ramming_parameters) + float unloading_speed, float delay, float cooling_time, std::string ramming_parameters, float nozzle_diameter) { //while (m_filpar.size() < idx+1) // makes sure the required element is in the vector m_filpar.push_back(FilamentParameters()); @@ -79,6 +79,9 @@ public: m_filpar[idx].unloading_speed = unloading_speed; m_filpar[idx].delay = delay; m_filpar[idx].cooling_time = cooling_time; + m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM + + m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter std::stringstream stream{ramming_parameters}; float speed = 0.f; @@ -171,8 +174,7 @@ private: const bool m_peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet - const float Filament_Area = M_PI * 1.75f * 1.75f / 4.f; // filament area in mm^3 - const float Nozzle_Diameter = 0.4f; // nozzle diameter in mm + const float Filament_Area = M_PI * 1.75f * 1.75f / 4.f; // filament area in mm^2 const float Width_To_Nozzle_Ratio = 1.25f; // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust const float WT_EPSILON = 1e-3f; @@ -194,7 +196,7 @@ private: float m_bridging = 0.f; bool m_adhesion = true; - float m_perimeter_width = Nozzle_Diameter * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. + float m_perimeter_width = 0.4 * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. float m_extrusion_flow = 0.038; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. @@ -209,6 +211,7 @@ private: float ramming_line_width_multiplicator = 0.f; float ramming_step_multiplicator = 0.f; std::vector ramming_speed; + float nozzle_diameter; }; // Extruder specific parameters. @@ -235,7 +238,7 @@ private: { if ( layer_height < 0 ) return m_extrusion_flow; - return layer_height * ( Width_To_Nozzle_Ratio * Nozzle_Diameter - layer_height * (1-M_PI/4.f)) / (Filament_Area); + return layer_height * ( m_perimeter_width - layer_height * (1-M_PI/4.f)) / Filament_Area; } // Calculates length of extrusion line to extrude given volume diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index cd66f6f56..168bf1302 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -581,6 +581,12 @@ std::string Print::validate() const return "The Spiral Vase option can only be used when printing single material objects."; } + if (this->config.single_extruder_multi_material) { + for (size_t i=1; iconfig.nozzle_diameter.values.size(); ++i) + if (this->config.nozzle_diameter.values[i] != this->config.nozzle_diameter.values[i-1]) + return "All extruders must have the same diameter for single extruder multimaterial printer."; + } + if (this->has_wipe_tower() && ! this->objects.empty()) { #if 0 for (auto dmr : this->config.nozzle_diameter.values) @@ -606,10 +612,10 @@ std::string Print::validate() const bool was_layer_height_profile_valid = object->layer_height_profile_valid; object->update_layer_height_profile(); object->layer_height_profile_valid = was_layer_height_profile_valid; - for (size_t i = 5; i < object->layer_height_profile.size(); i += 2) + /*for (size_t i = 5; i < object->layer_height_profile.size(); i += 2) if (object->layer_height_profile[i-1] > slicing_params.object_print_z_min + EPSILON && std::abs(object->layer_height_profile[i] - object->config.layer_height) > EPSILON) - return "The Wipe Tower is currently only supported with constant Z layer spacing. Layer editing is not allowed."; + return "The Wipe Tower is currently only supported with constant Z layer spacing. Layer editing is not allowed.";*/ } } @@ -1066,7 +1072,8 @@ void Print::_make_wipe_tower() this->config.filament_unloading_speed.get_at(i), this->config.filament_toolchange_delay.get_at(i), this->config.filament_cooling_time.get_at(i), - this->config.filament_ramming_parameters.get_at(i)); + this->config.filament_ramming_parameters.get_at(i), + this->config.nozzle_diameter.get_at(i)); // When printing the first layer's wipe tower, the first extruder is expected to be active and primed. // Therefore the number of wipe sections at the wipe tower will be (m_tool_ordering.front().extruders-1) at the 1st layer. From 89686b808d67f8d575ccd4b2f42ccc11e9846b51 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 3 Apr 2018 13:51:12 +0200 Subject: [PATCH 63/81] Added a check that all objects have the same layer height profile --- xs/src/libslic3r/Print.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 168bf1302..267062125 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -612,6 +612,15 @@ std::string Print::validate() const bool was_layer_height_profile_valid = object->layer_height_profile_valid; object->update_layer_height_profile(); object->layer_height_profile_valid = was_layer_height_profile_valid; + + PrintObject* first_object = this->objects.front(); + int i = 0; + while ( i < first_object->layer_height_profile.size() && i < object->layer_height_profile.size() ) { + if (std::abs(first_object->layer_height_profile[i] - object->layer_height_profile[i]) > EPSILON ) + return "The Wipe tower is only supported if all objects have the same layer height profile"; + ++i; + } + /*for (size_t i = 5; i < object->layer_height_profile.size(); i += 2) if (object->layer_height_profile[i-1] > slicing_params.object_print_z_min + EPSILON && std::abs(object->layer_height_profile[i] - object->config.layer_height) > EPSILON) From e5f23bc11d712f8c012197b0c5c1b50bf65d9077 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 3 Apr 2018 14:35:54 +0200 Subject: [PATCH 64/81] Fixed bug - negative feedrate was issued during loading of a new filament --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 889eaf2f5..4dbc7440e 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -786,7 +786,7 @@ void WipeTowerPrusaMM::toolchange_Unload( float edist = -(m_cooling_tube_retraction+m_cooling_tube_length/2.f-42); writer.suppress_preview() .load_move_x(turning_point,-15 , 60.f * std::hypot(xdist,15)/15 * 83 ) // fixed speed after ramming - .load_move_x(oldx ,edist , 60.f * std::hypot(xdist,edist)/edist * m_filpar[m_current_tool].unloading_speed ) + .load_move_x(oldx ,edist , 60.f * std::hypot(xdist,edist)/std::abs(edist) * m_filpar[m_current_tool].unloading_speed ) .load_move_x(turning_point,-15 , 60.f * std::hypot(xdist,15)/15 * m_filpar[m_current_tool].unloading_speed*0.55f ) .load_move_x(oldx ,-12 , 60.f * std::hypot(xdist,12)/12 * m_filpar[m_current_tool].unloading_speed*0.35f ) .resume_preview(); From d54425a901a8f04d9253ea630219f537765ad4ac Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 3 Apr 2018 22:07:59 +0200 Subject: [PATCH 65/81] Added show/hide of "Purging volumes" button depending on a state of "wipe_tower" --- xs/src/slic3r/GUI/GUI.cpp | 11 ++++++++--- xs/src/slic3r/GUI/GUI.hpp | 2 ++ xs/src/slic3r/GUI/OptionsGroup.cpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 6 +++++- xs/src/slic3r/GUI/WipeTowerDialog.cpp | 12 ++++++------ 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 3c8504756..933a1ce0e 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -182,6 +182,7 @@ wxLocale* g_wxLocale; std::shared_ptr m_optgroup; double m_brim_width = 0.0; +wxButton* g_wiping_dialog_button = nullptr; void set_wxapp(wxApp *app) { @@ -682,10 +683,10 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl Line line = { _(L("")), "" }; line.widget = [config](wxWindow* parent){ - auto wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT); + g_wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes")) + "\u2026", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(wiping_dialog_button); - wiping_dialog_button->Bind(wxEVT_BUTTON, ([config, parent](wxCommandEvent& e) + sizer->Add(g_wiping_dialog_button); + g_wiping_dialog_button->Bind(wxEVT_BUTTON, ([config, parent](wxCommandEvent& e) { std::vector init_matrix = (config->option("wiping_volumes_matrix"))->values; std::vector init_extruders = (config->option("wiping_volumes_extruders"))->values; @@ -713,4 +714,8 @@ ConfigOptionsGroup* get_optgroup() return m_optgroup.get(); } +wxButton* get_wiping_dialog_button(){ + return g_wiping_dialog_button; +} + } } diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index 084b6de46..7561d256d 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -18,6 +18,7 @@ class wxArrayLong; class wxColour; class wxBoxSizer; class wxFlexGridSizer; +class wxButton; namespace Slic3r { @@ -129,6 +130,7 @@ wxString from_u8(const std::string &str); void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer); ConfigOptionsGroup* get_optgroup(); +wxButton* get_wiping_dialog_button(); } } diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp index 0be24824c..0f165e2d3 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.cpp +++ b/xs/src/slic3r/GUI/OptionsGroup.cpp @@ -137,7 +137,7 @@ void OptionsGroup::append_line(const Line& line) { // If there's a widget, build it and add the result to the sizer. if (line.widget != nullptr) { auto wgt = line.widget(parent()); - grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, wxOSX ? 0 : 5); + grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, wxOSX ? 0 : 1); return; } diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 50de384de..1d92439f9 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -335,7 +335,11 @@ void Tab::on_value_change(std::string opt_key, boost::any value) bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; get_optgroup()->set_value("brim", val); } - + if (opt_key == "wipe_tower"){ + m_config->opt_bool("wipe_tower") ? + get_wiping_dialog_button()->Show() : + get_wiping_dialog_button()->Hide(); + } update(); } diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index df0552299..421ae272d 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -30,11 +30,11 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) EndModal(wxID_OK); },wxID_OK); this->Show(); - wxMessageDialog(this,L("Ramming denotes the rapid extrusion just before a tool change in a single-extruder MM printer. Its purpose is to " + wxMessageDialog(this,_(L("Ramming denotes the rapid extrusion just before a tool change in a single-extruder MM printer. Its purpose is to " "properly shape the end of the unloaded filament so it does not prevent insertion of the new filament and can itself " "be reinserted later. This phase is important and different materials can require different extrusion speeds to get " "the good shape. For this reason, the extrusion rates during ramming are adjustable.\n\nThis is an expert-level " - "setting, incorrect adjustment will likely lead to jams, extruder wheel grinding into filament etc."),L("Warning"),wxOK|wxICON_EXCLAMATION).ShowModal(); + "setting, incorrect adjustment will likely lead to jams, extruder wheel grinding into filament etc.")),_(L("Warning")),wxOK|wxICON_EXCLAMATION).ShowModal(); } @@ -249,7 +249,7 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con m_page_advanced->Bind(wxEVT_PAINT,[this](wxPaintEvent&) { wxPaintDC dc(m_page_advanced); int y_pos = 0.5 * (edit_boxes[0][0]->GetPosition().y + edit_boxes[0][edit_boxes.size()-1]->GetPosition().y + edit_boxes[0][edit_boxes.size()-1]->GetSize().y); - wxString label = L("From"); + wxString label = _(L("From")); int text_width = 0; int text_height = 0; dc.GetTextExtent(label,&text_width,&text_height); @@ -314,8 +314,8 @@ bool WipingPanel::advanced_matches_simple() { // Switches the dialog from simple to advanced mode and vice versa void WipingPanel::toggle_advanced(bool user_action) { if (m_advanced && !advanced_matches_simple() && user_action) { - if (wxMessageDialog(this,wxString(L("Switching to simple settings will discard changes done in the advanced mode!\n\nDo you want to proceed?")), - wxString(L("Warning")),wxYES_NO|wxICON_EXCLAMATION).ShowModal() != wxID_YES) + if (wxMessageDialog(this,wxString(_(L("Switching to simple settings will discard changes done in the advanced mode!\n\nDo you want to proceed?"))), + wxString(_(L("Warning"))),wxYES_NO|wxICON_EXCLAMATION).ShowModal() != wxID_YES) return; } if (user_action) @@ -326,7 +326,7 @@ void WipingPanel::toggle_advanced(bool user_action) { (m_advanced ? m_page_advanced : m_page_simple)->Show(); (!m_advanced ? m_page_advanced : m_page_simple)->Hide(); - m_widget_button->SetLabel(m_advanced ? L("Show simplified settings") : L("Show advanced settings")); + m_widget_button->SetLabel(m_advanced ? _(L("Show simplified settings")) : _(L("Show advanced settings"))); if (m_advanced) if (user_action) fill_in_matrix(); // otherwise keep values loaded from config From 42baeee0ed4f4346ab7dc1268614c9452e7325ff Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 4 Apr 2018 09:44:05 +0200 Subject: [PATCH 66/81] Fixed a bug regarding the sparse infill --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 4dbc7440e..e9523b731 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -1174,7 +1174,7 @@ void WipeTowerPrusaMM::generate(std::vector 1) { // we will merge it to the last toolchange + if ( ! layer.tool_changes.empty() ) { // we will merge it to the last toolchange auto& last_toolchange = layer_result.back(); if (last_toolchange.end_pos != finish_layer_toolchange.start_pos) { char buf[2048]; // Add a travel move from tc1.end_pos to tc2.start_pos. From 719adfbaf3c4584da520f5bc47c302b85c301c70 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 4 Apr 2018 09:59:41 +0200 Subject: [PATCH 67/81] The layer height check for multiple objects is now only enabled when variable layer height is enabled --- xs/src/libslic3r/Print.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 267062125..3ce73ab9a 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -613,12 +613,14 @@ std::string Print::validate() const object->update_layer_height_profile(); object->layer_height_profile_valid = was_layer_height_profile_valid; - PrintObject* first_object = this->objects.front(); - int i = 0; - while ( i < first_object->layer_height_profile.size() && i < object->layer_height_profile.size() ) { - if (std::abs(first_object->layer_height_profile[i] - object->layer_height_profile[i]) > EPSILON ) - return "The Wipe tower is only supported if all objects have the same layer height profile"; - ++i; + if ( this->config.variable_layer_height ) { + PrintObject* first_object = this->objects.front(); + int i = 0; + while ( i < first_object->layer_height_profile.size() && i < object->layer_height_profile.size() ) { + if (std::abs(first_object->layer_height_profile[i] - object->layer_height_profile[i]) > EPSILON ) + return "The Wipe tower is only supported if all objects have the same layer height profile"; + ++i; + } } /*for (size_t i = 5; i < object->layer_height_profile.size(); i += 2) From be8acc5ac41e9472d45224bce19b36d9c36affb3 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 4 Apr 2018 10:18:26 +0200 Subject: [PATCH 68/81] Moved "wiping_volumes_extruders", "wiping_volumes_matrix" from print settings to project settings. --- xs/src/slic3r/GUI/GUI.cpp | 11 ++-- xs/src/slic3r/GUI/Preset.cpp | 2 +- xs/src/slic3r/GUI/PresetBundle.cpp | 10 ++-- xs/src/slic3r/GUI/Tab.cpp | 89 +++++++----------------------- xs/src/slic3r/GUI/Tab.hpp | 1 - 5 files changed, 34 insertions(+), 79 deletions(-) diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 933a1ce0e..ce47d527b 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -686,18 +686,19 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl g_wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes")) + "\u2026", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(g_wiping_dialog_button); - g_wiping_dialog_button->Bind(wxEVT_BUTTON, ([config, parent](wxCommandEvent& e) + g_wiping_dialog_button->Bind(wxEVT_BUTTON, ([parent](wxCommandEvent& e) { - std::vector init_matrix = (config->option("wiping_volumes_matrix"))->values; - std::vector init_extruders = (config->option("wiping_volumes_extruders"))->values; + auto &config = g_PresetBundle->project_config; + std::vector init_matrix = (config.option("wiping_volumes_matrix"))->values; + std::vector init_extruders = (config.option("wiping_volumes_extruders"))->values; WipingDialog dlg(parent,std::vector(init_matrix.begin(),init_matrix.end()),std::vector(init_extruders.begin(),init_extruders.end())); if (dlg.ShowModal() == wxID_OK) { std::vector matrix = dlg.get_matrix(); std::vector extruders = dlg.get_extruders(); - (config->option("wiping_volumes_matrix"))->values = std::vector(matrix.begin(),matrix.end()); - (config->option("wiping_volumes_extruders"))->values = std::vector(extruders.begin(),extruders.end()); + (config.option("wiping_volumes_matrix"))->values = std::vector(matrix.begin(),matrix.end()); + (config.option("wiping_volumes_extruders"))->values = std::vector(extruders.begin(),extruders.end()); } })); return sizer; diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index a0d4fe5ff..c52df1e35 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -200,7 +200,7 @@ const std::vector& Preset::print_options() "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", - "wiping_volumes_matrix", "wiping_volumes_extruders", "compatible_printers", "compatible_printers_condition" + "compatible_printers", "compatible_printers_condition" }; return s_opts; diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 1d4795832..0026e5ccf 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -32,7 +32,9 @@ namespace Slic3r { -static std::vector s_project_options { +static std::vector s_project_options { + "wiping_volumes_extruders", + "wiping_volumes_matrix" }; PresetBundle::PresetBundle() : @@ -722,11 +724,11 @@ void PresetBundle::update_multi_material_filament_presets() // Now verify if wiping_volumes_matrix has proper size (it is used to deduce number of extruders in wipe tower generator): - std::vector old_matrix = (prints.get_edited_preset().config.option("wiping_volumes_matrix"))->values; + std::vector old_matrix = this->project_config.option("wiping_volumes_matrix")->values; size_t old_number_of_extruders = int(sqrt(old_matrix.size())+EPSILON); if (num_extruders != old_number_of_extruders) { // First verify if purging volumes presets for each extruder matches number of extruders - std::vector& extruders = (prints.get_edited_preset().config.option("wiping_volumes_extruders"))->values; + std::vector& extruders = this->project_config.option("wiping_volumes_extruders")->values; while (extruders.size() < 2*num_extruders) { extruders.push_back(extruders.size()>1 ? extruders[0] : 50.); // copy the values from the first extruder extruders.push_back(extruders.size()>1 ? extruders[1] : 50.); @@ -745,7 +747,7 @@ void PresetBundle::update_multi_material_filament_presets() else new_matrix.push_back( i==j ? 0. : extruders[2*i]+extruders[2*j+1]); // so it matches new extruder volumes } - (prints.get_edited_preset().config.option("wiping_volumes_matrix"))->values = new_matrix; + this->project_config.option("wiping_volumes_matrix")->values = new_matrix; } } diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 1d92439f9..32a56d9b5 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -523,28 +523,6 @@ void TabPrint::build() optgroup->append_single_option_line("wipe_tower_width"); optgroup->append_single_option_line("wipe_tower_rotation_angle"); optgroup->append_single_option_line("wipe_tower_bridging"); - line = { _(L("Advanced")), "" }; - line.widget = [this](wxWindow* parent){ - m_wipe_tower_btn = new wxButton(parent, wxID_ANY, _(L("Purging volumes"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(m_wipe_tower_btn); - m_wipe_tower_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) - { - std::vector init_matrix = (m_config->option("wiping_volumes_matrix"))->values; - std::vector init_extruders = (m_config->option("wiping_volumes_extruders"))->values; - - WipingDialog dlg(this,std::vector(init_matrix.begin(),init_matrix.end()),std::vector(init_extruders.begin(),init_extruders.end())); - - if (dlg.ShowModal() == wxID_OK) { - std::vector matrix = dlg.get_matrix(); - std::vector extruders = dlg.get_extruders(); - (m_config->option("wiping_volumes_matrix"))->values = std::vector(matrix.begin(),matrix.end()); - (m_config->option("wiping_volumes_extruders"))->values = std::vector(extruders.begin(),extruders.end()); - } - })); - return sizer; - }; - optgroup->append_line(line); optgroup = page->new_optgroup(_(L("Advanced"))); optgroup->append_single_option_line("interface_shells"); @@ -779,53 +757,40 @@ void TabPrint::update() } bool have_perimeters = m_config->opt_int("perimeters") > 0; - std::vector vec_enable = { "extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", - "seam_position", "external_perimeters_first", "external_perimeter_extrusion_width", - "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" }; - for (auto el : vec_enable) + for (auto el : {"extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", + "seam_position", "external_perimeters_first", "external_perimeter_extrusion_width", + "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" }) get_field(el)->toggle(have_perimeters); bool have_infill = m_config->option("fill_density")->value > 0; - vec_enable.resize(0); - vec_enable = { "fill_pattern", "infill_every_layers", "infill_only_where_needed", - "solid_infill_every_layers", "solid_infill_below_area", "infill_extruder" }; // infill_extruder uses the same logic as in Print::extruders() - for (auto el : vec_enable) + for (auto el : {"fill_pattern", "infill_every_layers", "infill_only_where_needed", + "solid_infill_every_layers", "solid_infill_below_area", "infill_extruder" }) get_field(el)->toggle(have_infill); bool have_solid_infill = m_config->opt_int("top_solid_layers") > 0 || m_config->opt_int("bottom_solid_layers") > 0; - vec_enable.resize(0); - vec_enable = { "external_fill_pattern", "infill_first", "solid_infill_extruder", - "solid_infill_extrusion_width", "solid_infill_speed" }; // solid_infill_extruder uses the same logic as in Print::extruders() - for (auto el : vec_enable) + for (auto el : {"external_fill_pattern", "infill_first", "solid_infill_extruder", + "solid_infill_extrusion_width", "solid_infill_speed" }) get_field(el)->toggle(have_solid_infill); - vec_enable.resize(0); - vec_enable = { "fill_angle", "bridge_angle", "infill_extrusion_width", - "infill_speed", "bridge_speed" }; - for (auto el : vec_enable) + for (auto el : {"fill_angle", "bridge_angle", "infill_extrusion_width", + "infill_speed", "bridge_speed" }) get_field(el)->toggle(have_infill || have_solid_infill); get_field("gap_fill_speed")->toggle(have_perimeters && have_infill); bool have_top_solid_infill = m_config->opt_int("top_solid_layers") > 0; - vec_enable.resize(0); - vec_enable = { "top_infill_extrusion_width", "top_solid_infill_speed" }; - for (auto el : vec_enable) + for (auto el : { "top_infill_extrusion_width", "top_solid_infill_speed" }) get_field(el)->toggle(have_top_solid_infill); bool have_default_acceleration = m_config->opt_float("default_acceleration") > 0; - vec_enable.resize(0); - vec_enable = { "perimeter_acceleration", "infill_acceleration", - "bridge_acceleration", "first_layer_acceleration" }; - for (auto el : vec_enable) + for (auto el : {"perimeter_acceleration", "infill_acceleration", + "bridge_acceleration", "first_layer_acceleration" }) get_field(el)->toggle(have_default_acceleration); bool have_skirt = m_config->opt_int("skirts") > 0 || m_config->opt_float("min_skirt_length") > 0; - vec_enable.resize(0); - vec_enable = { "skirt_distance", "skirt_height" }; - for (auto el : vec_enable) + for (auto el : { "skirt_distance", "skirt_height" }) get_field(el)->toggle(have_skirt); bool have_brim = m_config->opt_float("brim_width") > 0; @@ -836,18 +801,14 @@ void TabPrint::update() bool have_support_material = m_config->opt_bool("support_material") || have_raft; bool have_support_interface = m_config->opt_int("support_material_interface_layers") > 0; bool have_support_soluble = have_support_material && m_config->opt_float("support_material_contact_distance") == 0; - vec_enable.resize(0); - vec_enable = { "support_material_threshold", "support_material_pattern", "support_material_with_sheath", + for (auto el : {"support_material_threshold", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_angle", "support_material_interface_layers", "dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance", - "support_material_xy_spacing" }; - for (auto el : vec_enable) + "support_material_xy_spacing" }) get_field(el)->toggle(have_support_material); - vec_enable.resize(0); - vec_enable = { "support_material_interface_spacing", "support_material_interface_extruder", - "support_material_interface_speed", "support_material_interface_contact_loops" }; - for (auto el : vec_enable) + for (auto el : {"support_material_interface_spacing", "support_material_interface_extruder", + "support_material_interface_speed", "support_material_interface_contact_loops" }) get_field(el)->toggle(have_support_material && have_support_interface); get_field("support_material_synchronize_layers")->toggle(have_support_soluble); @@ -856,20 +817,15 @@ void TabPrint::update() get_field("support_material_speed")->toggle(have_support_material || have_brim || have_skirt); bool have_sequential_printing = m_config->opt_bool("complete_objects"); - vec_enable.resize(0); - vec_enable = { "extruder_clearance_radius", "extruder_clearance_height" }; - for (auto el : vec_enable) + for (auto el : { "extruder_clearance_radius", "extruder_clearance_height" }) get_field(el)->toggle(have_sequential_printing); bool have_ooze_prevention = m_config->opt_bool("ooze_prevention"); get_field("standby_temperature_delta")->toggle(have_ooze_prevention); bool have_wipe_tower = m_config->opt_bool("wipe_tower"); - vec_enable.resize(0); - vec_enable = { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging"}; - for (auto el : vec_enable) + for (auto el : { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging"}) get_field(el)->toggle(have_wipe_tower); - m_wipe_tower_btn->Enable(have_wipe_tower); m_recommended_thin_wall_thickness_description_line->SetText( from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle))); @@ -1020,13 +976,10 @@ void TabFilament::update() bool cooling = m_config->opt_bool("cooling", 0); bool fan_always_on = cooling || m_config->opt_bool("fan_always_on", 0); - std::vector vec_enable = { "max_fan_speed", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed" }; - for (auto el : vec_enable) + for (auto el : { "max_fan_speed", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed" }) get_field(el)->toggle(cooling); - vec_enable.resize(0); - vec_enable = { "min_fan_speed", "disable_fan_first_layers" }; - for (auto el : vec_enable) + for (auto el : { "min_fan_speed", "disable_fan_first_layers" }) get_field(el)->toggle(fan_always_on); } diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp index 234c90765..4f65f1475 100644 --- a/xs/src/slic3r/GUI/Tab.hpp +++ b/xs/src/slic3r/GUI/Tab.hpp @@ -90,7 +90,6 @@ protected: wxImageList* m_icons; wxCheckBox* m_compatible_printers_checkbox; wxButton* m_compatible_printers_btn; - wxButton* m_wipe_tower_btn; int m_icon_count; std::map m_icon_index; // Map from an icon file name to its index in $self->{icons}. From 1b08bc94f07930a5ebeb659f785b67a7c9eb6115 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 4 Apr 2018 11:13:28 +0200 Subject: [PATCH 69/81] Added g_wiping_dialog_button status update to update_frequently_changed_parameters() --- xs/src/slic3r/GUI/Tab.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 1d92439f9..534cd3aa9 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -372,6 +372,10 @@ void Tab::update_frequently_changed_parameters() bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; get_optgroup()->set_value("brim", val); + + m_config->opt_bool("wipe_tower") ? + get_wiping_dialog_button()->Show() : + get_wiping_dialog_button()->Hide(); } void Tab::reload_compatible_printers_widget() From 597e8650a6f35b5c40b98d5512598066bde2a464 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 4 Apr 2018 12:49:16 +0200 Subject: [PATCH 70/81] Fixed incorrect redraw of Purging volumes button in certain cases --- xs/src/slic3r/GUI/Tab.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 32fac1423..bb0e859e6 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -376,6 +376,7 @@ void Tab::update_frequently_changed_parameters() m_config->opt_bool("wipe_tower") ? get_wiping_dialog_button()->Show() : get_wiping_dialog_button()->Hide(); + (get_wiping_dialog_button()->GetParent())->Layout(); } void Tab::reload_compatible_printers_widget() From 290e3e66c01dbb181ab05a6fa551ec3b66dd7220 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 4 Apr 2018 14:41:23 +0200 Subject: [PATCH 71/81] Merge correction --- xs/src/slic3r/GUI/GUI.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 3fc3bfba2..80a6427d5 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -716,8 +716,10 @@ ConfigOptionsGroup* get_optgroup() } -wxButton* get_wiping_dialog_button(){ +wxButton* get_wiping_dialog_button() +{ return g_wiping_dialog_button; +} wxWindow* export_option_creator(wxWindow* parent) { @@ -762,6 +764,9 @@ int get_export_option(wxFileDialog* dlg) } return 0; + } -} } + +} // namespace GUI +} // namespace Slic3r From 706dd7020fedbd0aa8e0e90642fcf508350ec604 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 4 Apr 2018 14:59:31 +0200 Subject: [PATCH 72/81] New extruder temperature is only set when it differs from the old one --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index e9523b731..682845135 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -260,10 +260,13 @@ public: // Set extruder temperature, don't wait by default. Writer& set_extruder_temp(int temperature, bool wait = false) { - char buf[128]; - sprintf(buf, "M%d S%d\n", wait ? 109 : 104, temperature); - m_gcode += buf; - return *this; + if (temperature != current_temp) { + char buf[128]; + sprintf(buf, "M%d S%d\n", wait ? 109 : 104, temperature); + m_gcode += buf; + current_temp = temperature; + } + return *this; }; // Wait for a period of time (seconds). @@ -377,6 +380,7 @@ private: float m_wipe_tower_width = 0.f; float m_wipe_tower_depth = 0.f; float m_last_fan_speed = 0.f; + int current_temp = -1; std::string set_format_X(float x) From 6af45362ce85bf4debb3f4483d74a0e973ffb377 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 5 Apr 2018 10:44:31 +0200 Subject: [PATCH 73/81] Purging volumes button is only shown when the wipe tower is enabled and we have single extruder MM printer with more than one extruder --- xs/src/slic3r/GUI/Tab.cpp | 32 ++++++++++++++++++++++---------- xs/src/slic3r/GUI/Tab.hpp | 1 + 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index bb0e859e6..e05dda8c4 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -335,15 +335,28 @@ void Tab::on_value_change(std::string opt_key, boost::any value) bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; get_optgroup()->set_value("brim", val); } - if (opt_key == "wipe_tower"){ - m_config->opt_bool("wipe_tower") ? - get_wiping_dialog_button()->Show() : - get_wiping_dialog_button()->Hide(); - } - + + if (opt_key == "wipe_tower" || opt_key == "single_extruder_multi_material" || opt_key == "extruders_count" ) + update_wiping_button_visibility(); + update(); } + +// Show/hide the 'purging volumes' button +void Tab::update_wiping_button_visibility() { + bool wipe_tower_enabled = dynamic_cast( (m_preset_bundle->prints.get_edited_preset().config ).option("wipe_tower"))->value; + bool multiple_extruders = dynamic_cast((m_preset_bundle->printers.get_edited_preset().config).option("nozzle_diameter"))->values.size() > 1; + bool single_extruder_mm = dynamic_cast( (m_preset_bundle->printers.get_edited_preset().config).option("single_extruder_multi_material"))->value; + + if (wipe_tower_enabled && multiple_extruders && single_extruder_mm) + get_wiping_dialog_button()->Show(); + else get_wiping_dialog_button()->Hide(); + + (get_wiping_dialog_button()->GetParent())->Layout(); +} + + // Call a callback to update the selection of presets on the platter: // To update the content of the selection boxes, // to update the filament colors of the selection boxes, @@ -373,10 +386,7 @@ void Tab::update_frequently_changed_parameters() bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; get_optgroup()->set_value("brim", val); - m_config->opt_bool("wipe_tower") ? - get_wiping_dialog_button()->Show() : - get_wiping_dialog_button()->Hide(); - (get_wiping_dialog_button()->GetParent())->Layout(); + update_wiping_button_visibility(); } void Tab::reload_compatible_printers_widget() @@ -1062,6 +1072,8 @@ void TabPrinter::build() if (opt_key.compare("extruders_count")==0 || opt_key.compare("single_extruder_multi_material")==0) { extruders_count_changed(extruders_count); update_dirty(); + if (opt_key.compare("single_extruder_multi_material")==0) // the single_extruder_multimaterial was added to force pages + on_value_change(opt_key, value); // rebuild - let's make sure the on_value_change is not skipped } else { update_dirty(); diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp index 4f65f1475..f4aafd184 100644 --- a/xs/src/slic3r/GUI/Tab.hpp +++ b/xs/src/slic3r/GUI/Tab.hpp @@ -174,6 +174,7 @@ public: protected: void on_presets_changed(); void update_frequently_changed_parameters(); + void update_wiping_button_visibility(); }; //Slic3r::GUI::Tab::Print; From cb9937cde4c4d65fc4e7f8c71cf750f3a5e63974 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 6 Apr 2018 12:02:52 +0200 Subject: [PATCH 74/81] Corrected wipe tower comments in GCode --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 6 ++---- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 8 ++++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 682845135..dd75e03ed 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -460,7 +460,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( { this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false); - this->m_num_layer_changes = 0; this->m_current_tool = tools.front(); // The Prusa i3 MK2 has a working space of [0, -2.2] to [250, 210]. @@ -574,7 +573,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo .set_y_shift(m_y_shift + (tool!=(unsigned int)(-1) && (m_current_shape == SHAPE_REVERSED && !m_peters_wipe_tower) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f)) .append(";--------------------\n" "; CP TOOLCHANGE START\n") - .comment_with_value(" toolchange #", m_num_tool_changes) + .comment_with_value(" toolchange #", m_num_tool_changes + 1) // the number is zero-based .comment_material(m_filpar[m_current_tool].material) .append(";--------------------\n") .speed_override(100); @@ -975,8 +974,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() .set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED && !m_peters_wipe_tower ? m_layer_info->toolchanges_depth() : 0.f)) .append(";--------------------\n" "; CP EMPTY GRID START\n") - // m_num_layer_changes is incremented by set_z, so it is 1 based. - .comment_with_value(" layer #", m_num_layer_changes - 1); + .comment_with_value(" layer #", m_num_layer_changes + 1); // Slow down on the 1st layer. float speed_factor = m_is_first_layer ? 0.5f : 1.f; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 26c40fbc9..175de0276 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -121,8 +121,12 @@ public: m_print_brim = is_first_layer; m_depth_traversed = 0.f; m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL; - - ++ m_num_layer_changes; + if (is_first_layer) { + this->m_num_layer_changes = 0; + this->m_num_tool_changes = 0; + } + else + ++ m_num_layer_changes; // Calculate extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height: m_extrusion_flow = extrusion_flow(layer_height); From 9ebff9ce0046438ff4362e73996867714c367a0d Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 9 Apr 2018 13:35:39 +0200 Subject: [PATCH 75/81] Bugfix: a sign mistake was causing unnecessary travel moves --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 39 ++++++++++++--------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index dd75e03ed..ad7d91c50 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -72,7 +72,7 @@ public: { m_wipe_tower_pos = pos; m_wipe_tower_width = width; m_wipe_tower_depth=depth; m_angle_deg = angle; return (*this); } Writer& set_y_shift(float shift) { - m_current_pos.y += shift-m_y_shift; + m_current_pos.y -= shift-m_y_shift; m_y_shift = shift; return (*this); } @@ -112,8 +112,8 @@ public: // For rotated wipe tower, transform position to printer coordinates - WipeTower::xy rotated_current_pos(WipeTower::xy(m_current_pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); - WipeTower::xy rot(WipeTower::xy(x,y+m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); + WipeTower::xy rotated_current_pos(WipeTower::xy(m_current_pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); // this is where we are + WipeTower::xy rot(WipeTower::xy(x,y+m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); // this is where we want to go if (! m_preview_suppressed && e > 0.f && len > 0.) { // Width of a squished extrusion, corrected for the roundings of the squished extrusions. @@ -127,14 +127,14 @@ public: } m_gcode += "G1"; - if (rot.x != rotated_current_pos.x) - m_gcode += set_format_X(rot.x); - if (rot.y != rotated_current_pos.y) + if (rot.x != rotated_current_pos.x) { + m_gcode += set_format_X(rot.x); // Transform current position back to wipe tower coordinates (was updated by set_format_X) + m_current_pos.x = x; + } + if (rot.y != rotated_current_pos.y) { m_gcode += set_format_Y(rot.y); - - // Transform current position back to wipe tower coordinates (was updated by set_format_X) - m_current_pos.x = x; - m_current_pos.y = y; + m_current_pos.y = y; + } if (e != 0.f) m_gcode += set_format_E(e); @@ -179,16 +179,20 @@ public: corners[1] = WipeTower::xy(ld,width,0.f); corners[2] = WipeTower::xy(ld,width,height); corners[3] = WipeTower::xy(ld,0.f,height); - int index_of_closest = (x()-ld.x < ld.x+width-x() ? 0 : 1); - if (y()-ld.y > ld.y+height-x()) // closer to the top - index_of_closest += (index_of_closest==0 ? 3 : 1); - travel(corners[index_of_closest].x,y(),f); // travel to the closest corner - travel(x(),corners[index_of_closest].y,f); + int index_of_closest = 0; + if (x()-ld.x > ld.x+width-x()) // closer to the right + index_of_closest = 1; + if (y()-ld.y > ld.y+height-y()) // closer to the top + index_of_closest = (index_of_closest==0 ? 3 : 2); + + travel(corners[index_of_closest].x, y()); // travel to the closest corner + travel(x(),corners[index_of_closest].y); + int i = index_of_closest; do { ++i; if (i==4) i=0; - this->extrude(corners[i]); + extrude(corners[i]); } while (i != index_of_closest); return (*this); } @@ -611,7 +615,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo else { writer.rectangle(m_wipe_tower_pos,m_wipe_tower_width, m_layer_info->depth + m_perimeter_width); if (layer_finished()) { // no finish_layer will be called, we must wipe the nozzle - writer.travel(m_wipe_tower_pos.x + (writer.x()>m_wipe_tower_pos.x + EPSILON ? 0.f : m_wipe_tower_width), writer.y()); + writer.travel(m_wipe_tower_pos.x + (writer.x()> (m_wipe_tower_pos.x + m_wipe_tower_width) / 2.f ? 0.f : m_wipe_tower_width), writer.y()); } } } @@ -987,6 +991,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() else writer.set_initial_position(fill_box.lu); + box_coordinates box = fill_box; for (int i=0;i<2;++i) { if (m_layer_info->toolchanges_depth() < WT_EPSILON) { // there were no toolchanges on this layer From bbbb5c9a934e2fd1ad9a65a0af4ce186a43fe133 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 9 Apr 2018 14:49:32 +0200 Subject: [PATCH 76/81] Ramming chart is now drawn with double-buffering --- xs/src/slic3r/GUI/RammingChart.cpp | 5 ++++- xs/src/slic3r/GUI/RammingChart.hpp | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/xs/src/slic3r/GUI/RammingChart.cpp index 87ac9c769..ca76298af 100644 --- a/xs/src/slic3r/GUI/RammingChart.cpp +++ b/xs/src/slic3r/GUI/RammingChart.cpp @@ -1,4 +1,6 @@ #include +#include + #include "RammingChart.hpp" @@ -11,7 +13,8 @@ wxDEFINE_EVENT(EVT_WIPE_TOWER_CHART_CHANGED, wxCommandEvent); -void Chart::draw(wxDC& dc) { +void Chart::draw() { + wxAutoBufferedPaintDC dc(this); // unbuffered DC caused flickering on win dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxWHITE_BRUSH); dc.DrawRectangle(m_rect); diff --git a/xs/src/slic3r/GUI/RammingChart.hpp b/xs/src/slic3r/GUI/RammingChart.hpp index aa1e7acc7..7d3b9a962 100644 --- a/xs/src/slic3r/GUI/RammingChart.hpp +++ b/xs/src/slic3r/GUI/RammingChart.hpp @@ -16,6 +16,7 @@ public: Chart(wxWindow* parent, wxRect rect,const std::vector>& initial_buttons,int ramming_speed_size, float sampling) : wxWindow(parent,wxID_ANY,rect.GetTopLeft(),rect.GetSize()) { + SetBackgroundStyle(wxBG_STYLE_PAINT); m_rect = wxRect(wxPoint(50,0),rect.GetSize()-wxSize(50,50)); visible_area = wxRect2DDouble(0.0, 0.0, sampling*ramming_speed_size, 20.); m_buttons.clear(); @@ -36,7 +37,7 @@ public: std::vector get_ramming_speed(float sampling) const; //returns sampled ramming speed std::vector> get_buttons() const; // returns buttons position - void draw(wxDC& dc); + void draw(); void mouse_clicked(wxMouseEvent& event); void mouse_right_button_clicked(wxMouseEvent& event); @@ -44,7 +45,7 @@ public: void mouse_double_clicked(wxMouseEvent& event); void mouse_left_window(wxMouseEvent&) { m_dragged = nullptr; } void mouse_released(wxMouseEvent&) { m_dragged = nullptr; } - void paint_event(wxPaintEvent&) { wxPaintDC dc(this); draw(dc); } + void paint_event(wxPaintEvent&) { draw(); } DECLARE_EVENT_TABLE() From f49a7be90c93fbfa7c9d81f1560dea54b8116186 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 10 Apr 2018 10:50:18 +0200 Subject: [PATCH 77/81] An attempt to get RammingChart background colour consistent with its parent(s) on all platforms --- xs/src/slic3r/GUI/RammingChart.cpp | 5 +++++ xs/src/slic3r/GUI/WipeTowerDialog.cpp | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/xs/src/slic3r/GUI/RammingChart.cpp index ca76298af..1ef43be02 100644 --- a/xs/src/slic3r/GUI/RammingChart.cpp +++ b/xs/src/slic3r/GUI/RammingChart.cpp @@ -15,6 +15,11 @@ wxDEFINE_EVENT(EVT_WIPE_TOWER_CHART_CHANGED, wxCommandEvent); void Chart::draw() { wxAutoBufferedPaintDC dc(this); // unbuffered DC caused flickering on win + + dc.SetBrush(GetBackgroundColour()); + dc.SetPen(GetBackgroundColour()); + dc.DrawRectangle(GetClientRect()); // otherwise the background would end up black on windows + dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxWHITE_BRUSH); dc.DrawRectangle(m_rect); diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index 421ae272d..b34de0745 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -14,6 +14,13 @@ RammingDialog::RammingDialog(wxWindow* parent,const std::string& parameters) : wxDialog(parent, wxID_ANY, _(L("Ramming customization")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/) { m_panel_ramming = new RammingPanel(this,parameters); + + // Not found another way of getting the background colours of RammingDialog, RammingPanel and Chart correct than setting + // them all explicitely. Reading the parent colour yielded colour that didn't really match it, no wxSYS_COLOUR_... matched + // colour used for the dialog. Same issue (and "solution") here : https://forums.wxwidgets.org/viewtopic.php?f=1&t=39608 + // Whoever can fix this, feel free to do so. + this-> SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_FRAMEBK)); + m_panel_ramming->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_FRAMEBK)); m_panel_ramming->Show(true); this->Show(); @@ -63,6 +70,7 @@ RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters) buttons.push_back(std::make_pair(x, y)); m_chart = new Chart(this, wxRect(10, 10, 480, 360), buttons, ramming_speed_size, 0.25f); + m_chart->SetBackgroundColour(parent->GetBackgroundColour()); // see comment in RammingDialog constructor sizer_chart->Add(m_chart, 0, wxALL, 5); m_widget_time = new wxSpinCtrlDouble(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(75, -1),wxSP_ARROW_KEYS,0.,5.0,3.,0.5); From adbaa42b2b44c2d1bda43cd589fd83ed11476c6b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 12 Apr 2018 15:38:05 +0200 Subject: [PATCH 78/81] Bugfix: cooling tubes parameters change invalidates generated wipe tower --- xs/src/libslic3r/Print.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 3ce73ab9a..4012b91f8 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -90,8 +90,6 @@ bool Print::invalidate_state_by_config_options(const std::vector Date: Thu, 12 Apr 2018 16:13:59 +0200 Subject: [PATCH 79/81] Default purging volumes set to more appropriate values --- xs/src/libslic3r/PrintConfig.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index ef54b24cf..66576c9f1 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1038,7 +1038,7 @@ PrintConfigDef::PrintConfigDef() def = this->add("parking_pos_retraction", coFloat); def->label = L("Filament parking position"); - def->tooltip = L("Distance of the extruder tip from the position where the filament is parked" + def->tooltip = L("Distance of the extruder tip from the position where the filament is parked " "when unloaded. This should match the value in printer firmware. "); def->sidetext = L("mm"); def->cli = "parking_pos_retraction=f"; @@ -1818,18 +1818,18 @@ PrintConfigDef::PrintConfigDef() "wipe tower. These values are used to simplify creation of the full purging " "volumes below. "); def->cli = "wiping-volumes-extruders=f@"; - def->default_value = new ConfigOptionFloats { 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f }; + def->default_value = new ConfigOptionFloats { 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f }; def = this->add("wiping_volumes_matrix", coFloats); def->label = L("Purging volumes - matrix"); def->tooltip = L("This matrix describes volumes (in cubic milimetres) required to purge the" " new filament on the wipe tower for any given pair of tools. "); def->cli = "wiping-volumes-matrix=f@"; - def->default_value = new ConfigOptionFloats { 0.f, 100.f, 100.f, 100.f, 100.f, - 100.f, 0.f, 100.f, 100.f, 100.f, - 100.f, 100.f, 0.f, 100.f, 100.f, - 100.f, 100.f, 100.f, 0.f, 100.f, - 100.f, 100.f, 100.f, 100.f, 0.f }; + def->default_value = new ConfigOptionFloats { 0.f, 140.f, 140.f, 140.f, 140.f, + 140.f, 0.f, 140.f, 140.f, 140.f, + 140.f, 140.f, 0.f, 140.f, 140.f, + 140.f, 140.f, 140.f, 0.f, 140.f, + 140.f, 140.f, 140.f, 140.f, 0.f }; def = this->add("wipe_tower_x", coFloat); def->label = L("Position X"); From abe6e8a783b62fc402aaea783906cb52a6381478 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 13 Apr 2018 13:43:53 +0200 Subject: [PATCH 80/81] Bugfix: legacy config options were not properly processed --- xs/src/libslic3r/Print.cpp | 2 +- xs/src/libslic3r/PrintConfig.cpp | 3 ++- xs/src/libslic3r/PrintConfig.hpp | 7 +++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 4012b91f8..dcece7a9b 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -644,7 +644,7 @@ std::string Print::validate() const unsigned int total_extruders_count = this->config.nozzle_diameter.size(); for (const auto& extruder_idx : extruders) if ( extruder_idx >= total_extruders_count ) - return "One or more object have assigned an extruder that the printer does not have."; + return "One or more object were assigned an extruder that the printer does not have."; for (PrintObject *object : this->objects) { if ((object->config.support_material_extruder == -1 || object->config.support_material_interface_extruder == -1) && diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 66576c9f1..1e7e0bacc 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1944,8 +1944,9 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va "standby_temperature", "scale", "rotate", "duplicate", "duplicate_grid", "start_perimeters_at_concave_points", "start_perimeters_at_non_overhang", "randomize_start", "seal_position", "vibration_limit", "bed_size", "octoprint_host", - "print_center", "g0", "threads", "pressure_advance" + "print_center", "g0", "threads", "pressure_advance", "wipe_tower_per_color_wipe" }; + if (ignore.find(opt_key) != ignore.end()) { opt_key = ""; return; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index be64d35bd..967a87310 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -154,6 +154,13 @@ public: // Validate the PrintConfig. Returns an empty string on success, otherwise an error message is returned. std::string validate(); + + // Verify whether the opt_key has not been obsoleted or renamed. + // Both opt_key and value may be modified by handle_legacy(). + // If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy(). + // handle_legacy() is called internally by set_deserialize(). + void handle_legacy(t_config_option_key &opt_key, std::string &value) const override + { PrintConfigDef::handle_legacy(opt_key, value); } }; template From 68c3749696bcad48f0801129dd10a6f190a02a55 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 13 Apr 2018 13:46:31 +0200 Subject: [PATCH 81/81] Gyroid infill - automatic discretization steps and refactoring --- xs/src/libslic3r/Fill/FillGyroid.cpp | 162 ++++++++++++++++++--------- 1 file changed, 106 insertions(+), 56 deletions(-) diff --git a/xs/src/libslic3r/Fill/FillGyroid.cpp b/xs/src/libslic3r/Fill/FillGyroid.cpp index a3920caab..d66e63a60 100644 --- a/xs/src/libslic3r/Fill/FillGyroid.cpp +++ b/xs/src/libslic3r/Fill/FillGyroid.cpp @@ -9,77 +9,125 @@ namespace Slic3r { -static inline Polyline make_wave_vertical( - double width, double height, double x0, - double segmentSize, double scaleFactor, - double z_cos, double z_sin, bool flip) -{ - Polyline polyline; - polyline.points.emplace_back(Point(coord_t(clamp(0., width, x0) * scaleFactor), 0)); - double phase_offset_sin = (z_cos < 0 ? M_PI : 0) + M_PI; - double phase_offset_cos = (z_cos < 0 ? M_PI : 0) + M_PI + (flip ? M_PI : 0.); - for (double y = 0.; y < height + segmentSize; y += segmentSize) { - y = std::min(y, height); - double a = sin(y + phase_offset_sin); + +static inline double f(double x, double z_sin, double z_cos, bool vertical, bool flip) { + if (vertical) { + double phase_offset = (z_cos < 0 ? M_PI : 0) + M_PI; + double a = sin(x + phase_offset); double b = - z_cos; - double res = z_sin * cos(y + phase_offset_cos); + double res = z_sin * cos(x + phase_offset + (flip ? M_PI : 0.)); double r = sqrt(sqr(a) + sqr(b)); - double x = clamp(0., width, asin(a/r) + asin(res/r) + M_PI + x0); - polyline.points.emplace_back(convert_to(Pointf(x, y) * scaleFactor)); + return asin(a/r) + asin(res/r) + M_PI; } - if (flip) - std::reverse(polyline.points.begin(), polyline.points.end()); + else { + double phase_offset = z_sin < 0 ? M_PI : 0.; + double a = cos(x + phase_offset); + double b = - z_sin; + double res = z_cos * sin(x + phase_offset + (flip ? 0 : M_PI)); + double r = sqrt(sqr(a) + sqr(b)); + return (asin(a/r) + asin(res/r) + 0.5 * M_PI); + } +} + + +static inline Polyline make_wave( + const std::vector& one_period, double width, double height, double offset, double scaleFactor, + double z_cos, double z_sin, bool vertical) +{ + std::vector points = one_period; + double period = points.back().x; + points.pop_back(); + int n = points.size(); + do { + points.emplace_back(Pointf(points[points.size()-n].x + period, points[points.size()-n].y)); + } while (points.back().x < width); + points.back().x = width; + + // and construct the final polyline to return: + Polyline polyline; + for (auto& point : points) { + point.y += offset; + point.y = clamp(0., height, double(point.y)); + if (vertical) + std::swap(point.x, point.y); + polyline.points.emplace_back(convert_to(point * scaleFactor)); + } + return polyline; } -static inline Polyline make_wave_horizontal( - double width, double height, double y0, - double segmentSize, double scaleFactor, - double z_cos, double z_sin, bool flip) -{ - Polyline polyline; - polyline.points.emplace_back(Point(0, coord_t(clamp(0., height, y0) * scaleFactor))); - double phase_offset_sin = (z_sin < 0 ? M_PI : 0) + (flip ? 0 : M_PI); - double phase_offset_cos = z_sin < 0 ? M_PI : 0.; - for (double x = 0.; x < width + segmentSize; x += segmentSize) { - x = std::min(x, width); - double a = cos(x + phase_offset_cos); - double b = - z_sin; - double res = z_cos * sin(x + phase_offset_sin); - double r = sqrt(sqr(a) + sqr(b)); - double y = clamp(0., height, asin(a/r) + asin(res/r) + 0.5 * M_PI + y0); - polyline.points.emplace_back(convert_to(Pointf(x, y) * scaleFactor)); + +static std::vector make_one_period(double width, double scaleFactor, double z_cos, double z_sin, bool vertical, bool flip) { + std::vector points; + double dx = M_PI_4; // very coarse spacing to begin with + double limit = std::min(2*M_PI, width); + for (double x = 0.; x < limit + EPSILON; x += dx) { // so the last point is there too + x = std::min(x, limit); + points.emplace_back(Pointf(x,f(x, z_sin,z_cos, vertical, flip))); } - if (flip) - std::reverse(polyline.points.begin(), polyline.points.end()); - return polyline; + + // now we will check all internal points and in case some are too far from the line connecting its neighbours, + // we will add one more point on each side: + const double tolerance = .1; + for (unsigned int i=1;i tolerance) { // if the difference from straight line is more than this + double x = 0.5f * (points[i-1].x + points[i].x); + points.emplace_back(Pointf(x, f(x, z_sin, z_cos, vertical, flip))); + x = 0.5f * (points[i+1].x + points[i].x); + points.emplace_back(Pointf(x, f(x, z_sin, z_cos, vertical, flip))); + std::sort(points.begin(), points.end()); // we added the points to the end, but need them all in order + --i; // decrement i so we also check the first newly added point + } + } + return points; } + static Polylines make_gyroid_waves(double gridZ, double density_adjusted, double line_spacing, double width, double height) { - double scaleFactor = scale_(line_spacing) / density_adjusted; - double segmentSize = 0.5 * density_adjusted; + const double scaleFactor = scale_(line_spacing) / density_adjusted; //scale factor for 5% : 8 712 388 // 1z = 10^-6 mm ? - double z = gridZ / scaleFactor; - double z_sin = sin(z); - double z_cos = cos(z); - Polylines result; - if (abs(z_sin) <= abs(z_cos)) { - // Vertical wave - double x0 = M_PI * (int)((- 0.5 * M_PI) / M_PI - 1.); - bool flip = ((int)(x0 / M_PI + 1.) & 1) != 0; - for (; x0 < width - 0.5 * M_PI; x0 += M_PI, flip = ! flip) - result.emplace_back(make_wave_vertical(width, height, x0, segmentSize, scaleFactor, z_cos, z_sin, flip)); - } else { - // Horizontal wave - bool flip = true; - for (double y0 = 0.; y0 < height; y0 += M_PI, flip = !flip) - result.emplace_back(make_wave_horizontal(width, height, y0, segmentSize, scaleFactor, z_cos, z_sin, flip)); + const double z = gridZ / scaleFactor; + const double z_sin = sin(z); + const double z_cos = cos(z); + + bool vertical = (std::abs(z_sin) <= std::abs(z_cos)); + double lower_bound = 0.; + double upper_bound = height; + bool flip = true; + if (vertical) { + flip = false; + lower_bound = -M_PI; + upper_bound = width - M_PI_2; + std::swap(width,height); } + + std::vector one_period = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip); // creates one period of the waves, so it doesn't have to be recalculated all the time + Polylines result; + + for (double y0 = lower_bound; y0 < upper_bound+EPSILON; y0 += 2*M_PI) // creates odd polylines + result.emplace_back(make_wave(one_period, width, height, y0, scaleFactor, z_cos, z_sin, vertical)); + + flip = !flip; // even polylines are a bit shifted + one_period = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip); // updates the one period sample + for (double y0 = lower_bound + M_PI; y0 < upper_bound+EPSILON; y0 += 2*M_PI) // creates even polylines + result.emplace_back(make_wave(one_period, width, height, y0, scaleFactor, z_cos, z_sin, vertical)); + return result; } + + + + + void FillGyroid::_fill_surface_single( const FillParams ¶ms, unsigned int thickness_layers, @@ -90,13 +138,15 @@ void FillGyroid::_fill_surface_single( // no rotation is supported for this infill pattern (yet) BoundingBox bb = expolygon.contour.bounding_box(); // Density adjusted to have a good %of weight. - double density_adjusted = params.density * 1.75; + double density_adjusted = std::max(0., params.density * 2.); + + // Distance between the gyroid waves in scaled coordinates. coord_t distance = coord_t(scale_(this->spacing) / density_adjusted); // align bounding box to a multiple of our grid module bb.merge(_align_to_grid(bb.min, Point(2.*M_PI*distance, 2.*M_PI*distance))); - + // generate pattern Polylines polylines = make_gyroid_waves( scale_(this->z),