From 9b582a11ff80bcf08da2fefd958904d14a702c7b Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 16 Jul 2013 09:49:34 +0200 Subject: [PATCH] Adopt XS containers everywhere (incomplete work) --- lib/Slic3r.pm | 12 +++- lib/Slic3r/ExPolygon.pm | 61 +----------------- lib/Slic3r/ExtrusionLoop.pm | 36 +---------- lib/Slic3r/ExtrusionPath.pm | 20 +----- lib/Slic3r/ExtrusionPath/Collection.pm | 4 +- lib/Slic3r/Fill.pm | 4 +- lib/Slic3r/Fill/Rectilinear.pm | 2 +- lib/Slic3r/GCode.pm | 2 +- lib/Slic3r/GCode/Layer.pm | 14 ++--- lib/Slic3r/GCode/MotionPlanner.pm | 1 - lib/Slic3r/Geometry/Clipper.pm | 38 ++++++------ lib/Slic3r/Layer.pm | 2 +- lib/Slic3r/Layer/Region.pm | 15 +++-- lib/Slic3r/Line.pm | 8 --- lib/Slic3r/Polygon.pm | 31 ++-------- lib/Slic3r/Polyline.pm | 85 +------------------------- lib/Slic3r/Print.pm | 11 ++-- lib/Slic3r/Print/Object.pm | 1 - lib/Slic3r/Surface.pm | 2 +- t/clean_polylines.t | 6 +- t/dynamic.t | 2 +- t/fill.t | 10 +-- xs/lib/Slic3r/XS.pm | 4 +- xs/t/07_extrusionpath.t | 6 +- xs/t/08_extrusionloop.t | 8 +-- xs/xsp/ExtrusionLoop.xsp | 16 +++-- xs/xsp/ExtrusionPath.xsp | 16 +++-- xs/xsp/Line.xsp | 4 ++ xs/xsp/Polygon.xsp | 9 +++ xs/xsp/Polyline.xsp | 11 ++++ 30 files changed, 130 insertions(+), 311 deletions(-) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index fc6c6777f..2f10a9fe6 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -110,10 +110,16 @@ sub parallelize { sub thread_cleanup { # prevent destruction of shared objects no warnings 'redefine'; + *Slic3r::ExPolygon::DESTROY = sub {}; *Slic3r::ExPolygon::Collection::DESTROY = sub {}; - *Slic3r::ExPolygon::XS::DESTROY = sub {}; - *Slic3r::Point::DESTROY = sub {}; - *Slic3r::Surface::DESTROY = sub {}; + *Slic3r::ExtrusionLoop::DESTROY = sub {}; + *Slic3r::ExtrusionPath::DESTROY = sub {}; + *Slic3r::Line::DESTROY = sub {}; + *Slic3r::Point::DESTROY = sub {}; + *Slic3r::Polygon::DESTROY = sub {}; + *Slic3r::Polyline::DESTROY = sub {}; + *Slic3r::Surface::DESTROY = sub {}; + *Slic3r::Surface::Collection::DESTROY = sub {}; } sub encode_path { diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index 5fb0ca1c5..1fcdb00d9 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -1,4 +1,4 @@ -gpackage Slic3r::ExPolygon; +package Slic3r::ExPolygon; use strict; use warnings; @@ -9,32 +9,6 @@ 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) -sub new { - my $class = shift; - my $self; - if (@_ == 1 && ref $_[0] eq 'HASH') { - $self = [ - Slic3r::Polygon->new(@{$_[0]{outer}}), - map Slic3r::Polygon->new(@$_), @{$_[0]{holes}}, - ]; - } else { - $self = [ map Slic3r::Polygon->new(@$_), @_ ]; - } - bless $self, $class; - $self; -} - -sub clone { - Storable::dclone($_[0]) -} - -# no-op for legacy with ::XS -sub arrayref { $_[0] } -sub pp { [ map $_->pp, @{$_[0]} ] } sub contour { my $self = shift; @@ -46,19 +20,6 @@ sub holes { return @$self[1..$#$self]; } -sub lines { - my $self = shift; - return map $_->lines, @$self; -} - -sub clipper_expolygon { - my $self = shift; - return { - outer => $self->contour, - holes => [ $self->holes ], - }; -} - sub is_valid { my $self = shift; return (!first { !$_->is_valid } @$self) @@ -155,23 +116,6 @@ sub simplify { return @{ Slic3r::Geometry::Clipper::union_ex([ @simplified ]) }; } -sub scale { - my $self = shift; - $_->scale(@_) for @$self; -} - -sub translate { - my $self = shift; - $_->translate(@_) for @$self; - $self; -} - -sub rotate { - my $self = shift; - $_->rotate(@_) for @$self; - $self; -} - sub area { my $self = shift; my $area = $self->contour->area; @@ -298,9 +242,6 @@ sub medial_axis { return @result; } -package Slic3r::ExPolygon::XS; -use parent 'Slic3r::ExPolygon'; - package Slic3r::ExPolygon::Collection; use Slic3r::Geometry qw(X1 Y1); diff --git a/lib/Slic3r/ExtrusionLoop.pm b/lib/Slic3r/ExtrusionLoop.pm index 2f4933a8a..4298d0e0b 100644 --- a/lib/Slic3r/ExtrusionLoop.pm +++ b/lib/Slic3r/ExtrusionLoop.pm @@ -2,51 +2,17 @@ package Slic3r::ExtrusionLoop; use strict; use warnings; -use Slic3r::Geometry qw(same_point); - -sub polygon { $_[0] } - -# class or object method -sub pack { - my $self = shift; - - if (ref $self) { - return $self; - } else { - return $self->new(@_); - } -} - -# no-op -sub unpack { $_[0] } - -sub split_at_index { - my $self = shift; - - return Slic3r::ExtrusionPath->new( - polyline => $self->as_polygon->split_at_index(@_), - role => $self->role, - flow_spacing => $self->flow_spacing, - height => $self->height, - ); -} - sub split_at { my $self = shift; return Slic3r::ExtrusionPath->new( - polyline => $self->as_polygon->split_at(@_), + polyline => $self->polygon->split_at(@_), role => $self->role, flow_spacing => $self->flow_spacing, height => $self->height, ); } -sub split_at_first_point { - my $self = shift; - return $self->split_at_index(0); -} - sub first_point { my $self = shift; return $self->polygon->[0]; diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm index 38606ad84..facddd614 100644 --- a/lib/Slic3r/ExtrusionPath.pm +++ b/lib/Slic3r/ExtrusionPath.pm @@ -2,7 +2,6 @@ package Slic3r::ExtrusionPath; use strict; use warnings; -use parent -norequire, qw(Slic3r::Polyline::XS); use parent qw(Exporter); our @EXPORT_OK = qw(EXTR_ROLE_PERIMETER EXTR_ROLE_EXTERNAL_PERIMETER @@ -12,21 +11,6 @@ our @EXPORT_OK = qw(EXTR_ROLE_PERIMETER EXTR_ROLE_EXTERNAL_PERIMETER our %EXPORT_TAGS = (roles => \@EXPORT_OK); use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points); -sub polyline { $_[0] } - -# class or object method -sub pack { - my $self = shift; - - if (ref $self) { - return $self; - } else { - return $self->new(@_); - } -} - -# no-op, this allows to use both packed and non-packed objects in Collections -sub unpack { $_[0] } sub clip_with_polygon { my $self = shift; @@ -40,7 +24,7 @@ sub clip_with_expolygon { my ($expolygon) = @_; return map $self->clone(polyline => $_), - $self->as_polyline->clip_with_expolygon($expolygon); + $self->polyline->clip_with_expolygon($expolygon); } sub intersect_expolygons { @@ -61,7 +45,7 @@ sub subtract_expolygons { sub simplify { my $self = shift; - $self->set_polyline($self->as_polyline->simplify(@_)); + $self->set_polyline($self->polyline->simplify(@_)); } sub points { diff --git a/lib/Slic3r/ExtrusionPath/Collection.pm b/lib/Slic3r/ExtrusionPath/Collection.pm index 88cc12528..faee94af8 100644 --- a/lib/Slic3r/ExtrusionPath/Collection.pm +++ b/lib/Slic3r/ExtrusionPath/Collection.pm @@ -9,7 +9,7 @@ sub unpack { $_[0] } sub first_point { my $self = shift; - return $self->paths->[0]->unpack->polyline->[0]; + return $self->paths->[0]->polyline->[0]; } sub chained_path { @@ -21,7 +21,7 @@ sub chained_path { # make sure we pass the same path objects to the Collection constructor # and the ->chained_path() method because the latter will reverse the # paths in-place when needed and we need to return them that way - my @paths = map $_->unpack, @{$self->paths}; + my @paths = @{$self->paths}; my $collection = Slic3r::Polyline::Collection->new( polylines => [ map $_->polyline, @paths ], ); diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index 1efe8163d..18ad6d6f0 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -178,7 +178,7 @@ sub make_fill { push @fills, Slic3r::ExtrusionPath::Collection->new( no_sort => $params->{no_sort}, paths => [ - map Slic3r::ExtrusionPath->pack( + map Slic3r::ExtrusionPath->new( polyline => Slic3r::Polyline->new(@$_), role => ($surface->surface_type == S_TYPE_INTERNALBRIDGE ? EXTR_ROLE_INTERNALBRIDGE @@ -197,7 +197,7 @@ sub make_fill { # add thin fill regions push @fills, @{$layerm->thin_fills}; - push @fills_ordering_points, map $_->unpack->points->[0], @{$layerm->thin_fills}; + push @fills_ordering_points, map $_->points->[0], @{$layerm->thin_fills}; # organize infill paths using a nearest-neighbor search @fills = @fills[ chained_path(\@fills_ordering_points) ]; diff --git a/lib/Slic3r/Fill/Rectilinear.pm b/lib/Slic3r/Fill/Rectilinear.pm index ffca16005..54998cb40 100644 --- a/lib/Slic3r/Fill/Rectilinear.pm +++ b/lib/Slic3r/Fill/Rectilinear.pm @@ -67,7 +67,7 @@ sub fill_surface { # are kept even if the expolygon has vertical sides my @paths = @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection( +($expolygon->offset_ex(scaled_epsilon))[0]->pp, # TODO: we should use all the resulting expolygons and clip the linestrings to a multipolygon object - [ @{ $self->cache->{$cache_id} } ], + [ map $_->pp, @{ $self->cache->{$cache_id} } ], ) }; # connect lines diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 13c870098..aefb703b1 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -152,7 +152,7 @@ sub extrude_loop { my ($loop, $description) = @_; # extrude all loops ccw - my $polygon = $loop->as_polygon; + my $polygon = $loop->polygon; my $was_clockwise = $polygon->make_counter_clockwise; # find candidate starting points diff --git a/lib/Slic3r/GCode/Layer.pm b/lib/Slic3r/GCode/Layer.pm index 26db9fc06..f537357f5 100644 --- a/lib/Slic3r/GCode/Layer.pm +++ b/lib/Slic3r/GCode/Layer.pm @@ -124,24 +124,22 @@ sub process_layer { push @islands, { perimeters => [], fills => [] } for 1 .. (@{$layer->slices} || 1); # make sure we have at least one island hash to avoid failure of the -1 subscript below PERIMETER: foreach my $perimeter (@{$layerm->perimeters}) { - my $p = $perimeter->unpack; for my $i (0 .. $#{$layer->slices}-1) { - if ($layer->slices->[$i]->contour->encloses_point($p->first_point)) { - push @{ $islands[$i]{perimeters} }, $p; + if ($layer->slices->[$i]->contour->encloses_point($perimeter->first_point)) { + push @{ $islands[$i]{perimeters} }, $perimeter; next PERIMETER; } } - push @{ $islands[-1]{perimeters} }, $p; # optimization + push @{ $islands[-1]{perimeters} }, $perimeter; # optimization } FILL: foreach my $fill (@{$layerm->fills}) { - my $f = $fill->unpack; for my $i (0 .. $#{$layer->slices}-1) { - if ($layer->slices->[$i]->contour->encloses_point($f->first_point)) { - push @{ $islands[$i]{fills} }, $f; + if ($layer->slices->[$i]->contour->encloses_point($fill->first_point)) { + push @{ $islands[$i]{fills} }, $fill; next FILL; } } - push @{ $islands[-1]{fills} }, $f; # optimization + push @{ $islands[-1]{fills} }, $fill; # optimization } } else { push @islands, { diff --git a/lib/Slic3r/GCode/MotionPlanner.pm b/lib/Slic3r/GCode/MotionPlanner.pm index 026485357..dbdba2f67 100644 --- a/lib/Slic3r/GCode/MotionPlanner.pm +++ b/lib/Slic3r/GCode/MotionPlanner.pm @@ -53,7 +53,6 @@ sub BUILD { # offset the island outwards to make the boundaries for external movements $self->_outer->[$i] = [ offset([ $self->islands->[$i]->contour], $self->_outer_margin) ]; - bless $_, 'Slic3r::Polygon' for @{ $self->_outer->[$i] }; # if internal motion is enabled, build a set of utility expolygons representing # the outer boundaries (as contours) and the inner boundaries (as holes). whenever diff --git a/lib/Slic3r/Geometry/Clipper.pm b/lib/Slic3r/Geometry/Clipper.pm index a045ca90d..02ec5c557 100644 --- a/lib/Slic3r/Geometry/Clipper.pm +++ b/lib/Slic3r/Geometry/Clipper.pm @@ -15,12 +15,13 @@ our $clipper = Math::Clipper->new; sub safety_offset { my ($polygons, $factor) = @_; - return Math::Clipper::int_offset(_convert($polygons), $factor // (scale 1e-05), 100000, JT_MITER, 2); + return [ map Slic3r::Polygon->new(@$_), + @{Math::Clipper::int_offset(_convert($polygons), $factor // (scale 1e-05), 100000, JT_MITER, 2)} ]; } sub safety_offset_ex { my ($polygons, $factor) = @_; - return map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), + return map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @{Math::Clipper::ex_int_offset(_convert($polygons), $factor // (scale 1e-05), 100000, JT_MITER, 2)}; } @@ -51,7 +52,7 @@ sub offset_ex { $miterLimit //= 3; my $offsets = Math::Clipper::ex_int_offset(_convert($polygons), $distance, $scale, $joinType, $miterLimit); - return map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), @$offsets; + return map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @$offsets; } sub offset2_ex { @@ -61,7 +62,7 @@ sub offset2_ex { $miterLimit //= 3; my $offsets = Math::Clipper::ex_int_offset2(_convert($polygons), $delta1, $delta2, $scale, $joinType, $miterLimit); - return map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), @$offsets; + return map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @$offsets; } sub diff_ex { @@ -69,9 +70,9 @@ sub diff_ex { $clipper->clear; $clipper->add_subject_polygons(_convert($subject)); - $clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip)); + $clipper->add_clip_polygons($safety_offset ? _convert(safety_offset($clip)) : _convert($clip)); return [ - map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), + map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @{ $clipper->ex_execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) }, ]; } @@ -81,7 +82,7 @@ sub diff { $clipper->clear; $clipper->add_subject_polygons(_convert($subject)); - $clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip)); + $clipper->add_clip_polygons($safety_offset ? _convert(safety_offset($clip)) : _convert($clip)); return [ map Slic3r::Polygon->new(@$_), @{ $clipper->execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) }, @@ -92,10 +93,10 @@ sub union_ex { my ($polygons, $jointype, $safety_offset) = @_; $jointype = PFT_NONZERO unless defined $jointype; $clipper->clear; - $polygons = $polygons->arrayref if ref $polygons eq 'Slic3r::ExPolygon::XS'; - $clipper->add_subject_polygons($safety_offset ? safety_offset(_convert($polygons)) : _convert($polygons)); + $polygons = $polygons->arrayref if ref $polygons eq 'Slic3r::ExPolygon'; + $clipper->add_subject_polygons($safety_offset ? _convert(safety_offset($polygons)) : _convert($polygons)); return [ - map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), + map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @{ $clipper->ex_execute(CT_UNION, $jointype, $jointype) }, ]; } @@ -104,7 +105,7 @@ sub union_pt { my ($polygons, $jointype, $safety_offset) = @_; $jointype = PFT_NONZERO unless defined $jointype; $clipper->clear; - $clipper->add_subject_polygons($safety_offset ? safety_offset(_convert($polygons)) : _convert($polygons)); + $clipper->add_subject_polygons($safety_offset ? _convert(safety_offset($polygons)) : _convert($polygons)); return $clipper->pt_execute(CT_UNION, $jointype, $jointype); } @@ -113,9 +114,9 @@ sub intersection_ex { $jointype = PFT_NONZERO unless defined $jointype; $clipper->clear; $clipper->add_subject_polygons(_convert($subject)); - $clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip)); + $clipper->add_clip_polygons($safety_offset ? _convert(safety_offset($clip)) : _convert($clip)); return [ - map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), + map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @{ $clipper->ex_execute(CT_INTERSECTION, $jointype, $jointype) }, ]; } @@ -125,7 +126,7 @@ sub intersection { $jointype = PFT_NONZERO unless defined $jointype; $clipper->clear; $clipper->add_subject_polygons(_convert($subject)); - $clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip)); + $clipper->add_clip_polygons($safety_offset ? _convert(safety_offset($clip)) : _convert($clip)); return [ map Slic3r::Polygon->new(@$_), @{ $clipper->execute(CT_INTERSECTION, $jointype, $jointype) }, @@ -139,7 +140,7 @@ sub xor_ex { $clipper->add_subject_polygons(_convert($subject)); $clipper->add_clip_polygons(_convert($clip)); return [ - map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), + map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @{ $clipper->ex_execute(CT_XOR, $jointype, $jointype) }, ]; } @@ -178,10 +179,9 @@ sub traverse_pt { } sub _convert { - my $polygons = shift; - $polygons = $polygons->pp if ref $polygons eq 'Slic3r::ExPolygon::XS'; - $polygons = [ map $_->pp, @$polygons ] if @$polygons && ref $polygons->[0] eq 'Slic3r::Polygon'; - return $polygons; + my $p = shift; + $p = $p->pp if ref($p) ne 'ARRAY' && $p->can('pp'); + return [ map { ref($_) ne 'ARRAY' && $_->can('pp') ? $_->pp : $_ } @$p ]; } 1; diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index bd27e37ea..e8a289cd9 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -81,7 +81,7 @@ sub make_slices { my $slices = union_ex([ map $_->p, map @{$_->slices}, @{$self->regions} ]); $self->slices->clear; - $self->slices->append(map Slic3r::ExPolygon::XS->new(@$_), @$slices); + $self->slices->append(map Slic3r::ExPolygon->new(@$_), @$slices); } sub make_perimeters { diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index daef53ba9..64b6758d0 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -135,8 +135,7 @@ sub _merge_loops { $safety_offset //= scale 0.0499; @loops = @{ safety_offset(\@loops, $safety_offset) }; my $expolygons = []; - while (my $loop = shift @loops) { - bless $loop, 'Slic3r::Polygon'; + while (defined (my $loop = shift @loops)) { if ($loop->is_counter_clockwise) { $expolygons = union_ex([ $loop, map @$_, @$expolygons ]); } else { @@ -148,7 +147,7 @@ sub _merge_loops { Slic3r::debugf " %d surface(s) having %d holes detected from %d polylines\n", scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops); - return map Slic3r::Surface->new(expolygon => Slic3r::ExPolygon::XS->new(@$_), surface_type => S_TYPE_INTERNAL), @$expolygons; + return map Slic3r::Surface->new(expolygon => Slic3r::ExPolygon->new(@$_), surface_type => S_TYPE_INTERNAL), @$expolygons; } sub make_perimeters { @@ -257,7 +256,7 @@ sub make_perimeters { $role = EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER; } - push @loops, Slic3r::ExtrusionLoop->pack( + push @loops, Slic3r::ExtrusionLoop->new( polygon => $polygon, role => $role, flow_spacing => $self->perimeter_flow->spacing, @@ -285,7 +284,7 @@ sub make_perimeters { # add thin walls as perimeters push @{ $self->perimeters }, Slic3r::ExtrusionPath::Collection->new(paths => [ map { - Slic3r::ExtrusionPath->pack( + Slic3r::ExtrusionPath->new( polyline => ($_->isa('Slic3r::Polygon') ? $_->split_at_first_point : $_), role => EXTR_ROLE_EXTERNAL_PERIMETER, flow_spacing => $self->perimeter_flow->spacing, @@ -337,8 +336,8 @@ sub _fill_gaps { ); push @{ $self->thin_fills }, map { $_->isa('Slic3r::Polygon') - ? (map $_->pack, Slic3r::ExtrusionLoop->new(polygon => $_, %path_args)->split_at_first_point) # we should keep these as loops - : Slic3r::ExtrusionPath->pack(polyline => $_, %path_args), + ? Slic3r::ExtrusionLoop->new(polygon => $_, %path_args)->split_at_first_point # we should keep these as loops + : Slic3r::ExtrusionPath->new(polyline => $_, %path_args), } map $_->medial_axis($flow->scaled_width), @this_width; Slic3r::debugf " %d gaps filled with extrusion width = %s\n", scalar @this_width, $width @@ -361,7 +360,7 @@ sub _fill_gaps { push @{ $self->thin_fills }, map { $_->simplify($flow->scaled_width/3); - $_->pack; + $_; } map Slic3r::ExtrusionPath->new( polyline => Slic3r::Polyline->new(@$_), diff --git a/lib/Slic3r/Line.pm b/lib/Slic3r/Line.pm index ac2227006..a9829d848 100644 --- a/lib/Slic3r/Line.pm +++ b/lib/Slic3r/Line.pm @@ -7,14 +7,6 @@ use parent 'Slic3r::Polyline'; use Slic3r::Geometry qw(A B X Y); -sub new { - my $class = shift; - my $self; - $self = [ @_ ]; - bless $self, $class; - return $self; -} - sub coincides_with { my $self = shift; my ($line) = @_; diff --git a/lib/Slic3r/Polygon.pm b/lib/Slic3r/Polygon.pm index b29f78dc2..33e4da409 100644 --- a/lib/Slic3r/Polygon.pm +++ b/lib/Slic3r/Polygon.pm @@ -5,16 +5,11 @@ use warnings; # a polygon is a closed polyline. use parent 'Slic3r::Polyline'; -use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges - polygon_remove_acute_vertices polygon_segment_having_point point_in_polygon +use Slic3r::Geometry qw(polygon_remove_parallel_continuous_edges + polygon_remove_acute_vertices polygon_segment_having_point PI X1 X2 Y1 Y2 epsilon); use Slic3r::Geometry::Clipper qw(JT_MITER); -sub lines { - my $self = shift; - return polygon_lines($self); -} - sub wkt { my $self = shift; return sprintf "POLYGON((%s))", join ',', map "$_->[0] $_->[1]", @$self; @@ -46,7 +41,9 @@ sub make_clockwise { sub merge_continuous_lines { my $self = shift; - polygon_remove_parallel_continuous_edges($self); + my $p = $self->pp; + polygon_remove_parallel_continuous_edges($p); + return (ref $self)->new(@$p); } sub remove_acute_vertices { @@ -120,16 +117,6 @@ sub is_valid { return @$self >= 3; } -sub split_at_index { - my $self = shift; - my ($index) = @_; - - return Slic3r::Polyline->new( - @$self[$index .. $#$self], - @$self[0 .. $index], - ); -} - sub split_at { my $self = shift; my ($point) = @_; @@ -147,11 +134,6 @@ sub split_at { return $self->split_at_index($i); } -sub split_at_first_point { - my $self = shift; - return $self->split_at_index(0); -} - # for cw polygons this will return convex points! sub concave_points { my $self = shift; @@ -161,7 +143,4 @@ sub concave_points { -1 .. ($#$self-1); } -package Slic3r::Polygon::XS; -use parent -norequire, qw(Slic3r::Polygon Slic3r::Polyline::XS); - 1; \ No newline at end of file diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 350c69096..637c39b42 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -2,53 +2,10 @@ package Slic3r::Polyline; use strict; use warnings; -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 qw(A B X Y X1 X2 Y1 Y2 polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices); use Slic3r::Geometry::Clipper qw(JT_SQUARE); use Storable qw(); -# the constructor accepts an array(ref) of points -sub new { - my $class = shift; - - my $self = [ map { ref($_) eq 'Slic3r::Point' ? $_ : Slic3r::Point->new(@$_) } @_ ]; - bless $self, $class; - $self; -} - -sub arrayref { $_[0] } -sub pp { - my $self = shift; - if (ref($self->[0]) eq 'Slic3r::Point') { - return [ map $_->arrayref, @$self ]; - } else { - return $self; - } -} - -sub clone { - Storable::dclone($_[0]) -} - -sub serialize { - my $self = shift; - return pack 'l*', map @$_, @$self; -} - -sub deserialize { - my $class = shift; - my ($s) = @_; - - my @v = unpack '(l2)*', $s; - return $class->new(map [ $v[2*$_], $v[2*$_+1] ], 0 .. int($#v/2)); -} - -sub lines { - my $self = shift; - return polyline_lines($self); -} - sub wkt { my $self = shift; return sprintf "LINESTRING((%s))", join ',', map "$_->[0] $_->[1]", @$self; @@ -72,11 +29,6 @@ sub simplify { return (ref $self)->new(@$simplified); } -sub reverse { - my $self = shift; - @$self = CORE::reverse @$self; -} - sub length { my $self = shift; return Boost::Geometry::Utils::linestring_length($self->pp); @@ -120,7 +72,6 @@ sub clip_with_expolygon { my ($expolygon) = @_; my $result = Boost::Geometry::Utils::polygon_multi_linestring_intersection($expolygon->pp, [$self->pp]); - bless $_, 'Slic3r::Polyline' for @$result; return @$result; } @@ -140,37 +91,6 @@ sub align_to_origin { return $self->translate(-$bb->x_min, -$bb->y_min); } -sub rotate { - my $self = shift; - my ($angle, $center) = @_; - $_->rotate($angle, $center) for @$self; - return $self; -} - -sub translate { - my $self = shift; - my ($x, $y) = @_; - $_->translate($x, $y) for @$self; - return $self; -} - -sub scale { - my $self = shift; - my ($factor) = @_; - $_->scale($factor) for @$self; - return $self; -} - -sub pop_back { - my $self = shift; - return pop @$self; -} - -sub append { - my $self = shift; - push @$self, @_; -} - # removes the given distance from the end of the polyline sub clip_end { my $self = shift; @@ -255,7 +175,4 @@ sub chained_path { return map $items_map{"$_"}, @paths; } -package Slic3r::Polyline::XS; -use parent qw(Slic3r::Polyline); - 1; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index f8336ec45..338118a2b 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -587,7 +587,7 @@ sub make_skirt { my @layer_points = ( (map @$_, map @$_, map @{$_->slices}, @layers), (map @$_, map @{$_->thin_walls}, map @{$_->regions}, @layers), - (map @{$_->unpack->polyline}, map @{$_->support_fills->paths}, grep $_->support_fills, @layers), + (map @{$_->polyline}, map @{$_->support_fills->paths}, grep $_->support_fills, @layers), ); push @points, map move_points($_, @layer_points), @{$self->objects->[$obj_idx]->copies}; } @@ -611,14 +611,13 @@ sub make_skirt { for (my $i = $Slic3r::Config->skirts; $i > 0; $i--) { $distance += scale $spacing; my ($loop) = Slic3r::Geometry::Clipper::offset([$convex_hull], $distance, 0.0001, JT_ROUND); - push @{$self->skirt}, Slic3r::ExtrusionLoop->pack( + push @{$self->skirt}, Slic3r::ExtrusionLoop->new( polygon => Slic3r::Polygon->new(@$loop), role => EXTR_ROLE_SKIRT, flow_spacing => $spacing, ); if ($Slic3r::Config->min_skirt_length > 0) { - bless $loop, 'Slic3r::Polygon'; $extruded_length[$extruder_idx] ||= 0; $extruders_e_per_mm[$extruder_idx] ||= $self->extruders->[$extruder_idx]->e_per_mm($spacing, $first_layer_height); $extruded_length[$extruder_idx] += unscale $loop->length * $extruders_e_per_mm[$extruder_idx]; @@ -648,7 +647,7 @@ sub make_brim { my @object_islands = ( (map $_->contour, @{$layer0->slices}), (map { $_->isa('Slic3r::Polygon') ? $_ : $_->grow($grow_distance) } map @{$_->thin_walls}, @{$layer0->regions}), - (map $_->unpack->polyline->grow($grow_distance), map @{$_->support_fills->paths}, grep $_->support_fills, $layer0), + (map $_->polyline->grow($grow_distance), map @{$_->support_fills->paths}, grep $_->support_fills, $layer0), ); foreach my $copy (@{$self->objects->[$obj_idx]->copies}) { push @islands, map $_->clone->translate(@$copy), @object_islands; @@ -658,7 +657,7 @@ sub make_brim { # if brim touches skirt, make it around skirt too # TODO: calculate actual skirt width (using each extruder's flow in multi-extruder setups) if ($Slic3r::Config->skirt_distance + (($Slic3r::Config->skirts - 1) * $flow->spacing) <= $Slic3r::Config->brim_width) { - push @islands, map $_->unpack->split_at_first_point->polyline->grow($grow_distance), @{$self->skirt}; + push @islands, map $_->split_at_first_point->polyline->grow($grow_distance), @{$self->skirt}; } my @loops = (); @@ -670,7 +669,7 @@ sub make_brim { push @loops, offset2(\@islands, ($i - 1.5) * $flow->scaled_spacing, +1.0 * $flow->scaled_spacing, undef, JT_SQUARE); } - @{$self->brim} = map Slic3r::ExtrusionLoop->pack( + @{$self->brim} = map Slic3r::ExtrusionLoop->new( polygon => Slic3r::Polygon->new(@$_), role => EXTR_ROLE_SKIRT, flow_spacing => $flow->spacing, diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 9ed110f4b..69b4bfc40 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -969,7 +969,6 @@ sub generate_support_material { my @paths = (); foreach my $expolygon (@$expolygons) { push @paths, - map $_->pack, map { $_->height($height); diff --git a/lib/Slic3r/Surface.pm b/lib/Slic3r/Surface.pm index c33e2924a..3cc4b2c26 100644 --- a/lib/Slic3r/Surface.pm +++ b/lib/Slic3r/Surface.pm @@ -45,7 +45,7 @@ sub simplify { sub p { my $self = shift; - return @{$self->expolygon}; + return @{$self->expolygon->pp}; } sub is_solid { diff --git a/t/clean_polylines.t b/t/clean_polylines.t index 3aabf4715..300025dd4 100644 --- a/t/clean_polylines.t +++ b/t/clean_polylines.t @@ -16,7 +16,7 @@ use Slic3r; [5,0], [10,0], [15,0], [20,0], [20,10], [20,30], [0,0], ); - $polygon->merge_continuous_lines; + $polygon = $polygon->merge_continuous_lines; is scalar(@$polygon), 3, 'merge_continuous_lines'; } @@ -69,7 +69,7 @@ use Slic3r; [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; + $polygon = $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; ]; my $polygon = Slic3r::Polygon->new(@$circle); - $polygon->merge_continuous_lines; + $polygon = $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/dynamic.t b/t/dynamic.t index c9cb95823..4f33e8138 100644 --- a/t/dynamic.t +++ b/t/dynamic.t @@ -81,7 +81,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ } is scalar @{$layerm->thin_fills} ? 1 : 0, $widths{$width}{gaps}, ($widths{$width}{gaps} ? 'gaps were filled' : 'no gaps detected'); # TODO: we should check the exact number of gaps, but we need a better medial axis algorithm - my @gaps = map $_->unpack, @{$layerm->thin_fills}; + my @gaps = map $_, @{$layerm->thin_fills}; if (@gaps) { ok +(!first { abs($_->flow_spacing - $widths{$width}{gap_flow_spacing}) > epsilon } @gaps), 'flow spacing was dynamically adjusted'; diff --git a/t/fill.t b/t/fill.t index 58c539ba9..ed0505c89 100644 --- a/t/fill.t +++ b/t/fill.t @@ -33,7 +33,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ } } { - my $expolygon = Slic3r::ExPolygon::XS->new([ scale_points [0,0], [50,0], [50,50], [0,50] ]); + my $expolygon = Slic3r::ExPolygon->new([ scale_points [0,0], [50,0], [50,50], [0,50] ]); my $filler = Slic3r::Fill::Rectilinear->new( bounding_box => $expolygon->bounding_box, ); @@ -72,24 +72,24 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ } { my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [ - map Slic3r::ExtrusionPath->pack(polyline => $_, role => 0), + map Slic3r::ExtrusionPath->new(polyline => $_, role => 0), Slic3r::Polyline->new([0,15], [0,18], [0,20]), Slic3r::Polyline->new([0,10], [0,8], [0,5]), ]); is_deeply - [ map $_->[Y], map @{$_->unpack->polyline}, $collection->chained_path(Slic3r::Point->new(0,30)) ], + [ map $_->[Y], map @{$_->polyline}, $collection->chained_path(Slic3r::Point->new(0,30)) ], [20, 18, 15, 10, 8, 5], 'chained path'; } { my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [ - map Slic3r::ExtrusionPath->pack(polyline => $_, role => 0), + map Slic3r::ExtrusionPath->new(polyline => $_, role => 0), Slic3r::Polyline->new([15,0], [10,0], [4,0]), Slic3r::Polyline->new([10,5], [15,5], [20,5]), ]); is_deeply - [ map $_->[X], map @{$_->unpack->polyline}, $collection->chained_path(Slic3r::Point->new(30,0)) ], + [ map $_->[X], map @{$_->polyline}, $collection->chained_path(Slic3r::Point->new(30,0)) ], [reverse 4, 10, 15, 10, 15, 20], 'chained path'; } diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index c49c6afa5..363a95b82 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -48,7 +48,7 @@ sub clone { my ($self, %args) = @_; return (ref $self)->_new( - $args{polygon} // $self->as_polygon, + $args{polygon} // $self->polygon, $args{role} // $self->role, $args{height} // $self->height, $args{flow_spacing} // $self->flow_spacing, @@ -75,7 +75,7 @@ sub clone { my ($self, %args) = @_; return (ref $self)->_new( - $args{polyline} // $self->as_polyline, + $args{polyline} // $self->polyline, $args{role} // $self->role, $args{height} // $self->height, $args{flow_spacing} // $self->flow_spacing, diff --git a/xs/t/07_extrusionpath.t b/xs/t/07_extrusionpath.t index 54a86dbb3..b84631dd8 100644 --- a/xs/t/07_extrusionpath.t +++ b/xs/t/07_extrusionpath.t @@ -16,11 +16,11 @@ my $path = Slic3r::ExtrusionPath->new( polyline => Slic3r::Polyline->new(@$points), role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, ); -isa_ok $path->as_polyline, 'Slic3r::Polyline', 'path polyline'; -is_deeply $path->as_polyline->pp, $points, 'path points roundtrip'; +isa_ok $path->polyline, 'Slic3r::Polyline', 'path polyline'; +is_deeply $path->polyline->pp, $points, 'path points roundtrip'; $path->reverse; -is_deeply $path->as_polyline->pp, [ reverse @$points ], 'reverse path'; +is_deeply $path->polyline->pp, [ reverse @$points ], 'reverse path'; $path->append([ 150, 150 ]); is scalar(@$path), 4, 'append to path'; diff --git a/xs/t/08_extrusionloop.t b/xs/t/08_extrusionloop.t index 8ae7237d3..9a7a087d2 100644 --- a/xs/t/08_extrusionloop.t +++ b/xs/t/08_extrusionloop.t @@ -17,8 +17,8 @@ my $loop = Slic3r::ExtrusionLoop->new( polygon => Slic3r::Polygon->new(@$square), role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, ); -isa_ok $loop->as_polygon, 'Slic3r::Polygon', 'loop polygon'; -is_deeply $loop->as_polygon->pp, $square, 'polygon points roundtrip'; +isa_ok $loop->polygon, 'Slic3r::Polygon', 'loop polygon'; +is_deeply $loop->polygon->pp, $square, 'polygon points roundtrip'; $loop = $loop->clone; @@ -28,10 +28,10 @@ is $loop->role, Slic3r::ExtrusionPath::EXTR_ROLE_FILL, 'modify role'; { my $path = $loop->split_at_first_point; - is_deeply $path->as_polyline->pp, $square, 'split_at_first_point'; + is_deeply $path->polyline->pp, $square, 'split_at_first_point'; is $path->role, $loop->role, 'role preserved after split'; - is_deeply $loop->split_at_index(2)->as_polyline->pp, [ @$square[2,3,0,1] ], 'split_at_index'; + is_deeply $loop->split_at_index(2)->polyline->pp, [ @$square[2,3,0,1] ], 'split_at_index'; } __END__ diff --git a/xs/xsp/ExtrusionLoop.xsp b/xs/xsp/ExtrusionLoop.xsp index e401efc76..22d6b37d1 100644 --- a/xs/xsp/ExtrusionLoop.xsp +++ b/xs/xsp/ExtrusionLoop.xsp @@ -11,10 +11,6 @@ %code{% RETVAL = THIS->polygon.to_SV(); %}; SV* pp() %code{% RETVAL = THIS->polygon.to_SV_pureperl(); %}; - Polygon* as_polygon() - %code{% const char* CLASS = "Slic3r::Polygon"; RETVAL = new Polygon(THIS->polygon); %}; - void set_polygon(SV* polygon_sv) - %code{% THIS->polygon.from_SV_check(polygon_sv); %}; ExtrusionPath* split_at_index(int index) %code{% const char* CLASS = "Slic3r::ExtrusionPath"; RETVAL = THIS->split_at_index(index); %}; ExtrusionPath* split_at_first_point() @@ -37,6 +33,18 @@ _new(CLASS, polygon_sv, role, height, flow_spacing) OUTPUT: RETVAL +Polygon* +ExtrusionLoop::polygon(...) + PREINIT: + const char* CLASS = "Slic3r::Polygon"; + CODE: + if (items > 1) { + THIS->polygon.from_SV_check( ST(1) ); + } + RETVAL = new Polygon(THIS->polygon); + OUTPUT: + RETVAL + ExtrusionRole ExtrusionLoop::role(...) CODE: diff --git a/xs/xsp/ExtrusionPath.xsp b/xs/xsp/ExtrusionPath.xsp index 4294cc98a..782530454 100644 --- a/xs/xsp/ExtrusionPath.xsp +++ b/xs/xsp/ExtrusionPath.xsp @@ -11,10 +11,6 @@ %code{% RETVAL = THIS->polyline.to_SV(); %}; SV* pp() %code{% RETVAL = THIS->polyline.to_SV_pureperl(); %}; - Polyline* as_polyline() - %code{% const char* CLASS = "Slic3r::Polyline"; RETVAL = new Polyline(THIS->polyline); %}; - void set_polyline(SV* polyline_sv) - %code{% THIS->polyline.from_SV_check(polyline_sv); %}; void pop_back() %code{% THIS->polyline.points.pop_back(); %}; void reverse(); @@ -36,6 +32,18 @@ _new(CLASS, polyline_sv, role, height, flow_spacing) OUTPUT: RETVAL +Polyline* +ExtrusionPath::polyline(...) + PREINIT: + const char* CLASS = "Slic3r::Polyline"; + CODE: + if (items > 1) { + THIS->polyline.from_SV_check( ST(1) ); + } + RETVAL = new Polyline(THIS->polyline); + OUTPUT: + RETVAL + ExtrusionRole ExtrusionPath::role(...) CODE: diff --git a/xs/xsp/Line.xsp b/xs/xsp/Line.xsp index b4ccb8d6f..f80b27d38 100644 --- a/xs/xsp/Line.xsp +++ b/xs/xsp/Line.xsp @@ -13,6 +13,10 @@ %code{% RETVAL = THIS->to_SV(); %}; SV* pp() %code{% RETVAL = THIS->to_SV_pureperl(); %}; + Point* a() + %code{% const char* CLASS = "Slic3r::Point"; RETVAL = new Point(THIS->a); %}; + Point* b() + %code{% const char* CLASS = "Slic3r::Point"; RETVAL = new Point(THIS->b); %}; void reverse(); %{ diff --git a/xs/xsp/Polygon.xsp b/xs/xsp/Polygon.xsp index 69ad45cb9..0c5e7a1a5 100644 --- a/xs/xsp/Polygon.xsp +++ b/xs/xsp/Polygon.xsp @@ -34,5 +34,14 @@ Polygon::new(...) OUTPUT: RETVAL +void +Polygon::rotate(angle, center_sv) + double angle; + SV* center_sv; + CODE: + Point center; + center.from_SV_check(center_sv); + THIS->rotate(angle, ¢er); + %} }; diff --git a/xs/xsp/Polyline.xsp b/xs/xsp/Polyline.xsp index acce6b560..a2ce8a329 100644 --- a/xs/xsp/Polyline.xsp +++ b/xs/xsp/Polyline.xsp @@ -13,6 +13,8 @@ %code{% RETVAL = THIS->to_SV(); %}; SV* pp() %code{% RETVAL = THIS->to_SV_pureperl(); %}; + void scale(double factor); + void translate(double x, double y); void pop_back() %code{% THIS->points.pop_back(); %}; void reverse(); @@ -40,5 +42,14 @@ Polyline::append(...) THIS->points.push_back(p); } +void +Polyline::rotate(angle, center_sv) + double angle; + SV* center_sv; + CODE: + Point center; + center.from_SV_check(center_sv); + THIS->rotate(angle, ¢er); + %} };