From 172c324475ffcbaae36c5a8d3153aab6dea72c96 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 16 May 2017 21:49:00 +0200 Subject: [PATCH] Ignore small_perimeter_speed when perimeter has overhangs. #3951 --- lib/Slic3r/Test.pm | 7 ++++++ t/perimeters.t | 33 +++++++++++++++++++++++-- xs/src/libslic3r/ExtrusionEntity.hpp | 5 ++++ xs/src/libslic3r/GCode.cpp | 8 +++--- xs/src/libslic3r/PerimeterGenerator.cpp | 14 +++++------ 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/lib/Slic3r/Test.pm b/lib/Slic3r/Test.pm index dbd2d37f1..8f0b203e1 100644 --- a/lib/Slic3r/Test.pm +++ b/lib/Slic3r/Test.pm @@ -133,6 +133,13 @@ sub mesh { $facets = [ [0,1,2],[1,0,3],[2,1,4],[2,5,0],[0,6,3],[1,3,7],[1,8,4],[4,9,2],[10,5,2],[5,6,0],[6,11,3],[3,12,7],[7,8,1],[4,8,11],[4,11,9],[9,10,2],[10,13,5],[14,6,5],[9,11,6],[11,12,3],[12,8,7],[11,8,15],[13,10,9],[5,13,14],[14,13,6],[6,13,9],[15,12,11],[15,8,12] ]; + } elsif ($name eq 'bridge_with_hole') { + $vertices = [ + [75,69.5,8],[80,76.9091644287109,8],[75,94.5,8],[125,69.5,8],[120,76.9091644287109,8],[120,87.0908355712891,8],[80,87.0908355712891,8],[125,94.5,8],[80,87.0908355712891,5],[120,87.0908355712891,5],[125,94.5,0],[120,69.5,0],[120,94.5,0],[125,69.5,0],[120,94.5,5],[80,94.5,5],[80,94.5,0],[75,94.5,0],[80,69.5,5],[80,69.5,0],[80,76.9091644287109,5],[120,69.5,5],[75,69.5,0],[120,76.9091644287109,5] + ]; + $facets = [ + [0,1,2],[1,0,3],[1,3,4],[4,3,5],[2,6,7],[6,2,1],[7,6,5],[7,5,3],[5,8,9],[8,5,6],[10,11,12],[11,10,13],[14,8,15],[8,14,9],[2,16,17],[16,2,15],[15,2,14],[14,10,12],[10,14,7],[7,14,2],[16,18,19],[18,16,20],[20,16,1],[1,16,8],[8,16,15],[6,1,8],[3,11,13],[11,3,21],[21,3,18],[18,22,19],[22,18,0],[0,18,3],[16,22,17],[22,16,19],[2,22,0],[22,2,17],[5,23,4],[23,11,21],[11,23,12],[12,23,9],[9,23,5],[12,9,14],[23,18,20],[18,23,21],[10,3,13],[3,10,7],[1,23,20],[23,1,4] + ]; } elsif ($name eq 'step') { $vertices = [ [0,20,5],[0,20,0],[0,0,5],[0,0,0],[20,0,0],[20,0,5],[1,19,5],[1,1,5],[19,1,5],[20,20,5],[19,19,5],[20,20,0],[19,19,10],[1,19,10],[1,1,10],[19,1,10] diff --git a/t/perimeters.t b/t/perimeters.t index 828504311..68219782d 100644 --- a/t/perimeters.t +++ b/t/perimeters.t @@ -1,4 +1,4 @@ -use Test::More tests => 59; +use Test::More tests => 63; use strict; use warnings; @@ -393,10 +393,39 @@ use Slic3r::Test; }); return scalar keys %z_with_bridges; }; - ok $test->(Slic3r::Test::init_print('V', config => $config)) == 1, + is $test->(Slic3r::Test::init_print('V', config => $config)), 1, 'no overhangs printed with bridge speed'; # except for the first internal solid layers above void ok $test->(Slic3r::Test::init_print('V', config => $config, scale_xyz => [3,1,1])) > 1, 'overhangs printed with bridge speed'; + + $config->set('bottom_solid_layers', 0); + $config->set('top_solid_layers', 0); + my $test2 = sub { + my ($print) = @_; + my $num_bridges = 0; + Slic3r::GCode::Reader->new->parse(my $gcode = Slic3r::Test::gcode($print), sub { + my ($self, $cmd, $args, $info) = @_; + + if ($info->{extruding} && $info->{dist_XY} > 0) { + $num_bridges++ if ($args->{F} // $self->F) == $config->bridge_speed*60; + } + }); + open my $fh, ">", "bridges.gcode"; + print $fh $gcode; + return $num_bridges; + }; + is $test2->(Slic3r::Test::init_print('overhang', config => $config)), $config->perimeters*3, + 'expected number of segments use bridge speed (overhang)'; + is $test2->(Slic3r::Test::init_print('bridge', config => $config)), $config->perimeters*2, + 'expected number of segments use bridge speed (bridge)'; + is $test2->(Slic3r::Test::init_print('bridge_with_hole', config => $config)), $config->perimeters*4, + 'expected number of segments use bridge speed (bridge with hole)'; + + # scale the test model so that the hole perimeter length is smaller than small perimeter + # threshold (~40mm). check that we still use overhang settings regardless of it being small + is $test2->(Slic3r::Test::init_print('bridge_with_hole', config => $config, scale_xyz => [0.3,0.5,1])), + $config->perimeters*4, + 'expected number of segments use bridge speed (bridge with small hole)'; } { diff --git a/xs/src/libslic3r/ExtrusionEntity.hpp b/xs/src/libslic3r/ExtrusionEntity.hpp index b5bff5ab3..05dc00a58 100644 --- a/xs/src/libslic3r/ExtrusionEntity.hpp +++ b/xs/src/libslic3r/ExtrusionEntity.hpp @@ -167,6 +167,11 @@ class ExtrusionLoop : public ExtrusionEntity void append(const ExtrusionPath &path) { this->paths.push_back(path); }; + bool has(ExtrusionRole role) const { + for (const auto &path : this->paths) + if (path.role == role) return true; + return false; + }; }; } diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 38d36857a..56100f9f5 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -415,9 +415,11 @@ GCode::extrude(ExtrusionLoop loop, std::string description, double speed) if (paths.empty()) return ""; // apply the small perimeter speed - if (paths.front().is_perimeter() && loop.length() <= SMALL_PERIMETER_LENGTH) { - if (speed == -1) speed = this->config.get_abs_value("small_perimeter_speed"); - } + if (paths.front().is_perimeter() + && !loop.has(erOverhangPerimeter) + && loop.length() <= SMALL_PERIMETER_LENGTH + && speed == -1) + speed = this->config.get_abs_value("small_perimeter_speed"); // extrude along the path std::string gcode; diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/xs/src/libslic3r/PerimeterGenerator.cpp index b902f5307..02c2488df 100644 --- a/xs/src/libslic3r/PerimeterGenerator.cpp +++ b/xs/src/libslic3r/PerimeterGenerator.cpp @@ -349,11 +349,10 @@ PerimeterGenerator::_traverse_loops(const PerimeterGeneratorLoops &loops, && !(this->object_config->support_material && this->object_config->support_material_contact_distance.value == 0)) { // get non-overhang paths by intersecting this loop with the grown lower slices { - Polylines polylines = intersection_pl(loop->polygon, this->_lower_slices_p); - - for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) { + const Polylines polylines = intersection_pl(loop->polygon, this->_lower_slices_p); + for (const Polyline &polyline : polylines) { ExtrusionPath path(role); - path.polyline = *polyline; + path.polyline = polyline; path.mm3_per_mm = is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm; path.width = is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width; path.height = this->layer_height; @@ -365,11 +364,10 @@ PerimeterGenerator::_traverse_loops(const PerimeterGeneratorLoops &loops, // outside the grown lower slices (thus where the distance between // the loop centerline and original lower slices is >= half nozzle diameter { - Polylines polylines = diff_pl(loop->polygon, this->_lower_slices_p); - - for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) { + const Polylines polylines = diff_pl(loop->polygon, this->_lower_slices_p); + for (const Polyline &polyline : polylines) { ExtrusionPath path(erOverhangPerimeter); - path.polyline = *polyline; + path.polyline = polyline; path.mm3_per_mm = this->_mm3_per_mm_overhang; path.width = this->overhang_flow.width; path.height = this->overhang_flow.height;