Multiple solid layers near external surfaces
This commit is contained in:
parent
f892fde123
commit
03341f3485
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -67,6 +67,9 @@ sub parse_file {
|
||||
$layer->merge_contiguous_surfaces;
|
||||
}
|
||||
|
||||
# detect which surfaces are near external layers
|
||||
$print->discover_horizontal_shells;
|
||||
|
||||
return $print;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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 };
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user