Merge branch 'master' into xsdata
Conflicts: lib/Slic3r.pm lib/Slic3r/ExPolygon.pm lib/Slic3r/Fill.pm lib/Slic3r/Fill/Rectilinear.pm lib/Slic3r/GCode.pm lib/Slic3r/GUI/Plater.pm lib/Slic3r/Geometry/Clipper.pm lib/Slic3r/Layer/Region.pm lib/Slic3r/Print.pm lib/Slic3r/Print/Object.pm lib/Slic3r/TriangleMesh.pm t/shells.t xs/MANIFEST
This commit is contained in:
commit
b38cc2c244
60 changed files with 1432 additions and 798 deletions
|
@ -2,7 +2,7 @@ use Test::More;
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
plan tests => 7;
|
||||
plan tests => 10;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
|
@ -78,6 +78,28 @@ use Slic3r;
|
|||
ok @simplified == 1, 'gear simplified to a single polygon';
|
||||
note sprintf "original points: %d\nnew points: %d", $num_points, scalar(@{$simplified[0]});
|
||||
ok @{$simplified[0]} < $num_points, 'gear was further simplified using Douglas-Peucker';
|
||||
|
||||
my @simplified_ex = Slic3r::ExPolygon->new($polygon)->simplify(10);
|
||||
is_deeply [ map $_->pp, @simplified_ex ], [ [ map $_->pp, @simplified ] ], 'simplified polygon equals simplified expolygon';
|
||||
}
|
||||
|
||||
{
|
||||
my $square = Slic3r::Polygon->new( # ccw
|
||||
[100, 100],
|
||||
[200, 100],
|
||||
[200, 200],
|
||||
[100, 200],
|
||||
);
|
||||
my $hole_in_square = Slic3r::Polygon->new( # cw
|
||||
[140, 140],
|
||||
[140, 160],
|
||||
[160, 160],
|
||||
[160, 140],
|
||||
);
|
||||
my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
|
||||
my @simplified = $hole_in_square->simplify;
|
||||
is scalar(@simplified), 1, 'hole simplification returns one polygon';
|
||||
ok $simplified[0]->is_counter_clockwise, 'hole simplification turns cw polygon into ccw polygon';
|
||||
}
|
||||
|
||||
{
|
||||
|
|
56
t/fill.t
56
t/fill.t
|
@ -2,7 +2,7 @@ use Test::More;
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
plan tests => 10;
|
||||
plan tests => 32;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
|
@ -11,6 +11,7 @@ BEGIN {
|
|||
|
||||
use Slic3r;
|
||||
use Slic3r::Geometry qw(scale X Y);
|
||||
use Slic3r::Geometry::Clipper qw(diff_ex);
|
||||
use Slic3r::Surface qw(:types);
|
||||
use Slic3r::Test;
|
||||
|
||||
|
@ -48,6 +49,59 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $test = sub {
|
||||
my ($expolygon, $flow_spacing) = @_;
|
||||
|
||||
my $filler = Slic3r::Fill::Rectilinear->new(
|
||||
bounding_box => $expolygon->bounding_box,
|
||||
angle => 0,
|
||||
);
|
||||
my $surface = Slic3r::Surface->new(
|
||||
surface_type => S_TYPE_BOTTOM,
|
||||
expolygon => $expolygon,
|
||||
);
|
||||
my ($params, @paths) = $filler->fill_surface($surface, flow_spacing => $flow_spacing, density => 1);
|
||||
|
||||
# check whether any part was left uncovered
|
||||
my @grown_paths = map Slic3r::Polyline->new(@$_)->grow(scale $params->{flow_spacing}/2), @paths;
|
||||
my $uncovered = diff_ex([ @$expolygon ], [ @grown_paths ], 1);
|
||||
|
||||
# ignore very small dots
|
||||
@$uncovered = grep $_->area > (scale $flow_spacing)**2, @$uncovered;
|
||||
|
||||
is scalar(@$uncovered), 0, 'solid surface is fully filled';
|
||||
|
||||
if (0 && @$uncovered) {
|
||||
require "Slic3r/SVG.pm";
|
||||
Slic3r::SVG::output(
|
||||
"uncovered.svg",
|
||||
expolygons => [$expolygon],
|
||||
red_expolygons => $uncovered,
|
||||
);
|
||||
exit;
|
||||
}
|
||||
};
|
||||
|
||||
my $expolygon = Slic3r::ExPolygon->new([
|
||||
[6883102, 9598327.01296997],
|
||||
[6883102, 20327272.01297],
|
||||
[3116896, 20327272.01297],
|
||||
[3116896, 9598327.01296997],
|
||||
]);
|
||||
$test->($expolygon, 0.55);
|
||||
|
||||
for (1..20) {
|
||||
$expolygon->scale(1.05);
|
||||
$test->($expolygon, 0.55);
|
||||
}
|
||||
|
||||
$expolygon = Slic3r::ExPolygon->new(
|
||||
[[59515297,5422499],[59531249,5578697],[59695801,6123186],[59965713,6630228],[60328214,7070685],[60773285,7434379],[61274561,7702115],[61819378,7866770],[62390306,7924789],[62958700,7866744],[63503012,7702244],[64007365,7434357],[64449960,7070398],[64809327,6634999],[65082143,6123325],[65245005,5584454],[65266967,5422499],[66267307,5422499],[66269190,8310081],[66275379,17810072],[66277259,20697500],[65267237,20697500],[65245004,20533538],[65082082,19994444],[64811462,19488579],[64450624,19048208],[64012101,18686514],[63503122,18415781],[62959151,18251378],[62453416,18198442],[62390147,18197355],[62200087,18200576],[61813519,18252990],[61274433,18415918],[60768598,18686517],[60327567,19047892],[59963609,19493297],[59695865,19994587],[59531222,20539379],[59515153,20697500],[58502480,20697500],[58502480,5422499]]
|
||||
);
|
||||
$test->($expolygon, 0.524341649025257);
|
||||
}
|
||||
|
||||
{
|
||||
my $collection = Slic3r::Polyline::Collection->new(polylines => [
|
||||
Slic3r::Polyline->new([0,15], [0,18], [0,20]),
|
||||
|
|
|
@ -2,7 +2,7 @@ use Test::More;
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
plan tests => 24;
|
||||
plan tests => 25;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
|
@ -183,3 +183,10 @@ is Slic3r::Geometry::can_connect_points(@$points, $polygons), 0, 'can_connect_po
|
|||
}
|
||||
|
||||
#==========================================================
|
||||
|
||||
{
|
||||
my $line = Slic3r::Line->new([10,10], [20,10]);
|
||||
is +($line->grow(5))[0]->area, Slic3r::Polygon->new([5,5], [25,5], [25,15], [5,15])->area, 'grow line';
|
||||
}
|
||||
|
||||
#==========================================================
|
||||
|
|
13
t/layers.t
13
t/layers.t
|
@ -1,4 +1,4 @@
|
|||
use Test::More tests => 5;
|
||||
use Test::More tests => 4;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
|
@ -56,15 +56,4 @@ ok $test->(), "positive Z offset";
|
|||
$config->set('z_offset', -0.8);
|
||||
ok $test->(), "negative Z offset";
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
$config->set('nozzle_diameter', [0.35]);
|
||||
$config->set('layer_height', 0.1333);
|
||||
|
||||
my $print = Slic3r::Test::init_print('2x20x10', config => $config);
|
||||
$print->init_extruders;
|
||||
$_->region(0) for @{$print->objects->[0]->layers}; # init layer regions
|
||||
ok $print->objects->[0]->layers->[1]->support_material_contact_height > 0, 'support_material_contact_height is positive';
|
||||
}
|
||||
|
||||
__END__
|
||||
|
|
|
@ -48,8 +48,9 @@ my $test = sub {
|
|||
}
|
||||
if ($info->{dist_Z} < 0) {
|
||||
fail 'going down only after lifting' if !$lifted;
|
||||
fail 'going down by the same amount of the lift'
|
||||
if !_eq($info->{dist_Z}, -$print->extruders->[$tool]->retract_lift);
|
||||
fail 'going down by the same amount of the lift or by the amount needed to get to next layer'
|
||||
if !_eq($info->{dist_Z}, -$print->extruders->[$tool]->retract_lift)
|
||||
&& !_eq($info->{dist_Z}, -$print->extruders->[$tool]->retract_lift + $conf->layer_height);
|
||||
$lifted = 0;
|
||||
}
|
||||
fail 'move Z at travel speed' if ($args->{F} // $self->F) != $conf->travel_speed * 60;
|
||||
|
@ -123,6 +124,8 @@ $retract_tests->(' (G0 and duplicate)');
|
|||
$config->set('duplicate', 1);
|
||||
$config->set('g0', 0);
|
||||
$config->set('infill_extruder', 2);
|
||||
$retract_tests->(' (dual extruder)');
|
||||
$config->set('skirts', 4);
|
||||
$config->set('skirt_height', 3);
|
||||
$retract_tests->(' (dual extruder with multiple skirt layers)');
|
||||
|
||||
__END__
|
||||
|
|
70
t/shells.t
70
t/shells.t
|
@ -1,4 +1,4 @@
|
|||
use Test::More tests => 4;
|
||||
use Test::More tests => 10;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
|
@ -84,4 +84,72 @@ use Slic3r::Test;
|
|||
"correct number of top solid shells is generated in V-shaped object";
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
# we need to check against one perimeter because this test is calibrated
|
||||
# (shape, extrusion_width) so that perimeters cover the bottom surfaces of
|
||||
# their lower layer - the test checks that shells are not generated on the
|
||||
# above layers (thus 'across' the shadow perimeter)
|
||||
# the test is actually calibrated to leave a narrow bottom region for each
|
||||
# layer - we test that in case of fill_density = 0 such narrow shells are
|
||||
# discarded instead of grown
|
||||
$config->set('perimeters', 1);
|
||||
$config->set('fill_density', 0);
|
||||
$config->set('cooling', 0); # prevent speed alteration
|
||||
$config->set('first_layer_speed', '100%'); # prevent speed alteration
|
||||
$config->set('layer_height', 0.4);
|
||||
$config->set('first_layer_height', '100%');
|
||||
$config->set('extrusion_width', 0.5);
|
||||
$config->set('bottom_solid_layers', 3);
|
||||
$config->set('top_solid_layers', 0);
|
||||
$config->set('solid_infill_speed', 99);
|
||||
|
||||
my $print = Slic3r::Test::init_print('V', config => $config);
|
||||
my %layers = (); # Z => 1
|
||||
Slic3r::GCode::Reader->new(gcode => Slic3r::Test::gcode($print))->parse(sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
$layers{$self->Z} = 1
|
||||
if $info->{extruding} && ($args->{F} // $self->F) == $config->solid_infill_speed*60;
|
||||
});
|
||||
is scalar(keys %layers), $config->bottom_solid_layers,
|
||||
"shells are not propagated across perimeters of the neighbor layer";
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
$config->set('spiral_vase', 1);
|
||||
$config->set('bottom_solid_layers', 0);
|
||||
$config->set('skirts', 0);
|
||||
$config->set('first_layer_height', '100%');
|
||||
|
||||
# TODO: this needs to be tested with a model with sloping edges, where starting
|
||||
# points of each layer are not aligned - in that case we would test that no
|
||||
# travel moves are left to move to the new starting point - in a cube, end
|
||||
# points coincide with next layer starting points (provided there's no clipping)
|
||||
my $test = sub {
|
||||
my ($model_name, $description) = @_;
|
||||
my $print = Slic3r::Test::init_print($model_name, config => $config);
|
||||
my $travel_moves_after_first_extrusion = 0;
|
||||
my $started_extruding = 0;
|
||||
my @z_steps = ();
|
||||
Slic3r::GCode::Reader->new(gcode => Slic3r::Test::gcode($print))->parse(sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
$started_extruding = 1 if $info->{extruding};
|
||||
push @z_steps, ($args->{Z} - $self->Z)
|
||||
if $started_extruding && exists $args->{Z};
|
||||
$travel_moves_after_first_extrusion++
|
||||
if $info->{travel} && $started_extruding && !exists $args->{Z};
|
||||
});
|
||||
is $travel_moves_after_first_extrusion, 0, "no gaps in spiral vase ($description)";
|
||||
ok !(grep { $_ > $config->layer_height } @z_steps), "no gaps in Z ($description)";
|
||||
};
|
||||
|
||||
$test->('20mm_cube', 'solid model');
|
||||
$test->('40x10', 'hollow model');
|
||||
|
||||
$config->set('z_offset', -10);
|
||||
$test->('20mm_cube', 'solid model with negative z-offset');
|
||||
}
|
||||
|
||||
__END__
|
||||
|
|
45
t/support.t
45
t/support.t
|
@ -1,4 +1,4 @@
|
|||
use Test::More tests => 1;
|
||||
use Test::More tests => 13;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
|
@ -7,15 +7,58 @@ BEGIN {
|
|||
use lib "$FindBin::Bin/../lib";
|
||||
}
|
||||
|
||||
use List::Util qw(first);
|
||||
use Slic3r;
|
||||
use Slic3r::Geometry qw(epsilon);
|
||||
use Slic3r::Test;
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
my @contact_z = my @top_z = ();
|
||||
|
||||
my $test = sub {
|
||||
my $flow = Slic3r::Flow->new(nozzle_diameter => $config->nozzle_diameter->[0], layer_height => $config->layer_height);
|
||||
my @support_layers = Slic3r::Print::Object::_compute_support_layers(\@contact_z, \@top_z, $config, $flow);
|
||||
|
||||
is $support_layers[0], $config->first_layer_height,
|
||||
'first layer height is honored';
|
||||
is scalar(grep { $support_layers[$_]-$support_layers[$_-1] <= 0 } 1..$#support_layers), 0,
|
||||
'no null or negative support layers';
|
||||
is scalar(grep { $support_layers[$_]-$support_layers[$_-1] > $flow->nozzle_diameter + epsilon } 1..$#support_layers), 0,
|
||||
'no layers thicker than nozzle diameter';
|
||||
|
||||
my $wrong_top_spacing = 0;
|
||||
foreach my $top_z (@top_z) {
|
||||
# find layer index of this top surface
|
||||
my $layer_id = first { abs($support_layers[$_] - $top_z) < epsilon } 0..$#support_layers;
|
||||
|
||||
# check that first support layer above this top surface is spaced with nozzle diameter
|
||||
$wrong_top_spacing = 1
|
||||
if ($support_layers[$layer_id+1] - $support_layers[$layer_id]) != $flow->nozzle_diameter;
|
||||
}
|
||||
ok !$wrong_top_spacing, 'layers above top surfaces are spaced correctly';
|
||||
};
|
||||
|
||||
$config->set('layer_height', 0.2);
|
||||
$config->set('first_layer_height', 0.3);
|
||||
@contact_z = (1.9);
|
||||
@top_z = (1.1);
|
||||
$test->();
|
||||
|
||||
$config->set('first_layer_height', 0.4);
|
||||
$test->();
|
||||
|
||||
$config->set('layer_height', $config->nozzle_diameter->[0]);
|
||||
$test->();
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
$config->set('raft_layers', 3);
|
||||
$config->set('brim_width', 6);
|
||||
$config->set('skirts', 0);
|
||||
$config->set('support_material_extruder', 2);
|
||||
$config->set('support_material_interface_extruder', 2);
|
||||
$config->set('layer_height', 0.4);
|
||||
$config->set('first_layer_height', '100%');
|
||||
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue