Refactor/clean up. Merge remove_small_surfaces() into prepare_fill_surfaces(), rename infill_every_layers() to combine_infill(), remove $layer->fill_boundaries, initialize layer properties explicitely for clarity.

degen-loop-screen
Alessandro Ranellucci 2012-07-22 20:48:38 +02:00
parent a5d683a9b9
commit 1d04e15b63
3 changed files with 47 additions and 74 deletions

View File

@ -25,60 +25,36 @@ has 'infill_flow' => (is => 'lazy');
# collection of spare segments generated by slicing the original geometry;
# these need to be merged in continuos (closed) polylines
has 'lines' => (
is => 'rw',
#isa => 'ArrayRef[ArrayRef]',
default => sub { [] },
);
has 'lines' => (is => 'rw', default => sub { [] });
# collection of surfaces generated by slicing the original geometry
has 'slices' => (is => 'ro', default => sub { [] });
has 'slices' => (is => 'rw');
# collection of polygons or polylines representing thin walls contained
# in the original geometry
has 'thin_walls' => (is => 'ro', default => sub { [] });
# collection of expolygons generated by offsetting the innermost perimeter(s)
# they represent boundaries of areas to fill
has 'fill_boundaries' => (is => 'ro', default => sub { [] });
has 'thin_walls' => (is => 'rw');
# collection of polygons or polylines representing thin infill regions that
# need to be filled with a medial axis
has 'thin_fills' => (is => 'ro', default => sub { [] });
has 'thin_fills' => (is => 'rw');
# collection of surfaces generated by clipping the slices to the fill boundaries
has 'surfaces' => (
is => 'rw',
#isa => 'ArrayRef[Slic3r::Surface]',
default => sub { [] },
);
# collection of expolygons generated by offsetting the innermost perimeter(s)
# they represent boundaries of areas to fill, typed (top/bottom/internal)
has 'surfaces' => (is => 'rw');
# collection of surfaces for infill
has 'fill_surfaces' => (
is => 'rw',
#isa => 'ArrayRef[Slic3r::Surface]',
default => sub { [] },
);
# collection of surfaces for infill generation. the difference between surfaces
# fill_surfaces is that this one honors fill_density == 0 and turns small internal
# surfaces into solid ones
has 'fill_surfaces' => (is => 'rw');
# ordered collection of extrusion paths to build all perimeters
has 'perimeters' => (
is => 'rw',
#isa => 'ArrayRef[Slic3r::ExtrusionLoop]',
default => sub { [] },
);
# ordered collection of extrusion paths/loops to build all perimeters
has 'perimeters' => (is => 'rw');
# ordered collection of extrusion paths to fill surfaces for support material
has 'support_fills' => (
is => 'rw',
#isa => 'Slic3r::ExtrusionPath::Collection',
);
has 'support_fills' => (is => 'rw');
# ordered collection of extrusion paths to fill surfaces
has 'fills' => (
is => 'rw',
#isa => 'ArrayRef[Slic3r::ExtrusionPath::Collection]',
default => sub { [] },
);
has 'fills' => (is => 'rw');
# Z used for slicing
sub _build_slice_z {
@ -123,14 +99,6 @@ sub _build_infill_flow {
: $Slic3r::infill_flow;
}
sub add_line {
my $self = shift;
my ($line) = @_;
push @{ $self->lines }, $line;
return $line;
}
# build polylines from lines
sub make_surfaces {
my $self = shift;
@ -144,9 +112,10 @@ sub make_surfaces {
Slic3r::debugf " %d surface(s) having %d holes detected from %d polylines\n",
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
push @{$self->slices},
$self->slices([
map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_INTERNAL),
@$expolygons;
@$expolygons
]);
}
# the contours must be offsetted by half extrusion width inwards
@ -170,13 +139,12 @@ sub make_surfaces {
1,
);
$self->thin_walls([]);
if (@$diff) {
my $area_threshold = scale($self->perimeters_flow->spacing) ** 2;
@$diff = grep $_->area > ($area_threshold), @$diff;
push @{$self->thin_walls},
map $_->medial_axis(scale $self->perimeters_flow->width),
@$diff;
@{$self->thin_walls} = map $_->medial_axis(scale $self->perimeters_flow->width), @$diff;
Slic3r::debugf " %d thin walls detected\n", scalar(@{$self->thin_walls}) if @{$self->thin_walls};
}
@ -216,6 +184,10 @@ sub make_perimeters {
map [ $_->contour->[0], $_ ], @{$self->slices},
])};
$self->perimeters([]);
$self->surfaces([]);
$self->thin_fills([]);
# for each island:
foreach my $surface (@surfaces) {
my @last_offsets = ($surface->expolygon);
@ -276,7 +248,7 @@ sub make_perimeters {
{
my @fill_boundaries = map $_->offset_ex(-$distance), @last_offsets;
$_->simplify(scale $Slic3r::resolution) for @fill_boundaries;
push @{ $self->fill_boundaries }, @fill_boundaries;
push @{ $self->surfaces }, @fill_boundaries;
# detect the small gaps that we need to treat like thin polygons,
# thus generating the skeleton and using it to fill them
@ -336,13 +308,13 @@ sub make_perimeters {
}
# do holes, then contours starting from innermost one
$self->add_perimeter($holes[$_], $is_external{$_} ? EXTR_ROLE_EXTERNAL_PERIMETER : undef)
$self->_add_perimeter($holes[$_], $is_external{$_} ? EXTR_ROLE_EXTERNAL_PERIMETER : undef)
for reverse 0 .. $#holes;
for my $depth (reverse 0 .. $#$island) {
my $role = $depth == $#$island ? EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER
: $depth == 0 ? EXTR_ROLE_EXTERNAL_PERIMETER
: EXTR_ROLE_PERIMETER;
$self->add_perimeter($_, $role) for map $_->contour, @{$island->[$depth]};
$self->_add_perimeter($_, $role) for map $_->contour, @{$island->[$depth]};
}
}
@ -363,7 +335,7 @@ sub make_perimeters {
}
}
sub add_perimeter {
sub _add_perimeter {
my $self = shift;
my ($polygon, $role) = @_;
@ -381,6 +353,7 @@ sub prepare_fill_surfaces {
my @surfaces = @{$self->surfaces};
# if no solid layers are requested, turn top/bottom surfaces to internal
# note that this modifies $self->surfaces in place
if ($Slic3r::solid_layers == 0) {
$_->surface_type(S_TYPE_INTERNAL) for grep $_->surface_type != S_TYPE_INTERNAL, @surfaces;
}
@ -414,6 +387,7 @@ sub prepare_fill_surfaces {
# (those that are too tight for extrusion)
{
my $distance = scale $self->infill_flow->spacing / 2;
my @fill_surfaces = ();
foreach my $surface (@surfaces) {
# offset inwards
@ -423,25 +397,26 @@ sub prepare_fill_surfaces {
@offsets = map $_->offset_ex($distance), @offsets;
@offsets = @{ union_ex([ map @$_, @offsets ], undef, 1) };
push @{$self->fill_surfaces}, map Slic3r::Surface->new(
push @fill_surfaces, map Slic3r::Surface->new(
expolygon => $_,
surface_type => $surface->surface_type), @offsets;
}
Slic3r::debugf "identified %d small surfaces at layer %d\n",
(@surfaces - @{$self->fill_surfaces}), $self->id
if @{$self->fill_surfaces} != @surfaces;
(@surfaces - @fill_surfaces), $self->id
if @fill_surfaces != @surfaces;
# the difference between @surfaces and $self->fill_surfaces
# is what's too small; we add it back as solid infill
if ($Slic3r::fill_density > 0) {
my $diff = diff_ex(
[ map $_->p, @surfaces ],
[ map $_->p, @{$self->fill_surfaces} ],
[ map $_->p, @fill_surfaces ],
);
push @{$self->fill_surfaces}, map Slic3r::Surface->new(
push @surfaces, map Slic3r::Surface->new(
expolygon => $_,
surface_type => S_TYPE_INTERNALSOLID), @$diff;
surface_type => S_TYPE_INTERNALSOLID
), @$diff;
}
}

View File

@ -252,11 +252,11 @@ sub export_gcode {
$_->discover_horizontal_shells for @{$self->objects};
# free memory
@{$_->surfaces} = () for map @{$_->layers}, @{$self->objects};
$_->surfaces(undef) for map @{$_->layers}, @{$self->objects};
# combine fill surfaces to honor the "infill every N layers" option
$status_cb->(70, "Combining infill");
$_->infill_every_layers for @{$self->objects};
$_->combine_infill for @{$self->objects};
# this will generate extrusion paths for each layer
$status_cb->(80, "Infilling layers");
@ -284,13 +284,13 @@ sub export_gcode {
my $fills = shift;
foreach my $obj_idx (keys %$fills) {
foreach my $layer_id (keys %{$fills->{$obj_idx}}) {
@{$self->objects->[$obj_idx]->layers->[$layer_id]->fills} = @{$fills->{$obj_idx}{$layer_id}};
$self->objects->[$obj_idx]->layers->[$layer_id]->fills($fills->{$obj_idx}{$layer_id});
}
}
},
no_threads_cb => sub {
foreach my $layer (map @{$_->layers}, @{$self->objects}) {
@{$layer->fills} = $fill_maker->make_fill($layer);
$layer->fills([ $fill_maker->make_fill($layer) ]);
}
},
);
@ -303,7 +303,7 @@ sub export_gcode {
}
# free memory (note that support material needs fill_surfaces)
@{$_->fill_surfaces} = () for map @{$_->layers}, @{$self->objects};
$_->fill_surfaces(undef) for map @{$_->layers}, @{$self->objects};
# make skirt
$status_cb->(88, "Generating skirt");

View File

@ -48,7 +48,7 @@ sub slice {
my $lines = shift;
foreach my $layer_id (keys %$lines) {
my $layer = $self->layer($layer_id);
$layer->add_line($_) for @{ $lines->{$layer_id} };
push @{$layer->lines}, @{$lines->{$layer_id}};
}
};
Slic3r::parallelize(
@ -84,7 +84,7 @@ sub slice {
# remove last layer if empty
# (we might have created it because of the $max_layer = ... + 1 code below)
pop @{$self->layers} if !@{$self->layers->[-1]->surfaces} && !@{$self->layers->[-1]->lines};
pop @{$self->layers} if !@{$self->layers->[-1]->lines};
foreach my $layer (@{ $self->layers }) {
Slic3r::debugf "Making surfaces for layer %d (slice z = %f):\n",
@ -291,19 +291,17 @@ sub detect_surfaces_type {
# clip surfaces to the fill boundaries
foreach my $layer (@{$self->layers}) {
my $fill_boundaries = [ map @$_, @{$layer->surfaces} ];
@{$layer->surfaces} = ();
foreach my $surface (@{$layer->slices}) {
my $intersection = intersection_ex(
[ $surface->p ],
[ map @$_, @{$layer->fill_boundaries} ],
$fill_boundaries,
);
push @{$layer->surfaces}, map Slic3r::Surface->new
(expolygon => $_, surface_type => $surface->surface_type),
@$intersection;
}
# free memory
@{$layer->fill_boundaries} = ();
}
}
@ -394,7 +392,7 @@ sub discover_horizontal_shells {
}
# combine fill surfaces across layers
sub infill_every_layers {
sub combine_infill {
my $self = shift;
return unless $Slic3r::infill_every_layers > 1 && $Slic3r::fill_density > 0;