Optimization: cache scaled flow width and spacing

degen-loop-screen
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
{
my $distance = scale $layer->infill_flow->spacing / 2;
my $distance = $layer->infill_flow->scaled_spacing / 2;
my @offsets = ();
foreach my $surface (@surfaces) {
my $expolygon = $surface->expolygon;

View File

@ -63,7 +63,7 @@ sub fill_surface {
my $path = $loop->split_at_index($index);
# 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};
}

View File

@ -21,7 +21,7 @@ sub fill_surface {
# infill math
my $min_spacing = scale $params{flow_spacing};
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",
$params{density}, $params{flow_spacing}, $rotate_vector->[0][0];

View File

@ -31,7 +31,7 @@ sub fill_surface {
$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 $is_line_pattern = $self->isa('Slic3r::Fill::Line');

View File

@ -1,13 +1,15 @@
package Slic3r::Flow;
use Moo;
use Slic3r::Geometry qw(PI);
use Slic3r::Geometry qw(PI scale);
has 'nozzle_diameter' => (is => 'ro', required => 1);
has 'layer_height' => (is => 'ro', default => sub { $Slic3r::Config->layer_height });
has 'width' => (is => 'rwp', builder => 1);
has 'spacing' => (is => 'lazy');
has 'scaled_width' => (is => 'lazy');
has 'scaled_spacing' => (is => 'lazy');
sub BUILD {
my $self = shift;
@ -55,4 +57,14 @@ sub _build_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;

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;
# if polyline was shorter than the clipping distance we'd get a null polyline, so
# 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};
# extrude along the path

View File

@ -83,7 +83,7 @@ sub make_surfaces {
# 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};
@{$self->slices} = ();
foreach my $surface (@surfaces) {
@ -104,10 +104,10 @@ sub make_surfaces {
$self->thin_walls([]);
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;
@{$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};
}
@ -125,7 +125,7 @@ sub make_surfaces {
sub make_perimeters {
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);
# 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
# overcompensate for hexagons and other shapes having straight edges.
# 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
# of the hole
my $radius = ($circumference / PI / 2) - scale $self->perimeter_flow->spacing/2;
my $new_radius = (scale($self->perimeter_flow->width) + sqrt((scale($self->perimeter_flow->width)**2) + (4*($radius**2)))) / 2;
my $radius = ($circumference / PI / 2) - $self->perimeter_flow->scaled_spacing/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
$hole->reverse;
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 = ();
# 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,
# thus generating the skeleton and using it to fill them
push @{ $self->thin_fills },
map $_->medial_axis(scale $self->perimeter_flow->width),
map $_->medial_axis($self->perimeter_flow->scaled_width),
@gaps;
Slic3r::debugf " %d gaps filled\n", scalar @{ $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
# 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 {
my $surface = $_;

View File

@ -573,7 +573,7 @@ sub make_brim {
return unless $Slic3r::Config->brim_width > 0;
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
foreach my $obj_idx (0 .. $#{$self->objects}) {
my $layer0 = $self->objects->[$obj_idx]->layers->[0];
@ -593,7 +593,7 @@ sub make_brim {
push @{$self->brim}, Slic3r::ExtrusionLoop->pack(
polygon => Slic3r::Polygon->new($_),
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) {
for my $region_id (0 .. ($self->print->regions_count-1)) {
for my $layer_id (0 .. $self->layer_count-2) {
my $layerm = $self->layers->[$layer_id]->regions->[$region_id];
my $upper_layerm = $self->layers->[$layer_id+1]->regions->[$region_id];
my $perimeter_flow_spacing = $layerm->perimeter_flow->spacing;
my $scaled_perimeter_flow_spacing = scale $perimeter_flow_spacing;
my $layerm = $self->layers->[$layer_id]->regions->[$region_id];
my $upper_layerm = $self->layers->[$layer_id+1]->regions->[$region_id];
my $perimeter_flow = $layerm->perimeter_flow;
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
# the upper layer slices
my $upper = diff_ex(
[ map @$_, map $_->expolygon->offset_ex(+ 0.5 * $scaled_perimeter_flow_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(+ 0.5 * $perimeter_flow->scaled_spacing), @{$upper_layerm->slices} ],
[ map @$_, map $_->expolygon->offset_ex(- scale($overlap) + (0.5 * $perimeter_flow->scaled_spacing)), @{$upper_layerm->slices} ],
);
next if !@$upper;
@ -199,10 +198,10 @@ sub make_perimeters {
my $ignore = [];
{
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} ],
);
$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}) {
@ -212,9 +211,9 @@ sub make_perimeters {
# of our slice
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;
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;
$hypothetical_perimeter = diff_ex($outer, $inner);
}
@ -325,7 +324,7 @@ sub discover_horizontal_shells {
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 $i = 0; $i < $self->layer_count; $i++) {
@ -333,7 +332,7 @@ sub discover_horizontal_shells {
foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM) {
# find surfaces of current type for current layer
# 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;
my $surfaces_p = [ map $_->p, @surfaces ];
Slic3r::debugf "Layer %d has %d surfaces of type '%s'\n",
@ -413,7 +412,7 @@ sub combine_infill {
my $self = shift;
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)) {
# start from bottom, skip first layer
@ -505,7 +504,7 @@ sub generate_support_material {
my $flow = $self->print->support_material_flow;
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 $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)
Slic3r::debugf "Detecting regions\n";
@ -529,7 +528,7 @@ sub generate_support_material {
[ map @$_, @current_support_regions ],
[ 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
# we need an angle threshold for this
@ -551,7 +550,7 @@ sub generate_support_material {
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
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 ])};
my $fill = Slic3r::Fill->new(print => $self->print);