mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 09:17:52 -06:00
New simpler and more robust implementation of infill every 'n' layers
This commit is contained in:
parent
cac79c0575
commit
c9b506fa02
1 changed files with 44 additions and 78 deletions
|
@ -530,93 +530,59 @@ 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 $every = $Slic3r::Config->infill_every_layers;
|
||||||
my $area_threshold = $Slic3r::flow->scaled_spacing ** 2;
|
my $area_threshold = $Slic3r::flow->scaled_spacing ** 2;
|
||||||
|
|
||||||
|
my $layer_count = $self->layer_count;
|
||||||
for my $region_id (0 .. ($self->print->regions_count-1)) {
|
for my $region_id (0 .. ($self->print->regions_count-1)) {
|
||||||
# start from top, skip lowest layer
|
# skip bottom layer
|
||||||
for (my $i = $self->layer_count - 1; $i > 0; $i--) {
|
for (my $layer_id = $every; $layer_id <= $layer_count-1; $layer_id += $every) {
|
||||||
my $layerm = $self->layers->[$i]->regions->[$region_id];
|
# get the layers whose infill we want to combine (bottom-up)
|
||||||
|
my @layerms = map $self->layers->[$_]->regions->[$region_id],
|
||||||
|
($layer_id - ($every-1)) .. $layer_id;
|
||||||
|
|
||||||
# skip layer if no internal fill surfaces
|
# process internal and internal-solid infill separately
|
||||||
next if !grep $_->surface_type == S_TYPE_INTERNAL, @{$layerm->fill_surfaces};
|
for my $type (S_TYPE_INTERNAL, S_TYPE_INTERNALSOLID) {
|
||||||
|
# we need to perform a multi-layer intersection, so let's split it in pairs
|
||||||
# for each possible depth, look for intersections with the lower layer
|
|
||||||
# we do this from the greater depth to the smaller
|
|
||||||
for (my $d = $Slic3r::Config->infill_every_layers - 1; $d >= 1; $d--) {
|
|
||||||
next if ($i - $d) <= 0; # do not combine infill for bottom layer
|
|
||||||
my $lower_layerm = $self->layers->[$i - 1]->regions->[$region_id];
|
|
||||||
|
|
||||||
# select surfaces of the lower layer having the depth we're looking for
|
# initialize the intersection with the candidates of the lowest layer
|
||||||
my @lower_surfaces = grep $_->depth_layers == $d && $_->surface_type == S_TYPE_INTERNAL,
|
my $intersection = [ map $_->expolygon, grep $_->surface_type == $type, @{$layerms[0]->fill_surfaces} ];
|
||||||
@{$lower_layerm->fill_surfaces};
|
|
||||||
next if !@lower_surfaces;
|
|
||||||
|
|
||||||
# calculate intersection between our surfaces and theirs
|
# start looping from the second layer and intersect the current intersection with it
|
||||||
my $intersection = intersection_ex(
|
for my $layerm (@layerms[1 .. $#layerms]) {
|
||||||
[ map $_->p, grep $_->depth_layers <= $d, @lower_surfaces ],
|
$intersection = intersection_ex(
|
||||||
[ map $_->p, grep $_->surface_type == S_TYPE_INTERNAL, @{$layerm->fill_surfaces} ],
|
[ map @$_, @$intersection ],
|
||||||
undef, 1,
|
[ map @{$_->expolygon}, grep $_->surface_type == $type, @{$layerm->fill_surfaces} ],
|
||||||
);
|
);
|
||||||
|
|
||||||
# purge intersections, skip tiny regions
|
|
||||||
@$intersection = grep $_->area > $area_threshold, @$intersection;
|
|
||||||
next if !@$intersection;
|
|
||||||
|
|
||||||
# new fill surfaces of the current layer are:
|
|
||||||
# - any non-internal surface
|
|
||||||
# - intersections found (with a $d + 1 depth)
|
|
||||||
# - any internal surface not belonging to the intersection (with its original depth)
|
|
||||||
{
|
|
||||||
my @new_surfaces = ();
|
|
||||||
push @new_surfaces, grep $_->surface_type != S_TYPE_INTERNAL, @{$layerm->fill_surfaces};
|
|
||||||
push @new_surfaces, map Slic3r::Surface->new
|
|
||||||
(expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $d + 1), @$intersection;
|
|
||||||
|
|
||||||
foreach my $depth (reverse $d..$Slic3r::Config->infill_every_layers) {
|
|
||||||
push @new_surfaces, map Slic3r::Surface->new
|
|
||||||
(expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $depth),
|
|
||||||
|
|
||||||
# difference between our internal layers with depth == $depth
|
|
||||||
# and the intersection found
|
|
||||||
@{diff_ex(
|
|
||||||
[
|
|
||||||
map $_->p, grep $_->surface_type == S_TYPE_INTERNAL && $_->depth_layers == $depth,
|
|
||||||
@{$layerm->fill_surfaces},
|
|
||||||
],
|
|
||||||
[ map @$_, @$intersection ],
|
|
||||||
1,
|
|
||||||
)};
|
|
||||||
}
|
|
||||||
@{$layerm->fill_surfaces} = @new_surfaces;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# now we remove the intersections from lower layer
|
@$intersection = grep $_->area > $area_threshold, @$intersection;
|
||||||
{
|
next if !@$intersection;
|
||||||
my @new_surfaces = ();
|
Slic3r::debugf " combining %d %s regions from layers %d-%d\n",
|
||||||
push @new_surfaces, grep $_->surface_type != S_TYPE_INTERNAL, @{$lower_layerm->fill_surfaces};
|
scalar(@$intersection),
|
||||||
|
($type == S_TYPE_INTERNAL ? 'internal' : 'internal-solid'),
|
||||||
# offset for the two different flow spacings
|
$layer_id-($every-1), $layer_id;
|
||||||
$intersection = [ map $_->offset_ex(
|
|
||||||
$lower_layerm->infill_flow->scaled_spacing / 2
|
# $intersection now contains the regions that can be combined across the full amount of layers
|
||||||
+ $layerm->infill_flow->scaled_spacing / 2
|
# so let's remove those areas from all layers
|
||||||
), @$intersection];
|
foreach my $layerm (@layerms) {
|
||||||
|
my @this_type = grep $_->surface_type == $type, @{$layerm->fill_surfaces};
|
||||||
foreach my $depth (1..$Slic3r::Config->infill_every_layers) {
|
my @other_types = grep $_->surface_type != $type, @{$layerm->fill_surfaces};
|
||||||
push @new_surfaces, map Slic3r::Surface->new
|
|
||||||
(expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $depth),
|
@this_type = map Slic3r::Surface->new(expolygon => $_, surface_type => $type),
|
||||||
|
@{diff_ex(
|
||||||
# difference between internal layers with depth == $depth
|
[ map @{$_->expolygon}, @this_type ],
|
||||||
# and the intersection found
|
[ map @$_, @$intersection ],
|
||||||
@{diff_ex(
|
)};
|
||||||
[
|
|
||||||
map $_->p, grep $_->surface_type == S_TYPE_INTERNAL && $_->depth_layers == $depth,
|
# apply surfaces back with adjusted depth to the uppermost layer
|
||||||
@{$lower_layerm->fill_surfaces},
|
if ($layerm->id == $layer_id) {
|
||||||
],
|
push @this_type,
|
||||||
[ map @$_, @$intersection ],
|
map Slic3r::Surface->new(expolygon => $_, surface_type => $type, depth_layers => $every),
|
||||||
1,
|
@$intersection;
|
||||||
)};
|
|
||||||
}
|
}
|
||||||
@{$lower_layerm->fill_surfaces} = @new_surfaces;
|
|
||||||
|
@{$layerm->fill_surfaces} = (@this_type, @other_types);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue