Multiple solid layers near external surfaces

degen-loop-screen
Alessandro Ranellucci 2011-09-25 22:11:56 +02:00
parent f892fde123
commit 03341f3485
7 changed files with 96 additions and 7 deletions

View File

@ -31,17 +31,18 @@ Slic3r current features are:
* generate multiple perimeters (skins);
* generate rectilinear fill (100% solid for external surfaces or with customizable less density for inner surfaces);
* retraction;
* skirt;
* skirt (with rounded corners);
* use relative or absolute extrusion commands;
* center print around bed center point;
* multiple solid layers near horizontal external surfaces;
* use different speed for bottom layer.
Roadmap includes the following goals:
* output some statistics;
* allow the user to customize initial and final GCODE commands;
* option for filling multiple solid layers near external surfaces;
* support material for internal perimeters;
* travel path optimization;
* ability to infill in the direction of bridges;
* input object transform (scale, rotate, multiply);
* cool;

View File

@ -42,6 +42,7 @@ our $flow_width;
# print options
our $perimeter_offsets = 3;
our $solid_layers = 3;
our $fill_density = 0.4; # 1 = 100%
our $temperature = 195;
@ -51,7 +52,7 @@ our $retract_restart_extra = 0; # mm
our $retract_speed = 40; # mm/sec
# skirt options
our $skirts = 3;
our $skirts = 1;
our $skirt_distance = 6; # mm
1;

View File

@ -1,6 +1,9 @@
package Slic3r::Print;
use Moo;
use Math::Clipper ':all';
use XXX;
use constant PI => 4 * atan2(1, 1);
use constant X => 0;
use constant Y => 1;
@ -49,6 +52,76 @@ sub layer {
return $self->layers->[$layer_id];
}
sub discover_horizontal_shells {
my $self = shift;
Slic3r::debugf "==> DISCOVERING HORIZONTAL SHELLS\n";
my $clipper = Math::Clipper->new;
for (my $i = 0; $i < $self->layer_count; $i++) {
my $layer = $self->layers->[$i];
foreach my $type (qw(top bottom)) {
# find surfaces of current type for current layer
my @surfaces = grep $_->surface_type eq $type, @{$layer->surfaces} or next;
Slic3r::debugf "Layer %d has %d surfaces of type '%s'\n",
$i, scalar(@surfaces), $type;
for (my $n = $type eq 'top' ? $i-1 : $i+1;
abs($n - $i) <= $Slic3r::solid_layers-1;
$type eq 'top' ? $n-- : $n++) {
next if $n < 0 || $n >= $self->layer_count;
Slic3r::debugf " looking for neighbors on layer %d...\n", $n;
my $neighbor_polygons = [ map $_->p, grep $_->surface_type eq 'internal', @{$self->layers->[$n]->surfaces} ];
# find intersection between @surfaces and current layer's surfaces
$clipper->add_subject_polygons([ map $_->p, @surfaces ]);
$clipper->add_clip_polygons($neighbor_polygons);
# intersections have contours and holes
my $intersections = $clipper->ex_execute(CT_INTERSECTION, PFT_NONZERO, PFT_NONZERO);
$clipper->clear;
next if @$intersections == 0;
Slic3r::debugf " %d intersections found\n", scalar @$intersections;
# subtract intersections from layer surfaces to get resulting inner surfaces
$clipper->add_subject_polygons($neighbor_polygons);
$clipper->add_clip_polygons([ map { $_->{outer}, @{$_->{holes}} } @$intersections ]);
my $internal_polygons = $clipper->ex_execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO);
$clipper->clear;
# Note: due to floating point math we're going to get some very small
# polygons as $internal_polygons; they should be discarded, but a reliable
# way to detect them is needed, and they seem to be harmless so we keep them for now
# assign resulting inner surfaces to layer
$self->layers->[$n]->surfaces([]);
foreach my $p (@$internal_polygons) {
push @{$self->layers->[$n]->surfaces}, Slic3r::Surface->new(
surface_type => 'internal',
contour => Slic3r::Polyline::Closed->cast($p->{outer}),
holes => [
map Slic3r::Polyline::Closed->cast($_), @{$p->{holes}}
],
);
}
# assign new internal-solid surfaces to layer
foreach my $p (@$intersections) {
push @{$self->layers->[$n]->surfaces}, Slic3r::Surface->new(
surface_type => 'internal-solid',
contour => Slic3r::Polyline::Closed->cast($p->{outer}),
holes => [
map Slic3r::Polyline::Closed->cast($_), @{$p->{holes}}
],
);
}
}
}
}
}
sub extrude_perimeters {
my $self = shift;

View File

@ -67,6 +67,9 @@ sub parse_file {
$layer->merge_contiguous_surfaces;
}
# detect which surfaces are near external layers
$print->discover_horizontal_shells;
return $print;
}

View File

@ -8,7 +8,7 @@ use constant X => 0;
use constant Y => 1;
sub factor {
return $Slic3r::resolution * 10;
return $Slic3r::resolution * 100;
}
sub svg {
@ -24,6 +24,7 @@ sub output_polygons {
my $g = $svg->group(
style => {
'stroke-width' => 2,
'stroke' => 'black',
},
);
foreach my $polygon (@$polygons) {

View File

@ -16,11 +16,9 @@ has 'holes' => (
default => sub { [] },
);
# TODO: to allow for multiple solid skins to be filled near external
# surfaces, a new type should be defined: internal-solid
has 'surface_type' => (
is => 'rw',
#isa => enum([qw(internal bottom top)]),
#isa => enum([qw(internal internal-solid bottom top)]),
);
sub add_hole {
@ -78,6 +76,11 @@ sub clipper_polygon {
};
}
sub p {
my $self = shift;
return ($self->contour->p, map $_->p, @{$self->holes});
}
sub lines {
my $self = shift;
return @{ $self->contour->lines }, map @{ $_->lines }, @{ $self->holes };

View File

@ -39,6 +39,7 @@ GetOptions(
# print options
'perimeters=i' => \$Slic3r::perimeter_offsets,
'solid-layers=i' => \$Slic3r::solid_layers,
'fill-density=f' => \$Slic3r::fill_density,
'temperature=i' => \$Slic3r::temperature,
@ -75,6 +76,10 @@ GetOptions(
die "Invalid value for --perimeters\n"
if $Slic3r::perimeter_offsets < 1;
# --solid-layers
die "Invalid value for --solid-layers\n"
if $Slic3r::solid_layers < 1;
# --print-center
die "Invalid value for --print-center\n"
if !ref $Slic3r::print_center
@ -143,6 +148,8 @@ Usage: slic3r.pl [ OPTIONS ] file.stl
Print options:
--perimeters Number of perimeters/horizontal skins (range: 1+,
default: $Slic3r::perimeter_offsets)
--solid-layers Number of solid layers to do for top/bottom surfaces
(range: 1+, default: $Slic3r::solid_layers)
--fill-density Infill density (range: 0-1, default: $Slic3r::fill_density)
--temperature Extrusion temperature (default: $Slic3r::temperature)