diff --git a/MANIFEST b/MANIFEST index 40cfc3f6c..66051ba3c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -30,7 +30,6 @@ lib/Slic3r/Perimeter.pm lib/Slic3r/Point.pm lib/Slic3r/Polygon.pm lib/Slic3r/Polyline.pm -lib/Slic3r/Polyline/Closed.pm lib/Slic3r/Print.pm lib/Slic3r/Skein.pm lib/Slic3r/STL.pm diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 246dcb0f7..b692e662e 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -25,7 +25,6 @@ use Slic3r::Perimeter; use Slic3r::Point; use Slic3r::Polygon; use Slic3r::Polyline; -use Slic3r::Polyline::Closed; use Slic3r::Print; use Slic3r::Skein; use Slic3r::STL; diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index 50c9debac..e710b265f 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -40,6 +40,11 @@ sub holes { return @$self[1..$#$self]; } +sub lines { + my $self = shift; + return map $_->lines, @$self; +} + sub clipper_expolygon { my $self = shift; return { @@ -106,7 +111,7 @@ sub bounding_box { sub clip_line { my $self = shift; my ($line) = @_; - $line = Slic3r::Line->cast($line); + $line = Slic3r::Line->new($line) if ref $line eq 'ARRAY'; my @intersections = grep $_, map $_->intersection($line, 1), map $_->lines, @$self; my @dir = ( @@ -203,6 +208,8 @@ sub medial_axis { } return undef if !@skeleton_lines; + return undef if !@skeleton_lines; + # now build a single polyline my $polyline = []; { @@ -248,7 +255,7 @@ sub medial_axis { if (Slic3r::Geometry::same_point($polyline->[0], $polyline->[-1])) { return Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]); } else { - return Slic3r::Polyline->cast($polyline); + return Slic3r::Polyline->new($polyline); } } diff --git a/lib/Slic3r/ExtrusionLoop.pm b/lib/Slic3r/ExtrusionLoop.pm index 7df64a1e8..caee31ede 100644 --- a/lib/Slic3r/ExtrusionLoop.pm +++ b/lib/Slic3r/ExtrusionLoop.pm @@ -3,11 +3,21 @@ use Moo; use XXX; -extends 'Slic3r::Polyline::Closed'; +# the underlying Slic3r::Polygon objects holds the geometry +has 'polygon' => ( + is => 'ro', + required => 1, + handles => [qw(is_printable nearest_point_to)], +); # perimeter/fill/solid-fill/bridge/skirt has 'role' => (is => 'rw', required => 1); +sub BUILD { + my $self = shift; + bless $self->polygon, 'Slic3r::Polygon'; +} + sub split_at { my $self = shift; my ($point) = @_; @@ -16,8 +26,8 @@ sub split_at { # find index of point my $i = -1; - for (my $n = 0; $n <= $#{$self->points}; $n++) { - if ($point->id eq $self->points->[$n]->id) { + for (my $n = 0; $n <= $#{$self->polygon}; $n++) {ZZZ "here" if ref $self->polygon->[$n] eq 'ARRAY'; + if ($point->id eq $self->polygon->[$n]->id) { $i = $n; last; } @@ -25,10 +35,13 @@ sub split_at { die "Point not found" if $i == -1; my @new_points = (); - push @new_points, @{$self->points}[$i .. $#{$self->points}]; - push @new_points, @{$self->points}[0 .. $i]; + push @new_points, @{$self->polygon}[$i .. $#{$self->polygon}]; + push @new_points, @{$self->polygon}[0 .. $i]; - return Slic3r::ExtrusionPath->new(points => [@new_points], role => $self->role); + return Slic3r::ExtrusionPath->new( + polyline => Slic3r::Polyline->new(\@new_points), + role => $self->role, + ); } 1; diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm index 592a61638..4f8a5b4c2 100644 --- a/lib/Slic3r/ExtrusionPath.pm +++ b/lib/Slic3r/ExtrusionPath.pm @@ -1,7 +1,15 @@ package Slic3r::ExtrusionPath; use Moo; -extends 'Slic3r::Polyline'; +use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points); +use XXX; + +# the underlying Slic3r::Polyline objects holds the geometry +has 'polyline' => ( + is => 'ro', + required => 1, + handles => [qw(merge_continuous_lines lines)], +); # this integer represents the vertical thickness of the extrusion # expressed in layers @@ -12,8 +20,10 @@ has 'flow_spacing' => (is => 'rw'); # perimeter/fill/solid-fill/bridge/skirt has 'role' => (is => 'rw', required => 1); -use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points); -use XXX; +sub BUILD { + my $self = shift; + bless $self->polyline, 'Slic3r::Polyline'; +} sub clip_end { my $self = shift; @@ -35,6 +45,11 @@ sub clip_end { } } +sub points { + my $self = shift; + return $self->polyline; +} + sub endpoints { my $self = shift; return ($self->points->[0], $self->points->[-1]); @@ -68,10 +83,10 @@ 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, (ref $self)->cast( - [@p], - role => $self->role, - depth_layers => $self->depth_layers, + push @paths, (ref $self)->new( + polyline => Slic3r::Polyline->new(\@p), + role => $self->role, + depth_layers => $self->depth_layers, ); @p = ($p3); push @p, grep $_, shift @points or last; @@ -79,10 +94,10 @@ sub split_at_acute_angles { push @p, $p3; } } - push @paths, (ref $self)->cast( - [@p], - role => $self->role, - depth_layers => $self->depth_layers, + push @paths, (ref $self)->new( + polyline => Slic3r::Polyline->new(\@p), + role => $self->role, + depth_layers => $self->depth_layers, ) if @p > 1; return @paths; @@ -168,7 +183,7 @@ sub detect_arcs { } my $arc = Slic3r::ExtrusionPath::Arc->new( - points => [@arc_points], + polyline => Slic3r::Polyline->new(\@arc_points), role => $self->role, orientation => $orientation, center => $arc_center, @@ -177,9 +192,9 @@ sub detect_arcs { # points 0..$i form a linear path push @paths, (ref $self)->new( - points => [ @points[0..$i] ], - role => $self->role, - depth_layers => $self->depth_layers, + polyline => Slic3r::Polyline->new(@points[0..$i]), + role => $self->role, + depth_layers => $self->depth_layers, ) if $i > 0; # add our arc @@ -196,9 +211,9 @@ sub detect_arcs { # remaining points form a linear path push @paths, (ref $self)->new( - points => [@points], - role => $self->role, - depth_layers => $self->depth_layers, + polyline => Slic3r::Polyline->new(\@points), + role => $self->role, + depth_layers => $self->depth_layers, ) if @points > 1; return @paths; diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index e602301a5..a817c6ff5 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -71,7 +71,8 @@ sub make_fill { 1, ); - push @surfaces, map Slic3r::Surface->cast_from_expolygon($_, + push @surfaces, map Slic3r::Surface->new( + expolygon => $_, surface_type => $group->[0]->surface_type, bridge_angle => $group->[0]->bridge_angle, depth_layers => $group->[0]->depth_layers, @@ -100,7 +101,8 @@ sub make_fill { [ @offsets ], ); - push @new_surfaces, map Slic3r::Surface->cast_from_expolygon($_, + push @new_surfaces, map Slic3r::Surface->new( + expolygon => $_, surface_type => $surface->surface_type, bridge_angle => $surface->bridge_angle, depth_layers => $surface->depth_layers, @@ -111,7 +113,7 @@ sub make_fill { # organize infill surfaces using a shortest path search @surfaces = @{shortest_path([ - map [ $_->contour->points->[0], $_ ], @surfaces, + map [ $_->contour->[0], $_ ], @surfaces, ])}; SURFACE: foreach my $surface (@surfaces) { @@ -145,15 +147,14 @@ sub make_fill { # save into layer push @{ $layer->fills }, Slic3r::ExtrusionPath::Collection->new( paths => [ - map Slic3r::ExtrusionPath->cast( - [ @$_ ], + map Slic3r::ExtrusionPath->new( + polyline => Slic3r::Polyline->new(@$_), role => ($is_bridge ? 'bridge' : $is_solid ? 'solid-fill' : 'fill'), depth_layers => $surface->depth_layers, flow_spacing => $params->{flow_spacing}, ), @paths, ], ) if @paths; - ###$layer->fills->[-1]->cleanup; } } diff --git a/lib/Slic3r/Fill/Concentric.pm b/lib/Slic3r/Fill/Concentric.pm index 718bddd9f..a5dab2d24 100644 --- a/lib/Slic3r/Fill/Concentric.pm +++ b/lib/Slic3r/Fill/Concentric.pm @@ -51,7 +51,7 @@ sub fill_surface { ($bounding_box->[X1] + $bounding_box->[X2]) / 2, ($bounding_box->[Y1] + $bounding_box->[Y2]) / 2, ); - foreach my $loop (map Slic3r::ExtrusionLoop->cast($_, role => 'fill'), @loops) { + foreach my $loop (map Slic3r::ExtrusionLoop->new(polygon => $_, role => 'fill'), @loops) { # find the point of the loop that is closest to the current extruder position $cur_pos = $loop->nearest_point_to($cur_pos); diff --git a/lib/Slic3r/Fill/PlanePath.pm b/lib/Slic3r/Fill/PlanePath.pm index caf92c948..c3d3f5d12 100644 --- a/lib/Slic3r/Fill/PlanePath.pm +++ b/lib/Slic3r/Fill/PlanePath.pm @@ -40,7 +40,7 @@ sub fill_surface { my $path = "Math::PlanePath::$1"->new; my @n = $self->get_n($path, [map +($_ / $distance_between_lines), @$bounding_box]); - my $polyline = Slic3r::Polyline->cast([ + my $polyline = Slic3r::Polyline->new([ map [ map {$_*$distance_between_lines} $path->n_to_xy($_) ], @n, ]); return {} if !@{$polyline->points}; diff --git a/lib/Slic3r/Fill/Rectilinear.pm b/lib/Slic3r/Fill/Rectilinear.pm index 357284591..dcb14e6ea 100644 --- a/lib/Slic3r/Fill/Rectilinear.pm +++ b/lib/Slic3r/Fill/Rectilinear.pm @@ -55,7 +55,7 @@ sub fill_surface { # connect lines { my $collection = Slic3r::ExtrusionPath::Collection->new( - paths => [ map Slic3r::ExtrusionPath->cast([ @$_ ], role => 'bogus'), @paths ], + paths => [ map Slic3r::ExtrusionPath->new(polyline => Slic3r::Polyline->new(@$_), role => 'bogus'), @paths ], ); @paths = (); diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index b924e1902..3ccdbd32e 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -24,23 +24,15 @@ has 'lines' => ( ); # collection of surfaces generated by slicing the original geometry -has 'slices' => ( - is => 'rw', - #isa => 'ArrayRef[Slic3r::Surface]', - default => sub { [] }, -); +has 'slices' => (is => 'ro', default => sub { [] }); # collection of polygons or polylines representing thin walls contained # in the original geometry -has 'thin_walls' => (is => 'rw', default => sub { [] }); +has 'thin_walls' => (is => 'ro', default => sub { [] }); -# collection of surfaces generated by offsetting the innermost perimeter(s) +# collection of expolygons generated by offsetting the innermost perimeter(s) # they represent boundaries of areas to fill -has 'fill_boundaries' => ( - is => 'rw', - #isa => 'ArrayRef[Slic3r::Surface]', - default => sub { [] }, -); +has 'fill_boundaries' => (is => 'ro', default => sub { [] }); # collection of surfaces generated by clipping the slices to the fill boundaries has 'surfaces' => ( @@ -150,7 +142,7 @@ sub make_surfaces { scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops); push @{$self->slices}, - map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'internal'), + map Slic3r::Surface->new(expolygon => $_, surface_type => 'internal'), @$expolygons; } @@ -160,8 +152,8 @@ sub make_surfaces { my @surfaces = @{$self->slices}; @{$self->slices} = (); foreach my $surface (@surfaces) { - push @{$self->slices}, map Slic3r::Surface->cast_from_expolygon - ($_, surface_type => 'internal'), + push @{$self->slices}, map Slic3r::Surface->new + (expolygon => $_, surface_type => 'internal'), $surface->expolygon->offset_ex(-$distance); } @@ -183,7 +175,7 @@ sub make_surfaces { if (0) { require "Slic3r/SVG.pm"; Slic3r::SVG::output(undef, "surfaces.svg", - polygons => [ map $_->contour->p, @{$self->slices} ], + polygons => [ map $_->contour, @{$self->slices} ], red_polygons => [ map $_->p, map @{$_->holes}, @{$self->slices} ], ); } @@ -210,7 +202,7 @@ sub prepare_fill_surfaces { (map $_->p, grep $_->surface_type eq 'top', @surfaces), (map @$_, map $_->expolygon->safety_offset, @$small_internal), ]); - my @top = map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'top'), @$union; + my @top = map Slic3r::Surface->new(expolygon => $_, surface_type => 'top'), @$union; @surfaces = (grep($_->surface_type ne 'top', @surfaces), @top); } @@ -242,7 +234,8 @@ sub remove_small_surfaces { @offsets = map $_->offset_ex($distance), @offsets; @offsets = @{ union_ex([ map @$_, @offsets ], undef, 1) }; - push @{$self->fill_surfaces}, map Slic3r::Surface->cast_from_expolygon($_, + push @{$self->fill_surfaces}, map Slic3r::Surface->new( + expolygon => $_, surface_type => $surface->surface_type), @offsets; } @@ -257,7 +250,8 @@ sub remove_small_surfaces { [ map $_->p, @surfaces ], [ map $_->p, @{$self->fill_surfaces} ], ); - push @{$self->fill_surfaces}, map Slic3r::Surface->cast_from_expolygon($_, + push @{$self->fill_surfaces}, map Slic3r::Surface->new( + expolygon => $_, surface_type => 'internal-solid'), @$diff; } } @@ -382,7 +376,8 @@ sub process_bridges { [ $bridge_offset ], ); - push @bridges, map Slic3r::Surface->cast_from_expolygon($_, + push @bridges, map Slic3r::Surface->new( + expolygon => $_, surface_type => $surface->surface_type, bridge_angle => $bridge_angle, ), @$intersection; @@ -405,7 +400,8 @@ sub process_bridges { [ map $_->p, @bridges ], ); - push @bridges, map Slic3r::Surface->cast_from_expolygon($_, + push @bridges, map Slic3r::Surface->new( + expolygon => $_, surface_type => $surfaces->[0]->surface_type, bridge_angle => $surfaces->[0]->bridge_angle, ), @$union; @@ -424,7 +420,8 @@ sub process_bridges { [ $bridge->p ], ); - push @{$self->fill_surfaces}, map Slic3r::Surface->cast_from_expolygon($_, + push @{$self->fill_surfaces}, map Slic3r::Surface->new( + expolygon => $_, surface_type => $bridge->surface_type, bridge_angle => $bridge->bridge_angle, ), @$actual_bridge; @@ -436,7 +433,8 @@ sub process_bridges { [ map $_->p, @$group ], [ map $_->p, @bridges ], ); - push @{$self->fill_surfaces}, map Slic3r::Surface->cast_from_expolygon($_, + push @{$self->fill_surfaces}, map Slic3r::Surface->new( + expolygon => $_, surface_type => $group->[0]->surface_type), @$difference; } } diff --git a/lib/Slic3r/Line.pm b/lib/Slic3r/Line.pm index 541689d24..494eae4d6 100644 --- a/lib/Slic3r/Line.pm +++ b/lib/Slic3r/Line.pm @@ -21,13 +21,6 @@ sub new { return $self; } -sub cast { - my $class = shift; - my ($line) = @_; - return $line if ref $line eq __PACKAGE__; - return $class->new($line); -} - sub a { $_[0][0] } sub b { $_[0][1] } diff --git a/lib/Slic3r/Perimeter.pm b/lib/Slic3r/Perimeter.pm index ec24c0285..0b9b190bf 100644 --- a/lib/Slic3r/Perimeter.pm +++ b/lib/Slic3r/Perimeter.pm @@ -30,7 +30,7 @@ sub make_perimeter { # organize perimeter surfaces using a shortest path search my @surfaces = @{shortest_path([ - map [ $_->contour->points->[0], $_ ], @{$layer->slices}, + map [ $_->contour->[0], $_ ], @{$layer->slices}, ])}; foreach my $surface (@surfaces) { @@ -50,9 +50,7 @@ sub make_perimeter { # create one more offset to be used as boundary for fill { - my @fill_boundaries = map Slic3r::Surface->cast_from_expolygon - ($_, surface_type => $surface->surface_type), - map $_->offset_ex(-$distance), @last_offsets; + my @fill_boundaries = map $_->offset_ex(-$distance), @last_offsets; # TODO: diff(offset(@last_offsets, -$distance/2), offset(@fill_boundaries, +$distance/2)) # this represents the small gaps that we need to treat like thin polygons, @@ -66,12 +64,12 @@ sub make_perimeter { foreach my $island (@perimeters) { # do holes starting from innermost one foreach my $hole (map $_->holes, map @$_, @$island) { - push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($hole, role => 'perimeter'); + push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $hole, role => 'perimeter'); } # do contours starting from innermost one foreach my $contour (map $_->contour, map @$_, reverse @$island) { - push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($contour, role => 'perimeter'); + push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $contour, role => 'perimeter'); } } @@ -83,9 +81,9 @@ sub make_perimeter { # add thin walls as perimeters for (@{ $layer->thin_walls }) { if ($_->isa('Slic3r::Polygon')) { - push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($_, role => 'perimeter'); + push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $_, role => 'perimeter'); } else { - push @{ $layer->perimeters }, Slic3r::ExtrusionPath->cast($_->points, role => 'perimeter'); + push @{ $layer->perimeters }, Slic3r::ExtrusionPath->new(polyline => $_->points, role => 'perimeter'); } } } diff --git a/lib/Slic3r/Polygon.pm b/lib/Slic3r/Polygon.pm index 441b11056..1c5d9021d 100644 --- a/lib/Slic3r/Polygon.pm +++ b/lib/Slic3r/Polygon.pm @@ -3,11 +3,10 @@ use strict; use warnings; # a polygon is a closed polyline. -# if you're asking why there's a Slic3r::Polygon as well -# as a Slic3r::Polyline::Closed you're right. I plan to -# ditch the latter and port everything to this class. +use parent 'Slic3r::Polyline'; use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges + scale polygon_remove_acute_vertices polygon_segment_having_point point_in_polygon move_points rotate_points); use Slic3r::Geometry::Clipper qw(JT_MITER); @@ -31,12 +30,6 @@ sub clone { return (ref $self)->new(map $_->clone, @$self); } -# legacy method, to be removed when we ditch Slic3r::Polyline::Closed -sub closed_polyline { - my $self = shift; - return Slic3r::Polyline::Closed->cast($self); -} - sub lines { my $self = shift; return map Slic3r::Line->new($_), polygon_lines($self); @@ -44,7 +37,20 @@ sub lines { sub cleanup { my $self = shift; + $self->merge_continuous_lines; +} + +sub merge_continuous_lines { + my $self = shift; + polygon_remove_parallel_continuous_edges($self); + bless $_, 'Slic3r::Point' for @$self; +} + +sub remove_acute_vertices { + my $self = shift; + polygon_remove_acute_vertices($self); + bless $_, 'Slic3r::Point' for @$self; } sub point_on_segment { @@ -106,7 +112,8 @@ sub subdivide { # $num_points is the number of points to add between $i-1 and $i my $spacing = $len / ($num_points + 1); - my @new_points = map Slic3r::Geometry::point_along_segment($self->[$i-1], $self->[$i], $spacing * $_), + my @new_points = map Slic3r::Point->new($_), + map Slic3r::Geometry::point_along_segment($self->[$i-1], $self->[$i], $spacing * $_), 1..$num_points; splice @$self, $i, 0, @new_points; @@ -114,4 +121,22 @@ sub subdivide { } } +# returns false if the polyline is too tight to be printed +sub is_printable { + my $self = shift; + + # try to get an inwards offset + # for a distance equal to half of the extrusion width; + # if no offset is possible, then polyline is not printable + my $p = $self->clone; + @$p = reverse @$p if !Math::Clipper::is_counter_clockwise($p); + my $offsets = Math::Clipper::offset([$p], -(scale $Slic3r::flow_spacing / 2), $Slic3r::resolution * 100000, JT_MITER, 2); + return @$offsets ? 1 : 0; +} + +sub is_valid { + my $self = shift; + return @{$self->points} >= 3; +} + 1; \ No newline at end of file diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index c820f0b2e..43ee3948d 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -1,38 +1,37 @@ package Slic3r::Polyline; -use Moo; +use strict; +use warnings; use Math::Clipper qw(); use Slic3r::Geometry qw(A B polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices - polygon_remove_acute_vertices polygon_remove_parallel_continuous_edges move_points same_point); -use Sub::Quote; + move_points same_point); use XXX; -# arrayref of ordered points -has 'points' => ( - is => 'rw', - required => 1, - default => sub { [] }, - isa => quote_sub q{ use Carp; confess "invalid points" if grep ref $_ ne 'Slic3r::Point', @{$_[0]} }, -); +# the constructor accepts an array(ref) of points +sub new { + my $class = shift; + my $self; + if (@_ == 1) { + $self = [ @{$_[0]} ]; + } else { + $self = [ @_ ]; + } + + bless $self, $class; + bless $_, 'Slic3r::Point' for @$self; + $self; +} sub id { my $self = shift; - return join ' - ', sort map $_->id, @{$self->points}; -} - -sub cast { - my $class = shift; - my ($points, %args) = @_; - - $points = [ map Slic3r::Point->cast($_), @$points ]; - return $class->new(points => $points, %args); + return join ' - ', sort map $_->id, @$self; } sub lines { my $self = shift; my @lines = (); my $previous_point; - foreach my $point (@{ $self->points }) { + foreach my $point (@$self) { if ($previous_point) { push @lines, Slic3r::Line->new($previous_point, $point); } @@ -41,43 +40,25 @@ sub lines { return @lines; } -sub p { - my $self = shift; - return [ @{$self->points} ]; -} - sub merge_continuous_lines { my $self = shift; - my $points = $self->p; - if ($self->isa('Slic3r::Polyline::Closed')) { - polygon_remove_parallel_continuous_edges($points); - } else { - polyline_remove_parallel_continuous_edges($points); - } - @{$self->points} = map Slic3r::Point->new($_), @$points; + + polyline_remove_parallel_continuous_edges($self); + bless $_, 'Slic3r::Point' for @$self; } sub remove_acute_vertices { my $self = shift; - my $points = $self->p; - if ($self->isa('Slic3r::Polyline::Closed')) { - polygon_remove_acute_vertices($points); - } else { - polyline_remove_acute_vertices($points); - } - @{$self->points} = map Slic3r::Point->new($_), @$points; + polyline_remove_acute_vertices($self); + bless $_, 'Slic3r::Point' for @$self; } -sub cleanup { +sub simplify { my $self = shift; my $tolerance = shift || 10; - my $points = $self->p; - push @$points, $points->[0] if $self->isa('Slic3r::Polyline::Closed'); - my @clean_points = map Slic3r::Point->new($_), - Slic3r::Geometry::Douglas_Peucker($self->p, $tolerance); - pop @clean_points if $self->isa('Slic3r::Polyline::Closed'); - @{$self->points} = @clean_points; + @$self = Slic3r::Geometry::Douglas_Peucker($self, $tolerance); + bless $_, 'Slic3r::Point' for @$self; } sub reverse_points { @@ -104,7 +85,7 @@ sub nearest_point_to { my $self = shift; my ($point) = @_; - $point = Slic3r::Geometry::nearest_point($point, $self->p); + $point = Slic3r::Geometry::nearest_point($point, $self); return Slic3r::Point->new($point); } @@ -166,7 +147,7 @@ sub clip_with_expolygon { } } - return map Slic3r::Polyline->cast($_), @polylines; + return map Slic3r::Polyline->new($_), @polylines; } sub bounding_box { diff --git a/lib/Slic3r/Polyline/Closed.pm b/lib/Slic3r/Polyline/Closed.pm deleted file mode 100644 index 8d9d54c3a..000000000 --- a/lib/Slic3r/Polyline/Closed.pm +++ /dev/null @@ -1,49 +0,0 @@ -package Slic3r::Polyline::Closed; -use Moo; - -extends 'Slic3r::Polyline'; - -use Math::Clipper qw(JT_MITER); -use Slic3r::Geometry qw(scale); - -sub lines { - my $self = shift; - my @lines = $self->SUPER::lines(@_); - - # since this is a closed polyline, we just add a line at the end, - # connecting the last and the first point - push @lines, Slic3r::Line->new($self->points->[-1], $self->points->[0]); - return @lines; -} - -sub encloses_point { - my $self = shift; - my ($point) = @_; - - return Slic3r::Geometry::point_in_polygon($point->p, $self->p); -} - -# returns false if the polyline is too tight to be printed -sub is_printable { - my $self = shift; - - # try to get an inwards offset - # for a distance equal to half of the extrusion width; - # if no offset is possible, then polyline is not printable - my $p = $self->p; - @$p = reverse @$p if !Math::Clipper::is_counter_clockwise($p); - my $offsets = Math::Clipper::offset([$p], -(scale $Slic3r::flow_spacing / 2), $Slic3r::resolution * 100000, JT_MITER, 2); - return @$offsets ? 1 : 0; -} - -sub is_valid { - my $self = shift; - return @{$self->points} >= 3; -} - -sub polygon { - my $self = shift; - return Slic3r::Polygon->new($self->points); -} - -1; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 1129080d4..90157a4dc 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -125,8 +125,8 @@ sub new_from_mesh { [ map $_->expolygon->holes, @upper_surfaces, @lower_surfaces, ], ); - @{$layer->slices} = map Slic3r::Surface->cast_from_expolygon - ($_, surface_type => 'internal'), + @{$layer->slices} = map Slic3r::Surface->new + (expolygon => $_, surface_type => 'internal'), @$diff; } @@ -178,7 +178,7 @@ sub detect_surfaces_type { 1, ); return grep $_->contour->is_printable, - map Slic3r::Surface->cast_from_expolygon($_, surface_type => $result_type), + map Slic3r::Surface->new(expolygon => $_, surface_type => $result_type), @$expolygons; }; @@ -223,7 +223,7 @@ sub detect_surfaces_type { @internal = $surface_difference->($layer->slices, [@top, @bottom], 'internal'); # save surfaces to layer - $layer->slices([ @bottom, @top, @internal ]); + @{$layer->slices} = (@bottom, @top, @internal); Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n", $layer->id, scalar(@bottom), scalar(@top), scalar(@internal); @@ -235,10 +235,10 @@ sub detect_surfaces_type { foreach my $surface (@{$layer->slices}) { my $intersection = intersection_ex( [ $surface->p ], - [ map $_->p, @{$layer->fill_boundaries} ], + [ map @$_, @{$layer->fill_boundaries} ], ); - push @{$layer->surfaces}, map Slic3r::Surface->cast_from_expolygon - ($_, surface_type => $surface->surface_type), + push @{$layer->surfaces}, map Slic3r::Surface->new + (expolygon => $_, surface_type => $surface->surface_type), @$intersection; } } @@ -298,13 +298,13 @@ sub discover_horizontal_shells { # assign resulting inner surfaces to layer my $neighbor_fill_surfaces = $self->layers->[$n]->fill_surfaces; @$neighbor_fill_surfaces = (); - push @$neighbor_fill_surfaces, Slic3r::Surface->cast_from_expolygon - ($_, surface_type => 'internal') + push @$neighbor_fill_surfaces, Slic3r::Surface->new + (expolygon => $_, surface_type => 'internal') for @$internal; # assign new internal-solid surfaces to layer - push @$neighbor_fill_surfaces, Slic3r::Surface->cast_from_expolygon - ($_, surface_type => 'internal-solid') + push @$neighbor_fill_surfaces, Slic3r::Surface->new + (expolygon => $_, surface_type => 'internal-solid') for @$internal_solid; # assign top and bottom surfaces to layer @@ -313,8 +313,8 @@ sub discover_horizontal_shells { [ map $_->p, @$s ], [ map @$_, @$internal_solid, @$internal ], ); - push @$neighbor_fill_surfaces, Slic3r::Surface->cast_from_expolygon - ($_, surface_type => $s->[0]->surface_type, bridge_angle => $s->[0]->bridge_angle) + push @$neighbor_fill_surfaces, Slic3r::Surface->new + (expolygon => $_, surface_type => $s->[0]->surface_type, bridge_angle => $s->[0]->bridge_angle) for @$solid_surfaces; } } @@ -341,7 +341,10 @@ sub extrude_skirt { for (my $i = $Slic3r::skirts - 1; $i >= 0; $i--) { my $distance = scale ($Slic3r::skirt_distance + ($Slic3r::flow_spacing * $i)); my $outline = offset([$convex_hull], $distance, $Slic3r::resolution * 100, JT_ROUND); - push @skirts, Slic3r::ExtrusionLoop->cast([ @{$outline->[0]} ], role => 'skirt'); + push @skirts, Slic3r::ExtrusionLoop->new( + polygon => Slic3r::Polygon->new(@{$outline->[0]}), + role => 'skirt', + ); } # apply skirts to all layers @@ -387,12 +390,12 @@ sub infill_every_layers { { my @new_surfaces = (); push @new_surfaces, grep $_->surface_type ne 'internal', @{$layer->fill_surfaces}; - push @new_surfaces, map Slic3r::Surface->cast_from_expolygon - ($_, surface_type => 'internal', depth_layers => $d + 1), @$intersection; + push @new_surfaces, map Slic3r::Surface->new + (expolygon => $_, surface_type => 'internal', depth_layers => $d + 1), @$intersection; foreach my $depth (reverse $d..$Slic3r::infill_every_layers) { - push @new_surfaces, map Slic3r::Surface->cast_from_expolygon - ($_, surface_type => 'internal', depth_layers => $depth), + push @new_surfaces, map Slic3r::Surface->new + (expolygon => $_, surface_type => 'internal', depth_layers => $depth), # difference between our internal layers with depth == $depth # and the intersection found @@ -413,8 +416,8 @@ sub infill_every_layers { my @new_surfaces = (); push @new_surfaces, grep $_->surface_type ne 'internal', @{$lower_layer->fill_surfaces}; foreach my $depth (1..$Slic3r::infill_every_layers) { - push @new_surfaces, map Slic3r::Surface->cast_from_expolygon - ($_, surface_type => 'internal', depth_layers => $depth), + push @new_surfaces, map Slic3r::Surface->new + (expolygon => $_, surface_type => 'internal', depth_layers => $depth), # difference between internal layers with depth == $depth # and the intersection found diff --git a/lib/Slic3r/Surface.pm b/lib/Slic3r/Surface.pm index b1f3ee545..8605f7b81 100644 --- a/lib/Slic3r/Surface.pm +++ b/lib/Slic3r/Surface.pm @@ -1,17 +1,10 @@ package Slic3r::Surface; use Moo; -has 'contour' => ( - is => 'ro', - #isa => 'Slic3r::Polyline::Closed', - required => 1, -); - -has 'holes' => ( - traits => ['Array'], - is => 'rw', - #isa => 'ArrayRef[Slic3r::Polyline::Closed]', - default => sub { [] }, +has 'expolygon' => ( + is => 'ro', + required => 1, + handles => [qw(encloses_point lines contour holes)], ); has 'surface_type' => ( @@ -24,31 +17,6 @@ has 'depth_layers' => (is => 'ro', default => sub {1}); has 'bridge_angle' => (is => 'ro'); -sub cast_from_polygon { - my $class = shift; - my ($polygon, %args) = @_; - - return $class->new( - contour => Slic3r::Polyline::Closed->cast($polygon), - %args, - ); -} - -sub cast_from_expolygon { - my $class = shift; - my ($expolygon, %args) = @_; - - if (ref $expolygon eq 'HASH') { - $expolygon = Slic3r::ExPolygon->new($expolygon); - } - - return $class->new( - contour => $expolygon->contour->closed_polyline, - holes => [ map $_->closed_polyline, $expolygon->holes ], - %args, - ); -} - # static method to group surfaces having same surface_type, bridge_angle and depth_layers sub group { my $class = shift; @@ -73,7 +41,7 @@ sub add_hole { my $self = shift; my ($hole) = @_; - push @{ $self->holes }, $hole; + push @$self, $hole; } sub id { @@ -81,15 +49,6 @@ sub id { return $self->contour->id; } -sub encloses_point { - my $self = shift; - my ($point) = @_; - - return 0 if !$self->contour->encloses_point($point); - return 0 if grep $_->encloses_point($point), @{ $self->holes }; - return 1; -} - sub clipper_polygon { my $self = shift; @@ -102,18 +61,8 @@ sub clipper_polygon { } sub p { - my $self = shift; - return ($self->contour->p, map $_->p, @{$self->holes}); -} - -sub expolygon { - my $self = shift; - return Slic3r::ExPolygon->new($self->contour->p, map $_->p, @{$self->holes}); -} - -sub lines { - my $self = shift; - return @{ $self->contour->lines }, map @{ $_->lines }, @{ $self->holes }; + my $self = shift;use XXX; ZZZ $self->expolygon if !eval { 1 if @{$self->expolygon}; 1 }; + return @{$self->expolygon}; } 1; diff --git a/t/arcs.t b/t/arcs.t index 9faaaf8bc..2589e908f 100644 --- a/t/arcs.t +++ b/t/arcs.t @@ -13,13 +13,13 @@ use Slic3r; use Slic3r::Geometry qw(epsilon); { - my $path = Slic3r::ExtrusionPath->cast([ + my $path = Slic3r::ExtrusionPath->new(polyline => Slic3r::Polyline->new( [135322.42,26654.96], [187029.11,99546.23], [222515.14,92381.93], [258001.16,99546.23], [286979.42,119083.91], [306517.1,148062.17], [313681.4,183548.2], [306517.1,219034.23], [286979.42,248012.49], [258001.16,267550.17], [222515.14,274714.47], [187029.11,267550.17], [158050.85,248012.49], [138513.17,219034.23], [131348.87,183548.2], [86948.77,175149.09], [119825.35,100585], - ], role => 'fill'); + ), role => 'fill'); my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [$path]); $collection->detect_arcs(30); @@ -31,14 +31,17 @@ use Slic3r::Geometry qw(epsilon); #========================================================== { - my $path1 = Slic3r::ExtrusionPath->cast([ + my $path1 = Slic3r::ExtrusionPath->new(polyline => Slic3r::Polyline->new( [10,20], [10.7845909572784,19.9691733373313], [11.5643446504023,19.8768834059514], [12.3344536385591,19.7236992039768], [13.0901699437495,19.5105651629515], [13.8268343236509,19.2387953251129], [14.5399049973955,18.9100652418837], [15.2249856471595,18.5264016435409], [15.8778525229247,18.0901699437495], [16.4944804833018,17.6040596560003], - ], role => 'fill'); - my $path2 = Slic3r::ExtrusionPath->cast([ reverse @{$path1->points} ], role => 'fill'); + ), role => 'fill'); + my $path2 = Slic3r::ExtrusionPath->new( + polyline => Slic3r::Polyline->new(reverse @{$path1->points}), + role => 'fill', + ); my $collection1 = Slic3r::ExtrusionPath::Collection->new(paths => [$path1]); my $collection2 = Slic3r::ExtrusionPath::Collection->new(paths => [$path2]); diff --git a/t/clean_polylines.t b/t/clean_polylines.t index e87575ae9..8f9cbafa1 100644 --- a/t/clean_polylines.t +++ b/t/clean_polylines.t @@ -2,7 +2,7 @@ use Test::More; use strict; use warnings; -plan tests => 4; +plan tests => 3; BEGIN { use FindBin; @@ -11,87 +11,96 @@ BEGIN { use Slic3r; -my $polyline = Slic3r::Polyline::Closed->cast([ - [5,0], [10,0], [15,0], [20,0], [20,10], [20,30], [0,0], -]); +{ + 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'; +} -$polyline->merge_continuous_lines; -is scalar(@{$polyline->points}), 3, 'merge_continuous_lines'; +{ + my $gear = [ + [144.9694,317.1543], [145.4181,301.5633], [146.3466,296.921], [131.8436,294.1643], [131.7467,294.1464], + [121.7238,291.5082], [117.1631,290.2776], [107.9198,308.2068], [100.1735,304.5101], [104.9896,290.3672], + [106.6511,286.2133], [93.453,279.2327], [81.0065,271.4171], [67.7886,286.5055], [60.7927,280.1127], + [69.3928,268.2566], [72.7271,264.9224], [61.8152,253.9959], [52.2273,242.8494], [47.5799,245.7224], + [34.6577,252.6559], [30.3369,245.2236], [42.1712,236.3251], [46.1122,233.9605], [43.2099,228.4876], + [35.0862,211.5672], [33.1441,207.0856], [13.3923,212.1895], [10.6572,203.3273], [6.0707,204.8561], + [7.2775,204.4259], [29.6713,196.3631], [25.9815,172.1277], [25.4589,167.2745], [19.8337,167.0129], + [5.0625,166.3346], [5.0625,156.9425], [5.3701,156.9282], [21.8636,156.1628], [25.3713,156.4613], + [25.4243,155.9976], [29.3432,155.8157], [30.3838,149.3549], [26.3596,147.8137], [27.1085,141.2604], + [29.8466,126.8337], [24.5841,124.9201], [10.6664,119.8989], [13.4454,110.9264], [33.1886,116.0691], + [38.817,103.1819], [45.8311,89.8133], [30.4286,76.81], [35.7686,70.0812], [48.0879,77.6873], + [51.564,81.1635], [61.9006,69.1791], [72.3019,58.7916], [60.5509,42.5416], [68.3369,37.1532], + [77.9524,48.1338], [80.405,52.2215], [92.5632,44.5992], [93.0123,44.3223], [106.3561,37.2056], + [100.8631,17.4679], [108.759,14.3778], [107.3148,11.1283], [117.0002,32.8627], [140.9109,27.3974], + [145.7004,26.4994], [145.1346,6.1011], [154.502,5.4063], [156.9398,25.6501], [171.0557,26.2017], + [181.3139,27.323], [186.2377,27.8532], [191.6031,8.5474], [200.6724,11.2756], [197.2362,30.2334], + [220.0789,39.1906], [224.3261,41.031], [236.3506,24.4291], [243.6897,28.6723], [234.2956,46.7747], + [245.6562,55.1643], [257.2523,65.0901], [261.4374,61.5679], [273.1709,52.8031], [278.555,59.5164], + [268.4334,69.8001], [264.1615,72.3633], [268.2763,77.9442], [278.8488,93.5305], [281.4596,97.6332], + [286.4487,95.5191], [300.2821,90.5903], [303.4456,98.5849], [286.4523,107.7253], [293.7063,131.1779], + [294.9748,135.8787], [314.918,133.8172], [315.6941,143.2589], [300.9234,146.1746], [296.6419,147.0309], + [297.1839,161.7052], [296.6136,176.3942], [302.1147,177.4857], [316.603,180.3608], [317.1658,176.7341], + [315.215,189.6589], [315.1749,189.6548], [294.9411,187.5222], [291.13,201.7233], [286.2615,215.5916], + [291.1944,218.2545], [303.9158,225.1271], [299.2384,233.3694], [285.7165,227.6001], [281.7091,225.1956], + [273.8981,237.6457], [268.3486,245.2248], [267.4538,246.4414], [264.8496,250.0221], [268.6392,253.896], + [278.5017,265.2131], [272.721,271.4403], [257.2776,258.3579], [234.4345,276.5687], [242.6222,294.8315], + [234.9061,298.5798], [227.0321,286.2841], [225.2505,281.8301], [211.5387,287.8187], [202.3025,291.0935], + [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); + $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'; -my $gear = [ - [144.9694,317.1543], [145.4181,301.5633], [146.3466,296.921], [131.8436,294.1643], [131.7467,294.1464], - [121.7238,291.5082], [117.1631,290.2776], [107.9198,308.2068], [100.1735,304.5101], [104.9896,290.3672], - [106.6511,286.2133], [93.453,279.2327], [81.0065,271.4171], [67.7886,286.5055], [60.7927,280.1127], - [69.3928,268.2566], [72.7271,264.9224], [61.8152,253.9959], [52.2273,242.8494], [47.5799,245.7224], - [34.6577,252.6559], [30.3369,245.2236], [42.1712,236.3251], [46.1122,233.9605], [43.2099,228.4876], - [35.0862,211.5672], [33.1441,207.0856], [13.3923,212.1895], [10.6572,203.3273], [6.0707,204.8561], - [7.2775,204.4259], [29.6713,196.3631], [25.9815,172.1277], [25.4589,167.2745], [19.8337,167.0129], - [5.0625,166.3346], [5.0625,156.9425], [5.3701,156.9282], [21.8636,156.1628], [25.3713,156.4613], - [25.4243,155.9976], [29.3432,155.8157], [30.3838,149.3549], [26.3596,147.8137], [27.1085,141.2604], - [29.8466,126.8337], [24.5841,124.9201], [10.6664,119.8989], [13.4454,110.9264], [33.1886,116.0691], - [38.817,103.1819], [45.8311,89.8133], [30.4286,76.81], [35.7686,70.0812], [48.0879,77.6873], - [51.564,81.1635], [61.9006,69.1791], [72.3019,58.7916], [60.5509,42.5416], [68.3369,37.1532], - [77.9524,48.1338], [80.405,52.2215], [92.5632,44.5992], [93.0123,44.3223], [106.3561,37.2056], - [100.8631,17.4679], [108.759,14.3778], [107.3148,11.1283], [117.0002,32.8627], [140.9109,27.3974], - [145.7004,26.4994], [145.1346,6.1011], [154.502,5.4063], [156.9398,25.6501], [171.0557,26.2017], - [181.3139,27.323], [186.2377,27.8532], [191.6031,8.5474], [200.6724,11.2756], [197.2362,30.2334], - [220.0789,39.1906], [224.3261,41.031], [236.3506,24.4291], [243.6897,28.6723], [234.2956,46.7747], - [245.6562,55.1643], [257.2523,65.0901], [261.4374,61.5679], [273.1709,52.8031], [278.555,59.5164], - [268.4334,69.8001], [264.1615,72.3633], [268.2763,77.9442], [278.8488,93.5305], [281.4596,97.6332], - [286.4487,95.5191], [300.2821,90.5903], [303.4456,98.5849], [286.4523,107.7253], [293.7063,131.1779], - [294.9748,135.8787], [314.918,133.8172], [315.6941,143.2589], [300.9234,146.1746], [296.6419,147.0309], - [297.1839,161.7052], [296.6136,176.3942], [302.1147,177.4857], [316.603,180.3608], [317.1658,176.7341], - [315.215,189.6589], [315.1749,189.6548], [294.9411,187.5222], [291.13,201.7233], [286.2615,215.5916], - [291.1944,218.2545], [303.9158,225.1271], [299.2384,233.3694], [285.7165,227.6001], [281.7091,225.1956], - [273.8981,237.6457], [268.3486,245.2248], [267.4538,246.4414], [264.8496,250.0221], [268.6392,253.896], - [278.5017,265.2131], [272.721,271.4403], [257.2776,258.3579], [234.4345,276.5687], [242.6222,294.8315], - [234.9061,298.5798], [227.0321,286.2841], [225.2505,281.8301], [211.5387,287.8187], [202.3025,291.0935], - [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], -]; -$polyline = Slic3r::Polyline::Closed->cast($gear); -$polyline->merge_continuous_lines; -note sprintf "original points: %d\nnew points: %d", scalar(@$gear), scalar(@{$polyline->points}); -ok @{$polyline->points} < @$gear, 'gear was simplified using merge_continuous_lines'; + # simplify() is not being used, so we don't test it + if (0) { + my $num_points = scalar @$polygon; + $polygon->simplify; + note sprintf "original points: %d\nnew points: %d", $num_points, scalar(@$polygon); + ok @$polygon < $num_points, 'gear was further simplified using Douglas-Peucker'; + } +} -my $num_points = scalar @{$polyline->points}; -$polyline->cleanup; -note sprintf "original points: %d\nnew points: %d", $num_points, scalar(@{$polyline->points}); -ok @{$polyline->points} < $num_points, 'gear was further simplified using Douglas-Peucker'; - -my $circle = [ - [3744.8,8045.8],[3788.1,8061.4],[3940.6,8116.3],[3984.8,8129.2],[4140.6,8174.4],[4185.5,8184.4],[4343.8,8219.9], - [4389.2,8227.1],[4549.4,8252.4],[4595.2,8256.7],[4756.6,8272],[4802.6,8273.4],[4964.7,8278.5],[5010.7,8277.1], - [5172.8,8272],[5218.6,8267.7],[5380,8252.4],[5425.5,8245.2],[5585.6,8219.9],[5630.5,8209.8],[5788.8,8174.4], - [5833,8161.6],[5988.8,8116.3],[6032,8100.7],[6184.6,8045.8],[6226.8,8027.5],[6375.6,7963.2],[6416.6,7942.3], - [6561.1,7868.6],[6600.7,7845.2],[6740.3,7762.7],[6778.4,7736.8],[6912.5,7645.7],[6948.8,7617.5],[7077,7518], - [7111.5,7487.6],[7233.2,7380.4],[7347.9,7265.7],[7380.4,7233.2],[7410.8,7198.7],[7518,7077],[7546.2,7040.6], - [7645.7,6912.5],[7671.5,6874.4],[7762.7,6740.3],[7786.1,6700.7],[7868.6,6561.1],[7889.5,6520.2],[7963.2,6375.6], - [7981.4,6333.4],[8045.8,6184.6],[8061.4,6141.3],[8116.3,5988.8],[8129.2,5944.6],[8174.4,5788.8],[8184.4,5743.9], - [8219.9,5585.6],[8227.1,5540.2],[8252.4,5380],[8256.7,5334.2],[8272,5172.8],[8273.4,5126.8],[8278.5,4964.7], - [8277.1,4918.7],[8272,4756.6],[8267.7,4710.8],[8252.4,4549.4],[8245.2,4503.9],[8219.9,4343.8],[8209.8,4298.9], - [8174.4,4140.6],[8161.6,4096.4],[8116.3,3940.6],[8100.7,3897.4],[8045.8,3744.8],[8027.5,3702.6],[7963.2,3553.8], - [7942.3,3512.8],[7868.6,3368.3],[7845.2,3328.7],[7762.7,3189.1],[7736.8,3151],[7645.7,3016.9],[7617.5,2980.6], - [7518,2852.4],[7487.6,2817.9],[7380.4,2696.2],[7347.9,2663.7],[7233.2,2549],[7198.7,2518.6],[7077,2411.4], - [7040.6,2383.2],[6912.5,2283.7],[6874.4,2257.9],[6740.3,2166.7],[6700.7,2143.3],[6561.1,2060.8],[6520.2,2039.9], - [6375.6,1966.2],[6333.4,1948],[6184.6,1883.6],[6141.3,1868],[5988.8,1813.1],[5944.6,1800.2],[5788.8,1755], - [5743.9,1745],[5585.6,1709.5],[5540.2,1702.3],[5380,1677],[5334.2,1672.7],[5172.8,1657.4],[5126.8,1656], - [4964.7,1650.9],[4918.7,1652.3],[4756.6,1657.4],[4710.8,1661.7],[4549.4,1677],[4503.9,1684.2],[4343.8,1709.5], - [4298.9,1719.6],[4140.6,1755],[4096.4,1767.8],[3940.6,1813.1],[3897.4,1828.7],[3744.8,1883.6],[3702.6,1901.9], - [3553.8,1966.2],[3512.8,1987.1],[3368.3,2060.8],[3328.7,2084.2],[3189.1,2166.7],[3151,2192.6],[3016.9,2283.7], - [2980.6,2311.9],[2852.4,2411.4],[2817.9,2441.8],[2696.2,2549],[2581.5,2663.7],[2549,2696.2],[2518.6,2730.7], - [2411.4,2852.4],[2383.2,2888.8],[2283.7,3016.9],[2257.9,3055],[2166.7,3189.1],[2143.3,3228.7],[2060.8,3368.3], - [2039.9,3409.2],[1966.2,3553.8],[1948,3596],[1883.6,3744.8],[1868,3788.1],[1813.1,3940.6],[1800.2,3984.8], - [1755,4140.6],[1745,4185.5],[1709.5,4343.8],[1702.3,4389.2],[1677,4549.4],[1672.7,4595.2],[1657.4,4756.6], - [1656,4802.6],[1650.9,4964.7],[1652.3,5010.7],[1657.4,5172.8],[1661.7,5218.6],[1677,5380],[1684.2,5425.5], - [1709.5,5585.6],[1719.6,5630.5],[1755,5788.8],[1767.8,5833],[1813.1,5988.8],[1828.7,6032],[1883.6,6184.6], - [1901.9,6226.8],[1966.2,6375.6],[1987.1,6416.6],[2060.8,6561.1],[2084.2,6600.7],[2166.7,6740.3],[2192.6,6778.4], - [2283.7,6912.5],[2311.9,6948.8],[2411.4,7077],[2441.8,7111.5],[2549,7233.2],[2581.5,7265.7],[2696.2,7380.4], - [2730.7,7410.8],[2852.4,7518],[2888.8,7546.2],[3016.9,7645.7],[3055,7671.5],[3189.1,7762.7],[3228.7,7786.1], - [3368.3,7868.6],[3409.2,7889.5],[3553.8,7963.2],[3596,7981.4], -]; - -$polyline = Slic3r::Polyline::Closed->cast($circle); -$polyline->merge_continuous_lines; -note sprintf "original points: %d\nnew points: %d", scalar(@$circle), scalar(@{$polyline->points}); -ok @{$polyline->points} >= @$gear/3, 'circle was simplified using merge_continuous_lines'; +{ + my $circle = [ + [3744.8,8045.8],[3788.1,8061.4],[3940.6,8116.3],[3984.8,8129.2],[4140.6,8174.4],[4185.5,8184.4],[4343.8,8219.9], + [4389.2,8227.1],[4549.4,8252.4],[4595.2,8256.7],[4756.6,8272],[4802.6,8273.4],[4964.7,8278.5],[5010.7,8277.1], + [5172.8,8272],[5218.6,8267.7],[5380,8252.4],[5425.5,8245.2],[5585.6,8219.9],[5630.5,8209.8],[5788.8,8174.4], + [5833,8161.6],[5988.8,8116.3],[6032,8100.7],[6184.6,8045.8],[6226.8,8027.5],[6375.6,7963.2],[6416.6,7942.3], + [6561.1,7868.6],[6600.7,7845.2],[6740.3,7762.7],[6778.4,7736.8],[6912.5,7645.7],[6948.8,7617.5],[7077,7518], + [7111.5,7487.6],[7233.2,7380.4],[7347.9,7265.7],[7380.4,7233.2],[7410.8,7198.7],[7518,7077],[7546.2,7040.6], + [7645.7,6912.5],[7671.5,6874.4],[7762.7,6740.3],[7786.1,6700.7],[7868.6,6561.1],[7889.5,6520.2],[7963.2,6375.6], + [7981.4,6333.4],[8045.8,6184.6],[8061.4,6141.3],[8116.3,5988.8],[8129.2,5944.6],[8174.4,5788.8],[8184.4,5743.9], + [8219.9,5585.6],[8227.1,5540.2],[8252.4,5380],[8256.7,5334.2],[8272,5172.8],[8273.4,5126.8],[8278.5,4964.7], + [8277.1,4918.7],[8272,4756.6],[8267.7,4710.8],[8252.4,4549.4],[8245.2,4503.9],[8219.9,4343.8],[8209.8,4298.9], + [8174.4,4140.6],[8161.6,4096.4],[8116.3,3940.6],[8100.7,3897.4],[8045.8,3744.8],[8027.5,3702.6],[7963.2,3553.8], + [7942.3,3512.8],[7868.6,3368.3],[7845.2,3328.7],[7762.7,3189.1],[7736.8,3151],[7645.7,3016.9],[7617.5,2980.6], + [7518,2852.4],[7487.6,2817.9],[7380.4,2696.2],[7347.9,2663.7],[7233.2,2549],[7198.7,2518.6],[7077,2411.4], + [7040.6,2383.2],[6912.5,2283.7],[6874.4,2257.9],[6740.3,2166.7],[6700.7,2143.3],[6561.1,2060.8],[6520.2,2039.9], + [6375.6,1966.2],[6333.4,1948],[6184.6,1883.6],[6141.3,1868],[5988.8,1813.1],[5944.6,1800.2],[5788.8,1755], + [5743.9,1745],[5585.6,1709.5],[5540.2,1702.3],[5380,1677],[5334.2,1672.7],[5172.8,1657.4],[5126.8,1656], + [4964.7,1650.9],[4918.7,1652.3],[4756.6,1657.4],[4710.8,1661.7],[4549.4,1677],[4503.9,1684.2],[4343.8,1709.5], + [4298.9,1719.6],[4140.6,1755],[4096.4,1767.8],[3940.6,1813.1],[3897.4,1828.7],[3744.8,1883.6],[3702.6,1901.9], + [3553.8,1966.2],[3512.8,1987.1],[3368.3,2060.8],[3328.7,2084.2],[3189.1,2166.7],[3151,2192.6],[3016.9,2283.7], + [2980.6,2311.9],[2852.4,2411.4],[2817.9,2441.8],[2696.2,2549],[2581.5,2663.7],[2549,2696.2],[2518.6,2730.7], + [2411.4,2852.4],[2383.2,2888.8],[2283.7,3016.9],[2257.9,3055],[2166.7,3189.1],[2143.3,3228.7],[2060.8,3368.3], + [2039.9,3409.2],[1966.2,3553.8],[1948,3596],[1883.6,3744.8],[1868,3788.1],[1813.1,3940.6],[1800.2,3984.8], + [1755,4140.6],[1745,4185.5],[1709.5,4343.8],[1702.3,4389.2],[1677,4549.4],[1672.7,4595.2],[1657.4,4756.6], + [1656,4802.6],[1650.9,4964.7],[1652.3,5010.7],[1657.4,5172.8],[1661.7,5218.6],[1677,5380],[1684.2,5425.5], + [1709.5,5585.6],[1719.6,5630.5],[1755,5788.8],[1767.8,5833],[1813.1,5988.8],[1828.7,6032],[1883.6,6184.6], + [1901.9,6226.8],[1966.2,6375.6],[1987.1,6416.6],[2060.8,6561.1],[2084.2,6600.7],[2166.7,6740.3],[2192.6,6778.4], + [2283.7,6912.5],[2311.9,6948.8],[2411.4,7077],[2441.8,7111.5],[2549,7233.2],[2581.5,7265.7],[2696.2,7380.4], + [2730.7,7410.8],[2852.4,7518],[2888.8,7546.2],[3016.9,7645.7],[3055,7671.5],[3189.1,7762.7],[3228.7,7786.1], + [3368.3,7868.6],[3409.2,7889.5],[3553.8,7963.2],[3596,7981.4], + ]; + + 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 205f036c8..4b3006e1a 100644 --- a/t/polyclip.t +++ b/t/polyclip.t @@ -103,8 +103,8 @@ is_deeply $intersection, [ [12, 12], [18, 16] ], 'internal lines are preserved'; ], 'tangent line is clipped to square with hole'; } { - my $polyline = Slic3r::Polyline->cast([ [5, 18], [25, 18], [25, 15], [15, 15], [15, 12], [12, 12], [12, 5] ]); - is_deeply [ map $_->p, $polyline->clip_with_expolygon($expolygon) ], [ + my $polyline = Slic3r::Polyline->new([ [5, 18], [25, 18], [25, 15], [15, 15], [15, 12], [12, 12], [12, 5] ]); + is_deeply [ map $_, $polyline->clip_with_expolygon($expolygon) ], [ [ [10, 18], [20, 18] ], [ [20, 15], [16, 15] ], [ [15, 14], [15, 12], [12, 12], [12, 10] ],