Incomplete work for refactoring regions and flows

This commit is contained in:
Alessandro Ranellucci 2013-12-30 18:28:41 +01:00
parent 231bffa99b
commit beb1baa096
13 changed files with 297 additions and 148 deletions

View file

@ -3,6 +3,7 @@ use Moo;
use List::Util qw(sum first);
use Slic3r::ExtrusionPath ':roles';
use Slic3r::Flow ':roles';
use Slic3r::Geometry qw(PI A B scale unscale chained_path points_coincide);
use Slic3r::Geometry::Clipper qw(union_ex diff_ex intersection_ex
offset offset2 offset2_ex union_pt diff intersection
@ -17,10 +18,6 @@ has 'layer' => (
handles => [qw(id slice_z print_z height flow config)],
);
has 'region' => (is => 'ro', required => 1, handles => [qw(extruders)]);
has 'perimeter_flow' => (is => 'rw');
has 'infill_flow' => (is => 'rw');
has 'solid_infill_flow' => (is => 'rw');
has 'top_infill_flow' => (is => 'rw');
has 'infill_area_threshold' => (is => 'lazy');
has 'overhang_width' => (is => 'lazy');
@ -40,43 +37,26 @@ has 'perimeters' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collect
# ordered collection of extrusion paths to fill surfaces
has 'fills' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new });
sub BUILD {
my $self = shift;
$self->_update_flows;
}
sub _trigger_layer {
my $self = shift;
$self->_update_flows;
}
sub _update_flows {
my $self = shift;
return if !$self->region;
if ($self->id == 0) {
for (qw(perimeter infill solid_infill top_infill)) {
my $method = "${_}_flow";
$self->$method
($self->region->first_layer_flows->{$_} || $self->region->flows->{$_});
}
} else {
$self->perimeter_flow($self->region->flows->{perimeter});
$self->infill_flow($self->region->flows->{infill});
$self->solid_infill_flow($self->region->flows->{solid_infill});
$self->top_infill_flow($self->region->flows->{top_infill});
}
}
sub _build_overhang_width {
my $self = shift;
my $threshold_rad = PI/2 - atan2($self->perimeter_flow->width / $self->height / 2, 1);
my $threshold_rad = PI/2 - atan2($self->flow(FLOW_ROLE_PERIMETER)->width / $self->height / 2, 1);
return scale($self->height * ((cos $threshold_rad) / (sin $threshold_rad)));
}
sub _build_infill_area_threshold {
my $self = shift;
return $self->solid_infill_flow->scaled_spacing ** 2;
return $self->flow(FLOW_ROLE_SOLID_INFILL)->scaled_spacing ** 2;
}
sub flow {
my ($self, $role, $bridge, $width) = @_;
return $self->region->flow(
$role,
$self->layer->height,
$bridge // 0,
$self->layer->id == 0,
$width,
);
}
# build polylines from lines
@ -145,10 +125,11 @@ sub _merge_loops {
sub make_perimeters {
my $self = shift;
my $pwidth = $self->perimeter_flow->scaled_width;
my $pspacing = $self->perimeter_flow->scaled_spacing;
my $ispacing = $self->solid_infill_flow->scaled_spacing;
my $gap_area_threshold = $self->perimeter_flow->scaled_width ** 2;
my $perimeter_flow = $self->flow(FLOW_ROLE_PERIMETER);
my $pwidth = $perimeter_flow->scaled_width;
my $pspacing = $perimeter_flow->scaled_spacing;
my $ispacing = $self->flow(FLOW_ROLE_SOLID_INFILL)->scaled_spacing;
my $gap_area_threshold = $pwidth ** 2;
$self->perimeters->clear;
$self->fill_surfaces->clear;
@ -284,7 +265,7 @@ sub make_perimeters {
push @loops, Slic3r::ExtrusionLoop->new(
polygon => $polygon,
role => $role,
flow_spacing => $self->perimeter_flow->spacing,
flow_spacing => $perimeter_flow->spacing,
);
}
return @loops;
@ -311,7 +292,7 @@ sub make_perimeters {
next if $p->length <= $pspacing * 2;
my %params = (
role => EXTR_ROLE_EXTERNAL_PERIMETER,
flow_spacing => $self->perimeter_flow->spacing,
flow_spacing => $perimeter_flow->spacing,
);
push @paths, $p->isa('Slic3r::Polygon')
? Slic3r::ExtrusionLoop->new(polygon => $p, %params)
@ -345,10 +326,10 @@ sub _fill_gaps {
# we could try with 1.5*$w for example, but that doesn't work well for zigzag fill
# because it tends to create very sparse points along the gap when the infill direction
# is not parallel to the gap (1.5*$w thus may only work well with a straight line)
my $w = $self->perimeter_flow->width;
my $w = $self->flow(FLOW_ROLE_PERIMETER)->width;
my @widths = ($w, 0.4 * $w); # worth trying 0.2 too?
foreach my $width (@widths) {
my $flow = $self->perimeter_flow->clone(width => $width);
my $flow = $self->flow(FLOW_ROLE_PERIMETER, 0, $width);
# extract the gaps having this width
my @this_width = map @{$_->offset_ex(+0.5*$flow->scaled_width)},
@ -499,7 +480,10 @@ sub process_external_surfaces {
sub _detect_bridge_direction {
my ($self, $expolygon, $lower_layer) = @_;
my $grown = $expolygon->offset_ex(+$self->perimeter_flow->scaled_width);
my $perimeter_flow = $self->flow(FLOW_ROLE_PERIMETER);
my $infill_flow = $self->flow(FLOW_ROLE_INFILL);
my $grown = $expolygon->offset_ex(+$perimeter_flow->scaled_width);
my @lower = @{$lower_layer->slices}; # expolygons
# detect what edges lie on lower slices
@ -554,7 +538,7 @@ sub _detect_bridge_direction {
}
} elsif (@edges) {
# inset the bridge expolygon; we'll use this one to clip our test lines
my $inset = $expolygon->offset_ex($self->infill_flow->scaled_width);
my $inset = $expolygon->offset_ex($infill_flow->scaled_width);
# detect anchors as intersection between our bridge expolygon and the lower slices
my $anchors = intersection_ex(
@ -568,7 +552,7 @@ sub _detect_bridge_direction {
# endpoints within anchors
my %directions = (); # angle => score
my $angle_increment = PI/36; # 5°
my $line_increment = $self->infill_flow->scaled_width;
my $line_increment = $infill_flow->scaled_width;
for (my $angle = 0; $angle <= PI; $angle += $angle_increment) {
# rotate everything - the center point doesn't matter
$_->rotate($angle, [0,0]) for @$inset, @$anchors;