diff --git a/src/libslic3r/Arrange/Items/WritableItemTraits.hpp b/src/libslic3r/Arrange/Items/WritableItemTraits.hpp index 04281faa52..f80f449730 100644 --- a/src/libslic3r/Arrange/Items/WritableItemTraits.hpp +++ b/src/libslic3r/Arrange/Items/WritableItemTraits.hpp @@ -107,6 +107,30 @@ template int raise_priority(ArrItem &itm) return ret; } +template int reduce_priority(ArrItem &itm) +{ + int ret = get_priority(itm) - 1; + set_priority(itm, ret); + + return ret; +} + +template int lowest_priority(const Range &item_range) +{ + auto minp_it = std::min_element(item_range.begin(), + item_range.end(), + [](auto &itm1, auto &itm2) { + return get_priority(itm1) < + get_priority(itm2); + }); + + int min_priority = 0; + if (minp_it != item_range.end()) + min_priority = get_priority(*minp_it); + + return min_priority; +} + }} // namespace Slic3r::arr2 #endif // WRITABLEITEMTRAITS_HPP diff --git a/src/libslic3r/Arrange/Tasks/FillBedTaskImpl.hpp b/src/libslic3r/Arrange/Tasks/FillBedTaskImpl.hpp index 9c76a35c81..62b0d78270 100644 --- a/src/libslic3r/Arrange/Tasks/FillBedTaskImpl.hpp +++ b/src/libslic3r/Arrange/Tasks/FillBedTaskImpl.hpp @@ -66,6 +66,17 @@ void extract(FillBedTask &task, if (!task.prototype_item) return; + // Workaround for missing items when arranging the same geometry only: + // Injecting a number of items but with slightly shrinked shape, so that + // they can fill the emerging holes. Priority is set to lowest so that + // these filler items will only be inserted as the last ones. + ArrItem prototype_item_shrinked; + scene.model().visit_arrangeable(selected_ids.front(), + [&prototype_item_shrinked, &itm_conv](const Arrangeable &arrbl) { + if (arrbl.is_printable()) + prototype_item_shrinked = itm_conv.convert(arrbl, -SCALED_EPSILON); + }); + set_bed_index(*task.prototype_item, Unarranged); auto collect_task_items = [&prototype_geometry_id, &task, @@ -82,6 +93,10 @@ void extract(FillBedTask &task, } }; + // Set the lowest priority to the shrinked prototype (hole filler) item + set_priority(prototype_item_shrinked, + lowest_priority(range(task.selected)) - 1); + scene.model().for_each_arrangeable(collect_task_items); int needed_items = calculate_items_needed_to_fill_bed(task.bed, @@ -93,6 +108,11 @@ void extract(FillBedTask &task, task.selected.reserve(task.selected.size() + needed_items); std::fill_n(std::back_inserter(task.selected), needed_items, *task.prototype_item); + + // Add as many filler items as there are needed items. Most of them will + // be discarded anyways. + std::fill_n(std::back_inserter(task.selected), needed_items, + prototype_item_shrinked); } @@ -143,7 +163,8 @@ std::unique_ptr FillBedTask::process_native( void on_packed(ArrItem &itm) override { - do_stop = get_bed_index(itm) > PhysicalBedId && get_priority(itm) == 0; + // Stop at the first filler that is not on the physical bed + do_stop = get_bed_index(itm) > PhysicalBedId && get_priority(itm) < 0; } } subctl(ctl, *this);