diff --git a/lib/Slic3r/Test.pm b/lib/Slic3r/Test.pm index 4b4d35520d..dbd2d37f15 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 '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] + ]; + $facets = [ + [0,1,2],[1,3,2],[3,4,5],[2,3,5],[6,0,2],[6,2,7],[5,8,7],[5,7,2],[9,10,8],[9,8,5],[9,0,6],[9,6,10],[9,11,1],[9,1,0],[3,1,11],[4,3,11],[5,11,9],[5,4,11],[12,10,6],[12,6,13],[6,7,14],[13,6,14],[7,8,15],[14,7,15],[15,8,10],[15,10,12],[12,13,14],[12,14,15] + ]; } else { return undef; } diff --git a/t/shells.t b/t/shells.t index e6eb65a9df..63eb1905d5 100644 --- a/t/shells.t +++ b/t/shells.t @@ -1,4 +1,4 @@ -use Test::More tests => 21; +use Test::More tests => 24; use strict; use warnings; @@ -11,6 +11,7 @@ BEGIN { use List::Util qw(first sum); use Slic3r; use Slic3r::Geometry qw(epsilon); +use Slic3r::Surface qw(S_TYPE_TOP); use Slic3r::Test; { @@ -318,4 +319,23 @@ use Slic3r::Test; is $diagonal_moves, 0, 'no spiral moves on two-island object'; } +{ + # GH: #3732 + my $config = Slic3r::Config->new_from_defaults; + $config->set('perimeters', 2); + $config->set('extrusion_width', 0.55); + $config->set('first_layer_height', 0.25); + $config->set('infill_overlap', '50%'); + $config->set('layer_height', 0.25); + $config->set('perimeters', 2); + $config->set('extra_perimeters', 1); + + my $tprint = Slic3r::Test::init_print('step', config => $config); + $tprint->print->process; + my $layerm19 = $tprint->print->get_object(0)->get_layer(19)->get_region(0); + is scalar(@{$layerm19->slices->filter_by_type(S_TYPE_TOP)}), 1, 'top slice detected'; + is scalar(@{$layerm19->fill_surfaces->filter_by_type(S_TYPE_TOP)}), 0, 'no top fill_surface detected'; + is $layerm19->perimeters->items_count, 3, 'extra perimeter detected'; +} + __END__ diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/xs/src/libslic3r/PerimeterGenerator.cpp index ce24e1a7fc..b902f53073 100644 --- a/xs/src/libslic3r/PerimeterGenerator.cpp +++ b/xs/src/libslic3r/PerimeterGenerator.cpp @@ -315,8 +315,7 @@ PerimeterGenerator::process() ); // append infill areas to fill_surfaces - for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) - this->fill_surfaces->surfaces.push_back(Surface(stInternal, *ex)); // use a bogus surface type + this->fill_surfaces->append(expp, stInternal); // use a bogus surface type } } } diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 4f38cfa1d0..0b420e6a3d 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -384,7 +384,7 @@ PrintObject::detect_surfaces_type() const Layer* lower_layer = layer_idx > 0 ? this->get_layer(layer_idx-1) : NULL; // collapse very narrow parts (using the safety offset in the diff is not enough) - const float offset = layerm.flow(frExternalPerimeter).scaled_width() / 10.f; + const float offs = layerm.flow(frExternalPerimeter).scaled_width() / 10.f; const Polygons layerm_slices_surfaces = layerm.slices; @@ -392,14 +392,14 @@ PrintObject::detect_surfaces_type() // of current layer and upper one) SurfaceCollection top; if (upper_layer != NULL) { - const Polygons upper_slices = this->config.interface_shells.value + Polygons upper_slices = this->config.interface_shells.value ? (Polygons)upper_layer->get_region(region_id)->slices : (Polygons)upper_layer->slices; top.append( offset2_ex( diff(layerm_slices_surfaces, upper_slices, true), - -offset, offset + -offs, offs ), stTop ); @@ -426,7 +426,7 @@ PrintObject::detect_surfaces_type() bottom.append( offset2_ex( diff(layerm_slices_surfaces, lower_layer->slices, true), - -offset, offset + -offs, offs ), surface_type_bottom ); @@ -443,7 +443,7 @@ PrintObject::detect_surfaces_type() lower_layer->get_region(region_id)->slices, true ), - -offset, offset + -offs, offs ), stBottom ); @@ -470,7 +470,7 @@ PrintObject::detect_surfaces_type() const Polygons top_polygons = to_polygons(STDMOVE(top)); top.clear(); top.append( - offset2_ex(diff(top_polygons, bottom, true), -offset, offset), + offset2_ex(diff(top_polygons, bottom, true), -offs, offs), stTop ); } @@ -487,17 +487,18 @@ PrintObject::detect_surfaces_type() layerm.slices.append( offset2_ex( diff(layerm_slices_surfaces, topbottom, true), - -offset, offset + -offs, offs ), stInternal ); } - /* - Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n", - $layerm->layer->id, scalar(@bottom), scalar(@top), scalar(@internal) if $Slic3r::debug; - */ - + #ifdef SLIC3R_DEBUG + printf(" layer %zu has %zu bottom, %zu top and %zu internal surfaces\n", + layerm.layer()->id(), bottom.size(), top.size(), + layerm.slices.size()-bottom.size()-top.size()); + #endif + } // for each layer of a region /* Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces. @@ -782,7 +783,6 @@ PrintObject::_make_perimeters() size_t region_id = region_it - this->_print->regions.begin(); const PrintRegion ®ion = **region_it; - if (!region.config.extra_perimeters || region.config.perimeters == 0 || region.config.fill_density == 0 @@ -791,7 +791,13 @@ PrintObject::_make_perimeters() for (size_t i = 0; i <= (this->layer_count()-2); ++i) { LayerRegion &layerm = *this->get_layer(i)->get_region(region_id); const LayerRegion &upper_layerm = *this->get_layer(i+1)->get_region(region_id); - const Polygons upper_layerm_polygons = upper_layerm.slices; + + // In order to avoid diagonal gaps (GH #3732) we ignore the external half of the upper + // perimeter, since it's not truly covering this layer. + const Polygons upper_layerm_polygons = offset( + upper_layerm.slices, + -upper_layerm.flow(frExternalPerimeter).scaled_width()/2 + ); // Filter upper layer polygons in intersection_ppl by their bounding boxes? // my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ]; diff --git a/xs/src/libslic3r/SurfaceCollection.hpp b/xs/src/libslic3r/SurfaceCollection.hpp index e9d42fc49a..6c4fe05a76 100644 --- a/xs/src/libslic3r/SurfaceCollection.hpp +++ b/xs/src/libslic3r/SurfaceCollection.hpp @@ -29,6 +29,7 @@ class SurfaceCollection void append(const ExPolygons &src, SurfaceType surfaceType); size_t polygons_count() const; bool empty() const { return this->surfaces.empty(); }; + size_t size() const { return this->surfaces.size(); }; void clear() { this->surfaces.clear(); }; };