diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index 8c47800cd..e52d7a1ce 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -2092,17 +2092,24 @@ WipeTower::ToolChangeResult WipeTower::finish_layer_new(bool extrude_perimeter, bool toolchanges_on_layer = m_layer_info->toolchanges_depth() > WT_EPSILON; + std::vector finish_rect_wipe_path; if (extrude_fill_wall) { // inner perimeter of the sparse section, if there is space for it: - if (fill_box.ru.y() - fill_box.rd.y() > m_perimeter_width - WT_EPSILON) + if (fill_box.ru.y() - fill_box.rd.y() > m_perimeter_width - WT_EPSILON) { writer.rectangle_fill_box(this, fill_box.ld, fill_box.rd.x() - fill_box.ld.x(), fill_box.ru.y() - fill_box.rd.y(), feedrate); + Vec2f target = (writer.pos() == fill_box.ld ? fill_box.rd : + (writer.pos() == fill_box.rd ? fill_box.ru : + (writer.pos() == fill_box.ru ? fill_box.lu : + fill_box.ld))); + finish_rect_wipe_path.emplace_back(writer.pos()); + finish_rect_wipe_path.emplace_back(target); + } } // Extrude infill to support the material to be printed above. const float dy = (fill_box.lu.y() - fill_box.ld.y() - m_perimeter_width); float left = fill_box.lu.x() + 2 * m_perimeter_width; float right = fill_box.ru.x() - 2 * m_perimeter_width; - std::vector finish_rect_wipe_path; if (extrude_fill && dy > m_perimeter_width) { writer.travel(fill_box.ld + Vec2f(m_perimeter_width * 2, 0.f)) .append(";--------------------\n" @@ -2144,6 +2151,8 @@ WipeTower::ToolChangeResult WipeTower::finish_layer_new(bool extrude_perimeter, writer.travel(x, writer.y()); writer.extrude(x, i % 2 ? fill_box.rd.y() : fill_box.ru.y()); } + + finish_rect_wipe_path.clear(); // BBS: add wipe_path for this case: only with finish rectangle finish_rect_wipe_path.emplace_back(writer.pos()); finish_rect_wipe_path.emplace_back(Vec2f(left + dx * n, n % 2 ? fill_box.ru.y() : fill_box.rd.y())); @@ -2217,7 +2226,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer_new(bool extrude_perimeter, return construct_tcr(writer, false, m_current_tool, true, 0.f); } -WipeTower::ToolChangeResult WipeTower::finish_block(const WipeTowerBlock &block, int filament_id, bool extrude_perimeter, bool extrude_fill) +WipeTower::ToolChangeResult WipeTower::finish_block(const WipeTowerBlock &block, int filament_id, bool extrude_fill) { WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar); writer.set_extrusion_flow(m_extrusion_flow) @@ -2239,15 +2248,21 @@ WipeTower::ToolChangeResult WipeTower::finish_block(const WipeTowerBlock &block, bool toolchanges_on_layer = m_layer_info->toolchanges_depth() > WT_EPSILON; + std::vector finish_rect_wipe_path; // inner perimeter of the sparse section, if there is space for it: - if (fill_box.ru.y() - fill_box.rd.y() > m_perimeter_width - WT_EPSILON) + if (fill_box.ru.y() - fill_box.rd.y() > m_perimeter_width - WT_EPSILON) { writer.rectangle_fill_box(this, fill_box.ld, fill_box.rd.x() - fill_box.ld.x(), fill_box.ru.y() - fill_box.rd.y(), feedrate); + Vec2f target = (writer.pos() == fill_box.ld ? fill_box.rd : + (writer.pos() == fill_box.rd ? fill_box.ru : + (writer.pos() == fill_box.ru ? fill_box.lu : fill_box.ld))); + finish_rect_wipe_path.emplace_back(writer.pos()); + finish_rect_wipe_path.emplace_back(target); + } // Extrude infill to support the material to be printed above. const float dy = (fill_box.lu.y() - fill_box.ld.y() - m_perimeter_width); float left = fill_box.lu.x() + 2 * m_perimeter_width; float right = fill_box.ru.x() - 2 * m_perimeter_width; - std::vector finish_rect_wipe_path; if (extrude_fill && dy > m_perimeter_width) { writer.travel(fill_box.ld + Vec2f(m_perimeter_width * 2, 0.f)) .append(";--------------------\n" @@ -2289,6 +2304,7 @@ WipeTower::ToolChangeResult WipeTower::finish_block(const WipeTowerBlock &block, writer.travel(x, writer.y()); writer.extrude(x, i % 2 ? fill_box.rd.y() : fill_box.ru.y()); } + finish_rect_wipe_path.clear(); // BBS: add wipe_path for this case: only with finish rectangle finish_rect_wipe_path.emplace_back(writer.pos()); finish_rect_wipe_path.emplace_back(Vec2f(left + dx * n, n % 2 ? fill_box.ru.y() : fill_box.rd.y())); @@ -2302,9 +2318,6 @@ WipeTower::ToolChangeResult WipeTower::finish_block(const WipeTowerBlock &block, // BBS box_coordinates wt_box(Vec2f(0.f, 0.f), m_wipe_tower_width, m_layer_info->depth + m_perimeter_width); wt_box = align_perimeter(wt_box); - if (extrude_perimeter) { - writer.rectangle(wt_box, feedrate); - } // Now prepare future wipe. box contains rectangle that was extruded last (ccw). Vec2f target = (writer.pos() == wt_box.ld ? wt_box.rd : (writer.pos() == wt_box.rd ? wt_box.ru : (writer.pos() == wt_box.ru ? wt_box.lu : wt_box.ld))); @@ -2325,6 +2338,69 @@ WipeTower::ToolChangeResult WipeTower::finish_block(const WipeTowerBlock &block, return construct_block_tcr(writer, false, filament_id, true, 0.f); } +WipeTower::ToolChangeResult WipeTower::finish_block_solid(const WipeTowerBlock &block, int filament_id, bool extrude_fill) +{ + WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar); + writer.set_extrusion_flow(m_extrusion_flow) + .set_z(m_z_pos) + .set_initial_tool(filament_id) + .set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f)); + + writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_Start) + "\n"); + + // Slow down on the 1st layer. + bool first_layer = is_first_layer(); + // BBS: speed up perimeter speed to 90mm/s for non-first layer + float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : std::min(60.0f * m_filpar[filament_id].max_e_speed / m_extrusion_flow, 5400.f); + + box_coordinates fill_box(Vec2f(0, 0), 0, 0); + fill_box = box_coordinates(Vec2f(m_perimeter_width, block.cur_depth), m_wipe_tower_width - 2 * m_perimeter_width, + block.start_depth + block.layer_depths[m_cur_layer_id] - block.cur_depth - m_perimeter_width); + + writer.set_initial_position((m_left_to_right ? fill_box.rd : fill_box.ld), m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); + m_left_to_right = !m_left_to_right; + bool toolchanges_on_layer = m_layer_info->toolchanges_depth() > WT_EPSILON; + + // Extrude infill to support the material to be printed above. + const float dy = (fill_box.lu.y() - fill_box.ld.y()); + float left = fill_box.lu.x(); + float right = fill_box.ru.x(); + std::vector finish_rect_wipe_path; + { + writer.append(";--------------------\n" + "; CP EMPTY GRID START\n") + .comment_with_value(" layer #", m_num_layer_changes + 1); + + float y = fill_box.ld.y(); + int n = (dy + 0.25 * m_perimeter_width) / m_perimeter_width + 1; + float spacing = m_perimeter_width; + int i = 0; + for (i = 0; i < n; ++i) { + writer.extrude(m_left_to_right ? right : left, writer.y(), feedrate); + if (i == n - 1) { + writer.add_wipe_point(writer.pos()).add_wipe_point(Vec2f(m_left_to_right ? left : right, writer.y())); + break; + } + m_left_to_right = !m_left_to_right; + y = y + spacing; + writer.extrude(writer.x(), y, feedrate); + } + + writer.append("; CP EMPTY GRID END\n" + ";------------------\n\n\n\n\n\n\n"); + } + + writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_End) + "\n"); + + // Ask our writer about how much material was consumed. + // Skip this in case the layer is sparse and config option to not print sparse layers is enabled. + if (!m_no_sparse_layers || toolchanges_on_layer) + if (filament_id < m_used_filament_length.size()) + m_used_filament_length[filament_id] += writer.get_and_reset_used_filament_length(); + + return construct_block_tcr(writer, false, filament_id, true, 0.f); +} + void WipeTower::toolchange_wipe_new(WipeTowerWriter &writer, const box_coordinates &cleaning_box, float wipe_length) { writer.set_extrusion_flow(m_extrusion_flow * (is_first_layer() ? 1.15f : 1.f)).append("; CP TOOLCHANGE WIPE\n"); @@ -2511,8 +2587,8 @@ void WipeTower::generate_wipe_tower_blocks() for (auto& info : m_plan) { for (const WipeTowerInfo::ToolChange &tool_change : info.tool_changes) { if (is_in_same_extruder(tool_change.old_tool, tool_change.new_tool)) { - int filament_category = get_filament_category(tool_change.old_tool); - add_depth_to_block(tool_change.old_tool, filament_category, tool_change.required_depth); + int filament_category = get_filament_category(tool_change.new_tool); + add_depth_to_block(tool_change.new_tool, filament_category, tool_change.required_depth); } else { int old_filament_category = get_filament_category(tool_change.old_tool); @@ -2541,13 +2617,36 @@ void WipeTower::generate_wipe_tower_blocks() const auto &layer_category_depths = all_layer_category_to_depth[layer_id]; for (auto iter = layer_category_depths.begin(); iter != layer_category_depths.end(); ++iter) { auto& block = get_block_by_category(iter->first); - if (block.layer_depths.empty()) + if (block.layer_depths.empty()) { block.layer_depths.resize(all_layer_category_to_depth.size(), 0); + block.solid_infill.resize(all_layer_category_to_depth.size(), false); + } block.depth = std::max(block.depth, iter->second); block.layer_depths[layer_id] = iter->second; } } + // add solid infill flag + int solid_infill_layer = 2; + for (WipeTowerBlock& block : m_wipe_tower_blocks) { + for (int layer_id = 0; layer_id < all_layer_category_to_depth.size(); ++layer_id) { + std::unordered_map &category_to_depth = all_layer_category_to_depth[layer_id]; + if (is_approx(category_to_depth[block.filament_category], 0.f)) { + int layer_count = solid_infill_layer; + while (layer_count > 0) { + if (layer_id + layer_count < all_layer_category_to_depth.size()) { + std::unordered_map& up_layer_depth = all_layer_category_to_depth[layer_id + layer_count]; + if (!is_approx(up_layer_depth[block.filament_category], 0.f)) { + block.solid_infill[layer_id] = true; + break; + } + } + --layer_count; + } + } + } + } + // 4. get real depth for every layer for (int layer_id = m_plan.size() - 1; layer_id >= 0; --layer_id) { m_plan[layer_id].depth = 0; @@ -2757,10 +2856,22 @@ void WipeTower::generate_new(std::vector= block.start_depth + block.layer_depths[m_cur_layer_id]) { continue; @@ -2801,7 +2916,11 @@ void WipeTower::generate_new(std::vector layer_depths; + std::vector solid_infill; float depth{0}; float start_depth{0}; float cur_depth{0}; @@ -343,7 +344,8 @@ public: ToolChangeResult tool_change_new(size_t new_tool); NozzleChangeResult nozzle_change_new(int old_filament_id, int new_filament_id); ToolChangeResult finish_layer_new(bool extrude_perimeter = true, bool extrude_fill = true, bool extrude_fill_wall = true); - ToolChangeResult finish_block(const WipeTowerBlock &block, int filament_id, bool extrude_perimeter = true, bool extrude_fill = true); + ToolChangeResult finish_block(const WipeTowerBlock &block, int filament_id, bool extrude_fill = true); + ToolChangeResult finish_block_solid(const WipeTowerBlock &block, int filament_id, bool extrude_fill = true); void toolchange_wipe_new(WipeTowerWriter &writer, const box_coordinates &cleaning_box, float wipe_length); private: