~ubuntu-branches/ubuntu/utopic/slic3r/utopic

« back to all changes in this revision

Viewing changes to t/shells.t

  • Committer: Package Import Robot
  • Author(s): Chow Loong Jin
  • Date: 2014-06-17 01:27:26 UTC
  • Revision ID: package-import@ubuntu.com-20140617012726-2wrs4zdo251nr4vg
Tags: upstream-1.1.4+dfsg
ImportĀ upstreamĀ versionĀ 1.1.4+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
use Test::More tests => 17;
 
2
use strict;
 
3
use warnings;
 
4
 
 
5
BEGIN {
 
6
    use FindBin;
 
7
    use lib "$FindBin::Bin/../lib";
 
8
}
 
9
 
 
10
use List::Util qw(first sum);
 
11
use Slic3r;
 
12
use Slic3r::Geometry qw(epsilon);
 
13
use Slic3r::Test;
 
14
 
 
15
{
 
16
    my $config = Slic3r::Config->new_from_defaults;
 
17
    $config->set('skirts', 0);
 
18
    $config->set('perimeters', 0);
 
19
    $config->set('solid_infill_speed', 99);
 
20
    $config->set('top_solid_infill_speed', 99);
 
21
    $config->set('bridge_speed', 72);
 
22
    $config->set('first_layer_speed', '100%');
 
23
    $config->set('cooling', 0);
 
24
    
 
25
    my $test = sub {
 
26
        my ($conf) = @_;
 
27
        $conf ||= $config;
 
28
        
 
29
        my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
 
30
        
 
31
        my %z = ();                            # Z => 1
 
32
        my %layers_with_solid_infill    = ();  # Z => $count
 
33
        my %layers_with_bridge_infill   = ();  # Z => $count
 
34
        Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
 
35
            my ($self, $cmd, $args, $info) = @_;
 
36
            
 
37
            if ($self->Z > 0) {
 
38
                $z{ $self->Z } = 1;
 
39
                if ($info->{extruding} && $info->{dist_XY} > 0) {
 
40
                    my $F = $args->{F} // $self->F;
 
41
                    $layers_with_solid_infill{$self->Z} = 1
 
42
                        if $F == $config->solid_infill_speed*60;
 
43
                    $layers_with_bridge_infill{$self->Z} = 1
 
44
                        if $F == $config->bridge_speed*60;
 
45
                }
 
46
            }
 
47
        });
 
48
        my @z = sort { $a <=> $b } keys %z;
 
49
        my @shells = map $layers_with_solid_infill{$_} || $layers_with_bridge_infill{$_}, @z;
 
50
        fail "insufficient number of bottom solid layers"
 
51
            unless !defined(first { !$_ } @shells[0..$config->bottom_solid_layers-1]);
 
52
        fail "excessive number of bottom solid layers"
 
53
            unless scalar(grep $_, @shells[0 .. $#shells/2]) == $config->bottom_solid_layers;
 
54
        fail "insufficient number of top solid layers"
 
55
            unless !defined(first { !$_ } @shells[-$config->top_solid_layers..-1]);
 
56
        fail "excessive number of top solid layers"
 
57
            unless scalar(grep $_, @shells[($#shells/2)..$#shells]) == $config->top_solid_layers;
 
58
        if ($config->top_solid_layers > 0) {
 
59
            fail "unexpected solid infill speed in first solid layer over sparse infill"
 
60
                if $layers_with_solid_infill{ $z[-$config->top_solid_layers] };
 
61
            die "bridge speed not used in first solid layer over sparse infill"
 
62
                if !$layers_with_bridge_infill{ $z[-$config->top_solid_layers] };
 
63
        }
 
64
        1;
 
65
    };
 
66
    
 
67
    $config->set('top_solid_layers', 3);
 
68
    $config->set('bottom_solid_layers', 3);
 
69
    ok $test->(), "proper number of shells is applied";
 
70
    
 
71
    $config->set('top_solid_layers', 0);
 
72
    $config->set('bottom_solid_layers', 0);
 
73
    ok $test->(), "no shells are applied when both top and bottom are set to zero";
 
74
    
 
75
    $config->set('fill_density', 0);
 
76
    ok $test->(), "proper number of shells is applied even when fill density is none";
 
77
}
 
78
 
 
79
# issue #1161
 
80
{
 
81
    my $config = Slic3r::Config->new_from_defaults;
 
82
    $config->set('layer_height', 0.3);
 
83
    $config->set('first_layer_height', '100%');
 
84
    $config->set('bottom_solid_layers', 0);
 
85
    $config->set('top_solid_layers', 3);
 
86
    $config->set('cooling', 0);
 
87
    $config->set('bridge_speed', 99);
 
88
    $config->set('solid_infill_speed', 99);
 
89
    $config->set('top_solid_infill_speed', 99);
 
90
    $config->set('first_layer_speed', '100%');
 
91
    
 
92
    my $print = Slic3r::Test::init_print('V', config => $config);
 
93
    my %layers_with_solid_infill = ();  # Z => 1
 
94
    Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
 
95
        my ($self, $cmd, $args, $info) = @_;
 
96
        
 
97
        $layers_with_solid_infill{$self->Z} = 1
 
98
            if $info->{extruding} && ($args->{F} // $self->F) == $config->solid_infill_speed*60;
 
99
    });
 
100
    is scalar(map $layers_with_solid_infill{$_}, grep $_ <= 7.2, keys %layers_with_solid_infill), 3,
 
101
        "correct number of top solid shells is generated in V-shaped object";
 
102
}
 
103
 
 
104
{
 
105
    my $config = Slic3r::Config->new_from_defaults;
 
106
    # we need to check against one perimeter because this test is calibrated
 
107
    # (shape, extrusion_width) so that perimeters cover the bottom surfaces of
 
108
    # their lower layer - the test checks that shells are not generated on the
 
109
    # above layers (thus 'across' the shadow perimeter)
 
110
    # the test is actually calibrated to leave a narrow bottom region for each
 
111
    # layer - we test that in case of fill_density = 0 such narrow shells are 
 
112
    # discarded instead of grown
 
113
    $config->set('perimeters', 1);
 
114
    $config->set('fill_density', 0);
 
115
    $config->set('cooling', 0);                 # prevent speed alteration
 
116
    $config->set('first_layer_speed', '100%');  # prevent speed alteration
 
117
    $config->set('layer_height', 0.4);
 
118
    $config->set('first_layer_height', '100%');
 
119
    $config->set('extrusion_width', 0.55);
 
120
    $config->set('bottom_solid_layers', 3);
 
121
    $config->set('top_solid_layers', 0);
 
122
    $config->set('solid_infill_speed', 99);
 
123
    
 
124
    my $print = Slic3r::Test::init_print('V', config => $config);
 
125
    my %layers = ();  # Z => 1
 
126
    Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
 
127
        my ($self, $cmd, $args, $info) = @_;
 
128
        $layers{$self->Z} = 1
 
129
            if $info->{extruding} && ($args->{F} // $self->F) == $config->solid_infill_speed*60;
 
130
    });
 
131
    is scalar(keys %layers), $config->bottom_solid_layers,
 
132
        "shells are not propagated across perimeters of the neighbor layer";
 
133
}
 
134
 
 
135
{
 
136
    my $config = Slic3r::Config->new_from_defaults;
 
137
    $config->set('perimeters', 3);
 
138
    $config->set('cooling', 0);                 # prevent speed alteration
 
139
    $config->set('first_layer_speed', '100%');  # prevent speed alteration
 
140
    $config->set('layer_height', 0.4);
 
141
    $config->set('first_layer_height', '100%');
 
142
    $config->set('bottom_solid_layers', 3);
 
143
    $config->set('top_solid_layers', 3);
 
144
    $config->set('solid_infill_speed', 99);
 
145
    $config->set('top_solid_infill_speed', 99);
 
146
    
 
147
    my $print = Slic3r::Test::init_print('sloping_hole', config => $config);
 
148
    my %solid_layers = ();  # Z => 1
 
149
    Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
 
150
        my ($self, $cmd, $args, $info) = @_;
 
151
        $solid_layers{$self->Z} = 1
 
152
            if $info->{extruding} && ($args->{F} // $self->F) == $config->solid_infill_speed*60;
 
153
    });
 
154
    is scalar(keys %solid_layers), $config->bottom_solid_layers + $config->top_solid_layers,
 
155
        "no superfluous shells are generated";
 
156
}
 
157
 
 
158
{
 
159
    my $config = Slic3r::Config->new_from_defaults;
 
160
    $config->set('perimeters', 1);
 
161
    $config->set('fill_density', 0);
 
162
    $config->set('top_solid_layers', 0);
 
163
    $config->set('spiral_vase', 1);
 
164
    $config->set('bottom_solid_layers', 0);
 
165
    $config->set('skirts', 0);
 
166
    $config->set('first_layer_height', '100%');
 
167
    $config->set('start_gcode', '');
 
168
    
 
169
    # TODO: this needs to be tested with a model with sloping edges, where starting
 
170
    # points of each layer are not aligned - in that case we would test that no
 
171
    # travel moves are left to move to the new starting point - in a cube, end
 
172
    # points coincide with next layer starting points (provided there's no clipping)
 
173
    my $test = sub {
 
174
        my ($model_name, $description) = @_;
 
175
        my $print = Slic3r::Test::init_print($model_name, config => $config);
 
176
        my $travel_moves_after_first_extrusion = 0;
 
177
        my $started_extruding = 0;
 
178
        my @z_steps = ();
 
179
        Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
 
180
            my ($self, $cmd, $args, $info) = @_;
 
181
            
 
182
            if ($cmd eq 'G1') {
 
183
                $started_extruding = 1 if $info->{extruding};
 
184
                push @z_steps, $info->{dist_Z}
 
185
                    if $started_extruding && $info->{dist_Z} > 0;
 
186
                $travel_moves_after_first_extrusion++
 
187
                    if $info->{travel} && $started_extruding && !exists $args->{Z};
 
188
            }
 
189
        });
 
190
        
 
191
        # we allow one travel move after first extrusion: i.e. when moving to the first
 
192
        # spiral point after moving to second layer (bottom layer had loop clipping, so
 
193
        # we're slightly distant from the starting point of the loop)
 
194
        ok $travel_moves_after_first_extrusion <= 1, "no gaps in spiral vase ($description)";
 
195
        ok !(grep { $_ > $config->layer_height + epsilon } @z_steps), "no gaps in Z ($description)";
 
196
    };
 
197
    
 
198
    $test->('20mm_cube', 'solid model');
 
199
    
 
200
    $config->set('z_offset', -10);
 
201
    $test->('20mm_cube', 'solid model with negative z-offset');
 
202
    
 
203
    ### Disabled because the current unreliable medial axis code doesn't
 
204
    ### always produce valid loops.
 
205
    ###$test->('40x10', 'hollow model with negative z-offset');
 
206
}
 
207
 
 
208
{
 
209
    my $config = Slic3r::Config->new_from_defaults;
 
210
    $config->set('spiral_vase', 1);
 
211
    $config->set('perimeters', 1);
 
212
    $config->set('fill_density', 0);
 
213
    $config->set('top_solid_layers', 0);
 
214
    $config->set('bottom_solid_layers', 0);
 
215
    $config->set('retract_layer_change', [0]);
 
216
    $config->set('skirts', 0);
 
217
    $config->set('first_layer_height', '100%');
 
218
    $config->set('layer_height', 0.4);
 
219
    $config->set('start_gcode', '');
 
220
    $config->validate;
 
221
    
 
222
    my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
 
223
    my $z_moves = 0;
 
224
    my @this_layer = ();  # [ dist_Z, dist_XY ], ...
 
225
    
 
226
    my $bottom_layer_not_flat = 0;
 
227
    my $null_z_moves_not_layer_changes = 0;
 
228
    my $null_z_moves_not_multiples_of_layer_height = 0;
 
229
    my $sum_of_partial_z_equals_to_layer_height = 0;
 
230
    my $all_layer_segments_have_same_slope = 0;
 
231
    my $horizontal_extrusions = 0;
 
232
    
 
233
    Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
 
234
        my ($self, $cmd, $args, $info) = @_;
 
235
        
 
236
        if ($cmd eq 'G1') {
 
237
            if ($z_moves < 2) {
 
238
                # skip everything up to the second Z move
 
239
                # (i.e. start of second layer)
 
240
                if (exists $args->{Z}) {
 
241
                    $z_moves++;
 
242
                    $bottom_layer_not_flat = 1
 
243
                        if $info->{dist_Z} > 0 && $info->{dist_Z} != $config->layer_height;
 
244
                }
 
245
            } elsif ($info->{dist_Z} == 0 && $args->{Z}) {
 
246
                $null_z_moves_not_layer_changes = 1
 
247
                    if $info->{dist_XY} != 0;
 
248
                
 
249
                # % doesn't work easily with floats
 
250
                $null_z_moves_not_multiples_of_layer_height = 1
 
251
                    if abs(($args->{Z} / $config->layer_height) * $config->layer_height - $args->{Z}) > epsilon;
 
252
                
 
253
                my $total_dist_XY = sum(map $_->[1], @this_layer);
 
254
                $sum_of_partial_z_equals_to_layer_height = 1
 
255
                    if abs(sum(map $_->[0], @this_layer) - $config->layer_height) > epsilon;
 
256
                
 
257
                foreach my $segment (@this_layer) {
 
258
                    # check that segment's dist_Z is proportioned to its dist_XY
 
259
                    $all_layer_segments_have_same_slope = 1
 
260
                        if abs($segment->[0]*$total_dist_XY/$config->layer_height - $segment->[1]) > 0.1;
 
261
                }
 
262
                
 
263
                @this_layer = ();
 
264
            } elsif ($info->{extruding} && $info->{dist_XY} > 0) {
 
265
                $horizontal_extrusions = 1
 
266
                    if $info->{dist_Z} == 0;
 
267
                push @this_layer, [ $info->{dist_Z}, $info->{dist_XY} ];
 
268
            }
 
269
        }
 
270
    });
 
271
    ok !$bottom_layer_not_flat, 'bottom layer is flat when using spiral vase';
 
272
    ok !$null_z_moves_not_layer_changes, 'null Z moves are layer changes';
 
273
    ok !$null_z_moves_not_multiples_of_layer_height, 'null Z moves are multiples of layer height';
 
274
    ok !$sum_of_partial_z_equals_to_layer_height, 'sum of partial Z increments equals to a full layer height';
 
275
    ok !$all_layer_segments_have_same_slope, 'all layer segments have the same slope';
 
276
    ok !$horizontal_extrusions, 'no horizontal extrusions';
 
277
}
 
278
 
 
279
{
 
280
    my $config = Slic3r::Config->new_from_defaults;
 
281
    $config->set('perimeters', 1);
 
282
    $config->set('fill_density', 0);
 
283
    $config->set('top_solid_layers', 0);
 
284
    $config->set('spiral_vase', 1);
 
285
    $config->set('bottom_solid_layers', 0);
 
286
    $config->set('skirts', 0);
 
287
    $config->set('first_layer_height', '100%');
 
288
    $config->set('start_gcode', '');
 
289
    
 
290
    my $print = Slic3r::Test::init_print('two_hollow_squares', config => $config);
 
291
    my $diagonal_moves = 0;
 
292
    Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
 
293
        my ($self, $cmd, $args, $info) = @_;
 
294
        
 
295
        if ($cmd eq 'G1') {
 
296
            if ($info->{extruding} && $info->{dist_XY} > 0) {
 
297
                if ($info->{dist_Z} > 0) {
 
298
                    $diagonal_moves++;
 
299
                }
 
300
            }
 
301
        }
 
302
    });
 
303
    is $diagonal_moves, 0, 'no spiral moves on two-island object';
 
304
}
 
305
 
 
306
__END__