Merge branch 'new-extra-perimeters'
This commit is contained in:
commit
0326962d11
@ -216,7 +216,7 @@ sub make_perimeters {
|
|||||||
my @gaps = ();
|
my @gaps = ();
|
||||||
|
|
||||||
# generate perimeters inwards (loop 0 is the external one)
|
# generate perimeters inwards (loop 0 is the external one)
|
||||||
my $loop_number = $Slic3r::Config->perimeters + ($surface->additional_inner_perimeters || 0);
|
my $loop_number = $Slic3r::Config->perimeters + ($surface->extra_perimeters || 0);
|
||||||
push @perimeters, [] if $loop_number > 0;
|
push @perimeters, [] if $loop_number > 0;
|
||||||
|
|
||||||
# do one more loop (<= instead of <) so that we can detect gaps even after the desired
|
# do one more loop (<= instead of <) so that we can detect gaps even after the desired
|
||||||
|
@ -4,7 +4,7 @@ use Moo;
|
|||||||
use List::Util qw(min sum first);
|
use List::Util qw(min sum first);
|
||||||
use Slic3r::ExtrusionPath ':roles';
|
use Slic3r::ExtrusionPath ':roles';
|
||||||
use Slic3r::Geometry qw(Z PI scale unscale deg2rad rad2deg scaled_epsilon);
|
use Slic3r::Geometry qw(Z PI scale unscale deg2rad rad2deg scaled_epsilon);
|
||||||
use Slic3r::Geometry::Clipper qw(diff_ex intersection_ex union_ex);
|
use Slic3r::Geometry::Clipper qw(diff_ex intersection_ex union_ex offset);
|
||||||
use Slic3r::Surface ':types';
|
use Slic3r::Surface ':types';
|
||||||
|
|
||||||
has 'print' => (is => 'ro', weak_ref => 1, required => 1);
|
has 'print' => (is => 'ro', weak_ref => 1, required => 1);
|
||||||
@ -236,40 +236,43 @@ sub make_perimeters {
|
|||||||
|
|
||||||
my $overlap = $perimeter_spacing; # one perimeter
|
my $overlap = $perimeter_spacing; # one perimeter
|
||||||
|
|
||||||
# compute the polygon used to trigger the additional perimeters: the hole represents
|
my $diff = diff_ex(
|
||||||
# the required overlap, while the contour represents how different should the slices be
|
[ offset([ map @{$_->expolygon}, @{$layerm->slices} ], -($Slic3r::Config->perimeters * $perimeter_spacing)) ],
|
||||||
# (thus how horizontal should the slope be) before extra perimeters are not generated, and
|
[ offset([ map @{$_->expolygon}, @{$upper_layerm->slices} ], -$overlap) ],
|
||||||
# normal solid infill is used
|
|
||||||
my $upper = diff_ex(
|
|
||||||
[ map @$_, map $_->expolygon->offset_ex($overlap), @{$upper_layerm->slices} ],
|
|
||||||
[ map @$_, map $_->expolygon->offset_ex(-$overlap), @{$upper_layerm->slices} ],
|
|
||||||
);
|
);
|
||||||
next if !@$upper;
|
next if !@$diff;
|
||||||
|
# if we need more perimeters, $diff should contain a narrow region that we can collapse
|
||||||
|
|
||||||
|
$diff = diff_ex(
|
||||||
|
[ map @$_, @$diff ],
|
||||||
|
[ offset(
|
||||||
|
[ offset([ map @$_, @$diff ], -$perimeter_spacing) ],
|
||||||
|
+$perimeter_spacing
|
||||||
|
) ],
|
||||||
|
);
|
||||||
|
next if !@$diff;
|
||||||
|
# diff contains the collapsed area
|
||||||
|
|
||||||
foreach my $slice (@{$layerm->slices}) {
|
foreach my $slice (@{$layerm->slices}) {
|
||||||
my $hypothetical_perimeter_num = $Slic3r::Config->perimeters + 1;
|
my $extra_perimeters = 0;
|
||||||
CYCLE: while (1) {
|
CYCLE: while (1) {
|
||||||
# compute polygons representing the thickness of the hypotetical new internal perimeter
|
# compute polygons representing the thickness of the hypotetical new internal perimeter
|
||||||
# of our slice
|
# of our slice
|
||||||
my $hypothetical_perimeter;
|
$extra_perimeters++;
|
||||||
{
|
my $hypothetical_perimeter = diff_ex(
|
||||||
my $outer = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-1) * $perimeter_spacing - scaled_epsilon) ];
|
[ offset($slice->expolygon, -($perimeter_spacing * ($Slic3r::Config->perimeters + $extra_perimeters-1))) ],
|
||||||
last CYCLE if !@$outer;
|
[ offset($slice->expolygon, -($perimeter_spacing * ($Slic3r::Config->perimeters + $extra_perimeters))) ],
|
||||||
my $inner = [ map @$_, $slice->expolygon->offset_ex(- $hypothetical_perimeter_num * $perimeter_spacing) ];
|
);
|
||||||
last CYCLE if !@$inner;
|
last CYCLE if !@$hypothetical_perimeter; # no extra perimeter is possible
|
||||||
$hypothetical_perimeter = diff_ex($outer, $inner);
|
|
||||||
}
|
|
||||||
last CYCLE if !@$hypothetical_perimeter;
|
|
||||||
|
|
||||||
# compute the area of the hypothetical perimeter
|
# only add the perimeter if there's an intersection with the collapsed area
|
||||||
my $hp_area = sum(map $_->area, @$hypothetical_perimeter);
|
my $intersection = intersection_ex(
|
||||||
|
[ map @$_, @$diff ],
|
||||||
# only add the perimeter if the intersection is at least 20%, otherwise we'd get no benefit
|
[ map @$_, @$hypothetical_perimeter ],
|
||||||
my $intersection = intersection_ex([ map @$_, @$upper ], [ map @$_, @$hypothetical_perimeter ]);
|
);
|
||||||
last CYCLE if (sum(map $_->area, @{ $intersection }) // 0) < $hp_area * 0.2;
|
last CYCLE if !@$intersection;
|
||||||
Slic3r::debugf " adding one more perimeter at layer %d\n", $layer_id;
|
Slic3r::debugf " adding one more perimeter at layer %d\n", $layer_id;
|
||||||
$slice->additional_inner_perimeters(($slice->additional_inner_perimeters || 0) + 1);
|
$slice->extra_perimeters($extra_perimeters);
|
||||||
$hypothetical_perimeter_num++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ use SVG;
|
|||||||
use constant X => 0;
|
use constant X => 0;
|
||||||
use constant Y => 1;
|
use constant Y => 1;
|
||||||
|
|
||||||
|
our $filltype = 'evenodd';
|
||||||
|
|
||||||
sub factor {
|
sub factor {
|
||||||
return &Slic3r::SCALING_FACTOR * 10;
|
return &Slic3r::SCALING_FACTOR * 10;
|
||||||
}
|
}
|
||||||
@ -36,6 +38,25 @@ sub output {
|
|||||||
|
|
||||||
my $svg = svg();
|
my $svg = svg();
|
||||||
|
|
||||||
|
foreach my $type (qw(expolygons red_expolygons green_expolygons)) {
|
||||||
|
next if !$things{$type};
|
||||||
|
my ($colour) = $type =~ /^(red|green)_/;
|
||||||
|
my $g = $svg->group(
|
||||||
|
style => {
|
||||||
|
'stroke-width' => 2,
|
||||||
|
'stroke' => $colour || 'black',
|
||||||
|
'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
|
||||||
|
'fill-type' => $filltype,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
foreach my $expolygon (@{$things{$type}}) {
|
||||||
|
my $points = join ' ', map "M $_ z", map join(" ", reverse map $_->[0]*factor() . " " . $_->[1]*factor(), @$_), @$expolygon;
|
||||||
|
$g->path(
|
||||||
|
d => $points,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach my $type (qw(polygons polylines white_polygons green_polygons red_polygons red_polylines)) {
|
foreach my $type (qw(polygons polylines white_polygons green_polygons red_polygons red_polylines)) {
|
||||||
if ($things{$type}) {
|
if ($things{$type}) {
|
||||||
my $method = $type =~ /polygons/ ? 'polygon' : 'polyline';
|
my $method = $type =~ /polygons/ ? 'polygon' : 'polyline';
|
||||||
|
@ -11,7 +11,7 @@ use constant S_EXPOLYGON => 0;
|
|||||||
use constant S_SURFACE_TYPE => 1;
|
use constant S_SURFACE_TYPE => 1;
|
||||||
use constant S_DEPTH_LAYERS => 2;
|
use constant S_DEPTH_LAYERS => 2;
|
||||||
use constant S_BRIDGE_ANGLE => 3;
|
use constant S_BRIDGE_ANGLE => 3;
|
||||||
use constant S_ADDITIONAL_INNER_PERIMETERS => 4;
|
use constant S_EXTRA_PERIMETERS => 4;
|
||||||
|
|
||||||
use constant S_TYPE_TOP => 0;
|
use constant S_TYPE_TOP => 0;
|
||||||
use constant S_TYPE_BOTTOM => 1;
|
use constant S_TYPE_BOTTOM => 1;
|
||||||
@ -24,7 +24,7 @@ sub new {
|
|||||||
my %args = @_;
|
my %args = @_;
|
||||||
|
|
||||||
my $self = [
|
my $self = [
|
||||||
map delete $args{$_}, qw(expolygon surface_type depth_layers bridge_angle additional_inner_perimeters),
|
map delete $args{$_}, qw(expolygon surface_type depth_layers bridge_angle extra_perimeters),
|
||||||
];
|
];
|
||||||
$self->[S_DEPTH_LAYERS] //= 1; #/
|
$self->[S_DEPTH_LAYERS] //= 1; #/
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ sub expolygon { $_[0][S_EXPOLYGON] }
|
|||||||
sub surface_type { $_[0][S_SURFACE_TYPE] = $_[1] if defined $_[1]; $_[0][S_SURFACE_TYPE] }
|
sub surface_type { $_[0][S_SURFACE_TYPE] = $_[1] if defined $_[1]; $_[0][S_SURFACE_TYPE] }
|
||||||
sub depth_layers { $_[0][S_DEPTH_LAYERS] } # this integer represents the thickness of the surface expressed in layers
|
sub depth_layers { $_[0][S_DEPTH_LAYERS] } # this integer represents the thickness of the surface expressed in layers
|
||||||
sub bridge_angle { $_[0][S_BRIDGE_ANGLE] = $_[1] if defined $_[1]; $_[0][S_BRIDGE_ANGLE] }
|
sub bridge_angle { $_[0][S_BRIDGE_ANGLE] = $_[1] if defined $_[1]; $_[0][S_BRIDGE_ANGLE] }
|
||||||
sub additional_inner_perimeters { $_[0][S_ADDITIONAL_INNER_PERIMETERS] = $_[1] if defined $_[1]; $_[0][S_ADDITIONAL_INNER_PERIMETERS] }
|
sub extra_perimeters { $_[0][S_EXTRA_PERIMETERS] = $_[1] if defined $_[1]; $_[0][S_EXTRA_PERIMETERS] }
|
||||||
|
|
||||||
# delegate handles
|
# delegate handles
|
||||||
sub encloses_point { $_[0]->expolygon->encloses_point }
|
sub encloses_point { $_[0]->expolygon->encloses_point }
|
||||||
|
Loading…
Reference in New Issue
Block a user