From ace6cb1f78a65556d5b28973704a2c3efd519200 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 26 Jul 2023 12:30:22 +0200 Subject: [PATCH] Complete test for vbed involvement --- src/libslic3r/Arrange/ArrangeSettingsView.hpp | 12 ++--- .../Arrange/Core/NFP/PackStrategyNFP.hpp | 13 +++-- tests/arrange/test_arrange_integration.cpp | 47 ++++++++++++++++--- 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/Arrange/ArrangeSettingsView.hpp b/src/libslic3r/Arrange/ArrangeSettingsView.hpp index 5bd63aeea0..582e6bd5b7 100644 --- a/src/libslic3r/Arrange/ArrangeSettingsView.hpp +++ b/src/libslic3r/Arrange/ArrangeSettingsView.hpp @@ -102,12 +102,12 @@ public: void distance_from_obj_range(float &min, float &max) const override { min = 0.f; max = 100.f; } void distance_from_bed_range(float &min, float &max) const override { min = 0.f; max = 100.f; } - ArrangeSettingsDb& set_distance_from_objects(float v) override { m_v.d_obj = v; return *this; } - ArrangeSettingsDb& set_distance_from_bed(float v) override { m_v.d_bed = v; return *this; } - ArrangeSettingsDb& set_rotation_enabled(bool v) override { m_v.rotations = v; return *this; } - ArrangeSettingsDb& set_xl_alignment(XLPivots v) override { m_v.xl_align = v; return *this; } - ArrangeSettingsDb& set_geometry_handling(GeometryHandling v) override { m_v.geom_handling = v; return *this; } - ArrangeSettingsDb& set_arrange_strategy(ArrangeStrategy v) override { m_v.arr_strategy = v; return *this; } + ArrangeSettings& set_distance_from_objects(float v) override { m_v.d_obj = v; return *this; } + ArrangeSettings& set_distance_from_bed(float v) override { m_v.d_bed = v; return *this; } + ArrangeSettings& set_rotation_enabled(bool v) override { m_v.rotations = v; return *this; } + ArrangeSettings& set_xl_alignment(XLPivots v) override { m_v.xl_align = v; return *this; } + ArrangeSettings& set_geometry_handling(GeometryHandling v) override { m_v.geom_handling = v; return *this; } + ArrangeSettings& set_arrange_strategy(ArrangeStrategy v) override { m_v.arr_strategy = v; return *this; } auto & values() const { return m_v; } auto & values() { return m_v; } diff --git a/src/libslic3r/Arrange/Core/NFP/PackStrategyNFP.hpp b/src/libslic3r/Arrange/Core/NFP/PackStrategyNFP.hpp index 733694b28e..ea2f2a5100 100644 --- a/src/libslic3r/Arrange/Core/NFP/PackStrategyNFP.hpp +++ b/src/libslic3r/Arrange/Core/NFP/PackStrategyNFP.hpp @@ -226,6 +226,7 @@ bool pack(Strategy &strategy, { using KernelT = KernelTraits; + // The kernel might pack the item immediately bool packed = KernelT::on_start_packing(strategy.kernel, item, bed, packing_context, remaining_items); @@ -235,9 +236,10 @@ bool pack(Strategy &strategy, Vec2crd orig_tr = get_translation(item); Vec2crd final_tr = orig_tr; - bool cancelled = false; + bool cancelled = strategy.stop_condition(); const auto & rotations = allowed_rotations(item); + // Check all rotations but only if item is not already packed for (auto rot_it = rotations.begin(); !cancelled && !packed && rot_it != rotations.end(); ++rot_it) { @@ -261,12 +263,17 @@ bool pack(Strategy &strategy, } } - cancelled = !packed && (cancelled || std::isnan(final_score) || std::isinf(final_score)); - packed = !cancelled; + // If the score is not valid, and the item is not already packed, or + // the packing was cancelled asynchronously by stop condition, then + // discard the packing + bool is_score_valid = !std::isnan(final_score) && !std::isinf(final_score); + packed = !cancelled && (packed || is_score_valid); if (packed) { set_translation(item, final_tr); set_rotation(item, orig_rot + final_rot); + + // Finally, consult the kernel if the packing is sane packed = KernelT::on_item_packed(strategy.kernel, item); } diff --git a/tests/arrange/test_arrange_integration.cpp b/tests/arrange/test_arrange_integration.cpp index 383349c4a5..39bd70afa1 100644 --- a/tests/arrange/test_arrange_integration.cpp +++ b/tests/arrange/test_arrange_integration.cpp @@ -787,19 +787,50 @@ TEST_CASE("Testing arrangement involving virtual beds", "[arrange2][integration] using namespace Slic3r; Model model = get_example_model_with_arranged_primitives(); + DynamicPrintConfig cfg; + cfg.load_from_ini(std::string(TEST_DATA_DIR PATH_SEPARATOR) + "default_fff.ini", + ForwardCompatibilitySubstitutionRule::Enable); + auto bed = arr2::to_arrange_bed(get_bed_shape(cfg)); + auto bedbb = bounding_box(bed); + auto bedsz = unscaled(bedbb.size()); - arr2::ArrangeSettings settings; - auto bed = arr2::RectangleBed{scaled(250.), scaled(210.)}; + auto strategy = GENERATE(arr2::ArrangeSettingsView::asAuto, + arr2::ArrangeSettingsView::asPullToCenter); + + INFO ("Strategy = " << strategy); + + auto settings = arr2::ArrangeSettings{} + .set_distance_from_objects(0.) + .set_arrange_strategy(strategy); arr2::Scene scene{arr2::SceneBuilder{} .set_model(model) .set_arrange_settings(settings) - .set_bed(bed)}; + .set_bed(cfg)}; - auto task = arr2::ArrangeTask::create(scene); - task->printable.selected.emplace_back(arr2::ArrangeItem{arr2::to_rectangle(offset(bed, -scaled(1.)))}); + auto itm_conv = arr2::ArrangeableToItemConverter::create(scene); - REQUIRE(task->printable.selected.size() == arr2::model_instance_count(model) + 1); + auto task = arr2::ArrangeTask::create(scene, *itm_conv); + + ModelObject* new_object = model.add_object(); + new_object->name = "big_cube"; + ModelInstance *bigcube_inst = new_object->add_instance(); + TriangleMesh mesh = make_cube(bedsz.x() - 5., bedsz.y() - 5., 20.); + ModelVolume* new_volume = new_object->add_volume(mesh); + new_volume->name = new_object->name; + + { + arr2::ArrangeItem bigitm; + scene.model().visit_arrangeable(bigcube_inst->id(), + [&bigitm, &itm_conv]( + const arr2::Arrangeable &arrbl) { + bigitm = itm_conv->convert(arrbl); + }); + + task->printable.selected.emplace_back(std::move(bigitm)); + } + + REQUIRE(task->printable.selected.size() == arr2::model_instance_count(model)); auto result = task->process_native(arr2::DummyCtl{}); @@ -813,6 +844,10 @@ TEST_CASE("Testing arrangement involving virtual beds", "[arrange2][integration] REQUIRE(arr2::get_bed_index(result->items.back()) == arr2::PhysicalBedId); + bool applied = result->apply_on(scene.model()); + REQUIRE(applied); + store_3mf("vbed_test_result.3mf", &model, &cfg, false); + REQUIRE(std::all_of(task->printable.selected.begin(), task->printable.selected.end(), [&bed](auto &item) { return bounding_box(bed).contains(arr2::envelope_bounding_box(item)); }));