From f26f084064ec02767287262e842b8cab6183b5e8 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 3 Jul 2013 15:42:01 +0200 Subject: [PATCH 01/11] New freeze.t test --- MANIFEST | 1 + lib/Slic3r/Test.pm | 10 ++++++++-- t/freeze.t | 29 +++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 t/freeze.t diff --git a/MANIFEST b/MANIFEST index 02faef12..ca9cacc0 100644 --- a/MANIFEST +++ b/MANIFEST @@ -71,6 +71,7 @@ t/cooling.t t/custom_gcode.t t/dynamic.t t/fill.t +t/freeze.t t/gcode.t t/geometry.t t/layers.t diff --git a/lib/Slic3r/Test.pm b/lib/Slic3r/Test.pm index a8bcd242..dcb95d13 100644 --- a/lib/Slic3r/Test.pm +++ b/lib/Slic3r/Test.pm @@ -57,9 +57,15 @@ sub model { ], } + my $mesh = Slic3r::TriangleMesh->new( + vertices => $vertices, + facets => $facets, + ); + $mesh->scale($params{scale}) if $params{scale}; + my $model = Slic3r::Model->new; - my $object = $model->add_object(vertices => $vertices); - $object->add_volume(facets => $facets); + my $object = $model->add_object(vertices => $mesh->vertices); + $object->add_volume(facets => $mesh->facets); $object->add_instance( offset => [0,0], rotation => $params{rotation} // 0, diff --git a/t/freeze.t b/t/freeze.t new file mode 100644 index 00000000..f48cf04c --- /dev/null +++ b/t/freeze.t @@ -0,0 +1,29 @@ +use Test::More tests => 1; +use strict; +use warnings; + +BEGIN { + use FindBin; + use lib "$FindBin::Bin/../lib"; +} + +use Slic3r; +use Slic3r::Test; +use Storable qw(nstore retrieve); +use Time::HiRes qw(gettimeofday tv_interval); + +{ + my $t0 = [gettimeofday]; + my $print = Slic3r::Test::init_print('20mm_cube', scale => 2); + my $gcode = Slic3r::Test::gcode($print); + diag sprintf 'Slicing took %s seconds', tv_interval($t0); + + my $t1 = [gettimeofday]; + nstore $print, 'print.dat'; + $print = retrieve 'print.dat'; + diag sprintf 'Freezing and retrieving took %s seconds', tv_interval($t1); + + isa_ok $print, 'Slic3r::Print', 'restored Print object'; +} + +__END__ From 4d46ebc6cb26be085602f565fbcd2c679677c874 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 5 Jul 2013 14:17:09 +0200 Subject: [PATCH 02/11] Removed useless, slow, code --- lib/Slic3r/Layer/Region.pm | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index 3f71bfba..71bc4a27 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -226,19 +226,10 @@ sub make_perimeters { $self->_fill_gaps(\@gaps); - # TODO: can these be removed? - @contours = grep $_->is_printable($self->perimeter_flow->scaled_width), @contours; - @holes = grep $_->is_printable($self->perimeter_flow->scaled_width), @holes; - # find nesting hierarchies separately for contours and holes my $contours_pt = union_pt(\@contours, PFT_EVENODD); my $holes_pt = union_pt(\@holes, PFT_EVENODD); - # get lower layer slices for overhang check - my @lower_slices = $self->id == 0 - ? () - : map @$_, @{$self->layer->object->layers->[$self->id-1]->slices}; - # prepare a coderef for traversing the PolyTree object # external contours are root items of $contours_pt # internal contours are the ones next to external From b266d6217a02777ca0dc9f5c06cca312b5ca6bd5 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 5 Jul 2013 14:17:54 +0200 Subject: [PATCH 03/11] Skip slow gap detection if we aren't going to fill gaps anyway --- lib/Slic3r/Layer/Region.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index 71bc4a27..bab64317 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -195,7 +195,7 @@ sub make_perimeters { # where offset2() collapses the expolygon, then there's no room for an inner loop # and we can extract the gap for later processing - { + if ($Slic3r::Config->gap_fill_speed > 0 && $Slic3r::Config->fill_density > 0) { my $diff = diff_ex( [ offset(\@last, -0.5*$spacing) ], # +2 on the offset here makes sure that Clipper float truncation @@ -303,7 +303,7 @@ sub _fill_gaps { my $self = shift; my ($gaps) = @_; - return unless $Slic3r::Config->gap_fill_speed > 0 && $Slic3r::Config->fill_density > 0 && @$gaps; + return unless @$gaps; my $filler = $self->layer->object->fill_maker->filler('rectilinear'); $filler->layer_id($self->layer->id); From 27c421c27f2fb9bffc82446bbbd3fb809b8bed65 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 5 Jul 2013 14:21:20 +0200 Subject: [PATCH 04/11] Slight optimization --- lib/Slic3r/Layer/Region.pm | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index bab64317..3c79fd32 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -5,7 +5,7 @@ use List::Util qw(sum first); use Slic3r::ExtrusionPath ':roles'; use Slic3r::Geometry qw(PI A B scale chained_path_items points_coincide); use Slic3r::Geometry::Clipper qw(safety_offset union_ex diff_ex intersection_ex - offset offset2_ex PFT_EVENODD union_pt traverse_pt diff intersection); + offset offset2 offset2_ex PFT_EVENODD union_pt traverse_pt diff intersection); use Slic3r::Surface ':types'; has 'layer' => ( @@ -98,12 +98,9 @@ sub make_surfaces { # detect thin walls by offsetting slices by half extrusion inwards { my $width = $self->perimeter_flow->scaled_width; - my $outgrown = [ - offset2_ex([ map @$_, map $_->expolygon, @{$self->slices} ], -$width, +$width), - ]; my $diff = diff_ex( [ map $_->p, @{$self->slices} ], - [ map @$_, @$outgrown ], + [ offset2([ map @$_, map $_->expolygon, @{$self->slices} ], -$width, +$width) ], 1, ); From 8061cc6e30f8e81c65ecf4d181da3f8bf74243f0 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 5 Jul 2013 14:29:57 +0200 Subject: [PATCH 05/11] Optimization in Polyline instantiation --- lib/Slic3r/ExPolygon.pm | 8 ++++---- lib/Slic3r/ExtrusionPath.pm | 8 ++++---- lib/Slic3r/Fill/Honeycomb.pm | 6 +++--- lib/Slic3r/Fill/PlanePath.pm | 4 ++-- lib/Slic3r/GCode.pm | 4 ++-- lib/Slic3r/GUI/Plater.pm | 6 +++--- lib/Slic3r/Geometry/BoundingBox.pm | 4 ++-- lib/Slic3r/Geometry/Clipper.pm | 4 ++-- lib/Slic3r/Layer/Region.pm | 2 +- lib/Slic3r/Polyline.pm | 13 ++++--------- lib/Slic3r/Print.pm | 6 +++--- t/clean_polylines.t | 16 ++++++++-------- t/polyclip.t | 2 +- t/serialize.t | 2 +- 14 files changed, 40 insertions(+), 45 deletions(-) diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index 56dc5841..318573e0 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -17,11 +17,11 @@ sub new { my $self; if (@_ == 1 && ref $_[0] eq 'HASH') { $self = [ - Slic3r::Polygon->new($_[0]{outer}), - map Slic3r::Polygon->new($_), @{$_[0]{holes}}, + Slic3r::Polygon->new(@{$_[0]{outer}}), + map Slic3r::Polygon->new(@$_), @{$_[0]{holes}}, ]; } else { - $self = [ map Slic3r::Polygon->new($_), @_ ]; + $self = [ map Slic3r::Polygon->new(@$_), @_ ]; } bless $self, $class; $self; @@ -287,7 +287,7 @@ sub medial_axis { next if @$polyline == 2; push @result, Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]); } else { - push @result, Slic3r::Polyline->new($polyline); + push @result, Slic3r::Polyline->new(@$polyline); } } diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm index 49af9b82..3409a597 100644 --- a/lib/Slic3r/ExtrusionPath.pm +++ b/lib/Slic3r/ExtrusionPath.pm @@ -160,14 +160,14 @@ sub split_at_acute_angles { # if the angle between $p[-2], $p[-1], $p3 is too acute # then consider $p3 only as a starting point of a new # path and stop the current one as it is - push @paths, $self->clone(polyline => Slic3r::Polyline->new(\@p)); + push @paths, $self->clone(polyline => Slic3r::Polyline->new(@p)); @p = ($p3); push @p, grep $_, shift @points or last; } else { push @p, $p3; } } - push @paths, $self->clone(polyline => Slic3r::Polyline->new(\@p)) + push @paths, $self->clone(polyline => Slic3r::Polyline->new(@p)) if @p > 1; return @paths; @@ -254,7 +254,7 @@ sub detect_arcs { } my $arc = Slic3r::ExtrusionPath::Arc->new( - polyline => Slic3r::Polyline->new(\@arc_points), + polyline => Slic3r::Polyline->new(@arc_points), role => $self->role, flow_spacing => $self->flow_spacing, orientation => $orientation, @@ -279,7 +279,7 @@ sub detect_arcs { } # remaining points form a linear path - push @paths, $self->clone(polyline => Slic3r::Polyline->new(\@points)) + push @paths, $self->clone(polyline => Slic3r::Polyline->new(@points)) if @points > 1; return @paths; diff --git a/lib/Slic3r/Fill/Honeycomb.pm b/lib/Slic3r/Fill/Honeycomb.pm index 15d62fe8..fa25f5a6 100644 --- a/lib/Slic3r/Fill/Honeycomb.pm +++ b/lib/Slic3r/Fill/Honeycomb.pm @@ -71,7 +71,7 @@ sub fill_surface { $x += $m->{distance}; } - push @polygons, Slic3r::Polygon->new($p); + push @polygons, Slic3r::Polygon->new(@$p); } $_->rotate(-$rotate_vector->[0][0], $m->{hex_center}) for @polygons; @@ -88,7 +88,7 @@ sub fill_surface { # consider polygons as polylines without re-appending the initial point: # this cuts the last segment on purpose, so that the jump to the next # path is more straight - @paths = map Slic3r::Polyline->new($_), + @paths = map Slic3r::Polyline->new(@$_), @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection( $surface->expolygon, \@polygons, @@ -113,7 +113,7 @@ sub fill_surface { } # clip paths again to prevent connection segments from crossing the expolygon boundaries - @paths = map Slic3r::Polyline->new($_), + @paths = map Slic3r::Polyline->new(@$_), @{ Boost::Geometry::Utils::multi_polygon_multi_linestring_intersection( [ $surface->expolygon->offset_ex(scaled_epsilon) ], [ @paths ], diff --git a/lib/Slic3r/Fill/PlanePath.pm b/lib/Slic3r/Fill/PlanePath.pm index bf66b8c9..05983164 100644 --- a/lib/Slic3r/Fill/PlanePath.pm +++ b/lib/Slic3r/Fill/PlanePath.pm @@ -33,9 +33,9 @@ sub fill_surface { my $path = "Math::PlanePath::$1"->new; my @n = $self->get_n($path, [ map +($_ / $distance_between_lines), @{$bounding_box->bb} ]); - my $polyline = Slic3r::Polyline->new([ + my $polyline = Slic3r::Polyline->new( map [ map {$_*$distance_between_lines} $path->n_to_xy($_) ], @n, - ]); + ); return {} if !@$polyline; $self->process_polyline($polyline, $bounding_box); diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index a067c9fa..5b7ca6d7 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -295,7 +295,7 @@ sub extrude_path { $path_length += $line_length; $gcode .= $self->G1($line->[B], undef, $e * $line_length, $description); } - $self->wipe_path(Slic3r::Polyline->new([ reverse @{$path->points} ])) + $self->wipe_path(Slic3r::Polyline->new(reverse @{$path->points})) if $self->extruder->wipe; } @@ -409,7 +409,7 @@ sub retract { # wipe my $wipe_path; if ($self->extruder->wipe && $self->wipe_path) { - $wipe_path = Slic3r::Polyline->new([ $self->last_pos, @{$self->wipe_path}[1..$#{$self->wipe_path}] ]) + $wipe_path = Slic3r::Polyline->new($self->last_pos, @{$self->wipe_path}[1..$#{$self->wipe_path}]) ->clip_start($self->extruder->scaled_wipe_distance); } diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 3dae389c..d9ac19c5 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -888,7 +888,7 @@ sub repaint { # if sequential printing is enabled and we have more than one object if ($parent->{config}->complete_objects && (map @{$_->instances}, @{$parent->{objects}}) > 1) { - my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->contour}, @{$parent->{object_previews}->[-1][2]->expolygons} ])); + my $convex_hull = Slic3r::Polygon->new(@{convex_hull([ map @{$_->contour}, @{$parent->{object_previews}->[-1][2]->expolygons} ])}); my ($clearance) = @{offset([$convex_hull], $parent->{config}->extruder_clearance_radius / 2 * $parent->{scaling_factor}, 100, JT_ROUND)}; $dc->SetPen($parent->{clearance_pen}); $dc->SetBrush($parent->{transparent_brush}); @@ -899,7 +899,7 @@ sub repaint { # draw skirt if (@{$parent->{object_previews}} && $parent->{config}->skirts) { - my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->contour}, map @{$_->[2]->expolygons}, @{$parent->{object_previews}} ])); + my $convex_hull = Slic3r::Polygon->new(@{convex_hull([ map @{$_->contour}, map @{$_->[2]->expolygons}, @{$parent->{object_previews}} ])}); ($convex_hull) = @{offset([$convex_hull], $parent->{config}->skirt_distance * $parent->{scaling_factor}, 100, JT_ROUND)}; $dc->SetPen($parent->{skirt_pen}); $dc->SetBrush($parent->{transparent_brush}); @@ -1098,7 +1098,7 @@ sub _trigger_model_object { $self->bounding_box($self->model_object->bounding_box); my $mesh = $self->model_object->mesh; - $self->convex_hull(Slic3r::Polygon->new(Math::ConvexHull::MonotoneChain::convex_hull($mesh->used_vertices))); + $self->convex_hull(Slic3r::Polygon->new(@{Math::ConvexHull::MonotoneChain::convex_hull($mesh->used_vertices)})); $self->facets(scalar @{$mesh->facets}); $self->vertices(scalar @{$mesh->vertices}); diff --git a/lib/Slic3r/Geometry/BoundingBox.pm b/lib/Slic3r/Geometry/BoundingBox.pm index 1e0ed33c..67b77da8 100644 --- a/lib/Slic3r/Geometry/BoundingBox.pm +++ b/lib/Slic3r/Geometry/BoundingBox.pm @@ -38,12 +38,12 @@ sub polygon { my $self = shift; my $e = $self->extents; - return Slic3r::Polygon->new([ + return Slic3r::Polygon->new( [ $e->[X][MIN], $e->[Y][MIN] ], [ $e->[X][MAX], $e->[Y][MIN] ], [ $e->[X][MAX], $e->[Y][MAX] ], [ $e->[X][MIN], $e->[Y][MAX] ], - ]); + ); } # note to $self diff --git a/lib/Slic3r/Geometry/Clipper.pm b/lib/Slic3r/Geometry/Clipper.pm index 276a300b..aa124ba8 100644 --- a/lib/Slic3r/Geometry/Clipper.pm +++ b/lib/Slic3r/Geometry/Clipper.pm @@ -83,7 +83,7 @@ sub diff { $clipper->add_subject_polygons($subject); $clipper->add_clip_polygons($safety_offset ? safety_offset($clip) : $clip); return [ - map Slic3r::Polygon->new($_), + map Slic3r::Polygon->new(@$_), @{ $clipper->execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) }, ]; } @@ -126,7 +126,7 @@ sub intersection { $clipper->add_subject_polygons($subject); $clipper->add_clip_polygons($safety_offset ? safety_offset($clip) : $clip); return [ - map Slic3r::Polygon->new($_), + map Slic3r::Polygon->new(@$_), @{ $clipper->execute(CT_INTERSECTION, $jointype, $jointype) }, ]; } diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index 3c79fd32..8ab7a5a6 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -247,7 +247,7 @@ sub make_perimeters { # return ccw contours and cw holes # GCode.pm will convert all of them to ccw, but it needs to know # what the holes are in order to compute the correct inwards move - my $polygon = Slic3r::Polygon->new($polynode->{outer} // [ reverse @{$polynode->{hole}} ]); + my $polygon = Slic3r::Polygon->new(defined $polynode->{outer} ? @{$polynode->{outer}} : reverse @{$polynode->{hole}}); $polygon->reverse if !$is_contour; my $role = EXTR_ROLE_PERIMETER; diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 43a0917c..1f059e0d 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -10,13 +10,8 @@ use Slic3r::Geometry::Clipper qw(JT_SQUARE); # the constructor accepts an array(ref) of points sub new { my $class = shift; - my $self; - if (@_ == 1) { - $self = [ @{$_[0]} ]; - } else { - $self = [ @_ ]; - } + my $self = [ @_ ]; bless $self, $class; bless $_, 'Slic3r::Point' for @$self; $self; @@ -65,7 +60,7 @@ sub simplify { my $tolerance = shift || 10; my $simplified = Boost::Geometry::Utils::linestring_simplify($self, $tolerance); - return (ref $self)->new($simplified); + return (ref $self)->new(@$simplified); } sub reverse { @@ -83,9 +78,9 @@ sub grow { my ($distance, $scale, $joinType, $miterLimit) = @_; $joinType //= JT_SQUARE; - return map Slic3r::Polygon->new($_), + return map Slic3r::Polygon->new(@$_), Slic3r::Geometry::Clipper::offset( - [ Slic3r::Polygon->new(@$self, CORE::reverse @$self[1..($#$self-1)]) ], + [ [ @$self, CORE::reverse @$self[1..($#$self-1)] ] ], $distance, $scale, $joinType, $miterLimit, ); } diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index d5d90374..d62e84f0 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -170,8 +170,8 @@ sub validate { my $clearance; { my @points = map [ @$_[X,Y] ], map @{$_->vertices}, @{$self->objects->[$obj_idx]->meshes}; - my $convex_hull = Slic3r::Polygon->new(convex_hull(\@points)); - ($clearance) = map Slic3r::Polygon->new($_), + my $convex_hull = Slic3r::Polygon->new(@{convex_hull(\@points)}); + ($clearance) = map Slic3r::Polygon->new(@$_), Slic3r::Geometry::Clipper::offset( [$convex_hull], scale $Slic3r::Config->extruder_clearance_radius / 2, 1, JT_ROUND); } @@ -665,7 +665,7 @@ sub make_brim { } @{$self->brim} = map Slic3r::ExtrusionLoop->pack( - polygon => Slic3r::Polygon->new($_), + polygon => Slic3r::Polygon->new(@$_), role => EXTR_ROLE_SKIRT, flow_spacing => $flow->spacing, ), reverse traverse_pt( union_pt(\@loops, PFT_EVENODD) ); diff --git a/t/clean_polylines.t b/t/clean_polylines.t index 9f7b3ce2..17c4ad6a 100644 --- a/t/clean_polylines.t +++ b/t/clean_polylines.t @@ -12,26 +12,26 @@ BEGIN { use Slic3r; { - my $polygon = Slic3r::Polygon->new([ + my $polygon = Slic3r::Polygon->new( [5,0], [10,0], [15,0], [20,0], [20,10], [20,30], [0,0], - ]); + ); $polygon->merge_continuous_lines; is scalar(@$polygon), 3, 'merge_continuous_lines'; } { - my $polyline = Slic3r::Polyline->new([ + my $polyline = Slic3r::Polyline->new( [0,0],[1,0],[2,0],[2,1],[2,2],[1,2],[0,2],[0,1],[0,0], - ]); + ); $polyline = $polyline->simplify(1); is_deeply $polyline, [ [0, 0], [2, 0], [2, 2], [0, 2], [0, 0] ], 'Douglas-Peucker'; } { - my $polyline = Slic3r::Polyline->new([ + my $polyline = Slic3r::Polyline->new( [0,0],[0.5,0.5],[1,0],[1.25,-0.25],[1.5,.5], - ]); + ); $polyline->scale(100); $polyline = $polyline->simplify(25); is_deeply $polyline, [ [0, 0], [50, 50], [125, -25], [150, 50] ], 'Douglas-Peucker'; @@ -69,7 +69,7 @@ use Slic3r; [197.307,292.831], [199.808,313.1906], [191.5298,315.0787], [187.3082,299.8172], [186.4201,295.3766], [180.595,296.0487], [161.7854,297.4248], [156.8058,297.6214], [154.3395,317.8592], ]; - my $polygon = Slic3r::Polygon->new($gear); + my $polygon = Slic3r::Polygon->new(@$gear); $polygon->merge_continuous_lines; note sprintf "original points: %d\nnew points: %d", scalar(@$gear), scalar(@$polygon); ok @$polygon < @$gear, 'gear was simplified using merge_continuous_lines'; @@ -114,7 +114,7 @@ use Slic3r; [3368.3,7868.6],[3409.2,7889.5],[3553.8,7963.2],[3596,7981.4], ]; - my $polygon = Slic3r::Polygon->new($circle); + my $polygon = Slic3r::Polygon->new(@$circle); $polygon->merge_continuous_lines; note sprintf "original points: %d\nnew points: %d", scalar(@$circle), scalar(@$polygon); ok @$polygon >= @$circle/3, 'circle was simplified using merge_continuous_lines'; diff --git a/t/polyclip.t b/t/polyclip.t index c25ad0fb..509a353d 100644 --- a/t/polyclip.t +++ b/t/polyclip.t @@ -103,7 +103,7 @@ is_deeply $intersection, [ [120, 120], [180, 160] ], 'internal lines are preserv ], 'tangent line is clipped to square with hole'; } { - my $polyline = Slic3r::Polyline->new([ [50, 180], [250, 180], [250, 150], [150, 150], [150, 120], [120, 120], [120, 50] ]); + my $polyline = Slic3r::Polyline->new([50, 180], [250, 180], [250, 150], [150, 150], [150, 120], [120, 120], [120, 50]); is_deeply [ map $_, $polyline->clip_with_expolygon($expolygon) ], [ [ [100, 180], [200, 180] ], [ [200, 150], [160, 150] ], diff --git a/t/serialize.t b/t/serialize.t index c3d04d4b..0d93cd52 100644 --- a/t/serialize.t +++ b/t/serialize.t @@ -21,7 +21,7 @@ use Slic3r::Geometry qw(scale); foreach my $point (@$points) { @$point = map scale $_, @$point; } - my $polyline = Slic3r::Polyline->new($points); + my $polyline = Slic3r::Polyline->new(@$points); my $serialized = $polyline->serialize; my $deserialized = Slic3r::Polyline->deserialize($serialized); is scalar(@$deserialized), scalar(@$points), 'number of deserialized points'; From 72f77a34205a4177478aee3a98518455927bc713 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 5 Jul 2013 14:46:32 +0200 Subject: [PATCH 06/11] Use dclone() in Polyline and ExPolygon too --- lib/Slic3r/ExPolygon.pm | 4 ++-- lib/Slic3r/Polyline.pm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index 318573e0..fd1af58b 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -9,6 +9,7 @@ use List::Util qw(first); use Math::Geometry::Voronoi; use Slic3r::Geometry qw(X Y A B point_in_polygon same_line epsilon); use Slic3r::Geometry::Clipper qw(union_ex JT_MITER); +use Storable qw(); # the constructor accepts an array of polygons # or a Math::Clipper ExPolygon (hashref) @@ -28,8 +29,7 @@ sub new { } sub clone { - my $self = shift; - return (ref $self)->new(map $_->clone, @$self); + Storable::dclone($_[0]) } sub contour { diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 1f059e0d..f2a9cbd7 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -6,6 +6,7 @@ use Scalar::Util qw(reftype); use Slic3r::Geometry qw(A B X Y X1 X2 Y1 Y2 polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices polyline_lines move_points same_point); use Slic3r::Geometry::Clipper qw(JT_SQUARE); +use Storable qw(); # the constructor accepts an array(ref) of points sub new { @@ -18,8 +19,7 @@ sub new { } sub clone { - my $self = shift; - return (ref $self)->new(map $_->clone, @$self); + Storable::dclone($_[0]) } sub serialize { From be4eb3762f765b6532afd45536bfa63c1b471e39 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 5 Jul 2013 14:48:03 +0200 Subject: [PATCH 07/11] Use dclone() in Point class too --- lib/Slic3r/Point.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/Point.pm b/lib/Slic3r/Point.pm index b820a1e8..233f60f3 100644 --- a/lib/Slic3r/Point.pm +++ b/lib/Slic3r/Point.pm @@ -2,6 +2,8 @@ package Slic3r::Point; use strict; use warnings; +use Storable qw(); + sub new { my $class = shift; my $self; @@ -19,8 +21,7 @@ sub new { } sub clone { - my $self = shift; - return (ref $self)->new(@$self); + Storable::dclone($_[0]) } sub coincides_with { From d074b98aba60c385ca298086661f764abdc298dd Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 5 Jul 2013 15:03:08 +0200 Subject: [PATCH 08/11] Optimization: don't store wipe path if wipe is not requested --- lib/Slic3r/GCode.pm | 18 +++++++++++++++--- lib/Slic3r/Print.pm | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 5b7ca6d7..2d6e27f8 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -8,7 +8,9 @@ use Slic3r::Geometry::Clipper qw(union_ex); use Slic3r::Surface ':types'; has 'config' => (is => 'ro', required => 1); -has 'multiple_extruders' => (is => 'ro', default => sub {0} ); +has 'extruders' => (is => 'ro', default => sub {0}, required => 1); +has 'multiple_extruders' => (is => 'lazy'); +has 'enable_wipe' => (is => 'lazy'); # at least one extruder has wipe enabled has 'layer_count' => (is => 'ro', required => 1 ); has 'layer' => (is => 'rw'); has '_layer_overhangs' => (is => 'rw'); @@ -63,6 +65,16 @@ my %role_speeds = ( &EXTR_ROLE_GAPFILL => 'gap_fill', ); +sub _build_multiple_extruders { + my $self = shift; + return @{$self->extruders} > 1; +} + +sub _build_enable_wipe { + my $self = shift; + return (first { $_->wipe } @{$self->extruders}) ? 1 : 0; +} + sub set_shift { my $self = shift; my @shift = @_; @@ -205,7 +217,7 @@ sub extrude_loop { # extrude along the path my $gcode = join '', map $self->extrude_path($_, $description, %params), @paths; - $self->wipe_path($extrusion_path->polyline); + $self->wipe_path($extrusion_path->polyline) if $self->enable_wipe; # make a little move inwards before leaving loop if ($loop->role == EXTR_ROLE_EXTERNAL_PERIMETER && $self->config->perimeters > 1) { @@ -296,7 +308,7 @@ sub extrude_path { $gcode .= $self->G1($line->[B], undef, $e * $line_length, $description); } $self->wipe_path(Slic3r::Polyline->new(reverse @{$path->points})) - if $self->extruder->wipe; + if $self->enable_wipe; } if ($self->config->cooling) { diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index d62e84f0..53119758 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -711,7 +711,7 @@ sub write_gcode { # set up our extruder object my $gcodegen = Slic3r::GCode->new( config => $self->config, - multiple_extruders => (@{$self->extruders} > 1), + extruders => $self->extruders, layer_count => $self->layer_count, ); print $fh "G21 ; set units to millimeters\n" if $Slic3r::Config->gcode_flavor ne 'makerware'; From df4612a209dc172b629166d8565f83d609638372 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 5 Jul 2013 17:00:14 +0200 Subject: [PATCH 09/11] Prefer starting points that are NOT in overhangs --- lib/Slic3r/GCode.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 2d6e27f8..833fe18c 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -156,7 +156,7 @@ sub extrude_loop { # find candidate starting points # start looking for concave vertices not being overhangs my @concave = $loop->polygon->concave_points; - my @candidates = grep Boost::Geometry::Utils::point_covered_by_multi_polygon($_, $self->_layer_overhangs), + my @candidates = grep !Boost::Geometry::Utils::point_covered_by_multi_polygon($_, $self->_layer_overhangs), @concave; if (!@candidates) { # if none, look for any concave vertex From b3b2a1e8916113a549a3bb632826f4aa8d80cc84 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 5 Jul 2013 17:08:26 +0200 Subject: [PATCH 10/11] One more fix in overhang starting point detection --- lib/Slic3r/GCode.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 833fe18c..80b7f986 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -163,7 +163,7 @@ sub extrude_loop { @candidates = @concave; if (!@candidates) { # if none, look for any non-overhang vertex - @candidates = grep Boost::Geometry::Utils::point_covered_by_multi_polygon($_, $self->_layer_overhangs), + @candidates = grep !Boost::Geometry::Utils::point_covered_by_multi_polygon($_, $self->_layer_overhangs), @{$loop->polygon}; if (!@candidates) { # if none, all points are valid candidates From 339c487077d81c752b286f6f43d59acd6c3cfe37 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 5 Jul 2013 17:25:56 +0200 Subject: [PATCH 11/11] Fix starting point after overhang clipping is performed --- lib/Slic3r/GCode.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 80b7f986..403303d3 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -181,7 +181,8 @@ sub extrude_loop { } # split the loop at the starting point and make a path - my $extrusion_path = $loop->split_at(Slic3r::Geometry::nearest_point($last_pos, \@candidates)); + my $start_at = Slic3r::Geometry::nearest_point($last_pos, \@candidates); + my $extrusion_path = $loop->split_at($start_at); # clip the path to avoid the extruder to get exactly on the first point of the loop; # if polyline was shorter than the clipping distance we'd get a null polyline, so @@ -204,7 +205,7 @@ sub extrude_loop { # reapply the nearest point search for starting point @paths = Slic3r::ExtrusionPath::Collection ->new(paths => [@paths]) - ->chained_path($last_pos, 1); + ->chained_path($start_at, 1); } else { push @paths, $extrusion_path; }