Some fixes about overhang detection. Includes regression tests

This commit is contained in:
Alessandro Ranellucci 2013-06-21 14:52:35 +02:00
parent f5322596d9
commit c707073a73
6 changed files with 97 additions and 18 deletions

View File

@ -75,6 +75,7 @@ t/gcode.t
t/geometry.t t/geometry.t
t/layers.t t/layers.t
t/loops.t t/loops.t
t/perimeters.t
t/polyclip.t t/polyclip.t
t/print.t t/print.t
t/retraction.t t/retraction.t

View File

@ -14,7 +14,7 @@ sub first_point {
sub chained_path { sub chained_path {
my $self = shift; my $self = shift;
my ($start_near) = @_; my ($start_near, $no_reverse) = @_;
return @{$self->paths} if $self->no_sort; return @{$self->paths} if $self->no_sort;
@ -26,7 +26,7 @@ sub chained_path {
polylines => [ map $_->polyline, @paths ], polylines => [ map $_->polyline, @paths ],
); );
return $collection->chained_path($start_near, \@paths); return $collection->chained_path($start_near, \@paths, $no_reverse);
} }
sub cleanup { sub cleanup {

View File

@ -51,7 +51,7 @@ sub _build_speeds {
my %role_speeds = ( my %role_speeds = (
&EXTR_ROLE_PERIMETER => 'perimeter', &EXTR_ROLE_PERIMETER => 'perimeter',
&EXTR_ROLE_EXTERNAL_PERIMETER => 'external_perimeter', &EXTR_ROLE_EXTERNAL_PERIMETER => 'external_perimeter',
&EXTR_ROLE_OVERHANG_PERIMETER => 'external_perimeter', &EXTR_ROLE_OVERHANG_PERIMETER => 'bridge',
&EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER => 'perimeter', &EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER => 'perimeter',
&EXTR_ROLE_FILL => 'infill', &EXTR_ROLE_FILL => 'infill',
&EXTR_ROLE_SOLIDFILL => 'solid_infill', &EXTR_ROLE_SOLIDFILL => 'solid_infill',
@ -176,13 +176,19 @@ sub extrude_loop {
# inwards move consider the new actual starting point) # inwards move consider the new actual starting point)
@paths = Slic3r::ExtrusionPath::Collection @paths = Slic3r::ExtrusionPath::Collection
->new(paths => [@paths]) ->new(paths => [@paths])
->chained_path($last_pos); ->chained_path($last_pos, 1);
} else { } else {
push @paths, $extrusion_path; push @paths, $extrusion_path;
} }
# apply the small perimeter speed
my %params = ();
if ($extrusion_path->is_perimeter && abs($extrusion_path->length) <= &Slic3r::SMALL_PERIMETER_LENGTH) {
$params{speed} = 'small_perimeter';
}
# extrude along the path # extrude along the path
my $gcode = join '', map $self->extrude_path($_, $description), @paths; my $gcode = join '', map $self->extrude_path($_, $description, %params), @paths;
$self->wipe_path($extrusion_path->polyline); $self->wipe_path($extrusion_path->polyline);
# make a little move inwards before leaving loop # make a little move inwards before leaving loop
@ -211,23 +217,24 @@ sub extrude_loop {
sub extrude_path { sub extrude_path {
my $self = shift; my $self = shift;
my ($path, $description, $recursive) = @_; my ($path, $description, %params) = @_;
$path = $path->unpack if $path->isa('Slic3r::ExtrusionPath::Packed'); $path = $path->unpack if $path->isa('Slic3r::ExtrusionPath::Packed');
$path->simplify(&Slic3r::SCALED_RESOLUTION); $path->simplify(&Slic3r::SCALED_RESOLUTION);
# detect arcs # detect arcs
if ($self->config->gcode_arcs && !$recursive) { if ($self->config->gcode_arcs && !$params{dont_detect_arcs}) {
my $gcode = ""; my $gcode = "";
foreach my $arc_path ($path->detect_arcs) { foreach my $arc_path ($path->detect_arcs) {
$gcode .= $self->extrude_path($arc_path, $description, 1); $gcode .= $self->extrude_path($arc_path, $description, %params, dont_detect_arcs => 1);
} }
return $gcode; return $gcode;
} }
# go to first point of extrusion path # go to first point of extrusion path
my $gcode = ""; my $gcode = "";
$gcode .= $self->travel_to($path->points->[0], $path->role, "move to first $description point"); $gcode .= $self->travel_to($path->points->[0], $path->role, "move to first $description point")
if !$self->last_pos || !$self->last_pos->coincides_with($path->points->[0]);
# compensate retraction # compensate retraction
$gcode .= $self->unretract; $gcode .= $self->unretract;
@ -257,12 +264,7 @@ sub extrude_path {
my $e = $self->extruder->e_per_mm3 * $area; my $e = $self->extruder->e_per_mm3 * $area;
# set speed # set speed
$self->speed( $role_speeds{$path->role} || die "Unknown role: " . $path->role ); $self->speed( $params{speed} || $role_speeds{$path->role} || die "Unknown role: " . $path->role );
if ($path->role == EXTR_ROLE_PERIMETER || $path->role == EXTR_ROLE_EXTERNAL_PERIMETER || $path->role == EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER) {
if (abs($path->length) <= &Slic3r::SMALL_PERIMETER_LENGTH) {
$self->speed('small_perimeter');
}
}
# extrude arc or line # extrude arc or line
my $path_length = 0; my $path_length = 0;

View File

@ -221,7 +221,7 @@ has 'polylines' => (is => 'ro', default => sub { [] });
# Note that our polylines will be reversed in place when necessary. # Note that our polylines will be reversed in place when necessary.
sub chained_path { sub chained_path {
my $self = shift; my $self = shift;
my ($start_near, $items) = @_; my ($start_near, $items, $no_reverse) = @_;
$items ||= $self->polylines; $items ||= $self->polylines;
my %items_map = map { $self->polylines->[$_] => $items->[$_] } 0 .. $#{$self->polylines}; my %items_map = map { $self->polylines->[$_] => $items->[$_] } 0 .. $#{$self->polylines};
@ -229,7 +229,9 @@ sub chained_path {
my @paths = (); my @paths = ();
my $start_at; my $start_at;
my $endpoints = [ map { $_->[0], $_->[-1] } @my_paths ]; my $endpoints = $no_reverse
? [ map { $_->[0], $_->[0] } @my_paths ]
: [ map { $_->[0], $_->[-1] } @my_paths ];
while (@my_paths) { while (@my_paths) {
# find nearest point # find nearest point
my $start_index = $start_near my $start_index = $start_near
@ -237,7 +239,7 @@ sub chained_path {
: 0; : 0;
my $path_index = int($start_index/2); my $path_index = int($start_index/2);
if ($start_index%2) { # index is end so reverse to make it the start if ($start_index % 2 && !$no_reverse) { # index is end so reverse to make it the start
$my_paths[$path_index]->reverse; $my_paths[$path_index]->reverse;
} }
push @paths, splice @my_paths, $path_index, 1; push @paths, splice @my_paths, $path_index, 1;

View File

@ -34,6 +34,13 @@ sub model {
$facets = [ $facets = [
[0,1,2],[2,1,3],[1,0,4],[5,1,4],[4,0,2],[6,4,2],[7,6,2],[8,9,7],[9,6,7],[2,3,7],[7,3,10],[1,5,3],[3,5,11],[11,12,13],[11,13,3],[3,13,10],[5,4,6],[11,5,6],[6,9,11],[11,9,12],[12,9,8],[13,12,8],[8,7,10],[13,8,10] [0,1,2],[2,1,3],[1,0,4],[5,1,4],[4,0,2],[6,4,2],[7,6,2],[8,9,7],[9,6,7],[2,3,7],[7,3,10],[1,5,3],[3,5,11],[11,12,13],[11,13,3],[3,13,10],[5,4,6],[11,5,6],[6,9,11],[11,9,12],[12,9,8],[13,12,8],[8,7,10],[13,8,10]
], ],
} elsif ($model_name eq 'overhang') {
$vertices = [
[1364.68505859375,614.398010253906,20.002498626709],[1389.68505859375,614.398010253906,20.002498626709],[1377.18505859375,589.398986816406,20.002498626709],[1389.68505859375,589.398986816406,20.002498626709],[1389.68505859375,564.398986816406,20.0014991760254],[1364.68505859375,589.398986816406,20.002498626709],[1364.68505859375,564.398986816406,20.0014991760254],[1360.93505859375,589.398986816406,17.0014991760254],[1360.93505859375,585.64697265625,17.0014991760254],[1357.18505859375,564.398986816406,17.0014991760254],[1364.68505859375,589.398986816406,17.0014991760254],[1364.68505859375,571.899963378906,17.0014991760254],[1364.68505859375,564.398986816406,17.0014991760254],[1348.43603515625,564.398986816406,17.0014991760254],[1352.80908203125,589.398986816406,17.0014991760254],[1357.18408203125,589.398986816406,17.0014991760254],[1357.18310546875,614.398010253906,17.0014991760254],[1364.68505859375,606.89599609375,17.0014991760254],[1364.68505859375,614.398010253906,17.0014991760254],[1352.18603515625,564.398986816406,20.0014991760254],[1363.65405273438,589.398986816406,23.3004989624023],[1359.46704101562,589.398986816406,23.3004989624023],[1358.37109375,564.398986816406,23.3004989624023],[1385.56103515625,564.398986816406,23.3004989624023],[1373.06311035156,589.398986816406,23.3004989624023],[1368.80810546875,564.398986816406,23.3004989624023],[1387.623046875,589.398986816406,23.3004989624023],[1387.623046875,585.276000976562,23.3004989624023],[1389.68505859375,589.398986816406,23.3004989624023],[1389.68505859375,572.64599609375,23.3004989624023],[1389.68505859375,564.398986816406,23.3004989624023],[1367.77709960938,589.398986816406,23.3004989624023],[1366.7470703125,564.398986816406,23.3004989624023],[1354.31201171875,589.398986816406,23.3004989624023],[1352.18603515625,564.398986816406,23.3004989624023],[1389.68505859375,614.398010253906,23.3004989624023],[1377.31701660156,614.398010253906,23.3004989624023],[1381.43908691406,589.398986816406,23.3004989624023],[1368.80700683594,614.398010253906,23.3004989624023],[1368.80810546875,589.398986816406,23.3004989624023],[1356.43908691406,614.398010253906,23.3004989624023],[1357.40502929688,589.398986816406,23.3004989624023],[1360.56201171875,614.398010253906,23.3004989624023],[1348.705078125,614.398010253906,23.3004989624023],[1350.44506835938,589.398986816406,23.3004989624023],[1389.68505859375,606.153015136719,23.3004989624023],[1347.35205078125,589.398986816406,23.3004989624023],[1346.56005859375,589.398986816406,23.3004989624023],[1346.56005859375,594.159912109375,17.0014991760254],[1346.56005859375,589.398986816406,17.0014991760254],[1346.56005859375,605.250427246094,23.3004989624023],[1346.56005859375,614.398010253906,23.3004989624023],[1346.56005859375,614.398010253906,20.8258285522461],[1346.56005859375,614.398010253906,17.0014991760254],[1346.56005859375,564.398986816406,19.10133934021],[1346.56005859375,567.548583984375,23.3004989624023],[1346.56005859375,564.398986816406,17.0020332336426],[1346.56005859375,564.398986816406,23.0018501281738],[1346.56005859375,564.398986816406,23.3004989624023],[1346.56005859375,575.118957519531,17.0014991760254],[1346.56005859375,574.754028320312,23.3004989624023]
];
$facets = [
[0,1,2],[2,3,4],[2,5,0],[4,6,2],[2,6,5],[2,1,3],[7,8,9],[10,9,8],[11,9,10],[12,9,11],[9,13,14],[7,15,16],[10,17,0],[10,0,5],[12,11,6],[18,16,0],[6,19,13],[6,13,9],[9,12,6],[17,18,0],[11,10,5],[11,5,6],[14,16,15],[17,7,18],[16,18,7],[14,15,9],[7,9,15],[7,17,8],[10,8,17],[20,21,22],[23,24,25],[26,23,27],[28,27,23],[29,28,23],[30,29,23],[25,31,32],[22,33,34],[35,36,37],[24,38,39],[21,40,41],[38,42,20],[33,43,44],[6,4,23],[6,23,25],[36,35,1],[1,0,38],[1,38,36],[29,30,4],[25,32,6],[40,42,0],[35,45,1],[4,3,28],[4,28,29],[3,1,45],[3,45,28],[22,34,19],[19,6,32],[19,32,22],[42,38,0],[30,23,4],[0,16,43],[0,43,40],[24,37,36],[38,24,36],[24,23,37],[37,23,26],[22,32,20],[20,32,31],[33,41,40],[43,33,40],[45,35,26],[37,26,35],[33,44,34],[44,43,46],[20,42,21],[40,21,42],[31,39,38],[20,31,38],[33,22,41],[21,41,22],[31,25,39],[24,39,25],[26,27,45],[28,45,27],[47,48,49],[47,50,48],[51,48,50],[52,48,51],[53,48,52],[54,55,56],[57,55,54],[58,55,57],[49,59,47],[60,56,55],[59,56,60],[60,47,59],[48,53,16],[56,13,19],[54,56,19],[56,59,13],[59,49,14],[59,14,13],[49,48,16],[49,16,14],[44,46,60],[44,60,55],[51,50,43],[19,34,58],[19,58,57],[53,52,16],[43,16,52],[43,52,51],[57,54,19],[47,60,46],[55,58,34],[55,34,44],[50,47,46],[50,46,43]
],
} }
my $model = Slic3r::Model->new; my $model = Slic3r::Model->new;

67
t/perimeters.t Normal file
View File

@ -0,0 +1,67 @@
use Test::More tests => 2;
use strict;
use warnings;
BEGIN {
use FindBin;
use lib "$FindBin::Bin/../lib";
}
use Slic3r;
use Slic3r::Test;
{
my $config = Slic3r::Config->new_from_defaults;
$config->set('skirts', 0);
$config->set('fill_density', 0);
$config->set('perimeters', 3);
$config->set('top_solid_layers', 0);
$config->set('bottom_solid_layers', 0);
$config->set('cooling', 0); # to prevent speeds to be altered
$config->set('first_layer_speed', '100%'); # to prevent speeds to be altered
{
my $print = Slic3r::Test::init_print('overhang', config => $config);
my $has_cw_loops = 0;
my $cur_loop;
Slic3r::GCode::Reader->new(gcode => Slic3r::Test::gcode($print))->parse(sub {
my ($self, $cmd, $args, $info) = @_;
if ($info->{extruding}) {
$cur_loop ||= [ [$self->X, $self->Y] ];
push @$cur_loop, [ @$info{qw(new_X new_Y)} ];
} else {
if ($cur_loop) {
$has_cw_loops = 1 if !Slic3r::Geometry::Clipper::is_counter_clockwise($cur_loop);
$cur_loop = undef;
}
}
});
ok !$has_cw_loops, 'all perimeters extruded ccw';
}
{
$config->set('perimeters', 1);
$config->set('perimeter_speed', 77);
$config->set('external_perimeter_speed', 66);
$config->set('bridge_speed', 99);
my $print = Slic3r::Test::init_print('overhang', config => $config);
my %layer_speeds = (); # print Z => [ speeds ]
Slic3r::GCode::Reader->new(gcode => Slic3r::Test::gcode($print))->parse(sub {
my ($self, $cmd, $args, $info) = @_;
if ($info->{extruding} && $info->{dist_XY} > 0) {
$layer_speeds{$self->Z} ||= {};
$layer_speeds{$self->Z}{my $feedrate = $args->{F} // $self->F} = 1;
fail 'wrong speed found'
if $feedrate != $config->perimeter_speed*60
&& $feedrate != $config->external_perimeter_speed*60
&& $feedrate != $config->bridge_speed*60;
}
});
is scalar(grep { keys %$_ > 1 } values %layer_speeds), 1,
'only overhang layer has more than one speed';
}
}
__END__