diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 9cb2b30f2..2e8c65fb0 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -48,6 +48,7 @@ bottom_fill_pattern = rectilinear external_perimeters_first = 0 external_perimeter_extrusion_width = 0.45 extra_perimeters = 0 +only_one_perimeter_top = 0 extruder_clearance_height = 20 extruder_clearance_radius = 20 extrusion_width = 0.45 diff --git a/slic3r.pl b/slic3r.pl index 037910ed9..d96359491 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -395,6 +395,7 @@ Usage: slic3r.pl [ OPTIONS ] [ file.stl ] [ file2.stl ] ... Quality options (slower slicing): --extra-perimeters Add more perimeters when needed (default: yes) + --one-top-perimeter Only draw 1 perimeter for the top layers (default: yes) --ensure-vertical-shell-thickness Add solid infill near sloping surfaces to guarantee the vertical shell thickness (top+bottom solid layers). (default: no) --avoid-crossing-perimeters Optimize travel moves so that no perimeters are crossed (default: no) --thin-walls Detect single-width walls (default: yes) diff --git a/t/perimeters.t b/t/perimeters.t index ee332616d..74bfb045d 100644 --- a/t/perimeters.t +++ b/t/perimeters.t @@ -290,6 +290,7 @@ use Slic3r::Test; $config->set('layer_height', 0.4); $config->set('first_layer_height', 0.35); $config->set('extra_perimeters', 1); + $config->set('only_one_perimeter_top', 1); $config->set('cooling', [ 0 ]); # to prevent speeds from being altered $config->set('first_layer_speed', '100%'); # to prevent speeds from being altered $config->set('perimeter_speed', 99); diff --git a/xs/src/libslic3r/LayerRegion.cpp b/xs/src/libslic3r/LayerRegion.cpp index 68e17407e..66f9bc582 100644 --- a/xs/src/libslic3r/LayerRegion.cpp +++ b/xs/src/libslic3r/LayerRegion.cpp @@ -75,6 +75,8 @@ LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* if (this->layer()->lower_layer != NULL) // Cummulative sum of polygons over all the regions. g.lower_slices = &this->layer()->lower_layer->slices; + if (this->layer()->upper_layer != NULL) + g.upper_slices = &this->layer()->upper_layer->slices; g.layer_id = this->layer()->id(); g.ext_perimeter_flow = this->flow(frExternalPerimeter); diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/xs/src/libslic3r/PerimeterGenerator.cpp index ea9c73fa4..7a33cd00b 100644 --- a/xs/src/libslic3r/PerimeterGenerator.cpp +++ b/xs/src/libslic3r/PerimeterGenerator.cpp @@ -53,9 +53,17 @@ PerimeterGenerator::process() // extra perimeters for each one for (const Surface &surface : this->slices->surfaces) { // detect how many perimeters must be generated for this island - const int loop_number = this->config->perimeters + surface.extra_perimeters -1; // 0-indexed loops - + int loop_number = + //(config->only_one_perimeter_top && surface.is_external() && !surface.is_bridge() && surface.surface_type == stTop) ? + // 0 : // only 1 perimeter for top surface if the option is set (0-indexed loops) + (this->config->perimeters + surface.extra_perimeters -1); // normal case (0-indexed loops) + + if(config->only_one_perimeter_top && this->upper_slices == NULL){ + loop_number = 0; + } + Polygons gaps; + Polygons stored; Polygons last = surface.expolygon.simplify_p(SCALED_RESOLUTION); if (loop_number >= 0) { // no loops = -1 @@ -165,7 +173,21 @@ PerimeterGenerator::process() holes[i].push_back(loop); } } + + if(i==0 && config->only_one_perimeter_top && this->upper_slices != NULL){ + //split the polygons with top/not_top + Polygons upper_polygons((*(this->upper_slices))); + Polygons stored_toosmall = diff(last, (upper_polygons), true); + Polygons last_toosmall = diff(last, stored_toosmall, true); + // increase a bit the inner scpace to fill the frontier between last and stored. + stored = union_(stored, intersection(offset(stored_toosmall, perimeter_spacing/2), last)); + last = intersection(offset(last_toosmall, perimeter_spacing/2), last); + } + } + + // add stored polygons + last = union_(last, stored); // nest loops: holes first for (int d = 0; d <= loop_number; ++d) { diff --git a/xs/src/libslic3r/PerimeterGenerator.hpp b/xs/src/libslic3r/PerimeterGenerator.hpp index 04557a2c0..36e313fcc 100644 --- a/xs/src/libslic3r/PerimeterGenerator.hpp +++ b/xs/src/libslic3r/PerimeterGenerator.hpp @@ -39,6 +39,7 @@ class PerimeterGenerator { public: // Inputs: const SurfaceCollection* slices; + const ExPolygonCollection* upper_slices; const ExPolygonCollection* lower_slices; double layer_height; int layer_id; @@ -69,7 +70,7 @@ public: ExtrusionEntityCollection* gap_fill, // Infills without the gap fills SurfaceCollection* fill_surfaces) - : slices(slices), lower_slices(NULL), layer_height(layer_height), + : slices(slices), lower_slices(NULL), upper_slices(NULL), layer_height(layer_height), layer_id(-1), perimeter_flow(flow), ext_perimeter_flow(flow), overhang_flow(flow), solid_infill_flow(flow), config(config), object_config(object_config), print_config(print_config), diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 044480d01..3a2010793 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -318,6 +318,14 @@ PrintConfigDef::PrintConfigDef() "is supported."); def->cli = "extra-perimeters!"; def->default_value = new ConfigOptionBool(true); + + def = this->add("only_one_perimeter_top", coBool); + def->label = "Only one perimeter on Top surfaces"; + def->category = "Layers and Perimeters"; + def->tooltip = "Use only one perimeter on flat top surface, to let more space to the top infill pattern."; + def->cli = "one-top-perimeter!"; + def->default_value = new ConfigOptionBool(true); + def = this->add("extruder", coInt); def->gui_type = "i_enum_open"; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 159af5e71..0378c80ed 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -384,6 +384,7 @@ public: ConfigOptionFloatOrPercent external_perimeter_speed; ConfigOptionBool external_perimeters_first; ConfigOptionBool extra_perimeters; + ConfigOptionBool only_one_perimeter_top; ConfigOptionFloat fill_angle; ConfigOptionPercent fill_density; ConfigOptionEnum fill_pattern; @@ -423,6 +424,7 @@ protected: OPT_PTR(external_perimeter_speed); OPT_PTR(external_perimeters_first); OPT_PTR(extra_perimeters); + OPT_PTR(only_one_perimeter_top); OPT_PTR(fill_angle); OPT_PTR(fill_density); OPT_PTR(fill_pattern); diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index f398a1b85..0c8df208c 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -179,7 +179,7 @@ const std::vector& Preset::print_options() { static std::vector s_opts { "layer_height", "first_layer_height", "perimeters", "spiral_vase", "top_solid_layers", "bottom_solid_layers", - "extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs", + "extra_perimeters", "only_one_perimeter_top", "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", "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "max_print_speed", @@ -199,7 +199,7 @@ const std::vector& Preset::print_options() "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", - "wipe_tower_width", "wipe_tower_per_color_wipe", + "wipe_tower_width", "wipe_tower_per_color_wipe", "only_one_perimeter_top", "compatible_printers", "compatible_printers_condition" }; return s_opts; diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 20051da7a..cd95666a6 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -405,6 +405,7 @@ void TabPrint::build() optgroup = page->new_optgroup(_(L("Quality (slower slicing)"))); optgroup->append_single_option_line("extra_perimeters"); + optgroup->append_single_option_line("only_one_perimeter_top"); optgroup->append_single_option_line("ensure_vertical_shell_thickness"); optgroup->append_single_option_line("avoid_crossing_perimeters"); optgroup->append_single_option_line("thin_walls"); @@ -757,7 +758,7 @@ void TabPrint::update() } bool have_perimeters = m_config->opt_int("perimeters") > 0; - std::vector vec_enable = { "extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", + std::vector vec_enable = { "extra_perimeters", "only_one_perimeter_top", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", "seam_position", "external_perimeters_first", "external_perimeter_extrusion_width", "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" }; for (auto el : vec_enable)