mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-30 14:22:07 +00:00
fix: multi-material slicing crash with line width 0 (#14455)
This commit is contained in:
@@ -1177,6 +1177,18 @@ static bool is_volume_sinking(const indexed_triangle_set &its, const Transform3d
|
|||||||
|
|
||||||
//#define MMU_SEGMENTATION_DEBUG_TOP_BOTTOM
|
//#define MMU_SEGMENTATION_DEBUG_TOP_BOTTOM
|
||||||
|
|
||||||
|
double resolve_outer_wall_line_width(const PrintRegionConfig ®ion_config, const PrintObjectConfig &object_config, const PrintConfig &print_config)
|
||||||
|
{
|
||||||
|
// A filament id of 0 underflows, and get_at() then falls back to the first nozzle.
|
||||||
|
const double nozzle_diameter = print_config.nozzle_diameter.get_at(region_config.outer_wall_filament_id - 1);
|
||||||
|
ConfigOptionFloatOrPercent width = region_config.outer_wall_line_width;
|
||||||
|
if (width.value == 0)
|
||||||
|
width = object_config.line_width;
|
||||||
|
if (!width.percent && width.value <= 0.)
|
||||||
|
return Flow::auto_extrusion_width(frExternalPerimeter, float(nozzle_diameter));
|
||||||
|
return width.get_abs_value(nozzle_diameter);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns segmentation of top and bottom layers based on painting in segmentation gizmos.
|
// Returns segmentation of top and bottom layers based on painting in segmentation gizmos.
|
||||||
static inline std::vector<std::vector<ExPolygons>> segmentation_top_and_bottom_layers(const PrintObject &print_object,
|
static inline std::vector<std::vector<ExPolygons>> segmentation_top_and_bottom_layers(const PrintObject &print_object,
|
||||||
const std::vector<ExPolygons> &input_expolygons,
|
const std::vector<ExPolygons> &input_expolygons,
|
||||||
@@ -1347,8 +1359,7 @@ static inline std::vector<std::vector<ExPolygons>> segmentation_top_and_bottom_l
|
|||||||
// As this region may split existing regions, we collect statistics over all regions for color_idx == 0.
|
// As this region may split existing regions, we collect statistics over all regions for color_idx == 0.
|
||||||
color_idx == 0 || config.outer_wall_filament_id == int(color_idx)) {
|
color_idx == 0 || config.outer_wall_filament_id == int(color_idx)) {
|
||||||
//BBS: the extrusion line width is outer wall rather than inner wall
|
//BBS: the extrusion line width is outer wall rather than inner wall
|
||||||
const double nozzle_diameter = print_object.print()->config().nozzle_diameter.get_at(0);
|
double outer_wall_line_width = resolve_outer_wall_line_width(config, print_object.config(), print_object.print()->config());
|
||||||
double outer_wall_line_width = config.get_abs_value("outer_wall_line_width", nozzle_diameter);
|
|
||||||
out.extrusion_width = std::max<float>(out.extrusion_width, outer_wall_line_width);
|
out.extrusion_width = std::max<float>(out.extrusion_width, outer_wall_line_width);
|
||||||
out.top_shell_layers = std::max<int>(out.top_shell_layers, config.top_shell_layers);
|
out.top_shell_layers = std::max<int>(out.top_shell_layers, config.top_shell_layers);
|
||||||
out.bottom_shell_layers = std::max<int>(out.bottom_shell_layers, config.bottom_shell_layers);
|
out.bottom_shell_layers = std::max<int>(out.bottom_shell_layers, config.bottom_shell_layers);
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ namespace Slic3r {
|
|||||||
class ExPolygon;
|
class ExPolygon;
|
||||||
class ModelVolume;
|
class ModelVolume;
|
||||||
class PrintObject;
|
class PrintObject;
|
||||||
|
class PrintConfig;
|
||||||
|
class PrintObjectConfig;
|
||||||
|
class PrintRegionConfig;
|
||||||
class FacetsAnnotation;
|
class FacetsAnnotation;
|
||||||
|
|
||||||
using ExPolygons = std::vector<ExPolygon>;
|
using ExPolygons = std::vector<ExPolygon>;
|
||||||
@@ -52,6 +55,9 @@ std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(con
|
|||||||
// Returns fuzzy skin segmentation based on painting in fuzzy skin segmentation gizmo
|
// Returns fuzzy skin segmentation based on painting in fuzzy skin segmentation gizmo
|
||||||
std::vector<std::vector<ExPolygons>> fuzzy_skin_segmentation_by_painting(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback);
|
std::vector<std::vector<ExPolygons>> fuzzy_skin_segmentation_by_painting(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback);
|
||||||
|
|
||||||
|
// Effective outer-wall line width for a region, resolved against its own nozzle with PrintRegion::flow's fallback.
|
||||||
|
double resolve_outer_wall_line_width(const PrintRegionConfig ®ion_config, const PrintObjectConfig &object_config, const PrintConfig &print_config);
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
namespace boost::polygon {
|
namespace boost::polygon {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ add_executable(${_TEST_NAME}_tests
|
|||||||
test_preset_diff.cpp
|
test_preset_diff.cpp
|
||||||
test_elephant_foot_compensation.cpp
|
test_elephant_foot_compensation.cpp
|
||||||
test_geometry.cpp
|
test_geometry.cpp
|
||||||
|
test_multimaterial_segmentation.cpp
|
||||||
test_placeholder_parser.cpp
|
test_placeholder_parser.cpp
|
||||||
test_polygon.cpp
|
test_polygon.cpp
|
||||||
test_mutable_polygon.cpp
|
test_mutable_polygon.cpp
|
||||||
|
|||||||
57
tests/libslic3r/test_multimaterial_segmentation.cpp
Normal file
57
tests/libslic3r/test_multimaterial_segmentation.cpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include <catch2/catch_all.hpp>
|
||||||
|
|
||||||
|
// MultiMaterialSegmentation.hpp declares boost::polygon traits for ColoredLine, so its
|
||||||
|
// geometry/boost dependencies must be included first.
|
||||||
|
#include <boost/polygon/polygon.hpp>
|
||||||
|
#include "libslic3r/Line.hpp"
|
||||||
|
#include "libslic3r/Flow.hpp"
|
||||||
|
#include "libslic3r/MultiMaterialSegmentation.hpp"
|
||||||
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
|
|
||||||
|
TEST_CASE("Multi-material segmentation resolves the outer-wall line width", "[MultiMaterialSegmentation][Regression]")
|
||||||
|
{
|
||||||
|
struct Case
|
||||||
|
{
|
||||||
|
std::string description;
|
||||||
|
double outer_value;
|
||||||
|
bool outer_percent;
|
||||||
|
double line_value;
|
||||||
|
bool line_percent;
|
||||||
|
std::vector<double> nozzle_diameters;
|
||||||
|
int outer_wall_filament_id;
|
||||||
|
double expected;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto c = GENERATE(values<Case>({
|
||||||
|
{"absolute outer-wall width is used as-is", 0.6, false, 0.42, false, {0.4}, 1, 0.6},
|
||||||
|
{"percent outer-wall width uses the nozzle", 120, true, 0.42, false, {0.5}, 1, 0.6},
|
||||||
|
{"zero outer-wall width uses the line width", 0, false, 0.5, false, {0.4}, 1, 0.5},
|
||||||
|
{"zero outer-wall width uses a percent line", 0, false, 100, true, {0.5}, 1, 0.5},
|
||||||
|
{"zero width falls back to auto", 0, false, 0, false, {0.4}, 1, Flow::auto_extrusion_width(frExternalPerimeter, 0.4)},
|
||||||
|
{"the auto fallback scales with the nozzle", 0, false, 0, false, {0.6}, 1, Flow::auto_extrusion_width(frExternalPerimeter, 0.6)},
|
||||||
|
{"a percent width uses the outer wall's nozzle", 120, true, 0.42, false, {0.4, 0.8}, 2, 0.96},
|
||||||
|
{"the auto width uses the outer wall's nozzle", 0, false, 0, false, {0.4, 0.8}, 2, Flow::auto_extrusion_width(frExternalPerimeter, 0.8)},
|
||||||
|
{"an absolute width ignores the nozzle", 0.6, false, 0.42, false, {0.4, 0.8}, 2, 0.6},
|
||||||
|
{"a zero percent width uses the line width", 0, true, 0.5, false, {0.4}, 1, 0.5},
|
||||||
|
{"an unset filament id uses the first nozzle", 0, false, 0, false, {0.4, 0.8}, 0, Flow::auto_extrusion_width(frExternalPerimeter, 0.4)},
|
||||||
|
{"an out-of-range filament id uses nozzle 1", 0, false, 0, false, {0.4, 0.8}, 5, Flow::auto_extrusion_width(frExternalPerimeter, 0.4)},
|
||||||
|
}));
|
||||||
|
|
||||||
|
DYNAMIC_SECTION(c.description)
|
||||||
|
{
|
||||||
|
PrintConfig print_config;
|
||||||
|
print_config.nozzle_diameter.values = c.nozzle_diameters;
|
||||||
|
|
||||||
|
PrintObjectConfig object_config;
|
||||||
|
object_config.line_width = ConfigOptionFloatOrPercent(c.line_value, c.line_percent);
|
||||||
|
|
||||||
|
PrintRegionConfig region_config;
|
||||||
|
region_config.outer_wall_line_width = ConfigOptionFloatOrPercent(c.outer_value, c.outer_percent);
|
||||||
|
region_config.outer_wall_filament_id.value = c.outer_wall_filament_id;
|
||||||
|
|
||||||
|
REQUIRE_THAT(resolve_outer_wall_line_width(region_config, object_config, print_config),
|
||||||
|
Catch::Matchers::WithinAbs(c.expected, 1e-9));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user