New automatic detection of additional required perimeters for better quality with domes and sloping walls. #198
This commit is contained in:
parent
4b7e9fc284
commit
edbdc5ec55
@ -206,9 +206,10 @@ sub make_perimeters {
|
|||||||
$hole->reverse;
|
$hole->reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
# create other offsets
|
# generate perimeters inwards
|
||||||
|
my $loop_number = $Slic3r::perimeters + ($surface->additional_inner_perimeters || 0);
|
||||||
push @perimeters, [];
|
push @perimeters, [];
|
||||||
for (my $loop = 0; $loop < $Slic3r::perimeters; $loop++) {
|
for (my $loop = 0; $loop < $loop_number; $loop++) {
|
||||||
# offsetting a polygon can result in one or many offset polygons
|
# offsetting a polygon can result in one or many offset polygons
|
||||||
@last_offsets = map $_->offset_ex(-$distance), @last_offsets if $distance;
|
@last_offsets = map $_->offset_ex(-$distance), @last_offsets if $distance;
|
||||||
last if !@last_offsets;
|
last if !@last_offsets;
|
||||||
|
@ -166,7 +166,7 @@ sub export_gcode {
|
|||||||
# this will add a set of extrusion loops to each layer
|
# this will add a set of extrusion loops to each layer
|
||||||
# as well as generate infill boundaries
|
# as well as generate infill boundaries
|
||||||
$status_cb->(20, "Generating perimeters");
|
$status_cb->(20, "Generating perimeters");
|
||||||
$_->make_perimeters for map @{$_->layers}, @{$self->objects};
|
$_->make_perimeters for @{$self->objects};
|
||||||
|
|
||||||
# this will clip $layer->surfaces to the infill boundaries
|
# this will clip $layer->surfaces to the infill boundaries
|
||||||
# and split them in top/bottom/internal surfaces;
|
# and split them in top/bottom/internal surfaces;
|
||||||
|
@ -157,6 +157,67 @@ sub cleanup {
|
|||||||
@{$self->layers} = ();
|
@{$self->layers} = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub make_perimeters {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
# compare each layer to the one below, and mark those slices needing
|
||||||
|
# one additional inner perimeter, like the top of domed objects-
|
||||||
|
|
||||||
|
# this algorithm makes sure that almost one perimeter is overlapping:
|
||||||
|
my $overlap = $Slic3r::flow_spacing;
|
||||||
|
|
||||||
|
for my $layer_id (0 .. $self->layer_count-2) {
|
||||||
|
my $layer = $self->layers->[$layer_id];
|
||||||
|
my $upper_layer = $self->layers->[$layer_id+1];
|
||||||
|
|
||||||
|
# compute polygons representing the thickness of the first external perimeter of
|
||||||
|
# the upper layer slices
|
||||||
|
my $upper = diff_ex(
|
||||||
|
[ map @$_, map $_->expolygon->offset_ex(+ 0.5 * scale $Slic3r::flow_spacing), @{$upper_layer->slices} ],
|
||||||
|
[ map @$_, map $_->expolygon->offset_ex(- scale($overlap) + (0.5 * scale $Slic3r::flow_spacing)), @{$upper_layer->slices} ],
|
||||||
|
);
|
||||||
|
next if !@$upper;
|
||||||
|
|
||||||
|
# we need to limit our detection to the areas which would actually benefit from
|
||||||
|
# more perimeters. so, let's compute the area we want to ignore
|
||||||
|
my $ignore = [];
|
||||||
|
{
|
||||||
|
my $diff = diff_ex(
|
||||||
|
[ map @$_, map $_->expolygon->offset_ex(- ($Slic3r::perimeters-0.5) * scale $Slic3r::flow_spacing), @{$layer->slices} ],
|
||||||
|
[ map @{$_->expolygon}, @{$upper_layer->slices} ],
|
||||||
|
);
|
||||||
|
$ignore = [ map @$_, map $_->offset_ex(scale $Slic3r::flow_spacing), @$diff ];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $slice (@{$layer->slices}) {
|
||||||
|
my $hypothetical_perimeter_num = $Slic3r::perimeters + 1;
|
||||||
|
CYCLE: while (1) {
|
||||||
|
# compute polygons representing the thickness of the hypotetical new internal perimeter
|
||||||
|
# of our slice
|
||||||
|
my $hypothetical_perimeter;
|
||||||
|
{
|
||||||
|
my $outer = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-1.5) * scale $Slic3r::flow_spacing) ];
|
||||||
|
last CYCLE if !@$outer;
|
||||||
|
my $inner = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-0.5) * scale $Slic3r::flow_spacing) ];
|
||||||
|
last CYCLE if !@$inner;
|
||||||
|
$hypothetical_perimeter = diff_ex($outer, $inner);
|
||||||
|
}
|
||||||
|
last CYCLE if !@$hypothetical_perimeter;
|
||||||
|
|
||||||
|
|
||||||
|
my $intersection = intersection_ex([ map @$_, @$upper ], [ map @$_, @$hypothetical_perimeter ]);
|
||||||
|
$intersection = diff_ex([ map @$_, @$intersection ], $ignore) if @$ignore;
|
||||||
|
last CYCLE if !@{ $intersection };
|
||||||
|
Slic3r::debugf " adding one more perimeter at layer %d\n", $layer_id;
|
||||||
|
$slice->additional_inner_perimeters(($slice->additional_inner_perimeters || 0) + 1);
|
||||||
|
$hypothetical_perimeter_num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$_->make_perimeters for @{$self->layers};
|
||||||
|
}
|
||||||
|
|
||||||
sub detect_surfaces_type {
|
sub detect_surfaces_type {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Slic3r::debugf "Detecting solid surfaces...\n";
|
Slic3r::debugf "Detecting solid surfaces...\n";
|
||||||
|
@ -6,13 +6,14 @@ 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;
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
my %args = @_;
|
my %args = @_;
|
||||||
|
|
||||||
my $self = [
|
my $self = [
|
||||||
map delete $args{$_}, qw(expolygon surface_type depth_layers bridge_angle),
|
map delete $args{$_}, qw(expolygon surface_type depth_layers bridge_angle additional_inner_perimeters),
|
||||||
];
|
];
|
||||||
$self->[S_DEPTH_LAYERS] //= 1; #/
|
$self->[S_DEPTH_LAYERS] //= 1; #/
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ sub expolygon { $_[0][S_EXPOLYGON] }
|
|||||||
sub surface_type { $_[0][S_SURFACE_TYPE] = $_[1] if $_[1]; $_[0][S_SURFACE_TYPE] }
|
sub surface_type { $_[0][S_SURFACE_TYPE] = $_[1] if $_[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] }
|
sub bridge_angle { $_[0][S_BRIDGE_ANGLE] }
|
||||||
|
sub additional_inner_perimeters { $_[0][S_ADDITIONAL_INNER_PERIMETERS] = $_[1] if $_[1]; $_[0][S_ADDITIONAL_INNER_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