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 multiple perimeters (skins);
|
||||||
* generate rectilinear fill (100% solid for external surfaces or with customizable less density for inner surfaces);
|
* generate rectilinear fill (100% solid for external surfaces or with customizable less density for inner surfaces);
|
||||||
* retraction;
|
* retraction;
|
||||||
* skirt;
|
* skirt (with rounded corners);
|
||||||
* use relative or absolute extrusion commands;
|
* use relative or absolute extrusion commands;
|
||||||
* center print around bed center point;
|
* center print around bed center point;
|
||||||
|
* multiple solid layers near horizontal external surfaces;
|
||||||
* use different speed for bottom layer.
|
* use different speed for bottom layer.
|
||||||
|
|
||||||
Roadmap includes the following goals:
|
Roadmap includes the following goals:
|
||||||
|
|
||||||
* output some statistics;
|
* output some statistics;
|
||||||
* allow the user to customize initial and final GCODE commands;
|
* allow the user to customize initial and final GCODE commands;
|
||||||
* option for filling multiple solid layers near external surfaces;
|
|
||||||
* support material for internal perimeters;
|
* support material for internal perimeters;
|
||||||
|
* travel path optimization;
|
||||||
* ability to infill in the direction of bridges;
|
* ability to infill in the direction of bridges;
|
||||||
* input object transform (scale, rotate, multiply);
|
* input object transform (scale, rotate, multiply);
|
||||||
* cool;
|
* cool;
|
||||||
|
@ -42,6 +42,7 @@ our $flow_width;
|
|||||||
|
|
||||||
# print options
|
# print options
|
||||||
our $perimeter_offsets = 3;
|
our $perimeter_offsets = 3;
|
||||||
|
our $solid_layers = 3;
|
||||||
our $fill_density = 0.4; # 1 = 100%
|
our $fill_density = 0.4; # 1 = 100%
|
||||||
our $temperature = 195;
|
our $temperature = 195;
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ our $retract_restart_extra = 0; # mm
|
|||||||
our $retract_speed = 40; # mm/sec
|
our $retract_speed = 40; # mm/sec
|
||||||
|
|
||||||
# skirt options
|
# skirt options
|
||||||
our $skirts = 3;
|
our $skirts = 1;
|
||||||
our $skirt_distance = 6; # mm
|
our $skirt_distance = 6; # mm
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package Slic3r::Print;
|
package Slic3r::Print;
|
||||||
use Moo;
|
use Moo;
|
||||||
|
|
||||||
|
use Math::Clipper ':all';
|
||||||
|
use XXX;
|
||||||
|
|
||||||
use constant PI => 4 * atan2(1, 1);
|
use constant PI => 4 * atan2(1, 1);
|
||||||
use constant X => 0;
|
use constant X => 0;
|
||||||
use constant Y => 1;
|
use constant Y => 1;
|
||||||
@ -49,6 +52,76 @@ sub layer {
|
|||||||
return $self->layers->[$layer_id];
|
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 {
|
sub extrude_perimeters {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
@ -67,6 +67,9 @@ sub parse_file {
|
|||||||
$layer->merge_contiguous_surfaces;
|
$layer->merge_contiguous_surfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# detect which surfaces are near external layers
|
||||||
|
$print->discover_horizontal_shells;
|
||||||
|
|
||||||
return $print;
|
return $print;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use constant X => 0;
|
|||||||
use constant Y => 1;
|
use constant Y => 1;
|
||||||
|
|
||||||
sub factor {
|
sub factor {
|
||||||
return $Slic3r::resolution * 10;
|
return $Slic3r::resolution * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub svg {
|
sub svg {
|
||||||
@ -24,6 +24,7 @@ sub output_polygons {
|
|||||||
my $g = $svg->group(
|
my $g = $svg->group(
|
||||||
style => {
|
style => {
|
||||||
'stroke-width' => 2,
|
'stroke-width' => 2,
|
||||||
|
'stroke' => 'black',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
foreach my $polygon (@$polygons) {
|
foreach my $polygon (@$polygons) {
|
||||||
|
@ -16,11 +16,9 @@ has 'holes' => (
|
|||||||
default => sub { [] },
|
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' => (
|
has 'surface_type' => (
|
||||||
is => 'rw',
|
is => 'rw',
|
||||||
#isa => enum([qw(internal bottom top)]),
|
#isa => enum([qw(internal internal-solid bottom top)]),
|
||||||
);
|
);
|
||||||
|
|
||||||
sub add_hole {
|
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 {
|
sub lines {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return @{ $self->contour->lines }, map @{ $_->lines }, @{ $self->holes };
|
return @{ $self->contour->lines }, map @{ $_->lines }, @{ $self->holes };
|
||||||
|
@ -39,6 +39,7 @@ GetOptions(
|
|||||||
|
|
||||||
# print options
|
# print options
|
||||||
'perimeters=i' => \$Slic3r::perimeter_offsets,
|
'perimeters=i' => \$Slic3r::perimeter_offsets,
|
||||||
|
'solid-layers=i' => \$Slic3r::solid_layers,
|
||||||
'fill-density=f' => \$Slic3r::fill_density,
|
'fill-density=f' => \$Slic3r::fill_density,
|
||||||
'temperature=i' => \$Slic3r::temperature,
|
'temperature=i' => \$Slic3r::temperature,
|
||||||
|
|
||||||
@ -75,6 +76,10 @@ GetOptions(
|
|||||||
die "Invalid value for --perimeters\n"
|
die "Invalid value for --perimeters\n"
|
||||||
if $Slic3r::perimeter_offsets < 1;
|
if $Slic3r::perimeter_offsets < 1;
|
||||||
|
|
||||||
|
# --solid-layers
|
||||||
|
die "Invalid value for --solid-layers\n"
|
||||||
|
if $Slic3r::solid_layers < 1;
|
||||||
|
|
||||||
# --print-center
|
# --print-center
|
||||||
die "Invalid value for --print-center\n"
|
die "Invalid value for --print-center\n"
|
||||||
if !ref $Slic3r::print_center
|
if !ref $Slic3r::print_center
|
||||||
@ -143,6 +148,8 @@ Usage: slic3r.pl [ OPTIONS ] file.stl
|
|||||||
Print options:
|
Print options:
|
||||||
--perimeters Number of perimeters/horizontal skins (range: 1+,
|
--perimeters Number of perimeters/horizontal skins (range: 1+,
|
||||||
default: $Slic3r::perimeter_offsets)
|
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)
|
--fill-density Infill density (range: 0-1, default: $Slic3r::fill_density)
|
||||||
--temperature Extrusion temperature (default: $Slic3r::temperature)
|
--temperature Extrusion temperature (default: $Slic3r::temperature)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user