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:
parent
df87f1b929
commit
20ba7c0a1f
12 changed files with 96 additions and 33 deletions
|
@ -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); }
|
||||
|
||||
template <typename TSubject, typename TClip>
|
||||
static ExPolygons _clipper_ex(ClipperLib::ClipType clipType, TSubject &&subject, TClip &&clip, ApplySafetyOffset do_safety_offset)
|
||||
{ return PolyTreeToExPolygons(_clipper_do_polytree2(clipType, std::forward<TSubject>(subject), std::forward<TClip>(clip), ClipperLib::pftNonZero, 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), fill_type, 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); }
|
||||
|
@ -531,8 +531,9 @@ Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r
|
|||
{ 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)
|
||||
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesPtrProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
|
||||
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject)
|
||||
{ return _clipper_ex(ClipperLib::ctUnion, ClipperUtils::PolygonsProvider(subject), ClipperUtils::EmptyPathsProvider(), ApplySafetyOffset::No); }
|
||||
// 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)
|
||||
{ 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)); }
|
||||
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject)
|
||||
|
|
|
@ -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::ExPolygons &subject);
|
||||
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::Surfaces &subject);
|
||||
|
||||
|
|
|
@ -416,7 +416,7 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config)
|
|||
const std::vector<std::string>& Preset::print_options()
|
||||
{
|
||||
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",
|
||||
"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",
|
||||
|
@ -543,6 +543,7 @@ const std::vector<std::string>& Preset::sla_print_options()
|
|||
"support_points_density_relative",
|
||||
"support_points_minimal_distance",
|
||||
"slice_closing_radius",
|
||||
"slicing_mode",
|
||||
"pad_enable",
|
||||
"pad_wall_thickness",
|
||||
"pad_wall_height",
|
||||
|
|
|
@ -116,6 +116,13 @@ static t_config_enum_values s_keys_map_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 {
|
||||
{ "rectilinear", smpRectilinear },
|
||||
{ "rectilinear-grid", smpRectilinearGrid },
|
||||
|
@ -235,16 +242,6 @@ void PrintConfigDef::init_common_params()
|
|||
def->mode = comAdvanced;
|
||||
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->label = L("Hostname, IP or URL");
|
||||
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->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->label = L("Generate support material");
|
||||
def->category = L("Support material");
|
||||
|
|
|
@ -69,6 +69,16 @@ enum class IroningType {
|
|||
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 {
|
||||
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(InfillPattern)
|
||||
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(SupportMaterialStyle)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SupportMaterialInterfacePattern)
|
||||
|
@ -453,6 +464,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
// ((ConfigOptionFloat, seam_preferred_direction))
|
||||
// ((ConfigOptionFloat, seam_preferred_direction_jitter))
|
||||
((ConfigOptionFloat, slice_closing_radius))
|
||||
((ConfigOptionEnum<SlicingMode>, slicing_mode))
|
||||
((ConfigOptionBool, support_material))
|
||||
// Automatic supports (generated based on support_material_threshold).
|
||||
((ConfigOptionBool, support_material_auto))
|
||||
|
@ -758,6 +770,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionInt, faded_layers))/*= 10*/
|
||||
|
||||
((ConfigOptionFloat, slice_closing_radius))
|
||||
((ConfigOptionEnum<SlicingMode>, slicing_mode))
|
||||
|
||||
// Enabling or disabling support creation
|
||||
((ConfigOptionBool, supports_enable))
|
||||
|
|
|
@ -525,7 +525,8 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
|| opt_key == "mmu_segmented_region_max_width"
|
||||
|| opt_key == "raft_layers"
|
||||
|| opt_key == "raft_contact_distance"
|
||||
|| opt_key == "slice_closing_radius") {
|
||||
|| opt_key == "slice_closing_radius"
|
||||
|| opt_key == "slicing_mode") {
|
||||
steps.emplace_back(posSlice);
|
||||
} else if (
|
||||
opt_key == "clip_multipart_objects"
|
||||
|
|
|
@ -169,6 +169,14 @@ static std::vector<VolumeSlices> slice_volumes_inner(
|
|||
params_base.trafo = object_trafo;
|
||||
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));
|
||||
|
||||
for (const ModelVolume *model_volume : model_volumes)
|
||||
|
@ -184,7 +192,6 @@ static std::vector<VolumeSlices> slice_volumes_inner(
|
|||
params.mode = MeshSlicingParams::SlicingMode::PositiveLargestContour;
|
||||
// Slice the bottom layers with SlicingMode::Regular.
|
||||
// This needs to be in sync with LayerRegion::make_perimeters() spiral_vase!
|
||||
params.mode_below = MeshSlicingParams::SlicingMode::Regular;
|
||||
const PrintRegionConfig ®ion_config = it->region->config();
|
||||
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;
|
||||
|
|
|
@ -930,10 +930,10 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
|||
|| opt_key == "support_object_elevation"
|
||||
|| opt_key == "pad_around_object"
|
||||
|| opt_key == "pad_around_object_everywhere"
|
||||
|| opt_key == "slice_closing_radius") {
|
||||
|| opt_key == "slice_closing_radius"
|
||||
|| opt_key == "slicing_mode") {
|
||||
steps.emplace_back(slaposObjectSlice);
|
||||
} else if (
|
||||
|
||||
opt_key == "support_points_density_relative"
|
||||
|| opt_key == "support_points_minimal_distance") {
|
||||
steps.emplace_back(slaposSupportPoints);
|
||||
|
|
|
@ -472,11 +472,17 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
|||
po.m_model_height_levels.emplace_back(it->slice_level());
|
||||
|
||||
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 &slice_grid = po.m_model_height_levels;
|
||||
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 ?
|
||||
po.m_hollowing_data->interior.get() :
|
||||
|
@ -486,7 +492,8 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
|||
TriangleMesh interiormesh = sla::get_mesh(*interior);
|
||||
interiormesh.repaired = false;
|
||||
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(),
|
||||
[&po, &interior_slices] (size_t i) {
|
||||
|
|
|
@ -967,7 +967,7 @@ static ExPolygons make_expolygons_simple(std::vector<IntersectionLine> &lines)
|
|||
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
|
||||
|
@ -1049,10 +1049,10 @@ static void make_expolygons(const Polygons &loops, const float closing_radius, c
|
|||
|
||||
// append to the supplied collection
|
||||
expolygons_append(*slices,
|
||||
offset_out > 0 && offset_in < 0 ? offset2_ex(union_ex(loops), offset_out, offset_in) :
|
||||
offset_out > 0 ? offset_ex(union_ex(loops), offset_out) :
|
||||
offset_in < 0 ? offset_ex(union_ex(loops), offset_in) :
|
||||
union_ex(loops));
|
||||
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, fill_type), offset_out) :
|
||||
offset_in < 0 ? offset_ex(union_ex(loops, fill_type), offset_in) :
|
||||
union_ex(loops, fill_type));
|
||||
}
|
||||
|
||||
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) {
|
||||
throw_on_cancel();
|
||||
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;
|
||||
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)
|
||||
keep_largest_contour_only(expolygons);
|
||||
if (resolution != 0.)
|
||||
|
|
|
@ -12,8 +12,13 @@ struct MeshSlicingParams
|
|||
{
|
||||
enum class SlicingMode : uint32_t {
|
||||
// Regular slicing, maintain all contours and their orientation.
|
||||
// slice_mesh_ex() applies ClipperLib::pftPositive rule to the result of slice_mesh().
|
||||
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,
|
||||
// Orient all contours CCW and keep only the contour with the largest area.
|
||||
// This mode is useful for slicing complex objects in vase mode.
|
||||
|
|
|
@ -1610,6 +1610,7 @@ void TabPrint::build()
|
|||
|
||||
optgroup = page->new_optgroup(L("Slicing"));
|
||||
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("xy_size_compensation");
|
||||
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");
|
||||
optgroup = page->new_optgroup(L("Slicing"));
|
||||
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");
|
||||
optgroup = page->new_optgroup(L("Output file"));
|
||||
|
|
Loading…
Reference in a new issue