diff options
Diffstat (limited to 'xs/src/libslic3r')
-rw-r--r-- | xs/src/libslic3r/GCode.cpp | 77 | ||||
-rw-r--r-- | xs/src/libslic3r/GCode.hpp | 12 | ||||
-rw-r--r-- | xs/src/libslic3r/GCode/PrintExtents.cpp | 10 | ||||
-rw-r--r-- | xs/src/libslic3r/GCode/WipeTower.hpp | 29 | ||||
-rw-r--r-- | xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 66 | ||||
-rw-r--r-- | xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 3 | ||||
-rw-r--r-- | xs/src/libslic3r/Print.cpp | 20 | ||||
-rw-r--r-- | xs/src/libslic3r/Print.hpp | 4 | ||||
-rw-r--r-- | xs/src/libslic3r/PrintObject.cpp | 4 |
9 files changed, 168 insertions, 57 deletions
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 261c8e59d..1c1eeee6f 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -167,6 +167,18 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T { std::string gcode; + // Toolchangeresult.gcode assumes the wipe tower corner is at the origin + // We want to rotate and shift all extrusions (gcode postprocessing) and starting and ending position + float alpha = m_wipe_tower_rotation/180.f * M_PI; + WipeTower::xy start_pos = tcr.start_pos; + WipeTower::xy end_pos = tcr.end_pos; + start_pos.rotate(alpha); + start_pos.translate(m_wipe_tower_pos); + end_pos.rotate(alpha); + end_pos.translate(m_wipe_tower_pos); + std::string tcr_rotated_gcode = rotate_wipe_tower_moves(tcr.gcode, tcr.start_pos, m_wipe_tower_pos, alpha); + + // Disable linear advance for the wipe tower operations. gcode += "M900 K0\n"; // Move over the wipe tower. @@ -174,14 +186,14 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T gcode += gcodegen.retract(true); gcodegen.m_avoid_crossing_perimeters.use_external_mp_once = true; gcode += gcodegen.travel_to( - wipe_tower_point_to_object_point(gcodegen, tcr.start_pos), + wipe_tower_point_to_object_point(gcodegen, start_pos), erMixed, "Travel to a Wipe Tower"); gcode += gcodegen.unretract(); // Let the tool change be executed by the wipe tower class. // Inform the G-code writer about the changes done behind its back. - gcode += tcr.gcode; + gcode += tcr_rotated_gcode; // Let the m_writer know the current extruder_id, but ignore the generated G-code. if (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id)) gcodegen.writer().toolchange(new_extruder_id); @@ -195,18 +207,18 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T check_add_eol(gcode); } // A phony move to the end position at the wipe tower. - gcodegen.writer().travel_to_xy(Pointf(tcr.end_pos.x, tcr.end_pos.y)); - gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, tcr.end_pos)); + gcodegen.writer().travel_to_xy(Pointf(end_pos.x, end_pos.y)); + gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, end_pos)); // Prepare a future wipe. gcodegen.m_wipe.path.points.clear(); if (new_extruder_id >= 0) { // Start the wipe at the current position. - gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, tcr.end_pos)); + gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, end_pos)); // Wipe end point: Wipe direction away from the closer tower edge to the further tower edge. gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, - WipeTower::xy((std::abs(m_left - tcr.end_pos.x) < std::abs(m_right - tcr.end_pos.x)) ? m_right : m_left, - tcr.end_pos.y))); + WipeTower::xy((std::abs(m_left - end_pos.x) < std::abs(m_right - end_pos.x)) ? m_right : m_left, + end_pos.y))); } // Let the planner know we are traveling between objects. @@ -214,6 +226,57 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T return gcode; } +// This function postprocesses gcode_original, rotates and moves all G1 extrusions and returns resulting gcode +// Starting position has to be supplied explicitely (otherwise it would fail in case first G1 command only contained one coordinate) +std::string WipeTowerIntegration::rotate_wipe_tower_moves(const std::string& gcode_original, const WipeTower::xy& start_pos, const WipeTower::xy& translation, float angle) const +{ + std::istringstream gcode_str(gcode_original); + std::string gcode_out; + std::string line; + WipeTower::xy pos = start_pos; + WipeTower::xy transformed_pos; + WipeTower::xy old_pos(-1000.1f, -1000.1f); + + while (gcode_str) { + std::getline(gcode_str, line); // we read the gcode line by line + if (line.find("G1 ") == 0) { + std::ostringstream line_out; + std::istringstream line_str(line); + line_str >> std::noskipws; // don't skip whitespace + char ch = 0; + while (line_str >> ch) { + if (ch == 'X') + line_str >> pos.x; + else + if (ch == 'Y') + line_str >> pos.y; + else + line_out << ch; + } + + transformed_pos = pos; + transformed_pos.rotate(angle); + transformed_pos.translate(translation); + + if (transformed_pos != old_pos) { + line = line_out.str(); + char buf[2048] = "G1"; + if (transformed_pos.x != old_pos.x) + sprintf(buf + strlen(buf), " X%.3f", transformed_pos.x); + if (transformed_pos.y != old_pos.y) + sprintf(buf + strlen(buf), " Y%.3f", transformed_pos.y); + + line.replace(line.find("G1 "), 3, buf); + old_pos = transformed_pos; + } + } + gcode_out += line + "\n"; + } + return gcode_out; +} + + + std::string WipeTowerIntegration::prime(GCode &gcodegen) { assert(m_layer_idx == 0); diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp index 8b40385e6..4953c39fe 100644 --- a/xs/src/libslic3r/GCode.hpp +++ b/xs/src/libslic3r/GCode.hpp @@ -83,8 +83,10 @@ public: const WipeTower::ToolChangeResult &priming, const std::vector<std::vector<WipeTower::ToolChangeResult>> &tool_changes, const WipeTower::ToolChangeResult &final_purge) : - m_left(float(print_config.wipe_tower_x.value)), - m_right(float(print_config.wipe_tower_x.value + print_config.wipe_tower_width.value)), + m_left(/*float(print_config.wipe_tower_x.value)*/ 0.f), + m_right(float(/*print_config.wipe_tower_x.value +*/ print_config.wipe_tower_width.value)), + m_wipe_tower_pos(float(print_config.wipe_tower_x.value), float(print_config.wipe_tower_y.value)), + m_wipe_tower_rotation(float(print_config.wipe_tower_rotation_angle)), m_priming(priming), m_tool_changes(tool_changes), m_final_purge(final_purge), @@ -101,9 +103,14 @@ private: WipeTowerIntegration& operator=(const WipeTowerIntegration&); std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const; + // Postprocesses gcode: rotates and moves all G1 extrusions and returns result + std::string rotate_wipe_tower_moves(const std::string& gcode_original, const WipeTower::xy& start_pos, const WipeTower::xy& translation, float angle) const; + // Left / right edges of the wipe tower, for the planning of wipe moves. const float m_left; const float m_right; + const WipeTower::xy m_wipe_tower_pos; + const float m_wipe_tower_rotation; // Reference to cached values at the Printer class. const WipeTower::ToolChangeResult &m_priming; const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes; @@ -112,6 +119,7 @@ private: int m_layer_idx; int m_tool_change_idx; bool m_brim_done; + bool i_have_brim = false; }; class GCode { diff --git a/xs/src/libslic3r/GCode/PrintExtents.cpp b/xs/src/libslic3r/GCode/PrintExtents.cpp index 3c3f0f8d5..37b79f343 100644 --- a/xs/src/libslic3r/GCode/PrintExtents.cpp +++ b/xs/src/libslic3r/GCode/PrintExtents.cpp @@ -134,6 +134,11 @@ BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object // The projection does not contain the priming regions. BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_t max_print_z) { + // Wipe tower extrusions are saved as if the tower was at the origin with no rotation + // We need to get position and angle of the wipe tower to transform them to actual position. + Pointf wipe_tower_pos(print.config.wipe_tower_x.value, print.config.wipe_tower_y.value); + float wipe_tower_angle = print.config.wipe_tower_rotation_angle.value; + BoundingBoxf bbox; for (const std::vector<WipeTower::ToolChangeResult> &tool_changes : print.m_wipe_tower_tool_changes) { if (! tool_changes.empty() && tool_changes.front().print_z > max_print_z) @@ -144,6 +149,11 @@ BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_ if (e.width > 0) { Pointf p1((&e - 1)->pos.x, (&e - 1)->pos.y); Pointf p2(e.pos.x, e.pos.y); + p1.rotate(wipe_tower_angle); + p1.translate(wipe_tower_pos); + p2.rotate(wipe_tower_angle); + p2.translate(wipe_tower_pos); + bbox.merge(p1); coordf_t radius = 0.5 * e.width; bbox.min.x = std::min(bbox.min.x, std::min(p1.x, p2.x) - radius); diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index 36cebeb84..9bf350328 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -25,18 +25,30 @@ public: bool operator==(const xy &rhs) const { return x == rhs.x && y == rhs.y; } bool operator!=(const xy &rhs) const { return x != rhs.x || y != rhs.y; } - // Rotate the point around given point about given angle (in degrees) - // 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 { + // Rotate the point around center of the wipe tower about given angle (in degrees) + xy rotate(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 += (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; + out.x += temp_x * cos(angle) - temp_y * sin(angle) + width / 2.f; + out.y += temp_x * sin(angle) + temp_y * cos(angle) + depth / 2.f; + + return out; } - + + // Rotate the point around origin about given angle in degrees + void rotate(float angle) { + float temp_x = x * cos(angle) - y * sin(angle); + y = x * sin(angle) + y * cos(angle); + x = temp_x; + } + + void translate(const xy& vect) { + x += vect.x; + y += vect.y; + } + float x; float y; }; @@ -104,6 +116,9 @@ public: // This is useful not only for the print time estimation, but also for the control of layer cooling. float elapsed_time; + // Is this a priming extrusion? (If so, the wipe tower rotation & translation will not be applied later) + bool priming; + // Sum the total length of the extrusion. float total_extrusion_length_in_plane() { float e_length = 0.f; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index f466fc4f6..3d0dba07a 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -5,7 +5,7 @@ TODO LIST 1. cooling moves - DONE 2. account for perimeter and finish_layer extrusions and subtract it from last wipe - DONE -3. priming extrusions (last wipe must clear the color) +3. priming extrusions (last wipe must clear the color) - DONE 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) @@ -17,7 +17,6 @@ TODO LIST #include <assert.h> #include <math.h> -#include <fstream> #include <iostream> #include <vector> #include <numeric> @@ -68,8 +67,11 @@ public: return *this; } - Writer& set_initial_position(const WipeTower::xy &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); + Writer& set_initial_position(const WipeTower::xy &pos, float width = 0.f, float depth = 0.f, float internal_angle = 0.f) { + m_wipe_tower_width = width; + m_wipe_tower_depth = depth; + m_internal_angle = internal_angle; + m_start_pos = WipeTower::xy(pos,0.f,m_y_shift).rotate(m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle); m_current_pos = pos; return *this; } @@ -81,9 +83,6 @@ 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_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; @@ -110,7 +109,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; } - 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); } + const WipeTower::xy pos_rotated() const { return WipeTower::xy(m_current_pos, 0.f, m_y_shift).rotate(m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle); } float elapsed_time() const { return m_elapsed_time; } // Extrude with an explicitely provided amount of extrusion. @@ -125,9 +124,9 @@ public: double len = sqrt(dx*dx+dy*dy); - // 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)); // 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 + // Now do the "internal rotation" with respect to the wipe tower center + WipeTower::xy rotated_current_pos(WipeTower::xy(m_current_pos,0.f,m_y_shift).rotate(m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle)); // this is where we are + WipeTower::xy rot(WipeTower::xy(x,y+m_y_shift).rotate(m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle)); // 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. @@ -147,6 +146,7 @@ public: if (std::abs(rot.y - rotated_current_pos.y) > EPSILON) m_gcode += set_format_Y(rot.y); + if (e != 0.f) m_gcode += set_format_E(e); @@ -397,9 +397,8 @@ private: std::string m_gcode; std::vector<WipeTower::Extrusion> m_extrusions; float m_elapsed_time; - float m_angle_deg = 0.f; + float m_internal_angle = 0.f; float m_y_shift = 0.f; - WipeTower::xy m_wipe_tower_pos; float m_wipe_tower_width = 0.f; float m_wipe_tower_depth = 0.f; float m_last_fan_speed = 0.f; @@ -539,6 +538,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( m_print_brim = true; ToolChangeResult result; + result.priming = true; result.print_z = this->m_z_pos; result.layer_height = this->m_layer_height; result.gcode = writer.gcode(); @@ -575,7 +575,7 @@ 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), + 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*/wipe_area+m_depth_traversed-0.5*m_perimeter_width : m_wipe_tower_depth-m_perimeter_width)); @@ -584,7 +584,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo writer.set_extrusion_flow(m_extrusion_flow) .set_z(m_z_pos) .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 && !m_peters_wipe_tower) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f)) .append(";--------------------\n" "; CP TOOLCHANGE START\n") @@ -594,7 +593,7 @@ 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); + writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); // Increase the extruder driver current to allow fast ramming. writer.set_extruder_trimpot(750); @@ -616,11 +615,11 @@ 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 (m_peters_wipe_tower) - writer.rectangle(m_wipe_tower_pos,m_layer_info->depth + 3*m_perimeter_width,m_wipe_tower_depth); + writer.rectangle(WipeTower::xy(0.f, 0.f),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); + writer.rectangle(WipeTower::xy(0.f, 0.f),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 + m_wipe_tower_width) / 2.f ? 0.f : m_wipe_tower_width), writer.y()); + writer.travel(writer.x()> m_wipe_tower_width / 2.f ? 0.f : m_wipe_tower_width, writer.y()); } } } @@ -634,6 +633,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo "\n\n"); ToolChangeResult result; + result.priming = false; result.print_z = this->m_z_pos; result.layer_height = this->m_layer_height; result.gcode = writer.gcode(); @@ -647,7 +647,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, float y_offset) { const box_coordinates wipeTower_box( - m_wipe_tower_pos, + WipeTower::xy(0.f, 0.f), m_wipe_tower_width, m_wipe_tower_depth); @@ -655,12 +655,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, flo writer.set_extrusion_flow(m_extrusion_flow * 1.1f) .set_z(m_z_pos) // Let the writer know the current Z position as a base for Z-hop. .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); - writer.set_initial_position(initial_position); + writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); 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); @@ -685,6 +684,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, flo m_print_brim = false; // Mark the brim as extruded ToolChangeResult result; + result.priming = false; result.print_z = this->m_z_pos; result.layer_height = this->m_layer_height; result.gcode = writer.gcode(); @@ -724,7 +724,7 @@ void WipeTowerPrusaMM::toolchange_Unload( 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; + float sparse_beginning_y = 0.f; 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()) ; @@ -742,7 +742,7 @@ void WipeTowerPrusaMM::toolchange_Unload( 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; + float ramming_end_y = sum_of_depths; ramming_end_y -= (y_step/m_extra_spacing-m_perimeter_width) / 2.f; // center of final ramming line // debugging: @@ -950,7 +950,7 @@ void WipeTowerPrusaMM::toolchange_Wipe( 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()); + .travel(m_left_to_right ? m_wipe_tower_width : 0.f, writer.y()); } writer.set_extrusion_flow(m_extrusion_flow); // Reset the extrusion flow. @@ -969,7 +969,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() writer.set_extrusion_flow(m_extrusion_flow) .set_z(m_z_pos) .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 && !m_peters_wipe_tower ? m_layer_info->toolchanges_depth() : 0.f)) .append(";--------------------\n" "; CP EMPTY GRID START\n") @@ -978,14 +977,12 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() // Slow down on the 1st layer. float speed_factor = m_is_first_layer ? 0.5f : 1.f; 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), + box_coordinates fill_box(xy(m_perimeter_width, m_depth_traversed + m_perimeter_width), m_wipe_tower_width - 2 * m_perimeter_width, current_depth-m_perimeter_width); - 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); + writer.set_initial_position((m_left_to_right ? fill_box.ru : fill_box.lu), // so there is never a diagonal travel + m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); box_coordinates box = fill_box; for (int i=0;i<2;++i) { @@ -1044,6 +1041,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() m_depth_traversed = m_wipe_tower_depth-m_perimeter_width; ToolChangeResult result; + result.priming = false; result.print_z = this->m_z_pos; result.layer_height = this->m_layer_height; result.gcode = writer.gcode(); @@ -1165,9 +1163,9 @@ void WipeTowerPrusaMM::generate(std::vector<std::vector<WipeTower::ToolChangeRes { set_layer(layer.z,layer.height,0,layer.z == m_plan.front().z,layer.z == m_plan.back().z); if (m_peters_wipe_tower) - m_wipe_tower_rotation_angle += 90.f; + m_internal_rotation += 90.f; else - m_wipe_tower_rotation_angle += 180.f; + m_internal_rotation += 180.f; 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; @@ -1188,7 +1186,7 @@ void WipeTowerPrusaMM::generate(std::vector<std::vector<WipeTower::ToolChangeRes last_toolchange.gcode += buf; } 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.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 diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 1ae4616d8..e1529bcf4 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -102,6 +102,8 @@ public: // Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result" void generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &result); + float get_depth() const { return m_wipe_tower_depth; } + // Switch to a next layer. @@ -189,6 +191,7 @@ private: 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_internal_rotation = 0.f; 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/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 8c91eb192..bc403afb6 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -167,7 +167,10 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option "use_relative_e_distances", "use_volumetric_e", "variable_layer_height", - "wipe" + "wipe", + "wipe_tower_x", + "wipe_tower_y", + "wipe_tower_rotation_angle" }; std::vector<PrintStep> steps; @@ -176,7 +179,12 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option // Always invalidate the wipe tower. This is probably necessary because of the wipe_into_infill / wipe_into_objects // features - nearly anything can influence what should (and could) be wiped into. - steps.emplace_back(psWipeTower); + // Only these three parameters don't invalidate the wipe tower (they only affect the gcode export): + for (const t_config_option_key &opt_key : opt_keys) + if (opt_key != "wipe_tower_x" && opt_key != "wipe_tower_y" && opt_key != "wipe_tower_rotation_angle") { + steps.emplace_back(psWipeTower); + break; + } for (const t_config_option_key &opt_key : opt_keys) { if (steps_ignore.find(opt_key) != steps_ignore.end()) { @@ -213,10 +221,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option || opt_key == "spiral_vase" || opt_key == "temperature" || opt_key == "wipe_tower" - || opt_key == "wipe_tower_x" - || opt_key == "wipe_tower_y" || opt_key == "wipe_tower_width" - || opt_key == "wipe_tower_rotation_angle" || opt_key == "wipe_tower_bridging" || opt_key == "wiping_volumes_matrix" || opt_key == "parking_pos_retraction" @@ -1052,6 +1057,8 @@ void Print::_make_wipe_tower() if (! this->has_wipe_tower()) return; + m_wipe_tower_depth = 0.f; + // Get wiping matrix to get number of extruders and convert vector<double> to vector<float>: std::vector<float> wiping_matrix((this->config.wiping_volumes_matrix.values).begin(),(this->config.wiping_volumes_matrix.values).end()); // Extract purging volumes for each extruder pair: @@ -1163,7 +1170,8 @@ 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); - + m_wipe_tower_depth = wipe_tower.get_depth(); + // Unload the current filament over the purge tower. coordf_t layer_height = this->objects.front()->config.layer_height.value; if (m_tool_ordering.back().wipe_tower_partitions > 0) { diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index bcd61ea02..e3430ad0e 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -273,6 +273,7 @@ public: void add_model_object(ModelObject* model_object, int idx = -1); bool apply_config(DynamicPrintConfig config); + float get_wipe_tower_depth() const { return m_wipe_tower_depth; } bool has_infinite_skirt() const; bool has_skirt() const; // Returns an empty string if valid, otherwise returns an error message. @@ -326,6 +327,9 @@ private: bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys); PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume); + // Depth of the wipe tower to pass to GLCanvas3D for exact bounding box: + float m_wipe_tower_depth = 0.f; + // Has the calculation been canceled? tbb::atomic<bool> m_canceled; }; diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 47495dad8..7150ead59 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -75,6 +75,7 @@ bool PrintObject::delete_last_copy() bool PrintObject::set_copies(const Points &points) { + bool copies_num_changed = this->_copies.size() != points.size(); this->_copies = points; // order copies with a nearest neighbor search and translate them by _copies_shift @@ -93,7 +94,8 @@ bool PrintObject::set_copies(const Points &points) bool invalidated = this->_print->invalidate_step(psSkirt); invalidated |= this->_print->invalidate_step(psBrim); - invalidated |= this->_print->invalidate_step(psWipeTower); + if (copies_num_changed) + invalidated |= this->_print->invalidate_step(psWipeTower); return invalidated; } |