Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Ranellucci <aar@cpan.org>2013-12-23 23:12:39 +0400
committerAlessandro Ranellucci <aar@cpan.org>2013-12-23 23:12:39 +0400
commit74f2f455547f17e69d391aa291922e87be3062a5 (patch)
treeef837eab8c4b37ee6ba66186644842d0ce3fa3a0
parentc180a2de5701df17304f1acf6cfcf0b88a54b1b7 (diff)
Fix regression preventing raft from being generated for the entire object footprint. #1614 #1567
-rw-r--r--lib/Slic3r/Print/SupportMaterial.pm113
-rw-r--r--lib/Slic3r/Test.pm1
-rw-r--r--t/support.t39
3 files changed, 100 insertions, 53 deletions
diff --git a/lib/Slic3r/Print/SupportMaterial.pm b/lib/Slic3r/Print/SupportMaterial.pm
index 92ccb16e1..07f8624b1 100644
--- a/lib/Slic3r/Print/SupportMaterial.pm
+++ b/lib/Slic3r/Print/SupportMaterial.pm
@@ -81,6 +81,10 @@ sub contact_area {
my %contact = (); # contact_z => [ polygons ]
my %overhang = (); # contact_z => [ polygons ] - this stores the actual overhang supported by each contact layer
for my $layer_id (0 .. $#{$object->layers}) {
+ # note $layer_id might != $layer->id when raft_layers > 0
+ # so $layer_id == 0 means first object layer
+ # and $layer->id == 0 means first print layer (including raft)
+
if ($self->config->raft_layers == 0) {
next if $layer_id == 0;
} elsif (!$self->config->support_material) {
@@ -89,69 +93,76 @@ sub contact_area {
last if $layer_id > 0;
}
my $layer = $object->layers->[$layer_id];
- my $lower_layer = $object->layers->[$layer_id-1];
# detect overhangs and contact areas needed to support them
my (@overhang, @contact) = ();
- foreach my $layerm (@{$layer->regions}) {
- my $fw = $layerm->perimeter_flow->scaled_width;
- my $diff;
+ if ($layer_id == 0) {
+ # this is the first object layer, so we're here just to get the object
+ # footprint for the raft
+ push @overhang, map $_->clone, map @$_, @{$layer->slices};
+ push @contact, @{offset(\@overhang, scale +MARGIN)};
+ } else {
+ my $lower_layer = $object->layers->[$layer_id-1];
+ foreach my $layerm (@{$layer->regions}) {
+ my $fw = $layerm->perimeter_flow->scaled_width;
+ my $diff;
- # If a threshold angle was specified, use a different logic for detecting overhangs.
- if (defined $threshold_rad
- || $layer_id < $self->config->support_material_enforce_layers
- || $self->config->raft_layers > 0) {
- my $d = defined $threshold_rad
- ? scale $lower_layer->height * ((cos $threshold_rad) / (sin $threshold_rad))
- : 0;
+ # If a threshold angle was specified, use a different logic for detecting overhangs.
+ if (defined $threshold_rad
+ || $layer_id < $self->config->support_material_enforce_layers
+ || $self->config->raft_layers > 0) {
+ my $d = defined $threshold_rad
+ ? scale $lower_layer->height * ((cos $threshold_rad) / (sin $threshold_rad))
+ : 0;
- $diff = diff(
- offset([ map $_->p, @{$layerm->slices} ], -$d),
- [ map @$_, @{$lower_layer->slices} ],
- );
+ $diff = diff(
+ offset([ map $_->p, @{$layerm->slices} ], -$d),
+ [ map @$_, @{$lower_layer->slices} ],
+ );
- # only enforce spacing from the object ($fw/2) if the threshold angle
- # is not too high: in that case, $d will be very small (as we need to catch
- # very short overhangs), and such contact area would be eaten by the
- # enforced spacing, resulting in high threshold angles to be almost ignored
- $diff = diff(
- offset($diff, $d - $fw/2),
- [ map @$_, @{$lower_layer->slices} ],
- ) if $d > $fw/2;
- } else {
- $diff = diff(
- offset([ map $_->p, @{$layerm->slices} ], -$fw/2),
- [ map @$_, @{$lower_layer->slices} ],
- );
+ # only enforce spacing from the object ($fw/2) if the threshold angle
+ # is not too high: in that case, $d will be very small (as we need to catch
+ # very short overhangs), and such contact area would be eaten by the
+ # enforced spacing, resulting in high threshold angles to be almost ignored
+ $diff = diff(
+ offset($diff, $d - $fw/2),
+ [ map @$_, @{$lower_layer->slices} ],
+ ) if $d > $fw/2;
+ } else {
+ $diff = diff(
+ offset([ map $_->p, @{$layerm->slices} ], -$fw/2),
+ [ map @$_, @{$lower_layer->slices} ],
+ );
- # collapse very tiny spots
- $diff = offset2($diff, -$fw/10, +$fw/10);
+ # collapse very tiny spots
+ $diff = offset2($diff, -$fw/10, +$fw/10);
- # $diff now contains the ring or stripe comprised between the boundary of
- # lower slices and the centerline of the last perimeter in this overhanging layer.
- # Void $diff means that there's no upper perimeter whose centerline is
- # outside the lower slice boundary, thus no overhang
- }
+ # $diff now contains the ring or stripe comprised between the boundary of
+ # lower slices and the centerline of the last perimeter in this overhanging layer.
+ # Void $diff means that there's no upper perimeter whose centerline is
+ # outside the lower slice boundary, thus no overhang
+ }
- # TODO: this is the place to remove bridged areas
+ # TODO: this is the place to remove bridged areas
- next if !@$diff;
- push @overhang, @$diff; # NOTE: this is not the full overhang as it misses the outermost half of the perimeter width!
+ next if !@$diff;
+ push @overhang, @$diff; # NOTE: this is not the full overhang as it misses the outermost half of the perimeter width!
- # Let's define the required contact area by using a max gap of half the upper
- # extrusion width and extending the area according to the configured margin.
- # We increment the area in steps because we don't want our support to overflow
- # on the other side of the object (if it's very thin).
- {
- my @slices_margin = @{offset([ map @$_, @{$lower_layer->slices} ], $fw/2)};
- for ($fw/2, map {scale MARGIN_STEP} 1..(MARGIN / MARGIN_STEP)) {
- $diff = diff(
- offset($diff, $_),
- \@slices_margin,
- );
+ # Let's define the required contact area by using a max gap of half the upper
+ # extrusion width and extending the area according to the configured margin.
+ # We increment the area in steps because we don't want our support to overflow
+ # on the other side of the object (if it's very thin).
+ {
+ my @slices_margin = @{offset([ map @$_, @{$lower_layer->slices} ], $fw/2)};
+ for ($fw/2, map {scale MARGIN_STEP} 1..(MARGIN / MARGIN_STEP)) {
+ $diff = diff(
+ offset($diff, $_),
+ \@slices_margin,
+ );
+ }
}
+ push @contact, @$diff;
}
- push @contact, @$diff;
}
next if !@contact;
@@ -176,7 +187,7 @@ sub contact_area {
require "Slic3r/SVG.pm";
Slic3r::SVG::output("contact_" . $contact_z . ".svg",
expolygons => union_ex(\@contact),
- red_expolygons => \@overhang,
+ red_expolygons => union_ex(\@overhang),
);
}
}
diff --git a/lib/Slic3r/Test.pm b/lib/Slic3r/Test.pm
index 6f2b5d403..8c4a969eb 100644
--- a/lib/Slic3r/Test.pm
+++ b/lib/Slic3r/Test.pm
@@ -107,6 +107,7 @@ sub init_print {
$model_name = [$model_name] if ref($model_name) ne 'ARRAY';
for my $model (map model($_, %params), @$model_name) {
+ die "Unknown model in test" if !defined $model;
$model->arrange_objects($config);
$print->add_model($model);
}
diff --git a/t/support.t b/t/support.t
index 768ddc095..b7d1810df 100644
--- a/t/support.t
+++ b/t/support.t
@@ -1,4 +1,4 @@
-use Test::More tests => 13;
+use Test::More tests => 14;
use strict;
use warnings;
@@ -9,7 +9,8 @@ BEGIN {
use List::Util qw(first);
use Slic3r;
-use Slic3r::Geometry qw(epsilon);
+use Slic3r::Geometry qw(epsilon scale);
+use Slic3r::Geometry::Clipper qw(diff);
use Slic3r::Test;
{
@@ -88,4 +89,38 @@ use Slic3r::Test;
});
}
+{
+ my $config = Slic3r::Config->new_from_defaults;
+ $config->set('skirts', 0);
+ $config->set('raft_layers', 3);
+ $config->set('support_material_extrusion_width', 0.6);
+ $config->set('first_layer_extrusion_width', '100%');
+ my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
+
+ my $layer_id = 0;
+ my @raft = my @first_object_layer = ();
+ Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
+ my ($self, $cmd, $args, $info) = @_;
+
+ if ($info->{extruding} && $info->{dist_XY} > 0) {
+ if ($layer_id <= $config->raft_layers) {
+ # this is a raft layer or the first object layer
+ my $line = Slic3r::Line->new_scale([ $self->X, $self->Y ], [ $info->{new_X}, $info->{new_Y} ]);
+ my @path = $line->grow(scale($config->support_material_extrusion_width/2));
+ if ($layer_id < $config->raft_layers) {
+ # this is a raft layer
+ push @raft, @path;
+ } else {
+ push @first_object_layer, @path;
+ }
+ }
+ } elsif ($cmd eq 'G1' && $info->{dist_Z} > 0) {
+ $layer_id++;
+ }
+ });
+
+ ok !@{diff(\@first_object_layer, \@raft)},
+ 'first object layer is completely supported by raft';
+}
+
__END__