From 8aca7172092b2192d872d63772bab8043e9dd4b9 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 16 Nov 2011 16:35:20 +0100 Subject: [PATCH] Print solid infill without cutting an internal surface under small regions such as pillars. #39 --- lib/Slic3r/ExPolygon.pm | 8 +++++++- lib/Slic3r/Perimeter.pm | 4 ++-- lib/Slic3r/Polygon.pm | 5 +++++ lib/Slic3r/Print.pm | 14 ++++++++++---- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index 7abaf6b48..89b71324e 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -51,9 +51,15 @@ sub offset { $miterLimit ||= 2; my $offsets = Math::Clipper::offset($self, $distance, $scale, $joinType, $miterLimit); + return @$offsets; +} + +sub offset_ex { + my $self = shift; + my @offsets = $self->offset(@_); # apply holes to the right contours - return @{ union_ex($offsets) }; + return @{ union_ex(\@offsets) }; } sub encloses_point { diff --git a/lib/Slic3r/Perimeter.pm b/lib/Slic3r/Perimeter.pm index bf93315cb..5698ae22c 100644 --- a/lib/Slic3r/Perimeter.pm +++ b/lib/Slic3r/Perimeter.pm @@ -42,7 +42,7 @@ sub make_perimeter { push @perimeters, []; for (my $loop = 0; $loop < $Slic3r::perimeter_offsets; $loop++) { # offsetting a polygon can result in one or many offset polygons - @last_offsets = map $_->offset(-$distance), @last_offsets; + @last_offsets = map $_->offset_ex(-$distance), @last_offsets; push @{ $perimeters[-1] }, [@last_offsets]; # offset distance for inner loops @@ -54,7 +54,7 @@ sub make_perimeter { $distance -= $Slic3r::flow_width * $Slic3r::perimeter_infill_overlap_ratio / $Slic3r::resolution; my @fill_surfaces = map Slic3r::Surface->cast_from_expolygon ($_, surface_type => $surface->surface_type), - map $_->offset(-$distance), @last_offsets; + map $_->offset_ex(-$distance), @last_offsets; push @{ $layer->fill_surfaces }, [@fill_surfaces] if @fill_surfaces; } diff --git a/lib/Slic3r/Polygon.pm b/lib/Slic3r/Polygon.pm index 47e8ce51d..3d0224dd5 100644 --- a/lib/Slic3r/Polygon.pm +++ b/lib/Slic3r/Polygon.pm @@ -65,4 +65,9 @@ sub rotate { @$self = rotate_points($angle, $center, @$self); } +sub area { + my $self = shift; + return Slic3r::Geometry::Clipper::area($self); +} + 1; \ No newline at end of file diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index f87e95488..95f00f0f4 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -2,7 +2,7 @@ package Slic3r::Print; use Moo; use Math::ConvexHull 1.0.4 qw(convex_hull); -use Slic3r::Geometry qw(X Y); +use Slic3r::Geometry qw(X Y PI); use Slic3r::Geometry::Clipper qw(explode_expolygons safety_offset diff_ex intersection_ex offset JT_ROUND JT_MITER); use XXX; @@ -101,8 +101,14 @@ sub detect_surfaces_type { # find top surfaces (difference between current surfaces # of current layer and upper one) if ($upper_layer) { - # offset upper layer surfaces by extrusion_width * perimeters - @top = $surface_difference->($layer->surfaces, $upper_layer->surfaces, 'top'); + # only consider those upper surfaces that are not small + # (if they're too small, the interface with them can be treated + # like a continuous solid surface instead of cutting a little + # internal surface in it) + my $min_area = ((7 * $Slic3r::flow_width / $Slic3r::resolution)**2) * PI; + my $upper_surfaces = [ grep { $_->expolygon->contour->area > $min_area } @{$upper_layer->surfaces} ]; + + @top = $surface_difference->($layer->surfaces, $upper_surfaces, 'top'); } else { # if no upper layer, all surfaces of this one are solid @top = @{$layer->surfaces}; @@ -195,7 +201,7 @@ sub discover_horizontal_shells { Slic3r::debugf " looking for neighbors on layer %d...\n", $n; foreach my $surfaces (@{$self->layers->[$n]->fill_surfaces}) { - my $neighbor_polygons = [ map $_->p, grep $_->surface_type =~ /internal/, @$surfaces ]; + my $neighbor_polygons = [ map $_->p, grep $_->surface_type eq 'internal', @$surfaces ]; # find intersection between @surfaces and current layer's surfaces # intersections have contours and holes