2014-05-12 19:49:17 +00:00
use Test::More tests = > 10 ;
2013-06-21 12:52:35 +00:00
use strict ;
use warnings ;
BEGIN {
use FindBin ;
use lib "$FindBin::Bin/../lib" ;
}
2014-04-18 15:30:35 +00:00
use List::Util qw( first ) ;
2013-06-21 12:52:35 +00:00
use Slic3r ;
2014-04-14 22:57:43 +00:00
use Slic3r::Flow ':roles' ;
use Slic3r::Geometry qw( PI scale unscale ) ;
2014-04-11 21:10:14 +00:00
use Slic3r::Geometry::Clipper qw( union_ex diff union offset ) ;
use Slic3r::Surface ':types' ;
2013-06-21 12:52:35 +00:00
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 ) ;
2013-06-21 13:38:58 +00:00
$ config - > set ( 'cooling' , 0 ) ; # to prevent speeds from being altered
$ config - > set ( 'first_layer_speed' , '100%' ) ; # to prevent speeds from being altered
2013-06-21 12:52:35 +00:00
{
my $ print = Slic3r::Test:: init_print ( 'overhang' , config = > $ config ) ;
my $ has_cw_loops = 0 ;
my $ cur_loop ;
2013-08-28 14:51:58 +00:00
Slic3r::GCode::Reader - > new - > parse ( Slic3r::Test:: gcode ( $ print ) , sub {
2013-06-21 12:52:35 +00:00
my ( $ self , $ cmd , $ args , $ info ) = @ _ ;
2013-06-22 13:22:58 +00:00
if ( $ info - > { extruding } && $ info - > { dist_XY } > 0 ) {
2013-06-21 12:52:35 +00:00
$ cur_loop || = [ [ $ self - > X , $ self - > Y ] ] ;
push @$ cur_loop , [ @$ info { qw( new_X new_Y ) } ] ;
} else {
if ( $ cur_loop ) {
2013-08-26 23:26:44 +00:00
$ has_cw_loops = 1 if Slic3r::Polygon - > new ( @$ cur_loop ) - > is_clockwise ;
2013-06-21 12:52:35 +00:00
$ cur_loop = undef ;
}
}
} ) ;
ok ! $ has_cw_loops , 'all perimeters extruded ccw' ;
}
2013-06-22 22:05:08 +00:00
{
$ config - > set ( 'external_perimeter_speed' , 68 ) ;
2014-03-24 19:01:14 +00:00
my $ print = Slic3r::Test:: init_print (
'cube_with_hole' ,
config = > $ config ,
duplicate = > 2 , # we test two copies to make sure ExtrusionLoop objects are not modified in-place (the second object would not detect cw loops and thus would calculate wrong inwards moves)
) ;
2013-06-22 22:05:08 +00:00
my $ has_cw_loops = my $ has_outwards_move = 0 ;
my $ cur_loop ;
my % external_loops = ( ) ; # print_z => count of external loops
2013-08-28 14:51:58 +00:00
Slic3r::GCode::Reader - > new - > parse ( Slic3r::Test:: gcode ( $ print ) , sub {
2013-06-22 22:05:08 +00:00
my ( $ self , $ cmd , $ args , $ info ) = @ _ ;
if ( $ info - > { extruding } && $ info - > { dist_XY } > 0 ) {
$ cur_loop || = [ [ $ self - > X , $ self - > Y ] ] ;
push @$ cur_loop , [ @$ info { qw( new_X new_Y ) } ] ;
} else {
if ( $ cur_loop ) {
2013-09-02 20:10:52 +00:00
$ has_cw_loops = 1 if Slic3r::Polygon - > new_scale ( @$ cur_loop ) - > is_clockwise ;
2013-06-22 22:05:08 +00:00
if ( $ self - > F == $ config - > external_perimeter_speed * 60 ) {
2013-07-16 15:13:01 +00:00
my $ move_dest = Slic3r::Point - > new_scale ( @$ info { qw( new_X new_Y ) } ) ;
2014-03-24 19:01:14 +00:00
# reset counter for second object
$ external_loops { $ self - > Z } = 0
if defined ( $ external_loops { $ self - > Z } ) && $ external_loops { $ self - > Z } == 2 ;
2013-06-22 22:05:08 +00:00
$ external_loops { $ self - > Z } + + ;
2013-11-21 17:42:16 +00:00
my $ loop_contains_point = Slic3r::Polygon - > new_scale ( @$ cur_loop ) - > contains_point ( $ move_dest ) ;
2013-06-22 22:05:08 +00:00
$ has_outwards_move = 1
2013-11-21 17:42:16 +00:00
if ( ! $ loop_contains_point && $ external_loops { $ self - > Z } == 2 ) # contour should include destination
|| ( $ loop_contains_point && $ external_loops { $ self - > Z } == 1 ) ; # hole should not
2013-06-22 22:05:08 +00:00
}
$ cur_loop = undef ;
}
}
} ) ;
ok ! $ has_cw_loops , 'all perimeters extruded ccw' ;
ok ! $ has_outwards_move , 'move inwards after completing external loop' ;
}
2013-06-22 13:22:58 +00:00
{
2013-07-06 00:44:50 +00:00
$ config - > set ( 'start_perimeters_at_concave_points' , 1 ) ;
2013-06-22 13:22:58 +00:00
my $ print = Slic3r::Test:: init_print ( 'L' , config = > $ config ) ;
my $ loop_starts_from_convex_point = 0 ;
my $ cur_loop ;
2013-08-28 14:51:58 +00:00
Slic3r::GCode::Reader - > new - > parse ( Slic3r::Test:: gcode ( $ print ) , sub {
2013-06-22 13:22:58 +00:00
my ( $ self , $ cmd , $ args , $ info ) = @ _ ;
if ( $ info - > { extruding } && $ info - > { dist_XY } > 0 ) {
$ cur_loop || = [ [ $ self - > X , $ self - > Y ] ] ;
push @$ cur_loop , [ @$ info { qw( new_X new_Y ) } ] ;
} else {
if ( $ cur_loop ) {
$ loop_starts_from_convex_point = 1
if Slic3r::Geometry:: angle3points ( @$ cur_loop [ 0 , - 1 , 1 ] ) >= PI ;
$ cur_loop = undef ;
}
}
} ) ;
ok ! $ loop_starts_from_convex_point , 'avoid starting from convex points' ;
}
2013-06-21 12:52:35 +00:00
{
$ config - > set ( 'perimeters' , 1 ) ;
$ config - > set ( 'perimeter_speed' , 77 ) ;
$ config - > set ( 'external_perimeter_speed' , 66 ) ;
$ config - > set ( 'bridge_speed' , 99 ) ;
2013-06-21 13:38:58 +00:00
$ config - > set ( 'cooling' , 1 ) ;
$ config - > set ( 'fan_below_layer_time' , 0 ) ;
$ config - > set ( 'slowdown_below_layer_time' , 0 ) ;
$ config - > set ( 'bridge_fan_speed' , 100 ) ;
2013-09-17 08:36:06 +00:00
$ config - > set ( 'bridge_flow_ratio' , 33 ) ; # arbitrary value
2013-07-06 09:35:40 +00:00
$ config - > set ( 'overhangs' , 1 ) ;
2013-06-21 12:52:35 +00:00
my $ print = Slic3r::Test:: init_print ( 'overhang' , config = > $ config ) ;
my % layer_speeds = ( ) ; # print Z => [ speeds ]
2013-06-21 13:38:58 +00:00
my $ fan_speed = 0 ;
2013-09-17 08:36:06 +00:00
my $ bridge_mm_per_mm = ( $ config - > nozzle_diameter - > [ 0 ] ** 2 ) / ( $ config - > filament_diameter - > [ 0 ] ** 2 ) * $ config - > bridge_flow_ratio ;
2013-08-28 14:51:58 +00:00
Slic3r::GCode::Reader - > new - > parse ( Slic3r::Test:: gcode ( $ print ) , sub {
2013-06-21 12:52:35 +00:00
my ( $ self , $ cmd , $ args , $ info ) = @ _ ;
2013-06-21 13:38:58 +00:00
$ fan_speed = 0 if $ cmd eq 'M107' ;
$ fan_speed = $ args - > { S } if $ cmd eq 'M106' ;
2013-06-21 12:52:35 +00:00
if ( $ info - > { extruding } && $ info - > { dist_XY } > 0 ) {
$ layer_speeds { $ self - > Z } || = { } ;
$ layer_speeds { $ self - > Z } { my $ feedrate = $ args - > { F } // $ self - > F } = 1 ;
2013-06-21 13:38:58 +00:00
2013-06-21 12:52:35 +00:00
fail 'wrong speed found'
if $ feedrate != $ config - > perimeter_speed * 60
&& $ feedrate != $ config - > external_perimeter_speed * 60
&& $ feedrate != $ config - > bridge_speed * 60 ;
2013-06-21 13:38:58 +00:00
if ( $ feedrate == $ config - > bridge_speed * 60 ) {
fail 'printing overhang but fan is not enabled or running at wrong speed'
if $ fan_speed != 255 ;
2013-09-17 08:36:06 +00:00
my $ mm_per_mm = $ info - > { dist_E } / $ info - > { dist_XY } ;
fail 'wrong bridge flow' if abs ( $ mm_per_mm - $ bridge_mm_per_mm ) > 0.01 ;
2013-06-21 13:38:58 +00:00
} else {
fail 'fan is running when not supposed to'
if $ fan_speed > 0 ;
}
2013-06-21 12:52:35 +00:00
}
} ) ;
is scalar ( grep { keys %$ _ > 1 } values % layer_speeds ) , 1 ,
'only overhang layer has more than one speed' ;
}
}
2013-09-17 18:18:54 +00:00
{
my $ config = Slic3r::Config - > new_from_defaults ;
$ config - > set ( 'skirts' , 0 ) ;
$ config - > set ( 'perimeters' , 3 ) ;
$ config - > set ( 'layer_height' , 0.4 ) ;
$ config - > set ( 'first_layer_height' , 0.35 ) ;
$ config - > set ( 'extra_perimeters' , 1 ) ;
$ config - > set ( 'cooling' , 0 ) ; # to prevent speeds from being altered
$ config - > set ( 'first_layer_speed' , '100%' ) ; # to prevent speeds from being altered
$ config - > set ( 'perimeter_speed' , 99 ) ;
$ config - > set ( 'external_perimeter_speed' , 99 ) ;
$ config - > set ( 'small_perimeter_speed' , 99 ) ;
2014-03-02 21:26:52 +00:00
$ config - > set ( 'thin_walls' , 0 ) ;
2013-09-17 18:18:54 +00:00
my $ print = Slic3r::Test:: init_print ( 'ipadstand' , config = > $ config ) ;
my % perimeters = ( ) ; # z => number of loops
my $ in_loop = 0 ;
Slic3r::GCode::Reader - > new - > parse ( Slic3r::Test:: gcode ( $ print ) , sub {
my ( $ self , $ cmd , $ args , $ info ) = @ _ ;
if ( $ info - > { extruding } && $ info - > { dist_XY } > 0 && ( $ args - > { F } // $ self - > F ) == $ config - > perimeter_speed * 60 ) {
$ perimeters { $ self - > Z } + + if ! $ in_loop ;
$ in_loop = 1 ;
} else {
$ in_loop = 0 ;
}
} ) ;
ok ! ( grep { $ _ % $ config - > perimeters } values % perimeters ) , 'no superfluous extra perimeters' ;
}
2014-04-18 15:30:35 +00:00
{
my $ config = Slic3r::Config - > new_from_defaults ;
$ config - > set ( 'nozzle_diameter' , [ 0.4 ] ) ;
$ config - > set ( 'perimeters' , 2 ) ;
$ config - > set ( 'perimeter_extrusion_width' , 0.4 ) ;
$ config - > set ( 'infill_extrusion_width' , 0.53 ) ;
$ config - > set ( 'solid_infill_extrusion_width' , 0.53 ) ;
# we just need a pre-filled Print object
my $ print = Slic3r::Test:: init_print ( '20mm_cube' , config = > $ config ) ;
2014-05-09 12:24:35 +00:00
$ print - > print - > init_extruders ;
2014-04-18 15:30:35 +00:00
# override a layer's slices
my $ expolygon = Slic3r::ExPolygon - > new ( [ [ - 71974463 , - 139999376 ] , [ - 71731792 , - 139987456 ] , [ - 71706544 , - 139985616 ] , [ - 71682119 , - 139982639 ] , [ - 71441248 , - 139946912 ] , [ - 71417487 , - 139942895 ] , [ - 71379384 , - 139933984 ] , [ - 71141800 , - 139874480 ] , [ - 71105247 , - 139862895 ] , [ - 70873544 , - 139779984 ] , [ - 70838592 , - 139765856 ] , [ - 70614943 , - 139660064 ] , [ - 70581783 , - 139643567 ] , [ - 70368368 , - 139515680 ] , [ - 70323751 , - 139487872 ] , [ - 70122160 , - 139338352 ] , [ - 70082399 , - 139306639 ] , [ - 69894800 , - 139136624 ] , [ - 69878679 , - 139121327 ] , [ - 69707992 , - 138933008 ] , [ - 69668575 , - 138887343 ] , [ - 69518775 , - 138685359 ] , [ - 69484336 , - 138631632 ] , [ - 69356423 , - 138418207 ] , [ - 69250040 , - 138193296 ] , [ - 69220920 , - 138128976 ] , [ - 69137992 , - 137897168 ] , [ - 69126095 , - 137860255 ] , [ - 69066568 , - 137622608 ] , [ - 69057104 , - 137582511 ] , [ - 69053079 , - 137558751 ] , [ - 69017352 , - 137317872 ] , [ - 69014392 , - 137293456 ] , [ - 69012543 , - 137268207 ] , [ - 68999369 , - 137000000 ] , [ - 63999999 , - 137000000 ] , [ - 63705947 , - 136985551 ] , [ - 63654984 , - 136977984 ] , [ - 63414731 , - 136942351 ] , [ - 63364756 , - 136929840 ] , [ - 63129151 , - 136870815 ] , [ - 62851950 , - 136771631 ] , [ - 62585807 , - 136645743 ] , [ - 62377483 , - 136520895 ] , [ - 62333291 , - 136494415 ] , [ - 62291908 , - 136463728 ] , [ - 62096819 , - 136319023 ] , [ - 62058644 , - 136284432 ] , [ - 61878676 , - 136121328 ] , [ - 61680968 , - 135903184 ] , [ - 61650275 , - 135861807 ] , [ - 61505591 , - 135666719 ] , [ - 61354239 , - 135414191 ] , [ - 61332211 , - 135367615 ] , [ - 61228359 , - 135148063 ] , [ - 61129179 , - 134870847 ] , [ - 61057639 , - 134585262 ] , [ - 61014451 , - 134294047 ] , [ - 61000000 , - 134000000 ] , [ - 61000000 , - 107999999 ] , [ - 61014451 , - 107705944 ] , [ - 61057639 , - 107414736 ] , [ - 61129179 , - 107129152 ] , [ - 61228359 , - 106851953 ] , [ - 61354239 , - 106585808 ] , [ - 61505591 , - 106333288 ] , [ - 61680967 , - 106096816 ] , [ - 61878675 , - 105878680 ] , [ - 62096820 , - 105680967 ] , [ - 62138204 , - 105650279 ] , [ - 62333292 , - 105505591 ] , [ - 62585808 , - 105354239 ] , [ - 62632384 , - 105332207 ] , [ - 62851951 , - 105228360 ] , [ - 62900463 , - 105211008 ] , [ - 63129152 , - 105129183 ] , [ - 63414731 , - 105057640 ] , [ - 63705947 , - 105014448 ] , [ - 63999999 , - 105000000 ] , [ - 68999369 , - 105000000 ] , [ - 69012543 , - 104731792 ] , [ - 69014392 , - 104706544 ] , [ - 69017352 , - 104682119 ] , [ - 69053079 , - 104441248 ] , [ - 69057104 , - 104417487 ] , [ - 69066008 , - 104379383 ] , [ - 69125528 , - 104141799 ] , [ - 69137111 , - 104105248 ] , [ - 69220007 , - 103873544 ] , [ - 69234136 , - 103838591 ] , [ - 69339920 , - 103614943 ] , [ - 69356415 , - 103581784 ] , [ - 69484328 , - 103368367 ] , [ - 69512143 , - 103323752 ] , [ - 69661647 , - 103122160 ] , [ - 69693352 , - 103082399 ] , [ - 69863383 , - 102894800 ] , [ - 69878680 , - 102878679 ] , [ - 70066999 , - 102707992 ] , [ - 70112656 , - 102668576 ] , [ - 70314648 , - 102518775 ] , [ - 70368367 , - 102484336 ] , [ - 70581783 , - 102356424 ] , [ - 70806711 , - 102250040 ] , [ - 70871040 , - 102220919 ] , [ - 71102823 , - 102137992 ] , [ - 71139752 , - 102126095 ] , [ - 71377383 , - 102066568 ] , [ - 71417487 , - 102057104 ] , [ - 71441248 , - 102053079 ] , [ - 71682119 , - 102017352 ] , [ - 71706535 , - 102014392 ] , [ - 71731784 , - 102012543 ] , [ - 71974456 , - 102000624 ] , [ - 71999999 , - 102000000 ] , [ - 104000000 , - 102000000 ] , [ - 104025536 , - 102000624 ] , [ - 104268207 , - 102012543 ] , [ - 104293455 , - 102014392 ] , [ - 104317880 , - 102017352 ] , [ - 104558751 , - 102053079 ] , [ - 104582512 , - 102057104 ] , [ - 104620616 , - 102066008 ] , [ - 104858200 , - 102125528 ] , [ - 104894751 , - 102137111 ] , [ - 105126455 , - 102220007 ] , [ - 105161408 , - 102234136 ] , [ - 105385056 , - 102339920 ] , [ - 105418215 , - 102356415 ] , [ - 105631632 , - 102484328 ] , [ - 105676247 , - 102512143 ] , [ - 105877839 , - 102661647 ] , [ - 105917600 , - 102693352 ] , [ - 106105199 , - 102863383 ] , [ - 106121320 , - 102878680 ] , [ - 106292007 , - 103066999 ] , [ - 106331424 , - 103112656 ] , [ - 106481224 , - 103314648 ] , [ - 106515663 , - 103368367 ] , [ - 106643575 , - 103581783 ] , [ - 106749959 , - 103806711 ] , [ - 106779080 , - 103871040 ] , [ - 106862007 , - 104102823 ] , [ - 106873904 , - 104139752 ] , [ - 106933431 , - 104377383 ] , [ - 106942896 , - 104417487 ] , [ - 106946920 , - 104441248 ] , [ - 106982648 , - 104682119 ] , [ - 106985607 , - 104706535 ] , [ - 106987456 , - 104731784 ] , [ - 107000630 , - 105000000 ] , [ - 112000000 , - 105000000 ] , [ - 112294056 , - 105014448 ] , [ - 112585264 , - 105057640 ] , [ - 112870848 , - 105129184 ] , [ - 112919359 , - 105146535 ] , [ - 113148048 , - 105228360 ] , [ - 113194624 , - 105250392 ] , [ - 113414191 , - 105354239 ] , [ - 113666711 , - 105505591 ] , [ - 113708095 , - 105536279 ] , [ - 113903183 , - 105680967 ] , [ - 114121320 , - 105878679 ] , [ - 114319032 , - 106096816 ] , [ - 114349720 , - 106138200 ] , [ - 114494408 , - 106333288 ] , [ - 114645760 , - 106585808 ] , [ - 114667792 , - 106632384 ] , [ - 114771640 , - 106851952 ] , [ - 114788991 , - 106900463 ] , [ - 114870815 , - 107129151 ] , [ - 114942359 , - 107414735 ] , [ - 114985551 , - 107705943 ] , [ - 115000000 , - 1
2014-05-09 12:24:35 +00:00
my $ object = $ print - > print - > objects - > [ 0 ] ;
2014-04-18 15:30:35 +00:00
$ object - > slice ;
my $ layer = $ object - > layers - > [ 1 ] ;
my $ layerm = $ layer - > regions - > [ 0 ] ;
$ layerm - > slices - > clear ;
$ layerm - > slices - > append ( Slic3r::Surface - > new ( surface_type = > S_TYPE_INTERNAL , expolygon = > $ expolygon ) ) ;
# make perimeters
$ layer - > make_perimeters ;
# compute the covered area
my $ pflow = $ layerm - > flow ( FLOW_ROLE_PERIMETER ) ;
my $ covered_by_perimeters = union_ex ( [
( map @ { $ _ - > polygon - > split_at_first_point - > grow ( $ pflow - > scaled_width / 2 ) } , @ { $ layerm - > perimeters } ) ,
] ) ;
my $ covered_by_infill = union_ex ( [
( map $ _ - > p , @ { $ layerm - > fill_surfaces } ) ,
( map @ { $ _ - > polyline - > grow ( $ pflow - > scaled_width / 2 ) } , @ { $ layerm - > thin_fills } ) ,
] ) ;
# compute the non covered area
my $ non_covered = diff (
[ map @ { $ _ - > expolygon } , @ { $ layerm - > slices } ] ,
[ map @$ _ , ( @$ covered_by_perimeters , @$ covered_by_infill ) ] ,
) ;
if ( 0 ) {
printf "max non covered = %f\n" , List::Util:: max ( map unscale unscale $ _ - > area , @$ non_covered ) ;
require "Slic3r/SVG.pm" ;
Slic3r::SVG:: output (
"gaps.svg" ,
expolygons = > [ map $ _ - > expolygon , @ { $ layerm - > slices } ] ,
red_expolygons = > union_ex ( [ map @$ _ , ( @$ covered_by_perimeters , @$ covered_by_infill ) ] ) ,
green_expolygons = > union_ex ( $ non_covered ) ,
) ;
}
ok ! ( defined first { $ _ - > area > ( $ pflow - > scaled_width ** 2 ) } @$ non_covered ) , 'no gap between perimeters and infill' ;
}
2014-04-29 17:58:58 +00:00
{
my $ config = Slic3r::Config - > new_from_defaults ;
$ config - > set ( 'skirts' , 0 ) ;
$ config - > set ( 'perimeters' , 3 ) ;
$ config - > set ( 'layer_height' , 0.4 ) ;
$ config - > set ( 'bridge_speed' , 99 ) ;
$ config - > set ( 'fill_density' , 0 ) ; # to prevent bridging over sparse infill
$ config - > set ( 'overhangs' , 1 ) ;
$ config - > set ( 'cooling' , 0 ) ; # to prevent speeds from being altered
$ config - > set ( 'first_layer_speed' , '100%' ) ; # to prevent speeds from being altered
my $ test = sub {
my ( $ print ) = @ _ ;
my $ has_bridges = 0 ;
Slic3r::GCode::Reader - > new - > parse ( Slic3r::Test:: gcode ( $ print ) , sub {
my ( $ self , $ cmd , $ args , $ info ) = @ _ ;
if ( $ info - > { extruding } && $ info - > { dist_XY } > 0 ) {
$ has_bridges + + if ( $ args - > { F } // $ self - > F ) == $ config - > bridge_speed * 60 ;
}
} ) ;
return $ has_bridges ;
} ;
ok ! $ test - > ( Slic3r::Test:: init_print ( 'V' , config = > $ config ) ) ,
'no overhangs printed with bridge speed' ;
ok $ test - > ( Slic3r::Test:: init_print ( 'V' , config = > $ config , scale_xyz = > [ 3 , 1 , 1 ] ) ) ,
'overhangs printed with bridge speed' ;
}
2014-05-12 19:49:17 +00:00
{
my $ config = Slic3r::Config - > new_from_defaults ;
$ config - > set ( 'randomize_start' , 1 ) ;
my $ print = Slic3r::Test:: init_print ( '20mm_cube' , config = > $ config ) ;
ok Slic3r::Test:: gcode ( $ print ) , 'successful generation of G-code with randomize_start option' ;
}
2013-06-21 12:52:35 +00:00
__END__