From eb6d39afd4d35537e5475a44df0bc3bc91c4a19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Wed, 15 May 2024 15:54:51 +0200 Subject: [PATCH] Split get sorted extrusions to multiple functions --- src/libslic3r/GCode.cpp | 211 ++++++++++++++++++++++------------------ 1 file changed, 118 insertions(+), 93 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 419377e9f9..b042b05aef 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2864,109 +2864,134 @@ struct SliceExtrusions { std::vector ironing_extrusions; }; -std::vector get_sorted_extrusions(const Print &print, const Layer* layer, +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 std::vector &perimeters){ + if (!perimeters.empty()) { + auto last_perimeter{static_cast(perimeters.back())}; + if (last_perimeter != nullptr) { + return last_perimeter->seam; + } + } + return std::nullopt; +} + +std::vector extract_island_extrusions( + const LayerSlice &lslice, + const Print &print, + const Layer *layer, + const Seams::Placer &seam_placer, + const bool spiral_vase, + const GCode::ExtractEntityPredicate &predicate, + std::optional &previous_position +) { + std::vector result; + for (const LayerIsland &island : lslice.islands) { + const LayerRegion &layerm = *layer->get_region(island.perimeters.region()); + // PrintObjects own the PrintRegions, thus the pointer to PrintRegion would be + // unique to a PrintObject, they would not identify the content of PrintRegion + // accross the whole print uniquely. Translate to a Print specific PrintRegion. + const PrintRegion ®ion = print.get_print_region(layerm.region().print_region_id()); + + const auto infill_predicate = [&](const auto &eec, const auto ®ion) { + return predicate(eec, region) && eec.role() != ExtrusionRole::Ironing; + }; + + result.push_back(IslandExtrusions{®ion}); + IslandExtrusions &island_extrusions{result.back()}; + + island_extrusions.perimeters = GCode::extract_perimeter_extrusions(print, layer, island, predicate); + + if (print.config().infill_first) { + island_extrusions.infill_ranges = GCode::extract_infill_ranges( + print, layer, island, previous_position, infill_predicate + ); + if (const auto last_position = get_last_position(island_extrusions.infill_ranges)) { + previous_position = last_position; + } + + place_seams(layer, seam_placer, island_extrusions.perimeters, previous_position, spiral_vase); + + if (const auto last_position = get_last_position(island_extrusions.perimeters)) { + previous_position = last_position; + } + } else { + place_seams(layer, seam_placer, island_extrusions.perimeters, previous_position, spiral_vase); + + if (const auto last_position = get_last_position(island_extrusions.perimeters)) { + previous_position = last_position; + } + island_extrusions.infill_ranges = {GCode::extract_infill_ranges( + print, layer, island, previous_position, infill_predicate + )}; + if (const auto last_position = get_last_position(island_extrusions.infill_ranges)) { + previous_position = last_position; + } + } + } + return result; +} + +std::vector extract_ironing_extrusions( + const LayerSlice &lslice, + const Print &print, + const Layer *layer, + const GCode::ExtractEntityPredicate &predicate, + std::optional &previous_position +) { + std::vector result; + + for (const LayerIsland &island : lslice.islands) { + const auto ironing_predicate = [&](const auto &eec, const auto ®ion) { + return predicate(eec, region) && eec.role() == ExtrusionRole::Ironing; + }; + + const std::vector ironing_ranges{GCode::extract_infill_ranges( + print, layer, island, 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; +} + +std::vector get_sorted_extrusions( + const Print &print, + const Layer *layer, const Seams::Placer &seam_placer, std::optional previous_position, const bool spiral_vase, const GCode::ExtractEntityPredicate &predicate ) { - std::vector sorted_extrusions; + // Note: ironing. + // FIXME move ironing into the loop above over LayerIslands? + // First Ironing changes extrusion rate quickly, second single ironing may be done over + // multiple perimeter regions. Ironing in a second phase is safer, but it may be less + // efficient. + std::vector result; for (size_t idx : layer->lslice_indices_sorted_by_print_order) { const LayerSlice &lslice = layer->lslices_ex[idx]; - sorted_extrusions.emplace_back(); - for (const LayerIsland &island : lslice.islands) { - const LayerRegion &layerm = *layer->get_region(island.perimeters.region()); - // PrintObjects own the PrintRegions, thus the pointer to PrintRegion would be - // unique to a PrintObject, they would not identify the content of PrintRegion - // accross the whole print uniquely. Translate to a Print specific PrintRegion. - const PrintRegion ®ion = print.get_print_region( - layerm.region().print_region_id() - ); - - const auto infill_predicate = [&](const ExtrusionEntityCollection &entity_collection, const PrintRegion ®ion){ - return predicate(entity_collection, region) && entity_collection.role() != ExtrusionRole::Ironing; - }; - - sorted_extrusions.back().common_extrusions.push_back(IslandExtrusions{®ion}); - IslandExtrusions &island_extrusions{sorted_extrusions.back().common_extrusions.back()}; - - const std::vector perimeters{GCode::extract_perimeter_extrusions( - print, layer, island, predicate - )}; - if (print.config().infill_first) { - const std::vector infill_ranges{GCode::extract_infill_ranges( - print, - layer, - island, - previous_position, - infill_predicate - )}; - island_extrusions.infill_ranges = infill_ranges; - if (!infill_ranges.empty() && !infill_ranges.back().items.empty()) { - const ExtrusionEntityReference &last_infill{infill_ranges.back().items.back()}; - previous_position = last_infill.flipped() ? last_infill.extrusion_entity().first_point() : last_infill.extrusion_entity().last_point(); - } - - place_seams(layer, seam_placer, perimeters, previous_position, spiral_vase); - island_extrusions.perimeters = perimeters; - - if (!perimeters.empty()) { - auto last_perimeter{static_cast(perimeters.back())}; - if (last_perimeter != nullptr) { - previous_position = last_perimeter->seam; - } - } - } else { - place_seams(layer, seam_placer, perimeters, previous_position, spiral_vase); - island_extrusions.perimeters = perimeters; - - if (!perimeters.empty()) { - auto last_perimeter{static_cast(perimeters.back())}; - if (last_perimeter != nullptr) { - previous_position = last_perimeter->seam; - } - } - const std::vector infill_ranges{GCode::extract_infill_ranges( - print, - layer, - island, - previous_position, - infill_predicate - )}; - island_extrusions.infill_ranges = infill_ranges; - if (!infill_ranges.empty() && !infill_ranges.back().items.empty()) { - const ExtrusionEntityReference &last_infill{infill_ranges.back().items.back()}; - previous_position = last_infill.flipped() ? last_infill.extrusion_entity().first_point() : last_infill.extrusion_entity().last_point(); - } - } - } - // ironing - //FIXME move ironing into the loop above over LayerIslands? - // First Ironing changes extrusion rate quickly, second single ironing may be done over multiple perimeter regions. - // Ironing in a second phase is safer, but it may be less efficient. - for (const LayerIsland &island : lslice.islands) { - const auto ironing_predicate = [&](const ExtrusionEntityCollection &entity_collection, const PrintRegion ®ion){ - return predicate(entity_collection, region) && entity_collection.role() == ExtrusionRole::Ironing; - }; - - const std::vector ironing_ranges{GCode::extract_infill_ranges( - print, - layer, - island, - previous_position, - ironing_predicate - )}; - sorted_extrusions.back().ironing_extrusions.insert(sorted_extrusions.back().ironing_extrusions.end(), ironing_ranges.begin(), ironing_ranges.end()); - - if (!ironing_ranges.empty() && !ironing_ranges.back().items.empty()) { - const ExtrusionEntityReference &last_infill{ironing_ranges.back().items.back()}; - previous_position = last_infill.flipped() ? last_infill.extrusion_entity().first_point() : last_infill.extrusion_entity().last_point(); - } - } + result.emplace_back(SliceExtrusions{ + extract_island_extrusions( + lslice, print, layer, seam_placer, spiral_vase, predicate, previous_position + ), + extract_ironing_extrusions(lslice, print, layer, predicate, previous_position) + }); } - return sorted_extrusions; + return result; } void GCodeGenerator::process_layer_single_object(