Finished porting LayerRegion to C++
This commit is contained in:
parent
5b8ed7367a
commit
9fcec10737
28 changed files with 319 additions and 203 deletions
|
@ -48,9 +48,9 @@ sub make_fill {
|
|||
my $self = shift;
|
||||
my ($layerm) = @_;
|
||||
|
||||
Slic3r::debugf "Filling layer %d:\n", $layerm->id;
|
||||
Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id;
|
||||
|
||||
my $fill_density = $layerm->config->fill_density;
|
||||
my $fill_density = $layerm->region->config->fill_density;
|
||||
my $infill_flow = $layerm->flow(FLOW_ROLE_INFILL);
|
||||
my $solid_infill_flow = $layerm->flow(FLOW_ROLE_SOLID_INFILL);
|
||||
my $top_solid_infill_flow = $layerm->flow(FLOW_ROLE_TOP_SOLID_INFILL);
|
||||
|
@ -74,13 +74,13 @@ sub make_fill {
|
|||
for (my $i = 0; $i <= $#groups; $i++) {
|
||||
# we can only merge solid non-bridge surfaces, so discard
|
||||
# non-solid surfaces
|
||||
if ($groups[$i][0]->is_solid && (!$groups[$i][0]->is_bridge || $layerm->id == 0)) {
|
||||
if ($groups[$i][0]->is_solid && (!$groups[$i][0]->is_bridge || $layerm->layer->id == 0)) {
|
||||
$is_solid[$i] = 1;
|
||||
$fw[$i] = ($groups[$i][0]->surface_type == S_TYPE_TOP)
|
||||
? $top_solid_infill_flow->width
|
||||
: $solid_infill_flow->width;
|
||||
$pattern[$i] = $groups[$i][0]->is_external
|
||||
? $layerm->config->external_fill_pattern
|
||||
? $layerm->region->config->external_fill_pattern
|
||||
: 'rectilinear';
|
||||
} else {
|
||||
$is_solid[$i] = 0;
|
||||
|
@ -179,19 +179,19 @@ sub make_fill {
|
|||
my @fills = ();
|
||||
SURFACE: foreach my $surface (@surfaces) {
|
||||
next if $surface->surface_type == S_TYPE_INTERNALVOID;
|
||||
my $filler = $layerm->config->fill_pattern;
|
||||
my $filler = $layerm->region->config->fill_pattern;
|
||||
my $density = $fill_density;
|
||||
my $role = ($surface->surface_type == S_TYPE_TOP) ? FLOW_ROLE_TOP_SOLID_INFILL
|
||||
: $surface->is_solid ? FLOW_ROLE_SOLID_INFILL
|
||||
: FLOW_ROLE_INFILL;
|
||||
my $is_bridge = $layerm->id > 0 && $surface->is_bridge;
|
||||
my $is_bridge = $layerm->layer->id > 0 && $surface->is_bridge;
|
||||
my $is_solid = $surface->is_solid;
|
||||
|
||||
if ($surface->is_solid) {
|
||||
$density = 100;
|
||||
$filler = 'rectilinear';
|
||||
if ($surface->is_external && !$is_bridge) {
|
||||
$filler = $layerm->config->external_fill_pattern;
|
||||
$filler = $layerm->region->config->external_fill_pattern;
|
||||
}
|
||||
} else {
|
||||
next SURFACE unless $density > 0;
|
||||
|
@ -201,14 +201,14 @@ sub make_fill {
|
|||
my $f = $self->filler($filler);
|
||||
|
||||
# calculate the actual flow we'll be using for this infill
|
||||
my $h = $surface->thickness == -1 ? $layerm->height : $surface->thickness;
|
||||
my $h = $surface->thickness == -1 ? $layerm->layer->height : $surface->thickness;
|
||||
my $flow = $layerm->region->flow(
|
||||
$role,
|
||||
$h,
|
||||
$is_bridge || $f->use_bridge_flow,
|
||||
$layerm->id == 0,
|
||||
$layerm->layer->id == 0,
|
||||
-1,
|
||||
$layerm->object,
|
||||
$layerm->layer->object,
|
||||
);
|
||||
|
||||
# calculate flow spacing for infill pattern generation
|
||||
|
@ -220,11 +220,11 @@ sub make_fill {
|
|||
# layer height
|
||||
my $internal_flow = $layerm->region->flow(
|
||||
FLOW_ROLE_INFILL,
|
||||
$layerm->object->config->layer_height, # TODO: handle infill_every_layers?
|
||||
$layerm->layer->object->config->layer_height, # TODO: handle infill_every_layers?
|
||||
0, # no bridge
|
||||
0, # no first layer
|
||||
-1, # auto width
|
||||
$layerm->object,
|
||||
$layerm->layer->object,
|
||||
);
|
||||
$f->spacing($internal_flow->spacing);
|
||||
$using_internal_flow = 1;
|
||||
|
@ -232,9 +232,9 @@ sub make_fill {
|
|||
$f->spacing($flow->spacing);
|
||||
}
|
||||
|
||||
$f->layer_id($layerm->id);
|
||||
$f->z($layerm->print_z);
|
||||
$f->angle(deg2rad($layerm->config->fill_angle));
|
||||
$f->layer_id($layerm->layer->id);
|
||||
$f->z($layerm->layer->print_z);
|
||||
$f->angle(deg2rad($layerm->region->config->fill_angle));
|
||||
$f->loop_clipping(scale($flow->nozzle_diameter) * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER);
|
||||
|
||||
# apply half spacing using this flow's own spacing and generate infill
|
||||
|
|
|
@ -41,24 +41,25 @@ sub make_perimeters {
|
|||
|
||||
for my $region_id (0..$#{$self->regions}) {
|
||||
next if $done{$region_id};
|
||||
my $layerm = $self->regions->[$region_id];
|
||||
my $layerm = $self->get_region($region_id);
|
||||
my $config = $layerm->region->config;
|
||||
$done{$region_id} = 1;
|
||||
|
||||
# find compatible regions
|
||||
my @layerms = ($layerm);
|
||||
for my $i (($region_id+1)..$#{$self->regions}) {
|
||||
my $config = $self->regions->[$i]->config;
|
||||
my $layerm_config = $layerm->config;
|
||||
my $other_layerm = $self->get_region($i);
|
||||
my $other_config = $other_layerm->region->config;
|
||||
|
||||
if ($config->perimeter_extruder == $layerm_config->perimeter_extruder
|
||||
&& $config->perimeters == $layerm_config->perimeters
|
||||
&& $config->perimeter_speed == $layerm_config->perimeter_speed
|
||||
&& $config->gap_fill_speed == $layerm_config->gap_fill_speed
|
||||
&& $config->overhangs == $layerm_config->overhangs
|
||||
&& $config->perimeter_extrusion_width == $layerm_config->perimeter_extrusion_width
|
||||
&& $config->thin_walls == $layerm_config->thin_walls
|
||||
&& $config->external_perimeters_first == $layerm_config->external_perimeters_first) {
|
||||
push @layerms, $self->regions->[$i];
|
||||
if ($config->perimeter_extruder == $other_config->perimeter_extruder
|
||||
&& $config->perimeters == $other_config->perimeters
|
||||
&& $config->perimeter_speed == $other_config->perimeter_speed
|
||||
&& $config->gap_fill_speed == $other_config->gap_fill_speed
|
||||
&& $config->overhangs == $other_config->overhangs
|
||||
&& $config->perimeter_extrusion_width == $other_config->perimeter_extrusion_width
|
||||
&& $config->thin_walls == $other_config->thin_walls
|
||||
&& $config->external_perimeters_first == $other_config->external_perimeters_first) {
|
||||
push @layerms, $other_layerm;
|
||||
$done{$i} = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
package Slic3r::Layer::Region;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Slic3r::ExtrusionPath ':roles';
|
||||
use Slic3r::Flow ':roles';
|
||||
use Slic3r::Geometry qw(scale);
|
||||
use Slic3r::Geometry::Clipper qw(diff_ex intersection_ex
|
||||
);
|
||||
use Slic3r::Surface ':types';
|
||||
|
||||
|
||||
# TODO: lazy
|
||||
sub infill_area_threshold {
|
||||
my $self = shift;
|
||||
return $self->flow(FLOW_ROLE_SOLID_INFILL)->scaled_spacing ** 2;
|
||||
}
|
||||
|
||||
sub id { return $_[0]->layer->id; }
|
||||
sub slice_z { return $_[0]->layer->slice_z; }
|
||||
sub print_z { return $_[0]->layer->print_z; }
|
||||
sub height { return $_[0]->layer->height; }
|
||||
sub object { return $_[0]->layer->object; }
|
||||
sub print { return $_[0]->layer->print; }
|
||||
|
||||
sub config { return $_[0]->region->config; }
|
||||
|
||||
sub process_external_surfaces {
|
||||
my ($self, $lower_layer) = @_;
|
||||
|
||||
my @surfaces = @{$self->fill_surfaces};
|
||||
my $margin = scale &Slic3r::EXTERNAL_INFILL_MARGIN;
|
||||
|
||||
my @bottom = ();
|
||||
foreach my $surface (grep $_->is_bottom, @surfaces) {
|
||||
my $grown = $surface->expolygon->offset_ex(+$margin);
|
||||
|
||||
# detect bridge direction before merging grown surfaces otherwise adjacent bridges
|
||||
# would get merged into a single one while they need different directions
|
||||
# also, supply the original expolygon instead of the grown one, because in case
|
||||
# of very thin (but still working) anchors, the grown expolygon would go beyond them
|
||||
my $angle;
|
||||
if ($lower_layer) {
|
||||
my $bridge_detector = Slic3r::BridgeDetector->new(
|
||||
$surface->expolygon,
|
||||
$lower_layer->slices,
|
||||
$self->flow(FLOW_ROLE_INFILL, $self->height, 1)->scaled_width,
|
||||
);
|
||||
Slic3r::debugf "Processing bridge at layer %d:\n", $self->id;
|
||||
$bridge_detector->detect_angle;
|
||||
$angle = $bridge_detector->angle;
|
||||
|
||||
if (defined $angle && $self->object->config->support_material) {
|
||||
$self->bridged->append(Slic3r::ExPolygon->new($_))
|
||||
for @{ $bridge_detector->coverage_by_angle($angle) };
|
||||
$self->unsupported_bridge_edges->append($_) for @{ $bridge_detector->unsupported_edges };
|
||||
}
|
||||
}
|
||||
|
||||
push @bottom, map $surface->clone(expolygon => $_, bridge_angle => $angle), @$grown;
|
||||
}
|
||||
|
||||
my @top = ();
|
||||
foreach my $surface (grep $_->surface_type == S_TYPE_TOP, @surfaces) {
|
||||
# give priority to bottom surfaces
|
||||
my $grown = diff_ex(
|
||||
$surface->expolygon->offset(+$margin),
|
||||
[ map $_->p, @bottom ],
|
||||
);
|
||||
push @top, map $surface->clone(expolygon => $_), @$grown;
|
||||
}
|
||||
|
||||
# if we're slicing with no infill, we can't extend external surfaces
|
||||
# over non-existent infill
|
||||
my @fill_boundaries = $self->config->fill_density > 0
|
||||
? @surfaces
|
||||
: grep $_->surface_type != S_TYPE_INTERNAL, @surfaces;
|
||||
|
||||
# intersect the grown surfaces with the actual fill boundaries
|
||||
my @new_surfaces = ();
|
||||
foreach my $group (@{Slic3r::Surface::Collection->new(@top, @bottom)->group}) {
|
||||
push @new_surfaces,
|
||||
map $group->[0]->clone(expolygon => $_),
|
||||
@{intersection_ex(
|
||||
[ map $_->p, @$group ],
|
||||
[ map $_->p, @fill_boundaries ],
|
||||
1, # to ensure adjacent expolygons are unified
|
||||
)};
|
||||
}
|
||||
|
||||
# subtract the new top surfaces from the other non-top surfaces and re-add them
|
||||
my @other = grep $_->surface_type != S_TYPE_TOP && !$_->is_bottom, @surfaces;
|
||||
foreach my $group (@{Slic3r::Surface::Collection->new(@other)->group}) {
|
||||
push @new_surfaces, map $group->[0]->clone(expolygon => $_), @{diff_ex(
|
||||
[ map $_->p, @$group ],
|
||||
[ map $_->p, @new_surfaces ],
|
||||
)};
|
||||
}
|
||||
$self->fill_surfaces->clear;
|
||||
$self->fill_surfaces->append($_) for @new_surfaces;
|
||||
}
|
||||
|
||||
1;
|
|
@ -357,7 +357,7 @@ sub process_layer {
|
|||
$self->_spiral_vase->enable(
|
||||
($layer->id > 0 || $self->print->config->brim_width == 0)
|
||||
&& ($layer->id >= $self->print->config->skirt_height && !$self->print->has_infinite_skirt)
|
||||
&& !defined(first { $_->config->bottom_solid_layers > $layer->id } @{$layer->regions})
|
||||
&& !defined(first { $_->region->config->bottom_solid_layers > $layer->id } @{$layer->regions})
|
||||
&& !defined(first { $_->perimeters->items_count > 1 } @{$layer->regions})
|
||||
&& !defined(first { $_->fills->items_count > 0 } @{$layer->regions})
|
||||
);
|
||||
|
|
|
@ -830,17 +830,6 @@ sub clip_fill_surfaces {
|
|||
}
|
||||
}
|
||||
|
||||
sub process_external_surfaces {
|
||||
my ($self) = @_;
|
||||
|
||||
for my $region_id (0 .. ($self->print->region_count-1)) {
|
||||
$self->get_layer(0)->regions->[$region_id]->process_external_surfaces(undef);
|
||||
for my $i (1 .. ($self->layer_count - 1)) {
|
||||
$self->get_layer($i)->regions->[$region_id]->process_external_surfaces($self->get_layer($i-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub discover_horizontal_shells {
|
||||
my $self = shift;
|
||||
|
||||
|
@ -850,8 +839,8 @@ sub discover_horizontal_shells {
|
|||
for (my $i = 0; $i < $self->layer_count; $i++) {
|
||||
my $layerm = $self->get_layer($i)->regions->[$region_id];
|
||||
|
||||
if ($layerm->config->solid_infill_every_layers && $layerm->config->fill_density > 0
|
||||
&& ($i % $layerm->config->solid_infill_every_layers) == 0) {
|
||||
if ($layerm->region->config->solid_infill_every_layers && $layerm->region->config->fill_density > 0
|
||||
&& ($i % $layerm->region->config->solid_infill_every_layers) == 0) {
|
||||
$_->surface_type(S_TYPE_INTERNALSOLID) for @{$layerm->fill_surfaces->filter_by_type(S_TYPE_INTERNAL)};
|
||||
}
|
||||
|
||||
|
@ -873,8 +862,8 @@ sub discover_horizontal_shells {
|
|||
Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP) ? 'top' : 'bottom';
|
||||
|
||||
my $solid_layers = ($type == S_TYPE_TOP)
|
||||
? $layerm->config->top_solid_layers
|
||||
: $layerm->config->bottom_solid_layers;
|
||||
? $layerm->region->config->top_solid_layers
|
||||
: $layerm->region->config->bottom_solid_layers;
|
||||
NEIGHBOR: for (my $n = ($type == S_TYPE_TOP) ? $i-1 : $i+1;
|
||||
abs($n - $i) <= $solid_layers-1;
|
||||
($type == S_TYPE_TOP) ? $n-- : $n++) {
|
||||
|
@ -902,7 +891,7 @@ sub discover_horizontal_shells {
|
|||
);
|
||||
next EXTERNAL if !@$new_internal_solid;
|
||||
|
||||
if ($layerm->config->fill_density == 0) {
|
||||
if ($layerm->region->config->fill_density == 0) {
|
||||
# if we're printing a hollow object we discard any solid shell thinner
|
||||
# than a perimeter width, since it's probably just crossing a sloping wall
|
||||
# and it's not wanted in a hollow print even if it would make sense when
|
||||
|
@ -1100,12 +1089,12 @@ sub combine_infill {
|
|||
)};
|
||||
|
||||
# apply surfaces back with adjusted depth to the uppermost layer
|
||||
if ($layerm->id == $self->get_layer($layer_idx)->id) {
|
||||
if ($layerm->layer->id == $self->get_layer($layer_idx)->id) {
|
||||
push @new_this_type,
|
||||
map Slic3r::Surface->new(
|
||||
expolygon => $_,
|
||||
surface_type => $type,
|
||||
thickness => sum(map $_->height, @layerms),
|
||||
thickness => sum(map $_->layer->height, @layerms),
|
||||
thickness_layers => scalar(@layerms),
|
||||
),
|
||||
@$intersection;
|
||||
|
|
|
@ -235,7 +235,7 @@ sub contact_area {
|
|||
# just remove bridged areas
|
||||
$diff = diff(
|
||||
$diff,
|
||||
[ map @$_, @{$layerm->bridged} ],
|
||||
$layerm->bridged,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ sub contact_area {
|
|||
# get the average nozzle diameter used on this layer
|
||||
my @nozzle_diameters = map $self->print_config->get_at('nozzle_diameter', $_),
|
||||
map { $_->config->perimeter_extruder-1, $_->config->infill_extruder-1, $_->config->solid_infill_extruder-1 }
|
||||
@{$layer->regions};
|
||||
map $_->region, @{$layer->regions};
|
||||
my $nozzle_diameter = sum(@nozzle_diameters)/@nozzle_diameters;
|
||||
|
||||
my $contact_z = $layer->print_z - $self->contact_distance($layer->height, $nozzle_diameter);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue