From 0bc86ace2ef3366286823ec58b58eeb15e1eac0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Mon, 17 Jun 2024 13:58:46 +0200 Subject: [PATCH] Make previous position independent of the object instance (offset) --- src/libslic3r/GCode.cpp | 13 +- src/libslic3r/GCode/ExtrusionOrder.cpp | 185 ++++++++++++------------- src/libslic3r/GCode/ExtrusionOrder.hpp | 6 +- 3 files changed, 98 insertions(+), 106 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 392651e018..8ab4ffcd98 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2473,7 +2473,10 @@ LayerResult GCodeGenerator::process_layer( unsigned current_extruder_id{this->m_writer.extruder()->id()}; unsigned toolchange_number{0}; - std::optional previous_position{this->last_position}; + std::optional previous_position; + if (this->last_position) { + previous_position = this->point_to_gcode(*this->last_position); + } std::vector extrusions; for (const unsigned int extruder_id : layer_tools.extruders) @@ -2481,7 +2484,7 @@ LayerResult GCodeGenerator::process_layer( if (layer_tools.has_wipe_tower && m_wipe_tower) { if (is_toolchange_required(first_layer, layer_tools.extruders.back(), extruder_id, current_extruder_id)) { const WipeTower::ToolChangeResult tool_change{m_wipe_tower->get_toolchange(toolchange_number++)}; - previous_position = this->gcode_to_point(m_wipe_tower->transform_wt_pt(tool_change.end_pos).cast()); + previous_position = m_wipe_tower->transform_wt_pt(tool_change.end_pos).cast(); current_extruder_id = tool_change.new_tool; } } @@ -2495,14 +2498,14 @@ LayerResult GCodeGenerator::process_layer( } } + // Extrude brim with the extruder of the 1st region. using GCode::ExtrusionOrder::get_last_position; if (!m_brim_done) { extruder_extrusions.brim = print.brim().entities; - previous_position = get_last_position(extruder_extrusions.brim); + previous_position = get_last_position(extruder_extrusions.brim, {0.0, 0.0}); m_brim_done = true; } - const auto place_seam =[&]( const Layer &layer, ExtrusionEntity *perimeter, const std::optional &previous_position ) { @@ -2581,8 +2584,6 @@ LayerResult GCodeGenerator::process_layer( m_avoid_crossing_perimeters.disable_once(); } - - // Extrude brim with the extruder of the 1st region. if (!extruder_extrusions.brim.empty()) { if (!this->m_config.complete_objects.value) { diff --git a/src/libslic3r/GCode/ExtrusionOrder.cpp b/src/libslic3r/GCode/ExtrusionOrder.cpp index 2a1734d7f6..7404d7daf8 100644 --- a/src/libslic3r/GCode/ExtrusionOrder.cpp +++ b/src/libslic3r/GCode/ExtrusionOrder.cpp @@ -27,6 +27,50 @@ int get_extruder_id( return extruder_id; } +Vec2d get_gcode_point(const Point &point, const Vec2d &offset) { + return Vec2d(unscaled(point.x()), unscaled(point.y())) + offset; +} + +Point get_instance_point(const Vec2d &point, const Vec2d &offset) { + return Point::new_scale(point - offset); +} + +std::optional get_gcode_point(const std::optional &point, const Vec2d &offset) { + if (point) { + return get_gcode_point(*point, offset); + } + return std::nullopt; +} + +std::optional get_instance_point(const std::optional &point, const Vec2d &offset) { + if (point) { + return get_instance_point(*point, offset); + } + return std::nullopt; +} + +std::optional get_last_position(const ExtrusionEntityReferences &extrusions, const Vec2d &offset) { + if (!extrusions.empty()) { + const ExtrusionEntityReference &last_extrusion{extrusions.back()}; + auto last_loop{dynamic_cast(&last_extrusion.extrusion_entity())}; + if (last_loop != nullptr) { + return get_gcode_point(last_loop->seam, offset); + } + const Point last_point{ + last_extrusion.flipped() ? last_extrusion.extrusion_entity().first_point() : + last_extrusion.extrusion_entity().last_point()}; + return get_gcode_point(last_point, offset); + } + return std::nullopt; +} + +std::optional get_last_position(const ExtrusionEntitiesPtr &extrusions, const Vec2d &offset){ + if (!extrusions.empty()) { + return get_last_position({{*extrusions.back(), false}}, offset); + } + return std::nullopt; +} + using ExtractEntityPredicate = std::function; ExtrusionEntitiesPtr extract_infill_extrusions( @@ -111,7 +155,8 @@ std::vector extract_infill_ranges( const Print &print, const Layer &layer, const LayerIsland &island, - std::optional previous_position, + const Vec2d &offset, + std::optional &previous_position, const ExtractEntityPredicate &predicate ) { std::vector result; @@ -132,84 +177,29 @@ std::vector extract_infill_ranges( predicate )}; - const Point* start_near = previous_position ? &(*(previous_position)) : nullptr; - const std::vector sorted_extrusions{sort_fill_extrusions(extrusions, start_near)}; + const std::optional previous_position_scaled{get_instance_point(previous_position, offset)}; + const Point* start_near{previous_position_scaled ? &(*(previous_position_scaled)) : nullptr}; + const ExtrusionEntityReferences sorted_extrusions{sort_fill_extrusions(extrusions, start_near)}; - if (! sorted_extrusions.empty()) { + if (!sorted_extrusions.empty()) { result.push_back({sorted_extrusions, ®ion}); - previous_position = sorted_extrusions.back().flipped() ? - sorted_extrusions.back().extrusion_entity().first_point() : - sorted_extrusions.back().extrusion_entity().last_point(); + } + if (const auto last_position = get_last_position(sorted_extrusions, offset)) { + previous_position = last_position; } it = it_end; } return result; } -std::optional get_last_position(const std::vector &infill_ranges) { - if (!infill_ranges.empty() && !infill_ranges.back().items.empty()) { - const ExtrusionEntityReference &last_infill{infill_ranges.back().items.back()}; - return last_infill.flipped() ? last_infill.extrusion_entity().first_point() : - last_infill.extrusion_entity().last_point(); - } - return std::nullopt; -} - -std::optional get_last_position(const ExtrusionEntityReferences &extrusions) { - if (!extrusions.empty()) { - const ExtrusionEntityReference &last_extrusion{extrusions.back()}; - return last_extrusion.flipped() ? last_extrusion.extrusion_entity().first_point() : - last_extrusion.extrusion_entity().last_point(); - } - return std::nullopt; -} - -std::optional get_last_position(const ExtrusionEntitiesPtr &perimeters){ - if (!perimeters.empty()) { - auto last_perimeter_loop{dynamic_cast(perimeters.back())}; - if (last_perimeter_loop != nullptr) { - return last_perimeter_loop->seam; - } - auto last_perimeter_multi_path{dynamic_cast(perimeters.back())}; - if (last_perimeter_multi_path != nullptr) { - return last_perimeter_multi_path->last_point(); - } - } - return std::nullopt; -} - -std::optional get_last_position(const std::vector &slice_extrusions, const bool infill_first) { - if (slice_extrusions.empty()) { - return {}; - } - const SliceExtrusions &last_slice{slice_extrusions.back()}; - if (!last_slice.ironing_extrusions.empty()) { - return get_last_position(slice_extrusions.back().ironing_extrusions); - } - if (last_slice.common_extrusions.empty()) { - return {}; - } - const IslandExtrusions last_island{last_slice.common_extrusions.back()}; - if (infill_first) { - if (!last_island.perimeters.empty()) { - return get_last_position(last_island.perimeters); - } - return get_last_position(last_island.infill_ranges); - } else { - if (!last_island.infill_ranges.empty()) { - return get_last_position(last_island.infill_ranges); - } - return get_last_position(last_island.perimeters); - } -} - std::vector extract_island_extrusions( const LayerSlice &lslice, const Print &print, const Layer &layer, const ExtractEntityPredicate &predicate, const SeamPlacingFunciton &place_seam, - std::optional &previous_position + const Vec2d &offset, + std::optional &previous_position ) { std::vector result; for (const LayerIsland &island : lslice.islands) { @@ -230,33 +220,28 @@ std::vector extract_island_extrusions( if (print.config().infill_first) { island_extrusions.infill_ranges = extract_infill_ranges( - print, layer, island, previous_position, infill_predicate + print, layer, island, offset, previous_position, infill_predicate ); - if (const auto last_position = get_last_position(island_extrusions.infill_ranges)) { - previous_position = last_position; - } for (ExtrusionEntity* perimeter : island_extrusions.perimeters) { - previous_position = place_seam(layer, perimeter, previous_position); - } - - if (const auto last_position = get_last_position(island_extrusions.perimeters)) { - previous_position = last_position; + std::optional instance_point{get_instance_point(previous_position, offset)}; + const std::optional seam_point{place_seam(layer, perimeter, instance_point)}; + if (seam_point) { + previous_position = get_gcode_point(*seam_point, offset); + } } } else { for (ExtrusionEntity* perimeter : island_extrusions.perimeters) { - previous_position = place_seam(layer, perimeter, previous_position); + std::optional instance_point{get_instance_point(previous_position, offset)}; + const std::optional seam_point{place_seam(layer, perimeter, instance_point)}; + if (seam_point) { + previous_position = get_gcode_point(*seam_point, offset); + } } - if (const auto last_position = get_last_position(island_extrusions.perimeters)) { - previous_position = last_position; - } island_extrusions.infill_ranges = {extract_infill_ranges( - print, layer, island, previous_position, infill_predicate + print, layer, island, offset, previous_position, infill_predicate )}; - if (const auto last_position = get_last_position(island_extrusions.infill_ranges)) { - previous_position = last_position; - } } } return result; @@ -267,7 +252,8 @@ std::vector extract_ironing_extrusions( const Print &print, const Layer &layer, const ExtractEntityPredicate &predicate, - std::optional &previous_position + const Vec2d &offset, + std::optional &previous_position ) { std::vector result; @@ -277,15 +263,11 @@ std::vector extract_ironing_extrusions( }; const std::vector ironing_ranges{extract_infill_ranges( - print, layer, island, previous_position, ironing_predicate + print, layer, island, offset, previous_position, ironing_predicate )}; result.insert( result.end(), ironing_ranges.begin(), ironing_ranges.end() ); - - if (const auto last_position = get_last_position(ironing_ranges)) { - previous_position = last_position; - } } return result; } @@ -295,7 +277,8 @@ std::vector get_slices_extrusions( const Layer &layer, const ExtractEntityPredicate &predicate, const SeamPlacingFunciton &place_seam, - std::optional previous_position + const Vec2d &offset, + std::optional &previous_position ) { // Note: ironing. // FIXME move ironing into the loop above over LayerIslands? @@ -309,9 +292,9 @@ std::vector get_slices_extrusions( const LayerSlice &lslice = layer.lslices_ex[idx]; result.emplace_back(SliceExtrusions{ extract_island_extrusions( - lslice, print, layer, predicate, place_seam, previous_position + lslice, print, layer, predicate, place_seam, offset, previous_position ), - extract_ironing_extrusions(lslice, print, layer, predicate, previous_position) + extract_ironing_extrusions(lslice, print, layer, predicate, offset, previous_position) }); } return result; @@ -376,7 +359,7 @@ std::vector> get_overriden_extrusions( const std::vector &instances_to_print, const unsigned int extruder_id, const SeamPlacingFunciton &place_seam, - std::optional &previous_position + std::optional &previous_position ) { std::vector> result; @@ -396,10 +379,12 @@ std::vector> get_overriden_extrusions( return true; }; + const PrintObject &print_object = instance.print_object; + const Vec2d &offset = unscale(print_object.instances()[instance.instance_id].shift); + result.emplace_back(get_slices_extrusions( - print, *layer, predicate, place_seam, previous_position + print, *layer, predicate, place_seam, offset, previous_position )); - previous_position = get_last_position(result.back(), print.config().infill_first); } } return result; @@ -412,12 +397,15 @@ std::vector get_normal_extrusions( const std::vector &instances_to_print, const unsigned int extruder_id, const SeamPlacingFunciton &place_seam, - std::optional &previous_position + std::optional &previous_position ) { std::vector result; for (std::size_t i{0}; i < instances_to_print.size(); ++i) { const InstanceToPrint &instance{instances_to_print[i]}; + const PrintObject &print_object = instance.print_object; + const Vec2d &offset = unscale(print_object.instances()[instance.instance_id].shift); + result.emplace_back(); if (layers[instance.object_layer_to_print_id].support_layer != nullptr) { @@ -427,7 +415,10 @@ std::vector get_normal_extrusions( translate_support_extruder(instance.print_object.config().support_material_extruder.value, layer_tools, print.config().filament_soluble), translate_support_extruder(instance.print_object.config().support_material_interface_extruder.value, layer_tools, print.config().filament_soluble) ); - previous_position = get_last_position(result.back().support_extrusions); + + if (const auto last_position = get_last_position(result.back().support_extrusions, offset)) { + previous_position = last_position; + } } if (const Layer *layer = layers[instance.object_layer_to_print_id].object_layer; layer) { @@ -447,9 +438,9 @@ std::vector get_normal_extrusions( *layer, predicate, place_seam, + offset, previous_position ); - previous_position = get_last_position(result.back().slices_extrusions, print.config().infill_first); } } return result; diff --git a/src/libslic3r/GCode/ExtrusionOrder.hpp b/src/libslic3r/GCode/ExtrusionOrder.hpp index 36610c4b4f..75ea09d6c2 100644 --- a/src/libslic3r/GCode/ExtrusionOrder.hpp +++ b/src/libslic3r/GCode/ExtrusionOrder.hpp @@ -71,7 +71,7 @@ struct NormalExtrusions { std::vector slices_extrusions; }; -std::optional get_last_position(const ExtrusionEntitiesPtr &perimeters); +std::optional get_last_position(const ExtrusionEntitiesPtr &extrusions, const Vec2d &offset); using SeamPlacingFunciton = std::function(const Layer &layer, ExtrusionEntity* perimeter, const std::optional&)>; @@ -82,7 +82,7 @@ std::vector> get_overriden_extrusions( const std::vector &instances_to_print, const unsigned int extruder_id, const SeamPlacingFunciton &place_seam, - std::optional &previous_position + std::optional &previous_position ); std::vector get_normal_extrusions( @@ -92,7 +92,7 @@ std::vector get_normal_extrusions( const std::vector &instances_to_print, const unsigned int extruder_id, const SeamPlacingFunciton &place_seam, - std::optional &previous_position + std::optional &previous_position ); }