mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-15 21:17:41 +00:00
Extract Layer::choose_ironing_extruder for unit-testable ironing routing (#13467)
* Extract Layer::choose_ironing_extruder for unit-testable ironing routing The ironing extruder selection in make_ironing() was a 5-line nested conditional inlined at the top of the loop, with no isolated test coverage. Pull the gating into a static helper so the routing decision is unit-testable without spinning up the slicing pipeline. Pure refactor: the helper preserves the original logic bit-for-bit (NoIroning -> -1; AllSolid always enabled; TopSurfaces and TopmostOnly require some top shells or, in spiral mode, more than one bottom shell; TopmostOnly additionally requires being on the topmost layer; enabled ironing routes to solid_infill_filament). Add tests/fff_print/test_choose_ironing_extruder.cpp covering: - AllSolid regardless of layer position - TopSurfaces with top_shell_layers > 0 - TopSurfaces with top_shell_layers=0 + spiral mode + bottom_shell_layers>1 - TopmostOnly + topmost layer - NoIroning short-circuit - TopSurfaces with top_shell_layers=0 (and not spiral) -> disabled - TopSurfaces, spiral, but bottom_shell_layers=1 -> disabled - TopmostOnly on a non-topmost layer -> disabled * Move ironing routing test into the Fill subsystem file Rename the test to tests/libslic3r/test_fill.cpp and tag it [Fill] to match the subsystem it covers, use flat behavioral test cases with GENERATE for the parameterized ones, and drop the history narration from the code comments. * tests: move ironing routing tests into fff_print/test_fill.cpp Keeps the Fill tests in one file, alongside the existing ironing rotation-template test.
This commit is contained in:
@@ -1595,6 +1595,25 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
|
|||||||
return sparse_infill_polylines;
|
return sparse_infill_polylines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the filament id (1-based) the region is ironed with, or -1 when the
|
||||||
|
// region is not ironed. AllSolid always irons. TopSurfaces and TopmostOnly need
|
||||||
|
// either some top shells or, in spiral mode, more than one bottom shell, and
|
||||||
|
// TopmostOnly additionally needs the layer to be the topmost one.
|
||||||
|
int Layer::choose_ironing_extruder(const PrintRegionConfig &cfg,
|
||||||
|
bool spiral_mode,
|
||||||
|
bool is_topmost_layer)
|
||||||
|
{
|
||||||
|
if (cfg.ironing_type == IroningType::NoIroning)
|
||||||
|
return -1;
|
||||||
|
const bool gate = (cfg.ironing_type == IroningType::AllSolid)
|
||||||
|
|| ((cfg.top_shell_layers > 0 || (spiral_mode && cfg.bottom_shell_layers > 1))
|
||||||
|
&& (cfg.ironing_type == IroningType::TopSurfaces
|
||||||
|
|| (cfg.ironing_type == IroningType::TopmostOnly && is_topmost_layer)));
|
||||||
|
if (!gate)
|
||||||
|
return -1;
|
||||||
|
return cfg.top_surface_filament_id;
|
||||||
|
}
|
||||||
|
|
||||||
// Create ironing extrusions over top surfaces.
|
// Create ironing extrusions over top surfaces.
|
||||||
void Layer::make_ironing()
|
void Layer::make_ironing()
|
||||||
{
|
{
|
||||||
@@ -1664,19 +1683,10 @@ void Layer::make_ironing()
|
|||||||
if (! layerm->slices.empty()) {
|
if (! layerm->slices.empty()) {
|
||||||
IroningParams ironing_params;
|
IroningParams ironing_params;
|
||||||
const PrintRegionConfig &config = layerm->region().config();
|
const PrintRegionConfig &config = layerm->region().config();
|
||||||
if (config.ironing_type != IroningType::NoIroning &&
|
ironing_params.extruder = Layer::choose_ironing_extruder(
|
||||||
(config.ironing_type == IroningType::AllSolid ||
|
config,
|
||||||
((config.top_shell_layers > 0 || (this->object()->print()->config().spiral_mode && config.bottom_shell_layers > 1)) &&
|
/*spiral_mode=*/this->object()->print()->config().spiral_mode,
|
||||||
(config.ironing_type == IroningType::TopSurfaces ||
|
/*is_topmost_layer=*/layerm->layer()->upper_layer == nullptr);
|
||||||
(config.ironing_type == IroningType::TopmostOnly && layerm->layer()->upper_layer == nullptr))))) {
|
|
||||||
if (config.outer_wall_filament_id == config.top_surface_filament_id || config.wall_loops == 0) {
|
|
||||||
// Iron the whole face.
|
|
||||||
ironing_params.extruder = config.top_surface_filament_id;
|
|
||||||
} else {
|
|
||||||
// Iron just the infill.
|
|
||||||
ironing_params.extruder = config.top_surface_filament_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ironing_params.extruder != -1) {
|
if (ironing_params.extruder != -1) {
|
||||||
//TODO just_infill is currently not used.
|
//TODO just_infill is currently not used.
|
||||||
ironing_params.just_infill = false;
|
ironing_params.just_infill = false;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ using LayerPtrs = std::vector<Layer*>;
|
|||||||
class LayerRegion;
|
class LayerRegion;
|
||||||
using LayerRegionPtrs = std::vector<LayerRegion*>;
|
using LayerRegionPtrs = std::vector<LayerRegion*>;
|
||||||
class PrintRegion;
|
class PrintRegion;
|
||||||
|
class PrintRegionConfig;
|
||||||
class PrintObject;
|
class PrintObject;
|
||||||
class Print;
|
class Print;
|
||||||
|
|
||||||
@@ -200,6 +201,11 @@ public:
|
|||||||
FillAdaptive::Octree *support_fill_octree,
|
FillAdaptive::Octree *support_fill_octree,
|
||||||
FillLightning::Generator* lightning_generator) const;
|
FillLightning::Generator* lightning_generator) const;
|
||||||
void make_ironing();
|
void make_ironing();
|
||||||
|
// Returns the filament id (1-based) the region is ironed with, or -1 when the
|
||||||
|
// region is not ironed.
|
||||||
|
static int choose_ironing_extruder(const PrintRegionConfig &cfg,
|
||||||
|
bool spiral_mode,
|
||||||
|
bool is_topmost_layer);
|
||||||
void make_contour_z(const sla::IndexedMesh &mesh);
|
void make_contour_z(const sla::IndexedMesh &mesh);
|
||||||
|
|
||||||
void export_region_slices_to_svg(const char *path) const;
|
void export_region_slices_to_svg(const char *path) const;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "libslic3r/Geometry.hpp"
|
#include "libslic3r/Geometry.hpp"
|
||||||
#include "libslic3r/Layer.hpp"
|
#include "libslic3r/Layer.hpp"
|
||||||
#include "libslic3r/Print.hpp"
|
#include "libslic3r/Print.hpp"
|
||||||
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
#include "libslic3r/SVG.hpp"
|
#include "libslic3r/SVG.hpp"
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
|
|
||||||
@@ -676,6 +677,73 @@ TEST_CASE("Ironing follows the solid infill rotation template", "[Fill]")
|
|||||||
REQUIRE(compared > int(ironing.size()) / 2);
|
REQUIRE(compared > int(ironing.size()) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
PrintRegionConfig ironing_config(IroningType type,
|
||||||
|
int top_surface_filament_id = 1,
|
||||||
|
int top_shell_layers = 3,
|
||||||
|
int bottom_shell_layers = 1)
|
||||||
|
{
|
||||||
|
PrintRegionConfig cfg;
|
||||||
|
cfg.ironing_type.value = type;
|
||||||
|
cfg.top_surface_filament_id.value = top_surface_filament_id;
|
||||||
|
cfg.top_shell_layers.value = top_shell_layers;
|
||||||
|
cfg.bottom_shell_layers.value = bottom_shell_layers;
|
||||||
|
cfg.outer_wall_filament_id.value = 1;
|
||||||
|
cfg.wall_loops.value = 2;
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("Ironing an all-solid region uses the top surface filament on every layer", "[Fill]")
|
||||||
|
{
|
||||||
|
const PrintRegionConfig cfg = ironing_config(IroningType::AllSolid, /*top_surface_filament_id=*/2);
|
||||||
|
const bool is_topmost_layer = GENERATE(false, true);
|
||||||
|
CAPTURE(is_topmost_layer);
|
||||||
|
REQUIRE(Layer::choose_ironing_extruder(cfg, /*spiral_mode=*/false, is_topmost_layer) == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Ironing top surfaces uses the top surface filament when the region has top shells", "[Fill]")
|
||||||
|
{
|
||||||
|
const PrintRegionConfig cfg = ironing_config(IroningType::TopSurfaces,
|
||||||
|
/*top_surface_filament_id=*/3,
|
||||||
|
/*top_shell_layers=*/2);
|
||||||
|
REQUIRE(Layer::choose_ironing_extruder(cfg, /*spiral_mode=*/false, /*is_topmost_layer=*/false) == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Ironing top surfaces without top shells needs spiral mode and more than one bottom shell", "[Fill]")
|
||||||
|
{
|
||||||
|
const PrintRegionConfig one_bottom_shell = ironing_config(IroningType::TopSurfaces,
|
||||||
|
/*top_surface_filament_id=*/1,
|
||||||
|
/*top_shell_layers=*/0,
|
||||||
|
/*bottom_shell_layers=*/1);
|
||||||
|
const PrintRegionConfig two_bottom_shells = ironing_config(IroningType::TopSurfaces,
|
||||||
|
/*top_surface_filament_id=*/1,
|
||||||
|
/*top_shell_layers=*/0,
|
||||||
|
/*bottom_shell_layers=*/2);
|
||||||
|
|
||||||
|
REQUIRE(Layer::choose_ironing_extruder(two_bottom_shells, /*spiral_mode=*/true, /*is_topmost_layer=*/false) == 1);
|
||||||
|
REQUIRE(Layer::choose_ironing_extruder(one_bottom_shell, /*spiral_mode=*/true, /*is_topmost_layer=*/false) == -1);
|
||||||
|
REQUIRE(Layer::choose_ironing_extruder(two_bottom_shells, /*spiral_mode=*/false, /*is_topmost_layer=*/false) == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Ironing the topmost surface only applies to the topmost layer", "[Fill]")
|
||||||
|
{
|
||||||
|
const PrintRegionConfig cfg = ironing_config(IroningType::TopmostOnly, /*top_surface_filament_id=*/4);
|
||||||
|
REQUIRE(Layer::choose_ironing_extruder(cfg, /*spiral_mode=*/false, /*is_topmost_layer=*/true) == 4);
|
||||||
|
REQUIRE(Layer::choose_ironing_extruder(cfg, /*spiral_mode=*/false, /*is_topmost_layer=*/false) == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("A region with ironing turned off is never ironed", "[Fill]")
|
||||||
|
{
|
||||||
|
const PrintRegionConfig cfg = ironing_config(IroningType::NoIroning);
|
||||||
|
const bool spiral_mode = GENERATE(false, true);
|
||||||
|
CAPTURE(spiral_mode);
|
||||||
|
REQUIRE(Layer::choose_ironing_extruder(cfg, spiral_mode, /*is_topmost_layer=*/true) == -1);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Solid infill direction offsets every layer when no template is set", "[Fill]")
|
TEST_CASE("Solid infill direction offsets every layer when no template is set", "[Fill]")
|
||||||
{
|
{
|
||||||
auto angles_for = [](int direction) {
|
auto angles_for = [](int direction) {
|
||||||
|
|||||||
Reference in New Issue
Block a user