diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 7d1af094d..081057f88 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -59,6 +59,17 @@ void PrintConfigDef::init_common_params() def->cli = "max-print-height=f"; def->mode = comAdvanced; def->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->cli = "slice-closing-radius=f"; + def->min = 0; + def->mode = comAdvanced; + def->default_value = new ConfigOptionFloat(0.049); } void PrintConfigDef::init_fff_params() diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 9b6f72391..d72c48339 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -384,6 +384,7 @@ public: ConfigOptionEnum<SeamPosition> seam_position; // ConfigOptionFloat seam_preferred_direction; // ConfigOptionFloat seam_preferred_direction_jitter; + ConfigOptionFloat slice_closing_radius; ConfigOptionBool support_material; // Automatic supports (generated based on support_material_threshold). ConfigOptionBool support_material_auto; @@ -425,6 +426,7 @@ protected: OPT_PTR(layer_height); OPT_PTR(raft_layers); OPT_PTR(seam_position); + OPT_PTR(slice_closing_radius); // OPT_PTR(seam_preferred_direction); // OPT_PTR(seam_preferred_direction_jitter); OPT_PTR(support_material); @@ -963,6 +965,8 @@ public: //Number of the layers needed for the exposure time fade [3;20] ConfigOptionInt faded_layers /*= 10*/; + ConfigOptionFloat slice_closing_radius; + // Enabling or disabling support creation ConfigOptionBool supports_enable; @@ -1036,6 +1040,7 @@ protected: { OPT_PTR(layer_height); OPT_PTR(faded_layers); + OPT_PTR(slice_closing_radius); OPT_PTR(supports_enable); OPT_PTR(support_head_front_diameter); OPT_PTR(support_head_penetration); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 8fa143681..55eba0931 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -453,7 +453,8 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_ } else if ( opt_key == "layer_height" || opt_key == "first_layer_height" - || opt_key == "raft_layers") { + || opt_key == "raft_layers" + || opt_key == "slice_closing_radius") { steps.emplace_back(posSlice); } else if ( @@ -1643,7 +1644,7 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z, const Print *print = this->print(); auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();}); mslicer.init(&mesh, callback); - mslicer.slice(z, &layers, callback); + mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback); m_print->throw_if_canceled(); } } diff --git a/src/libslic3r/SLA/SLABasePool.cpp b/src/libslic3r/SLA/SLABasePool.cpp index 62d8f0f30..6fd218402 100644 --- a/src/libslic3r/SLA/SLABasePool.cpp +++ b/src/libslic3r/SLA/SLABasePool.cpp @@ -561,7 +561,7 @@ void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h, heights.emplace_back(hi); std::vector<ExPolygons> out; out.reserve(size_t(std::ceil(h/layerh))); - slicer.slice(heights, &out, thrfn); + slicer.slice(heights, 0.f, &out, thrfn); size_t count = 0; for(auto& o : out) count += o.size(); diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index 913e9beda..0ba09ead8 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -2105,7 +2105,7 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const fullmesh.merge(get_pad()); TriangleMeshSlicer slicer(&fullmesh); SlicedSupports ret; - slicer.slice(heights, &ret, get().ctl().cancelfn); + slicer.slice(heights, 0.f, &ret, get().ctl().cancelfn); return ret; } diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 8ce306869..8bfef55d6 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -625,7 +625,7 @@ void SLAPrint::process() ilh, float(lh)); auto& layers = po.m_model_slices; layers.clear(); - slicer.slice(heights, &layers, [this](){ throw_if_canceled(); }); + slicer.slice(heights, float(po.config().slice_closing_radius.value), &layers, [this](){ throw_if_canceled(); }); }; // In this step we check the slices, identify island and cover them with @@ -1358,7 +1358,8 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf bool invalidated = false; for (const t_config_option_key &opt_key : opt_keys) { if ( opt_key == "layer_height" - || opt_key == "faded_layers") { + || opt_key == "faded_layers" + || opt_key == "slice_closing_radius") { steps.emplace_back(slaposObjectSlice); } else if ( opt_key == "supports_enable" diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 0784b44f2..f75bd7fa9 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -852,7 +852,7 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLin } } -void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const +void TriangleMeshSlicer::slice(const std::vector<float> &z, const float closing_radius, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const { std::vector<Polygons> layers_p; this->slice(z, &layers_p, throw_on_cancel); @@ -861,13 +861,13 @@ void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<ExPolygo layers->resize(z.size()); tbb::parallel_for( tbb::blocked_range<size_t>(0, z.size()), - [&layers_p, layers, throw_on_cancel, this](const tbb::blocked_range<size_t>& range) { + [&layers_p, closing_radius, layers, throw_on_cancel, this](const tbb::blocked_range<size_t>& range) { for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) { #ifdef SLIC3R_TRIANGLEMESH_DEBUG printf("Layer " PRINTF_ZU " (slice_z = %.2f):\n", layer_id, z[layer_id]); #endif throw_on_cancel(); - this->make_expolygons(layers_p[layer_id], &(*layers)[layer_id]); + this->make_expolygons(layers_p[layer_id], closing_radius, &(*layers)[layer_id]); } }); BOOST_LOG_TRIVIAL(debug) << "TriangleMeshSlicer::make_expolygons in parallel - end"; @@ -1600,7 +1600,7 @@ void TriangleMeshSlicer::make_expolygons_simple(std::vector<IntersectionLine> &l #endif } -void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices) const +void TriangleMeshSlicer::make_expolygons(const Polygons &loops, const float closing_radius, ExPolygons* slices) const { /* Input loops are not suitable for evenodd nor nonzero fill types, as we might get @@ -1655,7 +1655,7 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic // 0.0499 comes from https://github.com/slic3r/Slic3r/issues/959 // double safety_offset = scale_(0.0499); // 0.0001 is set to satisfy GH #520, #1029, #1364 - double safety_offset = scale_(0.0001); + double safety_offset = scale_(closing_radius); /* The following line is commented out because it can generate wrong polygons, see for example issue #661 */ @@ -1670,17 +1670,17 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic #endif // append to the supplied collection - /* Fix for issue #661 { */ - expolygons_append(*slices, offset2_ex(union_(loops, false), +safety_offset, -safety_offset)); - //expolygons_append(*slices, ex_slices); - /* } */ + if (safety_offset > 0) + expolygons_append(*slices, offset2_ex(union_(loops, false), +safety_offset, -safety_offset)); + else + expolygons_append(*slices, union_ex(loops, false)); } -void TriangleMeshSlicer::make_expolygons(std::vector<IntersectionLine> &lines, ExPolygons* slices) const +void TriangleMeshSlicer::make_expolygons(std::vector<IntersectionLine> &lines, const float closing_radius, ExPolygons* slices) const { Polygons pp; this->make_loops(lines, &pp); - this->make_expolygons(pp, slices); + this->make_expolygons(pp, closing_radius, slices); } void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) const diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index be70ee79d..04c13e876 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -165,7 +165,7 @@ public: TriangleMeshSlicer(TriangleMesh* mesh) { this->init(mesh, [](){}); } void init(TriangleMesh *mesh, throw_on_cancel_callback_type throw_on_cancel); void slice(const std::vector<float> &z, std::vector<Polygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const; - void slice(const std::vector<float> &z, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const; + void slice(const std::vector<float> &z, const float closing_radius, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const; enum FacetSliceType { NoSlice = 0, Slicing = 1, @@ -184,9 +184,9 @@ private: void _slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, const std::vector<float> &z) const; void make_loops(std::vector<IntersectionLine> &lines, Polygons* loops) const; - void make_expolygons(const Polygons &loops, ExPolygons* slices) const; + void make_expolygons(const Polygons &loops, const float closing_radius, ExPolygons* slices) const; void make_expolygons_simple(std::vector<IntersectionLine> &lines, ExPolygons* slices) const; - void make_expolygons(std::vector<IntersectionLine> &lines, ExPolygons* slices) const; + void make_expolygons(std::vector<IntersectionLine> &lines, const float closing_radius, ExPolygons* slices) const; }; TriangleMesh make_cube(double x, double y, double z); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index ccccf7626..37b495a36 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -354,7 +354,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", "top_solid_layers", "bottom_solid_layers", + "layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "top_solid_layers", "bottom_solid_layers", "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", "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", @@ -460,6 +460,7 @@ const std::vector<std::string>& Preset::sla_print_options() "support_object_elevation", "support_points_density_relative", "support_points_minimal_distance", + "slice_closing_radius", "pad_enable", "pad_wall_thickness", "pad_wall_height", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index b52ddbf48..d4c6a051d 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1108,12 +1108,14 @@ void TabPrint::build() optgroup = page->new_optgroup(_(L("Flow"))); optgroup->append_single_option_line("bridge_flow_ratio"); + optgroup = page->new_optgroup(_(L("Slicing"))); + optgroup->append_single_option_line("slice_closing_radius"); + optgroup->append_single_option_line("resolution"); + optgroup->append_single_option_line("xy_size_compensation"); + optgroup->append_single_option_line("elefant_foot_compensation"); + optgroup = page->new_optgroup(_(L("Other"))); optgroup->append_single_option_line("clip_multipart_objects"); - optgroup->append_single_option_line("elefant_foot_compensation"); - optgroup->append_single_option_line("xy_size_compensation"); -// # optgroup->append_single_option_line("threads"); - optgroup->append_single_option_line("resolution"); page = add_options_page(_(L("Output options")), "page_white_go.png"); optgroup = page->new_optgroup(_(L("Sequential printing"))); @@ -3292,6 +3294,10 @@ void TabSLAPrint::build() // optgroup->append_single_option_line("pad_edge_radius"); optgroup->append_single_option_line("pad_wall_slope"); + page = add_options_page(_(L("Advanced")), "wrench.png"); + optgroup = page->new_optgroup(_(L("Slicing"))); + optgroup->append_single_option_line("slice_closing_radius"); + page = add_options_page(_(L("Output options")), "page_white_go.png"); optgroup = page->new_optgroup(_(L("Output file"))); Option option = optgroup->get_option("output_filename_format");