Optimization: cache scaled flow width and spacing

This commit is contained in:
Alessandro Ranellucci 2012-09-23 03:03:08 +02:00
parent ec0d3987db
commit bbe0a45b58
9 changed files with 46 additions and 35 deletions

View file

@ -99,7 +99,7 @@ sub make_fill {
# add spacing between adjacent surfaces # add spacing between adjacent surfaces
{ {
my $distance = scale $layer->infill_flow->spacing / 2; my $distance = $layer->infill_flow->scaled_spacing / 2;
my @offsets = (); my @offsets = ();
foreach my $surface (@surfaces) { foreach my $surface (@surfaces) {
my $expolygon = $surface->expolygon; my $expolygon = $surface->expolygon;

View file

@ -63,7 +63,7 @@ sub fill_surface {
my $path = $loop->split_at_index($index); my $path = $loop->split_at_index($index);
# clip the path to avoid the extruder to get exactly on the first point of the loop # clip the path to avoid the extruder to get exactly on the first point of the loop
$path->clip_end(scale($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) * 0.15); $path->clip_end($self->layer ? $self->layer->flow->scaled_width : $Slic3r::flow->scaled_width * 0.15);
push @paths, $path->points if @{$path->points}; push @paths, $path->points if @{$path->points};
} }

View file

@ -21,7 +21,7 @@ sub fill_surface {
# infill math # infill math
my $min_spacing = scale $params{flow_spacing}; my $min_spacing = scale $params{flow_spacing};
my $distance = $min_spacing / $params{density}; my $distance = $min_spacing / $params{density};
my $overlap_distance = scale($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) * 0.4; my $overlap_distance = $self->layer ? $self->layer->flow->scaled_width : $Slic3r::flow->scaled_width * 0.4;
my $cache_id = sprintf "d%s_s%s_a%s", my $cache_id = sprintf "d%s_s%s_a%s",
$params{density}, $params{flow_spacing}, $rotate_vector->[0][0]; $params{density}, $params{flow_spacing}, $rotate_vector->[0][0];

View file

@ -31,7 +31,7 @@ sub fill_surface {
$flow_spacing = unscale $distance_between_lines; $flow_spacing = unscale $distance_between_lines;
} }
my $overlap_distance = scale($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) * 0.4; my $overlap_distance = $self->layer ? $self->layer->flow->scaled_width : $Slic3r::flow->scaled_width * 0.4;
my $x = $bounding_box->[X1]; my $x = $bounding_box->[X1];
my $is_line_pattern = $self->isa('Slic3r::Fill::Line'); my $is_line_pattern = $self->isa('Slic3r::Fill::Line');

View file

@ -1,13 +1,15 @@
package Slic3r::Flow; package Slic3r::Flow;
use Moo; use Moo;
use Slic3r::Geometry qw(PI); use Slic3r::Geometry qw(PI scale);
has 'nozzle_diameter' => (is => 'ro', required => 1); has 'nozzle_diameter' => (is => 'ro', required => 1);
has 'layer_height' => (is => 'ro', default => sub { $Slic3r::Config->layer_height }); has 'layer_height' => (is => 'ro', default => sub { $Slic3r::Config->layer_height });
has 'width' => (is => 'rwp', builder => 1); has 'width' => (is => 'rwp', builder => 1);
has 'spacing' => (is => 'lazy'); has 'spacing' => (is => 'lazy');
has 'scaled_width' => (is => 'lazy');
has 'scaled_spacing' => (is => 'lazy');
sub BUILD { sub BUILD {
my $self = shift; my $self = shift;
@ -55,4 +57,14 @@ sub _build_spacing {
return $self->width - &Slic3r::OVERLAP_FACTOR * ($self->width - $min_flow_spacing); return $self->width - &Slic3r::OVERLAP_FACTOR * ($self->width - $min_flow_spacing);
} }
sub _build_scaled_width {
my $self = shift;
return scale $self->width;
}
sub _build_scaled_spacing {
my $self = shift;
return scale $self->spacing;
}
1; 1;

View file

@ -101,7 +101,7 @@ sub extrude_loop {
# clip the path to avoid the extruder to get exactly on the first point of the loop; # clip the path to avoid the extruder to get exactly on the first point of the loop;
# if polyline was shorter than the clipping distance we'd get a null polyline, so # if polyline was shorter than the clipping distance we'd get a null polyline, so
# we discard it in that case # we discard it in that case
$extrusion_path->clip_end(scale($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) * 0.15); $extrusion_path->clip_end($self->layer ? $self->layer->flow->scaled_width : $Slic3r::flow->scaled_width * 0.15);
return '' if !@{$extrusion_path->polyline}; return '' if !@{$extrusion_path->polyline};
# extrude along the path # extrude along the path

View file

@ -83,7 +83,7 @@ sub make_surfaces {
# the contours must be offsetted by half extrusion width inwards # the contours must be offsetted by half extrusion width inwards
{ {
my $distance = scale $self->perimeter_flow->width / 2; my $distance = $self->perimeter_flow->scaled_width / 2;
my @surfaces = @{$self->slices}; my @surfaces = @{$self->slices};
@{$self->slices} = (); @{$self->slices} = ();
foreach my $surface (@surfaces) { foreach my $surface (@surfaces) {
@ -104,10 +104,10 @@ sub make_surfaces {
$self->thin_walls([]); $self->thin_walls([]);
if (@$diff) { if (@$diff) {
my $area_threshold = scale($self->perimeter_flow->spacing) ** 2; my $area_threshold = $self->perimeter_flow->scaled_spacing ** 2;
@$diff = grep $_->area > ($area_threshold), @$diff; @$diff = grep $_->area > ($area_threshold), @$diff;
@{$self->thin_walls} = map $_->medial_axis(scale $self->perimeter_flow->width), @$diff; @{$self->thin_walls} = map $_->medial_axis($self->perimeter_flow->scaled_width), @$diff;
Slic3r::debugf " %d thin walls detected\n", scalar(@{$self->thin_walls}) if @{$self->thin_walls}; Slic3r::debugf " %d thin walls detected\n", scalar(@{$self->thin_walls}) if @{$self->thin_walls};
} }
@ -125,7 +125,7 @@ sub make_surfaces {
sub make_perimeters { sub make_perimeters {
my $self = shift; my $self = shift;
my $gap_area_threshold = scale($self->perimeter_flow->width)** 2; my $gap_area_threshold = $self->perimeter_flow->scaled_width ** 2;
# this array will hold one arrayref per original surface (island); # this array will hold one arrayref per original surface (island);
# each item of this arrayref is an arrayref representing a depth (from outer # each item of this arrayref is an arrayref representing a depth (from outer
@ -162,12 +162,12 @@ sub make_perimeters {
# this compensation only works for circular holes, while it would # this compensation only works for circular holes, while it would
# overcompensate for hexagons and other shapes having straight edges. # overcompensate for hexagons and other shapes having straight edges.
# so we require a minimum number of vertices. # so we require a minimum number of vertices.
next unless $circumference / @$hole >= scale 3 * $Slic3r::flow->width; next unless $circumference / @$hole >= 3 * $Slic3r::flow->scaled_width;
# revert the compensation done in make_surfaces() and get the actual radius # revert the compensation done in make_surfaces() and get the actual radius
# of the hole # of the hole
my $radius = ($circumference / PI / 2) - scale $self->perimeter_flow->spacing/2; my $radius = ($circumference / PI / 2) - $self->perimeter_flow->scaled_spacing/2;
my $new_radius = (scale($self->perimeter_flow->width) + sqrt((scale($self->perimeter_flow->width)**2) + (4*($radius**2)))) / 2; my $new_radius = ($self->perimeter_flow->scaled_width + sqrt(($self->perimeter_flow->scaled_width ** 2) + (4*($radius**2)))) / 2;
# holes are always turned to contours, so reverse point order before and after # holes are always turned to contours, so reverse point order before and after
$hole->reverse; $hole->reverse;
my @offsetted = $hole->offset(+ ($new_radius - $radius)); my @offsetted = $hole->offset(+ ($new_radius - $radius));
@ -177,7 +177,7 @@ sub make_perimeters {
} }
} }
my $distance = scale $self->perimeter_flow->spacing; my $distance = $self->perimeter_flow->scaled_spacing;
my @gaps = (); my @gaps = ();
# generate perimeters inwards (loop 0 is the external one) # generate perimeters inwards (loop 0 is the external one)
@ -211,7 +211,7 @@ sub make_perimeters {
# detect the small gaps that we need to treat like thin polygons, # detect the small gaps that we need to treat like thin polygons,
# thus generating the skeleton and using it to fill them # thus generating the skeleton and using it to fill them
push @{ $self->thin_fills }, push @{ $self->thin_fills },
map $_->medial_axis(scale $self->perimeter_flow->width), map $_->medial_axis($self->perimeter_flow->scaled_width),
@gaps; @gaps;
Slic3r::debugf " %d gaps filled\n", scalar @{ $self->thin_fills } Slic3r::debugf " %d gaps filled\n", scalar @{ $self->thin_fills }
if @{ $self->thin_fills }; if @{ $self->thin_fills };
@ -324,7 +324,7 @@ sub prepare_fill_surfaces {
# remove unprintable regions (they would slow down the infill process and also cause # remove unprintable regions (they would slow down the infill process and also cause
# some weird failures during bridge neighbor detection) # some weird failures during bridge neighbor detection)
{ {
my $distance = scale $self->infill_flow->spacing / 2; my $distance = $self->infill_flow->scaled_spacing / 2;
@surfaces = map { @surfaces = map {
my $surface = $_; my $surface = $_;

View file

@ -573,7 +573,7 @@ sub make_brim {
return unless $Slic3r::Config->brim_width > 0; return unless $Slic3r::Config->brim_width > 0;
my $flow = $Slic3r::first_layer_flow || $Slic3r::flow; my $flow = $Slic3r::first_layer_flow || $Slic3r::flow;
my $grow_distance = scale $flow->width / 2; my $grow_distance = $flow->scaled_width / 2;
my @islands = (); # array of polygons my @islands = (); # array of polygons
foreach my $obj_idx (0 .. $#{$self->objects}) { foreach my $obj_idx (0 .. $#{$self->objects}) {
my $layer0 = $self->objects->[$obj_idx]->layers->[0]; my $layer0 = $self->objects->[$obj_idx]->layers->[0];
@ -593,7 +593,7 @@ sub make_brim {
push @{$self->brim}, Slic3r::ExtrusionLoop->pack( push @{$self->brim}, Slic3r::ExtrusionLoop->pack(
polygon => Slic3r::Polygon->new($_), polygon => Slic3r::Polygon->new($_),
role => EXTR_ROLE_SKIRT, role => EXTR_ROLE_SKIRT,
) for @{Math::Clipper::offset(\@islands, $i * scale $flow->spacing, 100, JT_SQUARE)}; ) for @{Math::Clipper::offset(\@islands, $i * $flow->scaled_spacing, 100, JT_SQUARE)};
} }
} }

View file

@ -179,18 +179,17 @@ sub make_perimeters {
if ($Slic3r::Config->extra_perimeters && $Slic3r::Config->perimeters > 0) { if ($Slic3r::Config->extra_perimeters && $Slic3r::Config->perimeters > 0) {
for my $region_id (0 .. ($self->print->regions_count-1)) { for my $region_id (0 .. ($self->print->regions_count-1)) {
for my $layer_id (0 .. $self->layer_count-2) { for my $layer_id (0 .. $self->layer_count-2) {
my $layerm = $self->layers->[$layer_id]->regions->[$region_id]; my $layerm = $self->layers->[$layer_id]->regions->[$region_id];
my $upper_layerm = $self->layers->[$layer_id+1]->regions->[$region_id]; my $upper_layerm = $self->layers->[$layer_id+1]->regions->[$region_id];
my $perimeter_flow_spacing = $layerm->perimeter_flow->spacing; my $perimeter_flow = $layerm->perimeter_flow;
my $scaled_perimeter_flow_spacing = scale $perimeter_flow_spacing;
my $overlap = $perimeter_flow_spacing; # one perimeter my $overlap = $perimeter_flow->spacing; # one perimeter
# compute polygons representing the thickness of the first external perimeter of # compute polygons representing the thickness of the first external perimeter of
# the upper layer slices # the upper layer slices
my $upper = diff_ex( my $upper = diff_ex(
[ map @$_, map $_->expolygon->offset_ex(+ 0.5 * $scaled_perimeter_flow_spacing), @{$upper_layerm->slices} ], [ map @$_, map $_->expolygon->offset_ex(+ 0.5 * $perimeter_flow->scaled_spacing), @{$upper_layerm->slices} ],
[ map @$_, map $_->expolygon->offset_ex(- scale($overlap) + (0.5 * $scaled_perimeter_flow_spacing)), @{$upper_layerm->slices} ], [ map @$_, map $_->expolygon->offset_ex(- scale($overlap) + (0.5 * $perimeter_flow->scaled_spacing)), @{$upper_layerm->slices} ],
); );
next if !@$upper; next if !@$upper;
@ -199,10 +198,10 @@ sub make_perimeters {
my $ignore = []; my $ignore = [];
{ {
my $diff = diff_ex( my $diff = diff_ex(
[ map @$_, map $_->expolygon->offset_ex(- ($Slic3r::Config->perimeters-0.5) * $scaled_perimeter_flow_spacing), @{$layerm->slices} ], [ map @$_, map $_->expolygon->offset_ex(- ($Slic3r::Config->perimeters-0.5) * $perimeter_flow->scaled_spacing), @{$layerm->slices} ],
[ map @{$_->expolygon}, @{$upper_layerm->slices} ], [ map @{$_->expolygon}, @{$upper_layerm->slices} ],
); );
$ignore = [ map @$_, map $_->offset_ex($scaled_perimeter_flow_spacing), @$diff ]; $ignore = [ map @$_, map $_->offset_ex($perimeter_flow->scaled_spacing), @$diff ];
} }
foreach my $slice (@{$layerm->slices}) { foreach my $slice (@{$layerm->slices}) {
@ -212,9 +211,9 @@ sub make_perimeters {
# of our slice # of our slice
my $hypothetical_perimeter; my $hypothetical_perimeter;
{ {
my $outer = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-1.5) * $scaled_perimeter_flow_spacing) ]; my $outer = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-1.5) * $perimeter_flow->scaled_spacing) ];
last CYCLE if !@$outer; last CYCLE if !@$outer;
my $inner = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-0.5) * $scaled_perimeter_flow_spacing) ]; my $inner = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-0.5) * $perimeter_flow->scaled_spacing) ];
last CYCLE if !@$inner; last CYCLE if !@$inner;
$hypothetical_perimeter = diff_ex($outer, $inner); $hypothetical_perimeter = diff_ex($outer, $inner);
} }
@ -325,7 +324,7 @@ sub discover_horizontal_shells {
Slic3r::debugf "==> DISCOVERING HORIZONTAL SHELLS\n"; Slic3r::debugf "==> DISCOVERING HORIZONTAL SHELLS\n";
my $area_threshold = scale($Slic3r::flow->spacing) ** 2; my $area_threshold = $Slic3r::flow->scaled_spacing ** 2;
for my $region_id (0 .. ($self->print->regions_count-1)) { for my $region_id (0 .. ($self->print->regions_count-1)) {
for (my $i = 0; $i < $self->layer_count; $i++) { for (my $i = 0; $i < $self->layer_count; $i++) {
@ -333,7 +332,7 @@ sub discover_horizontal_shells {
foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM) { foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM) {
# find surfaces of current type for current layer # find surfaces of current type for current layer
# and offset them to take perimeters into account # and offset them to take perimeters into account
my @surfaces = map $_->offset($Slic3r::Config->perimeters * scale $layerm->perimeter_flow->width), my @surfaces = map $_->offset($Slic3r::Config->perimeters * $layerm->perimeter_flow->scaled_width),
grep $_->surface_type == $type, @{$layerm->fill_surfaces} or next; grep $_->surface_type == $type, @{$layerm->fill_surfaces} or next;
my $surfaces_p = [ map $_->p, @surfaces ]; my $surfaces_p = [ map $_->p, @surfaces ];
Slic3r::debugf "Layer %d has %d surfaces of type '%s'\n", Slic3r::debugf "Layer %d has %d surfaces of type '%s'\n",
@ -413,7 +412,7 @@ sub combine_infill {
my $self = shift; my $self = shift;
return unless $Slic3r::Config->infill_every_layers > 1 && $Slic3r::Config->fill_density > 0; return unless $Slic3r::Config->infill_every_layers > 1 && $Slic3r::Config->fill_density > 0;
my $area_threshold = scale($Slic3r::flow->spacing) ** 2; my $area_threshold = $Slic3r::flow->scaled_spacing ** 2;
for my $region_id (0 .. ($self->print->regions_count-1)) { for my $region_id (0 .. ($self->print->regions_count-1)) {
# start from bottom, skip first layer # start from bottom, skip first layer
@ -505,7 +504,7 @@ sub generate_support_material {
my $flow = $self->print->support_material_flow; my $flow = $self->print->support_material_flow;
my $threshold_rad = deg2rad($Slic3r::Config->support_material_threshold + 1); # +1 makes the threshold inclusive my $threshold_rad = deg2rad($Slic3r::Config->support_material_threshold + 1); # +1 makes the threshold inclusive
my $overhang_width = $threshold_rad == 0 ? undef : scale $Slic3r::Config->layer_height * ((cos $threshold_rad) / (sin $threshold_rad)); my $overhang_width = $threshold_rad == 0 ? undef : scale $Slic3r::Config->layer_height * ((cos $threshold_rad) / (sin $threshold_rad));
my $distance_from_object = 1.5 * scale $flow->width; my $distance_from_object = 1.5 * $flow->scaled_width;
# determine support regions in each layer (for upper layers) # determine support regions in each layer (for upper layers)
Slic3r::debugf "Detecting regions\n"; Slic3r::debugf "Detecting regions\n";
@ -529,7 +528,7 @@ sub generate_support_material {
[ map @$_, @current_support_regions ], [ map @$_, @current_support_regions ],
[ map @$_, map $_->offset_ex($distance_from_object), @{$layer->slices} ], [ map @$_, map $_->offset_ex($distance_from_object), @{$layer->slices} ],
); );
$_->simplify(scale $flow->spacing * 2) for @{$layers{$i}}; $_->simplify($flow->scaled_spacing * 2) for @{$layers{$i}};
# step 2: get layer overhangs and put them into queue for adding support inside lower layers # step 2: get layer overhangs and put them into queue for adding support inside lower layers
# we need an angle threshold for this # we need an angle threshold for this
@ -551,7 +550,7 @@ sub generate_support_material {
my $support_patterns = []; # in case we want cross-hatching my $support_patterns = []; # in case we want cross-hatching
{ {
# 0.5 makes sure the paths don't get clipped externally when applying them to layers # 0.5 makes sure the paths don't get clipped externally when applying them to layers
my @support_material_areas = map $_->offset_ex(- 0.5 * scale $flow->width), my @support_material_areas = map $_->offset_ex(- 0.5 * $flow->scaled_width),
@{union_ex([ map $_->contour, map @$_, values %layers ])}; @{union_ex([ map $_->contour, map @$_, values %layers ])};
my $fill = Slic3r::Fill->new(print => $self->print); my $fill = Slic3r::Fill->new(print => $self->print);