diff options
author | Vojtech Bubnik <bubnikv@gmail.com> | 2021-06-01 12:10:12 +0300 |
---|---|---|
committer | Vojtech Bubnik <bubnikv@gmail.com> | 2021-06-01 12:10:12 +0300 |
commit | 20ba7c0a1f934430ecdd300bb25f2377e552cc38 (patch) | |
tree | b2a1f2c4ecdc74f827a9c72ecb91a01475605d0b /src/libslic3r | |
parent | df87f1b929cb9c041805062bc24a166e7897c602 (diff) |
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
Diffstat (limited to 'src/libslic3r')
-rw-r--r-- | src/libslic3r/ClipperUtils.cpp | 13 | ||||
-rw-r--r-- | src/libslic3r/ClipperUtils.hpp | 3 | ||||
-rw-r--r-- | src/libslic3r/Preset.cpp | 3 | ||||
-rw-r--r-- | src/libslic3r/PrintConfig.cpp | 41 | ||||
-rw-r--r-- | src/libslic3r/PrintConfig.hpp | 13 | ||||
-rw-r--r-- | src/libslic3r/PrintObject.cpp | 3 | ||||
-rw-r--r-- | src/libslic3r/PrintObjectSlice.cpp | 9 | ||||
-rw-r--r-- | src/libslic3r/SLAPrint.cpp | 4 | ||||
-rw-r--r-- | src/libslic3r/SLAPrintSteps.cpp | 13 | ||||
-rw-r--r-- | src/libslic3r/TriangleMeshSlicer.cpp | 18 | ||||
-rw-r--r-- | src/libslic3r/TriangleMeshSlicer.hpp | 7 |
11 files changed, 94 insertions, 33 deletions
diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index 7216c7509..3df287f1d 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -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,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); } 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); } -Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons& 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) + { 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) +Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject) { return PolyTreeToExPolygons(_clipper_do_polytree2(ClipperLib::ctUnion, ClipperUtils::SurfacesProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); } template<typename PathsProvider1, typename PathsProvider2> diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp index 061658086..aa606e7c0 100644 --- a/src/libslic3r/ClipperUtils.hpp +++ b/src/libslic3r/ClipperUtils.hpp @@ -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); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 3be867d53..6db4b4ee8 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -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", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 3fffe7f7d..7478ec068 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -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"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index a4a52f7d4..5991be7ab 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -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)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index e69edd051..eb46537ec 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -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" diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index 8d606ebea..6ec37ce24 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -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; diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 42ed8b80f..c0c65d39b 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -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); diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index 51e2430aa..94b4c57a4 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -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) { diff --git a/src/libslic3r/TriangleMeshSlicer.cpp b/src/libslic3r/TriangleMeshSlicer.cpp index 95f41ebf7..d08696ab3 100644 --- a/src/libslic3r/TriangleMeshSlicer.cpp +++ b/src/libslic3r/TriangleMeshSlicer.cpp @@ -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.) diff --git a/src/libslic3r/TriangleMeshSlicer.hpp b/src/libslic3r/TriangleMeshSlicer.hpp index f6ac698cc..344b42416 100644 --- a/src/libslic3r/TriangleMeshSlicer.hpp +++ b/src/libslic3r/TriangleMeshSlicer.hpp @@ -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. |