New parameter "Slicing Mode" for supporting 3DLabPrint airplane models.

S3D's strategy for merging self intersecting models is "Even / Odd"
which PrusaSlicer now supports as an alternative to "Positive" rule.
Also added a "Close Holes" option to fill in all internal structures.
3D-Labprint Models aren't sliceable (till years) #3062 #3708
This commit is contained in:
Vojtech Bubnik 2021-06-01 11:10:12 +02:00
parent df87f1b929
commit 20ba7c0a1f
12 changed files with 96 additions and 33 deletions

View file

@ -487,8 +487,8 @@ Slic3r::Polygons union_(const Slic3r::Polygons &subject, const Slic3r::Polygons
{ return _clipper(ClipperLib::ctUnion, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(subject2), ApplySafetyOffset::No); } { return _clipper(ClipperLib::ctUnion, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(subject2), ApplySafetyOffset::No); }
template <typename TSubject, typename TClip> template <typename TSubject, typename TClip>
static ExPolygons _clipper_ex(ClipperLib::ClipType clipType, TSubject &&subject, TClip &&clip, ApplySafetyOffset do_safety_offset) static ExPolygons _clipper_ex(ClipperLib::ClipType clipType, TSubject &&subject, TClip &&clip, ApplySafetyOffset do_safety_offset, ClipperLib::PolyFillType fill_type = ClipperLib::pftPositive)
{ return PolyTreeToExPolygons(_clipper_do_polytree2(clipType, std::forward<TSubject>(subject), std::forward<TClip>(clip), ClipperLib::pftNonZero, do_safety_offset)); } { return PolyTreeToExPolygons(_clipper_do_polytree2(clipType, std::forward<TSubject>(subject), std::forward<TClip>(clip), fill_type, do_safety_offset)); }
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset) Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); } { return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
@ -531,11 +531,12 @@ Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesProvider(subject), ClipperUtils::SurfacesProvider(clip), do_safety_offset); } { return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesProvider(subject), ClipperUtils::SurfacesProvider(clip), do_safety_offset); }
Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset) Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset)
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesPtrProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); } { return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesPtrProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject) // May be used to "heal" unusual models (3DLabPrints etc.) by providing fill_type (pftEvenOdd, pftNonZero, pftPositive, pftNegative).
{ return _clipper_ex(ClipperLib::ctUnion, ClipperUtils::PolygonsProvider(subject), ClipperUtils::EmptyPathsProvider(), ApplySafetyOffset::No); } Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, ClipperLib::PolyFillType fill_type)
Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons& subject) { return _clipper_ex(ClipperLib::ctUnion, ClipperUtils::PolygonsProvider(subject), ClipperUtils::EmptyPathsProvider(), ApplySafetyOffset::No, fill_type); }
Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject)
{ return PolyTreeToExPolygons(_clipper_do_polytree2(ClipperLib::ctUnion, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); } { return PolyTreeToExPolygons(_clipper_do_polytree2(ClipperLib::ctUnion, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); }
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces& subject) Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject)
{ return PolyTreeToExPolygons(_clipper_do_polytree2(ClipperLib::ctUnion, ClipperUtils::SurfacesProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); } { return PolyTreeToExPolygons(_clipper_do_polytree2(ClipperLib::ctUnion, ClipperUtils::SurfacesProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); }
template<typename PathsProvider1, typename PathsProvider2> template<typename PathsProvider1, typename PathsProvider2>

View file

@ -356,7 +356,8 @@ inline Slic3r::Lines intersection_ln(const Slic3r::Line &subject, const Slic3r::
Slic3r::Polygons union_(const Slic3r::Polygons &subject); Slic3r::Polygons union_(const Slic3r::Polygons &subject);
Slic3r::Polygons union_(const Slic3r::ExPolygons &subject); Slic3r::Polygons union_(const Slic3r::ExPolygons &subject);
Slic3r::Polygons union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2); Slic3r::Polygons union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2);
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject); // May be used to "heal" unusual models (3DLabPrints etc.) by providing fill_type (pftEvenOdd, pftNonZero, pftPositive, pftNegative).
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, ClipperLib::PolyFillType fill_type = ClipperLib::pftPositive);
Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject); Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject);
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject); Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject);

View file

@ -416,7 +416,7 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config)
const std::vector<std::string>& Preset::print_options() const std::vector<std::string>& Preset::print_options()
{ {
static std::vector<std::string> s_opts { static std::vector<std::string> s_opts {
"layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "slicing_mode",
"top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness", "top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness",
"extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs", "extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs",
"seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern", "seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern",
@ -543,6 +543,7 @@ const std::vector<std::string>& Preset::sla_print_options()
"support_points_density_relative", "support_points_density_relative",
"support_points_minimal_distance", "support_points_minimal_distance",
"slice_closing_radius", "slice_closing_radius",
"slicing_mode",
"pad_enable", "pad_enable",
"pad_wall_thickness", "pad_wall_thickness",
"pad_wall_height", "pad_wall_height",

View file

@ -116,6 +116,13 @@ static t_config_enum_values s_keys_map_IroningType {
}; };
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(IroningType) CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(IroningType)
static t_config_enum_values s_keys_map_SlicingMode {
{ "regular", int(SlicingMode::Regular) },
{ "even_odd", int(SlicingMode::EvenOdd) },
{ "close_holes", int(SlicingMode::CloseHoles) }
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SlicingMode)
static t_config_enum_values s_keys_map_SupportMaterialPattern { static t_config_enum_values s_keys_map_SupportMaterialPattern {
{ "rectilinear", smpRectilinear }, { "rectilinear", smpRectilinear },
{ "rectilinear-grid", smpRectilinearGrid }, { "rectilinear-grid", smpRectilinearGrid },
@ -235,16 +242,6 @@ void PrintConfigDef::init_common_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(200.0)); def->set_default_value(new ConfigOptionFloat(200.0));
def = this->add("slice_closing_radius", coFloat);
def->label = L("Slice gap closing radius");
def->category = L("Advanced");
def->tooltip = L("Cracks smaller than 2x gap closing radius are being filled during the triangle mesh slicing. "
"The gap closing operation may reduce the final print resolution, therefore it is advisable to keep the value reasonably low.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0.049));
def = this->add("print_host", coString); def = this->add("print_host", coString);
def->label = L("Hostname, IP or URL"); def->label = L("Hostname, IP or URL");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain " def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
@ -2359,6 +2356,30 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false)); def->set_default_value(new ConfigOptionBool(false));
def = this->add("slice_closing_radius", coFloat);
def->label = L("Slice gap closing radius");
def->category = L("Advanced");
def->tooltip = L("Cracks smaller than 2x gap closing radius are being filled during the triangle mesh slicing. "
"The gap closing operation may reduce the final print resolution, therefore it is advisable to keep the value reasonably low.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0.049));
def = this->add("slicing_mode", coEnum);
def->label = L("Slicing Mode");
def->category = L("Advanced");
def->tooltip = L("Use \"Even / Odd\" for 3DLabPrint airplane models. Use \"Close holes\" to close all holes in the model.");
def->enum_keys_map = &ConfigOptionEnum<SlicingMode>::get_enum_values();
def->enum_values.push_back("regular");
def->enum_values.push_back("even_odd");
def->enum_values.push_back("close_holes");
def->enum_labels.push_back(L("Regular"));
def->enum_labels.push_back(L("Even / Odd"));
def->enum_labels.push_back(L("Close holes"));
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<SlicingMode>(SlicingMode::Regular));
def = this->add("support_material", coBool); def = this->add("support_material", coBool);
def->label = L("Generate support material"); def->label = L("Generate support material");
def->category = L("Support material"); def->category = L("Support material");

View file

@ -69,6 +69,16 @@ enum class IroningType {
Count, Count,
}; };
enum class SlicingMode
{
// Regular, applying ClipperLib::pftPositive rule when creating ExPolygons.
Regular,
// Compatible with 3DLabPrint models, applying ClipperLib::pftEvenOdd rule when creating ExPolygons.
EvenOdd,
// Orienting all contours CCW, thus closing all holes.
CloseHoles,
};
enum SupportMaterialPattern { enum SupportMaterialPattern {
smpRectilinear, smpRectilinearGrid, smpHoneycomb, smpRectilinear, smpRectilinearGrid, smpHoneycomb,
}; };
@ -123,6 +133,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(FuzzySkinType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(FuzzySkinType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(InfillPattern) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(InfillPattern)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(IroningType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(IroningType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SlicingMode)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SupportMaterialPattern) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SupportMaterialPattern)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SupportMaterialStyle) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SupportMaterialStyle)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SupportMaterialInterfacePattern) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SupportMaterialInterfacePattern)
@ -453,6 +464,7 @@ PRINT_CONFIG_CLASS_DEFINE(
// ((ConfigOptionFloat, seam_preferred_direction)) // ((ConfigOptionFloat, seam_preferred_direction))
// ((ConfigOptionFloat, seam_preferred_direction_jitter)) // ((ConfigOptionFloat, seam_preferred_direction_jitter))
((ConfigOptionFloat, slice_closing_radius)) ((ConfigOptionFloat, slice_closing_radius))
((ConfigOptionEnum<SlicingMode>, slicing_mode))
((ConfigOptionBool, support_material)) ((ConfigOptionBool, support_material))
// Automatic supports (generated based on support_material_threshold). // Automatic supports (generated based on support_material_threshold).
((ConfigOptionBool, support_material_auto)) ((ConfigOptionBool, support_material_auto))
@ -758,6 +770,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, faded_layers))/*= 10*/ ((ConfigOptionInt, faded_layers))/*= 10*/
((ConfigOptionFloat, slice_closing_radius)) ((ConfigOptionFloat, slice_closing_radius))
((ConfigOptionEnum<SlicingMode>, slicing_mode))
// Enabling or disabling support creation // Enabling or disabling support creation
((ConfigOptionBool, supports_enable)) ((ConfigOptionBool, supports_enable))

View file

@ -525,7 +525,8 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "mmu_segmented_region_max_width" || opt_key == "mmu_segmented_region_max_width"
|| opt_key == "raft_layers" || opt_key == "raft_layers"
|| opt_key == "raft_contact_distance" || opt_key == "raft_contact_distance"
|| opt_key == "slice_closing_radius") { || opt_key == "slice_closing_radius"
|| opt_key == "slicing_mode") {
steps.emplace_back(posSlice); steps.emplace_back(posSlice);
} else if ( } else if (
opt_key == "clip_multipart_objects" opt_key == "clip_multipart_objects"

View file

@ -169,6 +169,14 @@ static std::vector<VolumeSlices> slice_volumes_inner(
params_base.trafo = object_trafo; params_base.trafo = object_trafo;
params_base.resolution = print_config.resolution.value; params_base.resolution = print_config.resolution.value;
switch (print_object_config.slicing_mode.value) {
case SlicingMode::Regular: params_base.mode = MeshSlicingParams::SlicingMode::Regular; break;
case SlicingMode::EvenOdd: params_base.mode = MeshSlicingParams::SlicingMode::EvenOdd; break;
case SlicingMode::CloseHoles: params_base.mode = MeshSlicingParams::SlicingMode::Positive; break;
}
params_base.mode_below = params_base.mode;
const auto extra_offset = std::max(0.f, float(print_object_config.xy_size_compensation.value)); const auto extra_offset = std::max(0.f, float(print_object_config.xy_size_compensation.value));
for (const ModelVolume *model_volume : model_volumes) for (const ModelVolume *model_volume : model_volumes)
@ -184,7 +192,6 @@ static std::vector<VolumeSlices> slice_volumes_inner(
params.mode = MeshSlicingParams::SlicingMode::PositiveLargestContour; params.mode = MeshSlicingParams::SlicingMode::PositiveLargestContour;
// Slice the bottom layers with SlicingMode::Regular. // Slice the bottom layers with SlicingMode::Regular.
// This needs to be in sync with LayerRegion::make_perimeters() spiral_vase! // This needs to be in sync with LayerRegion::make_perimeters() spiral_vase!
params.mode_below = MeshSlicingParams::SlicingMode::Regular;
const PrintRegionConfig &region_config = it->region->config(); const PrintRegionConfig &region_config = it->region->config();
params.slicing_mode_normal_below_layer = size_t(region_config.bottom_solid_layers.value); params.slicing_mode_normal_below_layer = size_t(region_config.bottom_solid_layers.value);
for (; params.slicing_mode_normal_below_layer < zs.size() && zs[params.slicing_mode_normal_below_layer] < region_config.bottom_solid_min_thickness - EPSILON; for (; params.slicing_mode_normal_below_layer < zs.size() && zs[params.slicing_mode_normal_below_layer] < region_config.bottom_solid_min_thickness - EPSILON;

View file

@ -930,10 +930,10 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|| opt_key == "support_object_elevation" || opt_key == "support_object_elevation"
|| opt_key == "pad_around_object" || opt_key == "pad_around_object"
|| opt_key == "pad_around_object_everywhere" || opt_key == "pad_around_object_everywhere"
|| opt_key == "slice_closing_radius") { || opt_key == "slice_closing_radius"
|| opt_key == "slicing_mode") {
steps.emplace_back(slaposObjectSlice); steps.emplace_back(slaposObjectSlice);
} else if ( } else if (
opt_key == "support_points_density_relative" opt_key == "support_points_density_relative"
|| opt_key == "support_points_minimal_distance") { || opt_key == "support_points_minimal_distance") {
steps.emplace_back(slaposSupportPoints); steps.emplace_back(slaposSupportPoints);

View file

@ -472,11 +472,17 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
po.m_model_height_levels.emplace_back(it->slice_level()); po.m_model_height_levels.emplace_back(it->slice_level());
po.m_model_slices.clear(); po.m_model_slices.clear();
float closing_r = float(po.config().slice_closing_radius.value); MeshSlicingParamsEx params;
params.closing_radius = float(po.config().slice_closing_radius.value);
switch (po.config().slicing_mode.value) {
case SlicingMode::Regular: params.mode = MeshSlicingParams::SlicingMode::Regular; break;
case SlicingMode::EvenOdd: params.mode = MeshSlicingParams::SlicingMode::EvenOdd; break;
case SlicingMode::CloseHoles: params.mode = MeshSlicingParams::SlicingMode::Positive; break;
}
auto thr = [this]() { m_print->throw_if_canceled(); }; auto thr = [this]() { m_print->throw_if_canceled(); };
auto &slice_grid = po.m_model_height_levels; auto &slice_grid = po.m_model_height_levels;
assert(mesh.has_shared_vertices()); assert(mesh.has_shared_vertices());
po.m_model_slices = slice_mesh_ex(mesh.its, slice_grid, closing_r, thr); po.m_model_slices = slice_mesh_ex(mesh.its, slice_grid, params, thr);
sla::Interior *interior = po.m_hollowing_data ? sla::Interior *interior = po.m_hollowing_data ?
po.m_hollowing_data->interior.get() : po.m_hollowing_data->interior.get() :
@ -486,7 +492,8 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
TriangleMesh interiormesh = sla::get_mesh(*interior); TriangleMesh interiormesh = sla::get_mesh(*interior);
interiormesh.repaired = false; interiormesh.repaired = false;
interiormesh.repair(true); interiormesh.repair(true);
std::vector<ExPolygons> interior_slices = slice_mesh_ex(interiormesh.its, slice_grid, closing_r, thr); params.mode = MeshSlicingParams::SlicingMode::Regular;
std::vector<ExPolygons> interior_slices = slice_mesh_ex(interiormesh.its, slice_grid, params, thr);
sla::ccr::for_each(size_t(0), interior_slices.size(), sla::ccr::for_each(size_t(0), interior_slices.size(),
[&po, &interior_slices] (size_t i) { [&po, &interior_slices] (size_t i) {

View file

@ -967,7 +967,7 @@ static ExPolygons make_expolygons_simple(std::vector<IntersectionLine> &lines)
return slices; return slices;
} }
static void make_expolygons(const Polygons &loops, const float closing_radius, const float extra_offset, ExPolygons* slices) static void make_expolygons(const Polygons &loops, const float closing_radius, const float extra_offset, ClipperLib::PolyFillType fill_type, ExPolygons* slices)
{ {
/* /*
Input loops are not suitable for evenodd nor nonzero fill types, as we might get Input loops are not suitable for evenodd nor nonzero fill types, as we might get
@ -1049,10 +1049,10 @@ static void make_expolygons(const Polygons &loops, const float closing_radius, c
// append to the supplied collection // append to the supplied collection
expolygons_append(*slices, expolygons_append(*slices,
offset_out > 0 && offset_in < 0 ? offset2_ex(union_ex(loops), offset_out, offset_in) : offset_out > 0 && offset_in < 0 ? offset2_ex(union_ex(loops, fill_type), offset_out, offset_in) :
offset_out > 0 ? offset_ex(union_ex(loops), offset_out) : offset_out > 0 ? offset_ex(union_ex(loops, fill_type), offset_out) :
offset_in < 0 ? offset_ex(union_ex(loops), offset_in) : offset_in < 0 ? offset_ex(union_ex(loops, fill_type), offset_in) :
union_ex(loops)); union_ex(loops, fill_type));
} }
std::vector<Polygons> slice_mesh( std::vector<Polygons> slice_mesh(
@ -1175,9 +1175,13 @@ std::vector<ExPolygons> slice_mesh_ex(
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) { for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
throw_on_cancel(); throw_on_cancel();
ExPolygons &expolygons = layers[layer_id]; ExPolygons &expolygons = layers[layer_id];
Slic3r::make_expolygons(layers_p[layer_id], params.closing_radius, params.extra_offset, &expolygons);
//FIXME simplify
const auto this_mode = layer_id < params.slicing_mode_normal_below_layer ? params.mode_below : params.mode; const auto this_mode = layer_id < params.slicing_mode_normal_below_layer ? params.mode_below : params.mode;
Slic3r::make_expolygons(
layers_p[layer_id], params.closing_radius, params.extra_offset,
this_mode == MeshSlicingParams::SlicingMode::EvenOdd ? ClipperLib::pftEvenOdd :
this_mode == MeshSlicingParams::SlicingMode::PositiveLargestContour ? ClipperLib::pftNonZero : ClipperLib::pftPositive,
&expolygons);
//FIXME simplify
if (this_mode == MeshSlicingParams::SlicingMode::PositiveLargestContour) if (this_mode == MeshSlicingParams::SlicingMode::PositiveLargestContour)
keep_largest_contour_only(expolygons); keep_largest_contour_only(expolygons);
if (resolution != 0.) if (resolution != 0.)

View file

@ -12,8 +12,13 @@ struct MeshSlicingParams
{ {
enum class SlicingMode : uint32_t { enum class SlicingMode : uint32_t {
// Regular slicing, maintain all contours and their orientation. // Regular slicing, maintain all contours and their orientation.
// slice_mesh_ex() applies ClipperLib::pftPositive rule to the result of slice_mesh().
Regular, Regular,
// Maintain all contours, orient all contours CCW, therefore all holes are being closed. // For slicing 3DLabPrints plane models (aka to be compatible with S3D default strategy).
// slice_mesh_ex() applies ClipperLib::pftEvenOdd rule. slice_mesh() slices EvenOdd as Regular.
EvenOdd,
// Maintain all contours, orient all contours CCW.
// slice_mesh_ex() applies ClipperLib::pftPositive rule, thus holes will be closed.
Positive, Positive,
// Orient all contours CCW and keep only the contour with the largest area. // Orient all contours CCW and keep only the contour with the largest area.
// This mode is useful for slicing complex objects in vase mode. // This mode is useful for slicing complex objects in vase mode.

View file

@ -1610,6 +1610,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(L("Slicing")); optgroup = page->new_optgroup(L("Slicing"));
optgroup->append_single_option_line("slice_closing_radius"); optgroup->append_single_option_line("slice_closing_radius");
optgroup->append_single_option_line("slicing_mode");
optgroup->append_single_option_line("resolution"); optgroup->append_single_option_line("resolution");
optgroup->append_single_option_line("xy_size_compensation"); optgroup->append_single_option_line("xy_size_compensation");
optgroup->append_single_option_line("elefant_foot_compensation", "elephant-foot-compensation_114487"); optgroup->append_single_option_line("elefant_foot_compensation", "elephant-foot-compensation_114487");
@ -4318,6 +4319,7 @@ void TabSLAPrint::build()
page = add_options_page(L("Advanced"), "wrench"); page = add_options_page(L("Advanced"), "wrench");
optgroup = page->new_optgroup(L("Slicing")); optgroup = page->new_optgroup(L("Slicing"));
optgroup->append_single_option_line("slice_closing_radius"); optgroup->append_single_option_line("slice_closing_radius");
optgroup->append_single_option_line("slicing_mode");
page = add_options_page(L("Output options"), "output+page_white"); page = add_options_page(L("Output options"), "output+page_white");
optgroup = page->new_optgroup(L("Output file")); optgroup = page->new_optgroup(L("Output file"));