diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index d5ee6a048..81880831f 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -169,6 +169,9 @@ static inline Point wipe_tower_point_to_object_point(GCode &gcodegen, const Vec2 std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const { + if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool) + throw std::invalid_argument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect."); + std::string gcode; // Toolchangeresult.gcode assumes the wipe tower corner is at the origin @@ -182,8 +185,11 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T end_pos = Eigen::Rotation2Df(alpha) * end_pos; end_pos += m_wipe_tower_pos; } - std::string tcr_rotated_gcode = tcr.priming ? tcr.gcode : rotate_wipe_tower_moves(tcr.gcode, tcr.start_pos, m_wipe_tower_pos, alpha); - + + Vec2f wipe_tower_offset = tcr.priming ? Vec2f::Zero() : m_wipe_tower_pos; + float wipe_tower_rotation = tcr.priming ? 0.f : alpha; + + std::string tcr_rotated_gcode = post_process_wipe_tower_moves(tcr, wipe_tower_offset, wipe_tower_rotation); // Disable linear advance for the wipe tower operations. gcode += (gcodegen.config().gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n")); @@ -285,17 +291,21 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T // 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 Vec2f& start_pos, const Vec2f& translation, float angle) const +std::string WipeTowerIntegration::post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const { - std::istringstream gcode_str(gcode_original); + Vec2f extruder_offset = m_extruder_offsets[tcr.initial_tool].cast(); + + std::istringstream gcode_str(tcr.gcode); std::string gcode_out; std::string line; - Vec2f pos = start_pos; - Vec2f transformed_pos; + Vec2f pos = tcr.start_pos; + Vec2f transformed_pos = pos; Vec2f old_pos(-1000.1f, -1000.1f); while (gcode_str) { std::getline(gcode_str, line); // we read the gcode line by line + + // All G1 commands should be translated and rotated if (line.find("G1 ") == 0) { std::ostringstream line_out; std::istringstream line_str(line); @@ -317,17 +327,34 @@ std::string WipeTowerIntegration::rotate_wipe_tower_moves(const std::string& gco if (transformed_pos != old_pos) { line = line_out.str(); - char buf[2048] = "G1"; + std::ostringstream oss; + oss << std::fixed << std::setprecision(3) << "G1 "; if (transformed_pos.x() != old_pos.x()) - sprintf(buf + strlen(buf), " X%.3f", transformed_pos.x()); + oss << " X" << transformed_pos.x() - extruder_offset.x(); if (transformed_pos.y() != old_pos.y()) - sprintf(buf + strlen(buf), " Y%.3f", transformed_pos.y()); + oss << " Y" << transformed_pos.y() - extruder_offset.y(); - line.replace(line.find("G1 "), 3, buf); + line.replace(line.find("G1 "), 3, oss.str()); old_pos = transformed_pos; } } + gcode_out += line + "\n"; + + // If this was a toolchange command, we should change current extruder offset + if (line == "[toolchange_gcode]") { + extruder_offset = m_extruder_offsets[tcr.new_tool].cast(); + + // If the extruder offset changed, add an extra move so everything is continuous + if (extruder_offset != m_extruder_offsets[tcr.initial_tool].cast()) { + std::ostringstream oss; + oss << std::fixed << std::setprecision(3) + << "G1 X" << transformed_pos.x() - extruder_offset.x() + << " Y" << transformed_pos.y() - extruder_offset.y() + << "\n"; + gcode_out += oss.str(); + } + } } return gcode_out; } diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 4b81b42aa..f2a67f600 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -90,6 +90,7 @@ public: 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_extruder_offsets(print_config.extruder_offset.values), m_priming(priming), m_tool_changes(tool_changes), m_final_purge(final_purge), @@ -107,14 +108,16 @@ 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 Vec2f& start_pos, const Vec2f& translation, float angle) const; + // Postprocesses gcode: rotates and moves G1 extrusions and returns result + std::string post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& 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 Vec2f m_wipe_tower_pos; const float m_wipe_tower_rotation; + const std::vector m_extruder_offsets; + // Reference to cached values at the Printer class. const std::vector &m_priming; const std::vector> &m_tool_changes; diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index 37e4040d1..354ec6d9e 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -553,7 +553,7 @@ std::vector WipeTower::prime( result.elapsed_time = writer.elapsed_time(); result.extrusions = writer.extrusions(); result.start_pos = writer.start_pos_rotated(); - result.end_pos = writer.pos_rotated(); + result.end_pos = writer.pos(); results.push_back(std::move(result)); @@ -643,7 +643,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_ 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); - writer.travel(writer.x(),writer.y()-m_perimeter_width); // cooling and loading were done a bit down the road + 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. ++ m_num_tool_changes; } else diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp index c18a502b1..badb3e8b2 100644 --- a/src/libslic3r/GCode/WipeTower.hpp +++ b/src/libslic3r/GCode/WipeTower.hpp @@ -139,13 +139,15 @@ public: m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter - std::stringstream stream{m_semm ? ramming_parameters : std::string()}; - 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); + if (m_semm) { + 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); + } m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later } @@ -241,8 +243,8 @@ public: int cooling_moves = 0; float cooling_initial_speed = 0.f; float cooling_final_speed = 0.f; - float ramming_line_width_multiplicator = 0.f; - float ramming_step_multiplicator = 0.f; + float ramming_line_width_multiplicator = 1.f; + float ramming_step_multiplicator = 1.f; float max_e_speed = std::numeric_limits::max(); std::vector ramming_speed; float nozzle_diameter;