Some fixes about overhang detection. Includes regression tests
This commit is contained in:
parent
f5322596d9
commit
c707073a73
1
MANIFEST
1
MANIFEST
@ -75,6 +75,7 @@ t/gcode.t
|
||||
t/geometry.t
|
||||
t/layers.t
|
||||
t/loops.t
|
||||
t/perimeters.t
|
||||
t/polyclip.t
|
||||
t/print.t
|
||||
t/retraction.t
|
||||
|
@ -14,7 +14,7 @@ sub first_point {
|
||||
|
||||
sub chained_path {
|
||||
my $self = shift;
|
||||
my ($start_near) = @_;
|
||||
my ($start_near, $no_reverse) = @_;
|
||||
|
||||
return @{$self->paths} if $self->no_sort;
|
||||
|
||||
@ -26,7 +26,7 @@ sub chained_path {
|
||||
polylines => [ map $_->polyline, @paths ],
|
||||
);
|
||||
|
||||
return $collection->chained_path($start_near, \@paths);
|
||||
return $collection->chained_path($start_near, \@paths, $no_reverse);
|
||||
}
|
||||
|
||||
sub cleanup {
|
||||
|
@ -51,7 +51,7 @@ sub _build_speeds {
|
||||
my %role_speeds = (
|
||||
&EXTR_ROLE_PERIMETER => '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_FILL => 'infill',
|
||||
&EXTR_ROLE_SOLIDFILL => 'solid_infill',
|
||||
@ -176,13 +176,19 @@ sub extrude_loop {
|
||||
# inwards move consider the new actual starting point)
|
||||
@paths = Slic3r::ExtrusionPath::Collection
|
||||
->new(paths => [@paths])
|
||||
->chained_path($last_pos);
|
||||
->chained_path($last_pos, 1);
|
||||
} else {
|
||||
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
|
||||
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);
|
||||
|
||||
# make a little move inwards before leaving loop
|
||||
@ -211,23 +217,24 @@ sub extrude_loop {
|
||||
|
||||
sub extrude_path {
|
||||
my $self = shift;
|
||||
my ($path, $description, $recursive) = @_;
|
||||
my ($path, $description, %params) = @_;
|
||||
|
||||
$path = $path->unpack if $path->isa('Slic3r::ExtrusionPath::Packed');
|
||||
$path->simplify(&Slic3r::SCALED_RESOLUTION);
|
||||
|
||||
# detect arcs
|
||||
if ($self->config->gcode_arcs && !$recursive) {
|
||||
if ($self->config->gcode_arcs && !$params{dont_detect_arcs}) {
|
||||
my $gcode = "";
|
||||
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;
|
||||
}
|
||||
|
||||
# go to first point of extrusion path
|
||||
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
|
||||
$gcode .= $self->unretract;
|
||||
@ -257,12 +264,7 @@ sub extrude_path {
|
||||
my $e = $self->extruder->e_per_mm3 * $area;
|
||||
|
||||
# set speed
|
||||
$self->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');
|
||||
}
|
||||
}
|
||||
$self->speed( $params{speed} || $role_speeds{$path->role} || die "Unknown role: " . $path->role );
|
||||
|
||||
# extrude arc or line
|
||||
my $path_length = 0;
|
||||
|
@ -221,7 +221,7 @@ has 'polylines' => (is => 'ro', default => sub { [] });
|
||||
# Note that our polylines will be reversed in place when necessary.
|
||||
sub chained_path {
|
||||
my $self = shift;
|
||||
my ($start_near, $items) = @_;
|
||||
my ($start_near, $items, $no_reverse) = @_;
|
||||
|
||||
$items ||= $self->polylines;
|
||||
my %items_map = map { $self->polylines->[$_] => $items->[$_] } 0 .. $#{$self->polylines};
|
||||
@ -229,7 +229,9 @@ sub chained_path {
|
||||
|
||||
my @paths = ();
|
||||
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) {
|
||||
# find nearest point
|
||||
my $start_index = $start_near
|
||||
@ -237,7 +239,7 @@ sub chained_path {
|
||||
: 0;
|
||||
|
||||
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;
|
||||
}
|
||||
push @paths, splice @my_paths, $path_index, 1;
|
||||
|
@ -34,6 +34,13 @@ sub model {
|
||||
$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]
|
||||
],
|
||||
} 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;
|
||||
|
67
t/perimeters.t
Normal file
67
t/perimeters.t
Normal 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__
|
Loading…
Reference in New Issue
Block a user