From 9af2a1c007ae185ef665efe80e576b1997d2e819 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 15 Jul 2013 20:31:43 +0200 Subject: [PATCH] Use XS Point everywhere --- lib/Slic3r.pm | 2 +- lib/Slic3r/ExPolygon.pm | 9 +++--- lib/Slic3r/ExtrusionPath.pm | 2 +- lib/Slic3r/Fill/Honeycomb.pm | 2 +- lib/Slic3r/Fill/Rectilinear.pm | 4 +-- lib/Slic3r/GCode.pm | 4 +-- lib/Slic3r/GUI/Plater.pm | 4 +-- lib/Slic3r/Geometry.pm | 2 +- lib/Slic3r/Geometry/Clipper.pm | 49 ++++++++++++++++------------- lib/Slic3r/Point.pm | 57 ---------------------------------- lib/Slic3r/Polygon.pm | 10 ++---- lib/Slic3r/Polyline.pm | 37 ++++++++++------------ lib/Slic3r/Print.pm | 4 +-- t/clean_polylines.t | 7 ++--- t/gcode.t | 2 +- t/geometry.t | 6 ++-- t/polyclip.t | 12 +++---- t/serialize.t | 33 -------------------- xs/lib/Slic3r/XS.pm | 2 +- xs/src/ExPolygon.hpp | 45 ++++++++++++++++++++------- xs/src/Point.hpp | 21 +++++++++---- xs/src/Polygon.hpp | 42 +++++-------------------- xs/src/Polyline.hpp | 29 +++++++++++------ xs/src/myinit.h | 6 ---- xs/t/03_point.t | 6 ++-- xs/t/04_expolygon.t | 36 ++++++++++++--------- xs/t/05_surface.t | 4 +-- xs/t/06_polygon.t | 7 +++-- xs/t/07_extrusionpath.t | 4 +-- xs/t/08_extrusionloop.t | 2 +- xs/xsp/ExPolygon.xsp | 19 +++++++++--- xs/xsp/ExPolygonCollection.xsp | 25 ++++++++++----- xs/xsp/ExtrusionLoop.xsp | 8 +++-- xs/xsp/ExtrusionPath.xsp | 8 +++-- xs/xsp/Point.xsp | 23 +++++--------- xs/xsp/Polygon.xsp | 4 ++- xs/xsp/Polyline.xsp | 4 ++- 37 files changed, 238 insertions(+), 303 deletions(-) delete mode 100644 t/serialize.t diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 782179da..fc6c6777 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -112,7 +112,7 @@ sub thread_cleanup { no warnings 'redefine'; *Slic3r::ExPolygon::Collection::DESTROY = sub {}; *Slic3r::ExPolygon::XS::DESTROY = sub {}; - *Slic3r::Point::XS::DESTROY = sub {}; + *Slic3r::Point::DESTROY = sub {}; *Slic3r::Surface::DESTROY = sub {}; } diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index 1d1793a7..12d66fdd 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -34,6 +34,7 @@ sub clone { # no-op for legacy with ::XS sub arrayref { $_[0] } +sub arrayref_pp { [ map $_->arrayref_pp, @{$_[0]} ] } sub contour { my $self = shift; @@ -107,7 +108,7 @@ sub noncollapsing_offset_ex { sub encloses_point { my $self = shift; my ($point) = @_; - return Boost::Geometry::Utils::point_covered_by_polygon($point, $self); + return Boost::Geometry::Utils::point_covered_by_polygon($point->arrayref, $self->arrayref_pp); } # A version of encloses_point for use when hole borders do not matter. @@ -116,7 +117,7 @@ sub encloses_point { sub encloses_point_quick { my $self = shift; my ($point) = @_; - return Boost::Geometry::Utils::point_within_polygon($point, $self->arrayref); + return Boost::Geometry::Utils::point_within_polygon($point->arrayref, $self->arrayref); } sub encloses_line { @@ -140,7 +141,7 @@ sub clip_line { my $self = shift; my ($line) = @_; # line must be a Slic3r::Line object - return Boost::Geometry::Utils::polygon_multi_linestring_intersection($self->arrayref, [$line]); + return Boost::Geometry::Utils::polygon_multi_linestring_intersection($self->arrayref_pp, [$line->arrayref_pp]); } sub simplify { @@ -149,7 +150,7 @@ sub simplify { # it would be nice to have a multilinestring_simplify method in B::G::U my @simplified = Slic3r::Geometry::Clipper::simplify_polygons( - [ map Boost::Geometry::Utils::linestring_simplify($_, $tolerance), @$self ], + [ map Boost::Geometry::Utils::linestring_simplify($_, $tolerance), @{$self->arrayref_pp} ], ); return @{ Slic3r::Geometry::Clipper::union_ex([ @simplified ]) }; } diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm index 620a1787..38606ad8 100644 --- a/lib/Slic3r/ExtrusionPath.pm +++ b/lib/Slic3r/ExtrusionPath.pm @@ -207,7 +207,7 @@ sub detect_arcs { my $rotation_angle = PI/2 * ($orientation eq 'ccw' ? -1 : 1); my $ray1 = Slic3r::Line->new($s1_mid, rotate_points($rotation_angle, $s1_mid, $points[$i+1])); my $last_ray = Slic3r::Line->new($last_mid, rotate_points($rotation_angle, $last_mid, $points[$last_j])); - $arc_center = $ray1->intersection($last_ray, 0) or next POINT; + $arc_center = $ray1->intersection($last_ray, 0) // next POINT; } my $arc = Slic3r::ExtrusionPath::Arc->new( diff --git a/lib/Slic3r/Fill/Honeycomb.pm b/lib/Slic3r/Fill/Honeycomb.pm index 714f82a5..6c1ca6df 100644 --- a/lib/Slic3r/Fill/Honeycomb.pm +++ b/lib/Slic3r/Fill/Honeycomb.pm @@ -90,7 +90,7 @@ sub fill_surface { # path is more straight @paths = map Slic3r::Polyline->new(@$_), @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection( - $surface->expolygon->arrayref, + $surface->expolygon->arrayref_pp, \@polygons, ) }; diff --git a/lib/Slic3r/Fill/Rectilinear.pm b/lib/Slic3r/Fill/Rectilinear.pm index b78b2a30..66170401 100644 --- a/lib/Slic3r/Fill/Rectilinear.pm +++ b/lib/Slic3r/Fill/Rectilinear.pm @@ -66,7 +66,7 @@ sub fill_surface { # clip paths against a slightly offsetted expolygon, so that the first and last paths # are kept even if the expolygon has vertical sides my @paths = @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection( - +($expolygon->offset_ex(scaled_epsilon))[0]->arrayref, # TODO: we should use all the resulting expolygons and clip the linestrings to a multipolygon object + +($expolygon->offset_ex(scaled_epsilon))[0]->arrayref_pp, # TODO: we should use all the resulting expolygons and clip the linestrings to a multipolygon object [ @{ $self->cache->{$cache_id} } ], ) }; @@ -92,7 +92,7 @@ sub fill_surface { # TODO: we should also check that both points are on a fill_boundary to avoid # connecting paths on the boundaries of internal regions - if ($can_connect->(@distance, $paths[-1][-1], $path->[0]) + if ($can_connect->(@distance) && $expolygon_off->encloses_line(Slic3r::Line->new($paths[-1][-1], $path->[0]), $tolerance)) { push @{$paths[-1]}, @$path; next; diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 80458179..13c87009 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -242,7 +242,7 @@ sub extrude_loop { my $first_segment = Slic3r::Line->new(@{$extrusion_path->polyline}[0,1]); my $distance = min(scale $extrusion_path->flow_spacing, $first_segment->length); my $point = Slic3r::Geometry::point_along_segment(@$first_segment, $distance); - bless $point, 'Slic3r::Point'; + $point = Slic3r::Point->new(@$point); $point->rotate($angle, $extrusion_path->polyline->[0]); # generate the travel move @@ -558,7 +558,7 @@ sub _G0_G1 { my ($gcode, $point, $z, $e, $comment) = @_; my $dec = $self->dec; - if ($point) { + if (defined $point) { $gcode .= sprintf " X%.${dec}f Y%.${dec}f", ($point->x * &Slic3r::SCALING_FACTOR) + $self->shift_x - $self->extruder->extruder_offset->[X], ($point->y * &Slic3r::SCALING_FACTOR) + $self->shift_y - $self->extruder->extruder_offset->[Y]; #** diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 8df97c65..b0bc0119 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -891,7 +891,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]} ])}); + my $convex_hull = Slic3r::Polygon->new(@{convex_hull([ map @{$_->contour->arrayref_pp}, @{$parent->{object_previews}->[-1][2]} ])}); 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}); @@ -1198,7 +1198,7 @@ sub _apply_transform { # the order of these transformations MUST be the same everywhere, including # in Slic3r::Print->add_model() my $result = $entity->clone; - $result->rotate(deg2rad($self->rotate), Slic3r::Point::XS->new(@{$self->bounding_box->center_2D})); + $result->rotate(deg2rad($self->rotate), $self->bounding_box->center_2D); $result->scale($self->scale); return $result; } diff --git a/lib/Slic3r/Geometry.pm b/lib/Slic3r/Geometry.pm index 7f992129..24856782 100644 --- a/lib/Slic3r/Geometry.pm +++ b/lib/Slic3r/Geometry.pm @@ -504,7 +504,7 @@ sub polygon_points_visibility { my $our_line = [ $p1, $p2 ]; foreach my $line (polygon_lines($polygon)) { - my $intersection = line_intersection($our_line, $line, 1) or next; + my $intersection = line_intersection($our_line, $line, 1) // next; next if grep points_coincide($intersection, $_), $p1, $p2; return 0; } diff --git a/lib/Slic3r/Geometry/Clipper.pm b/lib/Slic3r/Geometry/Clipper.pm index e8af9e4d..42f8cd22 100644 --- a/lib/Slic3r/Geometry/Clipper.pm +++ b/lib/Slic3r/Geometry/Clipper.pm @@ -15,13 +15,13 @@ our $clipper = Math::Clipper->new; sub safety_offset { my ($polygons, $factor) = @_; - return Math::Clipper::int_offset($polygons, $factor // (scale 1e-05), 100000, JT_MITER, 2); + return 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}}), - @{Math::Clipper::ex_int_offset($polygons, $factor // (scale 1e-05), 100000, JT_MITER, 2)}; + @{Math::Clipper::ex_int_offset(_convert($polygons), $factor // (scale 1e-05), 100000, JT_MITER, 2)}; } sub offset { @@ -30,8 +30,7 @@ sub offset { $joinType //= JT_MITER; $miterLimit //= 3; - $polygons = $polygons->arrayref if ref $polygons eq 'Slic3r::ExPolygon::XS'; - my $offsets = Math::Clipper::int_offset($polygons, $distance, $scale, $joinType, $miterLimit); + my $offsets = Math::Clipper::int_offset(_convert($polygons), $distance, $scale, $joinType, $miterLimit); return @$offsets; } @@ -41,7 +40,7 @@ sub offset2 { $joinType //= JT_MITER; $miterLimit //= 3; - my $offsets = Math::Clipper::int_offset2($polygons, $distance1, $distance2, $scale, $joinType, $miterLimit); + my $offsets = Math::Clipper::int_offset2(_convert($polygons), $distance1, $distance2, $scale, $joinType, $miterLimit); return @$offsets; } @@ -51,8 +50,7 @@ sub offset_ex { $joinType //= JT_MITER; $miterLimit //= 3; - $polygons = $polygons->arrayref if ref $polygons eq 'Slic3r::ExPolygon::XS'; - my $offsets = Math::Clipper::ex_int_offset($polygons, $distance, $scale, $joinType, $miterLimit); + my $offsets = Math::Clipper::ex_int_offset(_convert($polygons), $distance, $scale, $joinType, $miterLimit); return map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), @$offsets; } @@ -62,7 +60,7 @@ sub offset2_ex { $joinType //= JT_MITER; $miterLimit //= 3; - my $offsets = Math::Clipper::ex_int_offset2($polygons, $delta1, $delta2, $scale, $joinType, $miterLimit); + my $offsets = Math::Clipper::ex_int_offset2(_convert($polygons), $delta1, $delta2, $scale, $joinType, $miterLimit); return map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), @$offsets; } @@ -70,8 +68,8 @@ sub diff_ex { my ($subject, $clip, $safety_offset) = @_; $clipper->clear; - $clipper->add_subject_polygons($subject); - $clipper->add_clip_polygons($safety_offset ? safety_offset($clip) : $clip); + $clipper->add_subject_polygons(_convert($subject)); + $clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip)); return [ map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), @{ $clipper->ex_execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) }, @@ -82,8 +80,8 @@ sub diff { my ($subject, $clip, $safety_offset) = @_; $clipper->clear; - $clipper->add_subject_polygons($subject); - $clipper->add_clip_polygons($safety_offset ? safety_offset($clip) : $clip); + $clipper->add_subject_polygons(_convert($subject)); + $clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip)); return [ map Slic3r::Polygon->new(@$_), @{ $clipper->execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) }, @@ -95,7 +93,7 @@ sub union_ex { $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($polygons) : $polygons); + $clipper->add_subject_polygons($safety_offset ? safety_offset(_convert($polygons)) : _convert($polygons)); return [ map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), @{ $clipper->ex_execute(CT_UNION, $jointype, $jointype) }, @@ -106,7 +104,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($polygons) : $polygons); + $clipper->add_subject_polygons($safety_offset ? safety_offset(_convert($polygons)) : _convert($polygons)); return $clipper->pt_execute(CT_UNION, $jointype, $jointype); } @@ -114,8 +112,8 @@ sub intersection_ex { my ($subject, $clip, $jointype, $safety_offset) = @_; $jointype = PFT_NONZERO unless defined $jointype; $clipper->clear; - $clipper->add_subject_polygons($subject); - $clipper->add_clip_polygons($safety_offset ? safety_offset($clip) : $clip); + $clipper->add_subject_polygons(_convert($subject)); + $clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip)); return [ map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), @{ $clipper->ex_execute(CT_INTERSECTION, $jointype, $jointype) }, @@ -126,8 +124,8 @@ sub intersection { my ($subject, $clip, $jointype, $safety_offset) = @_; $jointype = PFT_NONZERO unless defined $jointype; $clipper->clear; - $clipper->add_subject_polygons($subject); - $clipper->add_clip_polygons($safety_offset ? safety_offset($clip) : $clip); + $clipper->add_subject_polygons(_convert($subject)); + $clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip)); return [ map Slic3r::Polygon->new(@$_), @{ $clipper->execute(CT_INTERSECTION, $jointype, $jointype) }, @@ -138,8 +136,8 @@ sub xor_ex { my ($subject, $clip, $jointype) = @_; $jointype = PFT_NONZERO unless defined $jointype; $clipper->clear; - $clipper->add_subject_polygons($subject); - $clipper->add_clip_polygons($clip); + $clipper->add_subject_polygons(_convert($subject)); + $clipper->add_clip_polygons(_convert($clip)); return [ map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), @{ $clipper->ex_execute(CT_XOR, $jointype, $jointype) }, @@ -153,12 +151,12 @@ sub collapse_ex { sub simplify_polygon { my ($polygon, $pft) = @_; - return @{ Math::Clipper::simplify_polygon($polygon, $pft // PFT_NONZERO) }; + return @{ Math::Clipper::simplify_polygon(_convert([$polygon])->[0], $pft // PFT_NONZERO) }; } sub simplify_polygons { my ($polygons, $pft) = @_; - return @{ Math::Clipper::simplify_polygons($polygons, $pft // PFT_NONZERO) }; + return @{ Math::Clipper::simplify_polygons(_convert($polygons), $pft // PFT_NONZERO) }; } sub traverse_pt { @@ -179,4 +177,11 @@ sub traverse_pt { return @polygons; } +sub _convert { + my $polygons = shift; + $polygons = $polygons->arrayref_pp if ref $polygons eq 'Slic3r::ExPolygon::XS'; + $polygons = [ map $_->arrayref_pp, @$polygons ] if @$polygons && ref $polygons->[0] eq 'Slic3r::Polygon'; + return $polygons; +} + 1; diff --git a/lib/Slic3r/Point.pm b/lib/Slic3r/Point.pm index f8567f3e..0f7354e2 100644 --- a/lib/Slic3r/Point.pm +++ b/lib/Slic3r/Point.pm @@ -2,67 +2,10 @@ package Slic3r::Point; use strict; use warnings; -use Storable qw(); - -sub new { - my $class = shift; - my $self; - if (@_ == 2) { - $self = [@_]; - } elsif ((ref $_[0]) =~ 'ARRAY' || (ref $_[0]) =~ /Slic3r::Point/) { - $self = [@{$_[0]}]; - } elsif ($_[0]->isa(__PACKAGE__)) { - return $_[0]; - } else { - die "Invalid arguments for ${class}->new"; - } - bless $self, $class; - return $self; -} - -sub clone { - return Slic3r::Point::XS->new(@{$_[0]}); -} - -sub threadsafe_clone { - my $self = shift; - return (ref $self)->new(@$self); -} - -sub coincides_with { - my $self = shift; - my ($point) = @_; - return Slic3r::Geometry::points_coincide($self, $point); -} - sub distance_to { my $self = shift; my ($point) = @_; return Slic3r::Geometry::distance_between_points($self, $point); } -sub scale { - my $self = shift; - my ($factor) = @_; - $_ *= $factor for @$self; - $self; -} - -sub rotate { - my $self = shift; - my ($angle, $center) = @_; - @$self = @{ +(Slic3r::Geometry::rotate_points($angle, $center, $self))[0] }; - $self; -} - -sub translate { - my $self = shift; - my ($x, $y) = @_; - @$self = @{ +(Slic3r::Geometry::move_points([$x, $y], $self))[0] }; - $self; -} - -sub x { $_[0]->[0] } -sub y { $_[0]->[1] } - 1; diff --git a/lib/Slic3r/Polygon.pm b/lib/Slic3r/Polygon.pm index 252cd1c1..b99a1ce8 100644 --- a/lib/Slic3r/Polygon.pm +++ b/lib/Slic3r/Polygon.pm @@ -10,8 +10,6 @@ use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges PI X1 X2 Y1 Y2 epsilon); use Slic3r::Geometry::Clipper qw(JT_MITER); -sub arrayref { $_[0] } - sub lines { my $self = shift; return polygon_lines($self); @@ -24,7 +22,7 @@ sub wkt { sub is_counter_clockwise { my $self = shift; - return Slic3r::Geometry::Clipper::is_counter_clockwise($self->arrayref); + return Slic3r::Geometry::Clipper::is_counter_clockwise($self->arrayref_pp); } sub make_counter_clockwise { @@ -49,24 +47,22 @@ 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 encloses_point { my $self = shift; my ($point) = @_; - return Boost::Geometry::Utils::point_covered_by_polygon($point, [$self]); + return Boost::Geometry::Utils::point_covered_by_polygon($point->arrayref, [$self->arrayref_pp]); } sub area { my $self = shift; - return Slic3r::Geometry::Clipper::area($self); + return Slic3r::Geometry::Clipper::area($self->arrayref_pp); } sub grow { diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 08950355..a24c5678 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -12,19 +12,25 @@ use Storable qw(); sub new { my $class = shift; - my $self = [ @_ ]; + my $self = [ map { ref($_) eq 'Slic3r::Point' ? $_ : Slic3r::Point->new(@$_) } @_ ]; bless $self, $class; - bless $_, 'Slic3r::Point' for @$self; $self; } +sub arrayref { $_[0] } +sub arrayref_pp { + my $self = shift; + if (ref($self->[0]) eq 'Slic3r::Point') { + return [ map $_->arrayref, @$self ]; + } else { + return $self; + } +} + sub clone { Storable::dclone($_[0]) } -# compability with ::XS -sub arrayref { $_[0] } - sub serialize { my $self = shift; return pack 'l*', map @$_, @$self; @@ -62,7 +68,7 @@ sub simplify { my $self = shift; my $tolerance = shift || 10; - my $simplified = Boost::Geometry::Utils::linestring_simplify($self->arrayref, $tolerance); + my $simplified = Boost::Geometry::Utils::linestring_simplify($self->arrayref_pp, $tolerance); return (ref $self)->new(@$simplified); } @@ -73,7 +79,7 @@ sub reverse { sub length { my $self = shift; - return Boost::Geometry::Utils::linestring_length($self->arrayref); + return Boost::Geometry::Utils::linestring_length($self->arrayref_pp); } sub grow { @@ -113,9 +119,8 @@ sub clip_with_expolygon { my $self = shift; my ($expolygon) = @_; - my $result = Boost::Geometry::Utils::polygon_multi_linestring_intersection($expolygon->arrayref, [$self->arrayref]); + my $result = Boost::Geometry::Utils::polygon_multi_linestring_intersection($expolygon->arrayref_pp, [$self->arrayref_pp]); bless $_, 'Slic3r::Polyline' for @$result; - bless $_, 'Slic3r::Point' for map @$_, @$result; return @$result; } @@ -138,29 +143,21 @@ sub align_to_origin { sub rotate { my $self = shift; my ($angle, $center) = @_; - @$self = Slic3r::Geometry::rotate_points($angle, $center, @$self); - bless $_, 'Slic3r::Point' for @$self; + $_->rotate($angle, $center) for @$self; return $self; } sub translate { my $self = shift; my ($x, $y) = @_; - @$self = Slic3r::Geometry::move_points([$x, $y], @$self); - bless $_, 'Slic3r::Point' for @$self; + $_->translate($x, $y) for @$self; return $self; } sub scale { my $self = shift; my ($factor) = @_; - - # transform point coordinates - if ($factor != 1) { - foreach my $point (@$self) { - $point->[$_] *= $factor for X,Y; - } - } + $_->scale($factor) for @$self; return $self; } diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 3088b67e..a1f214d0 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -594,7 +594,7 @@ sub make_skirt { return if @points < 3; # at least three points required for a convex hull # find out convex hull - my $convex_hull = convex_hull(\@points); + my $convex_hull = convex_hull([ map $_->arrayref, @points ]); my @extruded_length = (); # for each extruder @@ -763,7 +763,7 @@ sub write_gcode { my @islands = (); foreach my $obj_idx (0 .. $#{$self->objects}) { my $convex_hull = convex_hull([ - map @{$_->contour}, map @{$_->slices}, @{$self->objects->[$obj_idx]->layers}, + map @{$_->contour->arrayref_pp}, map @{$_->slices}, @{$self->objects->[$obj_idx]->layers}, ]); # discard layers only containing thin walls (offset would fail on an empty polygon) if (@$convex_hull) { diff --git a/t/clean_polylines.t b/t/clean_polylines.t index 17c4ad6a..092b0792 100644 --- a/t/clean_polylines.t +++ b/t/clean_polylines.t @@ -25,16 +25,15 @@ use Slic3r; [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'; + is_deeply $polyline->arrayref_pp, [ [0, 0], [2, 0], [2, 2], [0, 2], [0, 0] ], 'Douglas-Peucker'; } { my $polyline = Slic3r::Polyline->new( - [0,0],[0.5,0.5],[1,0],[1.25,-0.25],[1.5,.5], + [0,0], [50,50], [100,0], [125,-25], [150,50], ); - $polyline->scale(100); $polyline = $polyline->simplify(25); - is_deeply $polyline, [ [0, 0], [50, 50], [125, -25], [150, 50] ], 'Douglas-Peucker'; + is_deeply $polyline->arrayref_pp, [ [0, 0], [50, 50], [125, -25], [150, 50] ], 'Douglas-Peucker'; } { diff --git a/t/gcode.t b/t/gcode.t index 61c940fa..0cdf4711 100644 --- a/t/gcode.t +++ b/t/gcode.t @@ -16,7 +16,7 @@ use Slic3r::Geometry qw(scale); layer_count => 1, ); $gcodegen->set_shift(10, 10); - is_deeply $gcodegen->last_pos, [scale -10, scale -10], 'last_pos is shifted correctly'; + is_deeply $gcodegen->last_pos->arrayref, [scale -10, scale -10], 'last_pos is shifted correctly'; } __END__ diff --git a/t/geometry.t b/t/geometry.t index edbe7262..e96ec729 100644 --- a/t/geometry.t +++ b/t/geometry.t @@ -18,7 +18,7 @@ use Slic3r::Geometry qw(PI polyline_remove_parallel_continuous_edges my $line1 = [ [5, 15], [30, 15] ]; my $line2 = [ [10, 20], [10, 10] ]; -is_deeply Slic3r::Geometry::line_intersection($line1, $line2, 1), [10, 15], 'line_intersection'; +is_deeply Slic3r::Geometry::line_intersection($line1, $line2, 1)->arrayref, [10, 15], 'line_intersection'; #========================================================== @@ -158,7 +158,7 @@ is Slic3r::Geometry::can_connect_points(@$points, $polygons), 0, 'can_connect_po { my $polyline = Slic3r::Polyline->new([0, 0], [10, 0], [20, 0]); - is_deeply [$polyline->lines], [ + is_deeply [ map $_->arrayref_pp, $polyline->lines ], [ [ [0, 0], [10, 0] ], [ [10, 0], [20, 0] ], ], 'polyline_lines'; @@ -170,7 +170,7 @@ is Slic3r::Geometry::can_connect_points(@$points, $polygons), 0, 'can_connect_po my $polyline = Slic3r::Polygon->new([0, 0], [10, 0], [5, 5]); my $result = $polyline->split_at_index(1); is ref($result), 'Slic3r::Polyline', 'split_at_index returns polyline'; - is_deeply $result, [ [10, 0], [5, 5], [0, 0], [10, 0] ], 'split_at_index'; + is_deeply $result->arrayref_pp, [ [10, 0], [5, 5], [0, 0], [10, 0] ], 'split_at_index'; } #========================================================== diff --git a/t/polyclip.t b/t/polyclip.t index 509a353d..4882892b 100644 --- a/t/polyclip.t +++ b/t/polyclip.t @@ -60,10 +60,10 @@ is_deeply $intersection, [ [120, 120], [180, 160] ], 'internal lines are preserv [160, 140], ]; my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square); - is $expolygon->encloses_point([100, 100]), 1, 'corner point is recognized'; - is $expolygon->encloses_point([100, 180]), 1, 'point on contour is recognized'; - is $expolygon->encloses_point([140, 150]), 1, 'point on hole contour is recognized'; - is $expolygon->encloses_point([140, 140]), 1, 'point on hole corner is recognized'; + is $expolygon->encloses_point(Slic3r::Point->new(100, 100)), 1, 'corner point is recognized'; + is $expolygon->encloses_point(Slic3r::Point->new(100, 180)), 1, 'point on contour is recognized'; + is $expolygon->encloses_point(Slic3r::Point->new(140, 150)), 1, 'point on hole contour is recognized'; + is $expolygon->encloses_point(Slic3r::Point->new(140, 140)), 1, 'point on hole corner is recognized'; { my $intersections = $expolygon->clip_line(Slic3r::Line->new([150,180], [150,150])); is_deeply $intersections, [ @@ -144,8 +144,8 @@ is_deeply $intersection, [ [120, 120], [180, 160] ], 'internal lines are preserv my $intersections = $expolygon->clip_line($line); is_deeply $intersections, [ - [ [152.742, 288.086660915295], [152.742, 215.178843238354], ], - [ [152.742, 108.087506777797], [152.742, 35.1664774739315] ], + [ [152.742, 287.908315789474], [152.742, 214.522], ], + [ [152.742, 107.478], [152.742, 35] ], ], 'line is clipped to square with hole'; } diff --git a/t/serialize.t b/t/serialize.t deleted file mode 100644 index 0d93cd52..00000000 --- a/t/serialize.t +++ /dev/null @@ -1,33 +0,0 @@ -use Test::More; -use strict; -use warnings; - -plan tests => 2; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; -} - -use Slic3r; -use Slic3r::Geometry qw(scale); - -#========================================================== - -{ - my $points = [ - [226,701], [260,681], [109,420], [149,397], [300,658], [308,654], - ]; - foreach my $point (@$points) { - @$point = map scale $_, @$point; - } - 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'; - is_deeply $deserialized, $points, 'deserialized points coordinates'; -} - -#========================================================== - -__END__ diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index cd115a37..c34f1a78 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -7,7 +7,7 @@ our $VERSION = '0.01'; use XSLoader; XSLoader::load(__PACKAGE__, $VERSION); -package Slic3r::Point::XS; +package Slic3r::Point; use overload '@{}' => sub { $_[0]->arrayref }; diff --git a/xs/src/ExPolygon.hpp b/xs/src/ExPolygon.hpp index b339bfdc..26608b12 100644 --- a/xs/src/ExPolygon.hpp +++ b/xs/src/ExPolygon.hpp @@ -9,6 +9,7 @@ extern "C" { } #include "Polygon.hpp" +#include namespace Slic3r { @@ -17,7 +18,8 @@ class ExPolygon public: Polygon contour; Polygons holes; - SV* arrayref(); + bool in_collection; + SV* to_SV(bool pureperl = false, bool pureperl_children = false); void scale(double factor); void translate(double x, double y); void rotate(double angle, Point* center); @@ -52,6 +54,25 @@ ExPolygon::rotate(double angle, Point* center) } } +SV* +ExPolygon::to_SV(bool pureperl, bool pureperl_children) +{ + if (pureperl) { + const unsigned int num_holes = this->holes.size(); + AV* av = newAV(); + av_extend(av, num_holes); // -1 +1 + av_store(av, 0, this->contour.to_SV(pureperl_children, pureperl_children)); + for (unsigned int i = 0; i < num_holes; i++) { + av_store(av, i+1, this->holes[i].to_SV(pureperl_children, pureperl_children)); + } + return sv_bless(newRV_noinc((SV*)av), gv_stashpv("Slic3r::ExPolygon", GV_ADD)); + } else { + SV* sv = newSV(0); + sv_setref_pv( sv, "Slic3r::ExPolygon::XS", this ); + return sv; + } +} + void perl2expolygon(SV* expoly_sv, ExPolygon& expoly) { @@ -60,23 +81,23 @@ perl2expolygon(SV* expoly_sv, ExPolygon& expoly) expoly.holes.resize(num_polygons-1); SV** polygon_sv = av_fetch(expoly_av, 0, 0); - perl2polygon(*polygon_sv, expoly.contour); + expoly.contour.from_SV(*polygon_sv); for (unsigned int i = 0; i < num_polygons-1; i++) { polygon_sv = av_fetch(expoly_av, i+1, 0); - perl2polygon(*polygon_sv, expoly.holes[i]); + expoly.holes[i].from_SV(*polygon_sv); } } -SV* -expolygon2perl(ExPolygon& expoly) { - const unsigned int num_holes = expoly.holes.size(); - AV* av = newAV(); - av_extend(av, num_holes); // -1 +1 - av_store(av, 0, polygon2perl(expoly.contour)); - for (unsigned int i = 0; i < num_holes; i++) { - av_store(av, i+1, polygon2perl(expoly.holes[i])); +void +perl2expolygon_check(SV* expoly_sv, ExPolygon& expoly) +{ + if (sv_isobject(expoly_sv) && (SvTYPE(SvRV(expoly_sv)) == SVt_PVMG)) { + // a XS ExPolygon was supplied + expoly = *(ExPolygon *)SvIV((SV*)SvRV( expoly_sv )); + } else { + // a Perl arrayref was supplied + perl2expolygon(expoly_sv, expoly); } - return sv_bless(newRV_noinc((SV*)av), gv_stashpv("Slic3r::ExPolygon", GV_ADD)); } } diff --git a/xs/src/Point.hpp b/xs/src/Point.hpp index 9288d98f..78e60003 100644 --- a/xs/src/Point.hpp +++ b/xs/src/Point.hpp @@ -8,6 +8,7 @@ extern "C" { #include "ppport.h" } +#include #include namespace Slic3r { @@ -17,7 +18,8 @@ class Point public: long x; long y; - Point(long _x = 0, long _y = 0): x(_x), y(_y) {}; + explicit Point(long _x = 0, long _y = 0): x(_x), y(_y) {}; + SV* to_SV(bool pureperl = false); void scale(double factor); void translate(double x, double y); void rotate(double angle, Point* center); @@ -56,11 +58,18 @@ Point::coincides_with(Point* point) } SV* -point2perl(Point& point) { - AV* av = newAV(); - av_fill(av, 1); - av_store_point_xy(av, point.x, point.y); - return sv_bless(newRV_noinc((SV*)av), gv_stashpv("Slic3r::Point", GV_ADD)); +Point::to_SV(bool pureperl) { + if (pureperl) { + AV* av = newAV(); + av_fill(av, 1); + av_store(av, 0, newSViv(this->x)); + av_store(av, 1, newSViv(this->y)); + return newRV_noinc((SV*)av); + } else { + SV* sv = newSV(0); + sv_setref_pv( sv, "Slic3r::Point", new Point(*this) ); + return sv; + } } void diff --git a/xs/src/Polygon.hpp b/xs/src/Polygon.hpp index 6d31796f..a52674b7 100644 --- a/xs/src/Polygon.hpp +++ b/xs/src/Polygon.hpp @@ -8,48 +8,20 @@ extern "C" { #include "ppport.h" } +#include #include "Polyline.hpp" namespace Slic3r { -class Polygon : public Polyline {}; +class Polygon : public Polyline { + protected: + char* perl_class() { + return (char*)"Slic3r::Polygon"; + } +}; typedef std::vector Polygons; -void -perl2polygon(SV* poly_sv, Polygon& poly) -{ - AV* poly_av = (AV*)SvRV(poly_sv); - const unsigned int num_points = av_len(poly_av)+1; - poly.points.resize(num_points); - - for (unsigned int i = 0; i < num_points; i++) { - SV** point_sv = av_fetch(poly_av, i, 0); - perl2point(*point_sv, poly.points[i]); - } -} - -void -perl2polygon_check(SV* poly_sv, Polygon& poly) -{ - if (sv_isobject(poly_sv) && (SvTYPE(SvRV(poly_sv)) == SVt_PVMG)) { - poly = *(Polygon*)SvIV((SV*)SvRV( poly_sv )); - } else { - perl2polygon(poly_sv, poly); - } -} - -SV* -polygon2perl(Polygon& poly) { - const unsigned int num_points = poly.points.size(); - AV* av = newAV(); - av_extend(av, num_points-1); - for (unsigned int i = 0; i < num_points; i++) { - av_store(av, i, point2perl(poly.points[i])); - } - return sv_bless(newRV_noinc((SV*)av), gv_stashpv("Slic3r::Polygon", GV_ADD)); -} - } #endif diff --git a/xs/src/Polyline.hpp b/xs/src/Polyline.hpp index e3496158..6e243f89 100644 --- a/xs/src/Polyline.hpp +++ b/xs/src/Polyline.hpp @@ -10,6 +10,8 @@ extern "C" { #include "Point.hpp" #include +#include +#include namespace Slic3r { @@ -17,10 +19,17 @@ class Polyline { public: Points points; + void from_SV(SV* poly_sv); + void from_SV_check(SV* poly_sv); + SV* to_SV(bool pureperl = false, bool pureperl_children = false); void scale(double factor); void translate(double x, double y); void rotate(double angle, Point* center); void reverse(); + protected: + virtual char* perl_class() { + return (char*)"Slic3r::Polyline"; + } }; typedef std::vector Polylines; @@ -56,37 +65,37 @@ Polyline::reverse() } void -perl2polyline(SV* poly_sv, Polyline& poly) +Polyline::from_SV(SV* poly_sv) { AV* poly_av = (AV*)SvRV(poly_sv); const unsigned int num_points = av_len(poly_av)+1; - poly.points.resize(num_points); + this->points.resize(num_points); for (unsigned int i = 0; i < num_points; i++) { SV** point_sv = av_fetch(poly_av, i, 0); - perl2point(*point_sv, poly.points[i]); + perl2point_check(*point_sv, this->points[i]); } } void -perl2polyline_check(SV* poly_sv, Polyline& poly) +Polyline::from_SV_check(SV* poly_sv) { if (sv_isobject(poly_sv) && (SvTYPE(SvRV(poly_sv)) == SVt_PVMG)) { - poly = *(Polyline*)SvIV((SV*)SvRV( poly_sv )); + *this = *(Polyline*)SvIV((SV*)SvRV( poly_sv )); } else { - perl2polyline(poly_sv, poly); + this->from_SV(poly_sv); } } SV* -polyline2perl(Polyline& poly) { - const unsigned int num_points = poly.points.size(); +Polyline::to_SV(bool pureperl, bool pureperl_children) { + const unsigned int num_points = this->points.size(); AV* av = newAV(); av_extend(av, num_points-1); for (unsigned int i = 0; i < num_points; i++) { - av_store(av, i, point2perl(poly.points[i])); + av_store(av, i, this->points[i].to_SV(pureperl_children)); } - return sv_bless(newRV_noinc((SV*)av), gv_stashpv("Slic3r::Polyline", GV_ADD)); + return sv_bless(newRV_noinc((SV*)av), gv_stashpv(this->perl_class(), GV_ADD)); } } diff --git a/xs/src/myinit.h b/xs/src/myinit.h index 633fe758..641099a4 100644 --- a/xs/src/myinit.h +++ b/xs/src/myinit.h @@ -1,13 +1,7 @@ #ifndef _myinit_h_ #define _myinit_h_ -#include - namespace Slic3r {} using namespace Slic3r; -#define av_store_point_xy(AV, X, Y) \ - av_store(AV, 0, newSViv(X)); \ - av_store(AV, 1, newSViv(Y)) - #endif diff --git a/xs/t/03_point.t b/xs/t/03_point.t index c40641c4..a6e18827 100644 --- a/xs/t/03_point.t +++ b/xs/t/03_point.t @@ -4,13 +4,11 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 6; +use Test::More tests => 5; -my $point = Slic3r::Point::XS->new(10, 15); +my $point = Slic3r::Point->new(10, 15); is_deeply [ @$point ], [10, 15], 'point roundtrip'; -isa_ok $point->arrayref, 'Slic3r::Point', 'Perl point is blessed'; - my $point2 = $point->clone; $point2->scale(2); is_deeply [ @$point2 ], [20, 30], 'scale'; diff --git a/xs/t/04_expolygon.t b/xs/t/04_expolygon.t index b8e920e4..fb729536 100644 --- a/xs/t/04_expolygon.t +++ b/xs/t/04_expolygon.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 13; +use Test::More tests => 15; use constant PI => 4 * atan2(1, 1); @@ -22,15 +22,19 @@ my $hole_in_square = [ # cw ]; my $expolygon = Slic3r::ExPolygon::XS->new($square, $hole_in_square); -is_deeply [ @$expolygon ], [$square, $hole_in_square], 'expolygon roundtrip'; +is_deeply [ @{$expolygon->arrayref_pp} ], [$square, $hole_in_square], 'expolygon roundtrip'; -isa_ok $expolygon->arrayref, 'Slic3r::ExPolygon', 'Perl expolygon is blessed'; -isa_ok $expolygon->[0], 'Slic3r::Polygon', 'Perl polygons are blessed'; -isa_ok $expolygon->[0][0], 'Slic3r::Point', 'Perl polygon points are blessed'; +my $arrayref = $expolygon->arrayref; +isa_ok $arrayref, 'Slic3r::ExPolygon', 'Perl expolygon is blessed'; + +my $arrayref_pp = $expolygon->arrayref_pp; +isa_ok $arrayref_pp, 'Slic3r::ExPolygon', 'Perl expolygon is blessed'; +isa_ok $arrayref_pp->[0], 'Slic3r::Polygon', 'Perl polygons are blessed'; +isnt ref($arrayref_pp->[0][0]), 'Slic3r::Point', 'Perl polygon points are not blessed'; { my $clone = $expolygon->clone; - is_deeply [ @$clone ], [$square, $hole_in_square], 'clone'; + is_deeply [ @{$clone->arrayref_pp} ], [$square, $hole_in_square], 'clone'; # The following tests implicitely check that modifying clones # does not modify the original one. } @@ -38,7 +42,7 @@ isa_ok $expolygon->[0][0], 'Slic3r::Point', 'Perl polygon points are blessed'; { my $expolygon2 = $expolygon->clone; $expolygon2->scale(2.5); - is_deeply [ @$expolygon2 ], [ + is_deeply [ @{$expolygon2->arrayref_pp} ], [ [map [ 2.5*$_->[0], 2.5*$_->[1] ], @$square], [map [ 2.5*$_->[0], 2.5*$_->[1] ], @$hole_in_square] ], 'scale'; @@ -47,7 +51,7 @@ isa_ok $expolygon->[0][0], 'Slic3r::Point', 'Perl polygon points are blessed'; { my $expolygon2 = $expolygon->clone; $expolygon2->translate(10, -5); - is_deeply [ @$expolygon2 ], [ + is_deeply [ @{$expolygon2->arrayref_pp} ], [ [map [ $_->[0]+10, $_->[1]-5 ], @$square], [map [ $_->[0]+10, $_->[1]-5 ], @$hole_in_square] ], 'translate'; @@ -55,17 +59,17 @@ isa_ok $expolygon->[0][0], 'Slic3r::Point', 'Perl polygon points are blessed'; { my $expolygon2 = $expolygon->clone; - $expolygon2->rotate(PI/2, Slic3r::Point::XS->new(150,150)); - is_deeply [ @$expolygon2 ], [ + $expolygon2->rotate(PI/2, Slic3r::Point->new(150,150)); + is_deeply [ @{$expolygon2->arrayref_pp} ], [ [ @$square[1,2,3,0] ], [ @$hole_in_square[3,0,1,2] ] - ], 'rotate around Point::XS'; + ], 'rotate around Point'; } { my $expolygon2 = $expolygon->clone; $expolygon2->rotate(PI/2, [150,150]); - is_deeply [ @$expolygon2 ], [ + is_deeply [ @{$expolygon2->arrayref_pp} ], [ [ @$square[1,2,3,0] ], [ @$hole_in_square[3,0,1,2] ] ], 'rotate around pure-Perl Point'; @@ -74,17 +78,19 @@ isa_ok $expolygon->[0][0], 'Slic3r::Point', 'Perl polygon points are blessed'; { my $expolygon2 = $expolygon->clone; $expolygon2->scale(2); - my $collection = Slic3r::ExPolygon::Collection->new($expolygon->arrayref, $expolygon2->arrayref); - is_deeply [ @$collection ], [ $expolygon->arrayref, $expolygon2->arrayref ], + my $collection = Slic3r::ExPolygon::Collection->new($expolygon->arrayref_pp, $expolygon2->arrayref_pp); + is_deeply [ @{$collection->arrayref_pp} ], [ $expolygon->arrayref_pp, $expolygon2->arrayref_pp ], 'expolygon collection'; my $collection2 = Slic3r::ExPolygon::Collection->new($expolygon, $expolygon2); - is_deeply [ @$collection ], [ @$collection2 ], + is_deeply [ @{$collection->arrayref_pp} ], [ @{$collection2->arrayref_pp} ], 'expolygon collection with XS expolygons'; $collection->clear; is scalar(@$collection), 0, 'clear collection'; $collection->append($expolygon); is scalar(@$collection), 1, 'append to collection'; + + is_deeply $collection->[0]->clone->arrayref_pp, $expolygon->arrayref_pp, 'clone collection item'; } __END__ diff --git a/xs/t/05_surface.t b/xs/t/05_surface.t index 94b308a8..b167ba1a 100644 --- a/xs/t/05_surface.t +++ b/xs/t/05_surface.t @@ -28,7 +28,7 @@ my $surface = Slic3r::Surface->new( $surface = $surface->clone; isa_ok $surface->expolygon, 'Slic3r::ExPolygon::XS', 'expolygon'; -is_deeply [ @{$surface->expolygon} ], [$square, $hole_in_square], 'expolygon roundtrip'; +is_deeply [ @{$surface->expolygon->arrayref_pp} ], [$square, $hole_in_square], 'expolygon roundtrip'; is $surface->surface_type, Slic3r::Surface::S_TYPE_INTERNAL, 'surface_type'; $surface->surface_type(Slic3r::Surface::S_TYPE_BOTTOM); @@ -43,7 +43,7 @@ is $surface->extra_perimeters, 2, 'extra_perimeters'; { my $collection = Slic3r::Surface::Collection->new($surface, $surface->clone); is scalar(@$collection), 2, 'collection has the right number of items'; - is_deeply $collection->[0]->expolygon->arrayref, [$square, $hole_in_square], + is_deeply $collection->[0]->expolygon->arrayref_pp, [$square, $hole_in_square], 'collection returns a correct surface expolygon'; $collection->clear; is scalar(@$collection), 0, 'clear collection'; diff --git a/xs/t/06_polygon.t b/xs/t/06_polygon.t index cca7032b..b1a9015b 100644 --- a/xs/t/06_polygon.t +++ b/xs/t/06_polygon.t @@ -14,9 +14,10 @@ my $square = [ # ccw ]; my $polygon = Slic3r::Polygon::XS->new(@$square); -is_deeply [ @$polygon ], [ @$square ], 'polygon roundtrip'; +is_deeply [ @{$polygon->arrayref_pp} ], [ @$square ], 'polygon roundtrip'; -isa_ok $polygon->arrayref, 'Slic3r::Polygon', 'Perl polygon is blessed'; -isa_ok $polygon->[0], 'Slic3r::Point', 'Perl points are blessed'; +my $arrayref = $polygon->arrayref; +isa_ok $arrayref, 'Slic3r::Polygon', 'Perl polygon is blessed'; +isa_ok $arrayref->[0], 'Slic3r::Point', 'Perl points are blessed'; __END__ diff --git a/xs/t/07_extrusionpath.t b/xs/t/07_extrusionpath.t index 5a8d4c5c..b1420ff3 100644 --- a/xs/t/07_extrusionpath.t +++ b/xs/t/07_extrusionpath.t @@ -17,10 +17,10 @@ my $path = Slic3r::ExtrusionPath->new( role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, ); isa_ok $path->as_polyline, 'Slic3r::Polyline::XS', 'path polyline'; -is_deeply [ @{ $path->as_polyline } ], [ @$points ], 'path points roundtrip'; +is_deeply [ @{ $path->as_polyline->arrayref_pp } ], [ @$points ], 'path points roundtrip'; $path->reverse; -is_deeply [ @{ $path->as_polyline } ], [ reverse @$points ], 'reverse path'; +is_deeply [ @{ $path->as_polyline->arrayref_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 f880a9f1..98e4a6bd 100644 --- a/xs/t/08_extrusionloop.t +++ b/xs/t/08_extrusionloop.t @@ -18,7 +18,7 @@ my $loop = Slic3r::ExtrusionLoop->new( role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, ); isa_ok $loop->as_polygon, 'Slic3r::Polygon::XS', 'loop polygon'; -is_deeply [ @{ $loop->as_polygon } ], [ @$square ], 'polygon points roundtrip'; +is_deeply [ @{ $loop->as_polygon->arrayref_pp } ], [ @$square ], 'polygon points roundtrip'; $loop = $loop->clone; diff --git a/xs/xsp/ExPolygon.xsp b/xs/xsp/ExPolygon.xsp index 93eef621..27cbac90 100644 --- a/xs/xsp/ExPolygon.xsp +++ b/xs/xsp/ExPolygon.xsp @@ -6,11 +6,12 @@ %} %name{Slic3r::ExPolygon::XS} class ExPolygon { - ~ExPolygon(); ExPolygon* clone() - %code{% const char* CLASS = "Slic3r::ExPolygon::XS"; RETVAL = new ExPolygon(*THIS); %}; + %code{% const char* CLASS = "Slic3r::ExPolygon::XS"; RETVAL = new ExPolygon(*THIS); RETVAL->in_collection = false; %}; SV* arrayref() - %code{% RETVAL = expolygon2perl(*THIS); %}; + %code{% RETVAL = THIS->to_SV(true, false); %}; + SV* arrayref_pp() + %code{% RETVAL = THIS->to_SV(true, true); %}; void scale(double factor); void translate(double x, double y); %{ @@ -20,14 +21,22 @@ ExPolygon::new(...) CODE: RETVAL = new ExPolygon (); // ST(0) is class name, ST(1) is contour and others are holes - perl2polygon(ST(1), RETVAL->contour); + RETVAL->contour.from_SV_check(ST(1)); RETVAL->holes.resize(items-2); for (unsigned int i = 2; i < items; i++) { - perl2polygon(ST(i), RETVAL->holes[i-2]); + RETVAL->holes[i-2].from_SV_check(ST(i)); } OUTPUT: RETVAL +void +ExPolygon::DESTROY() + CODE: + if (!THIS->in_collection) { + delete THIS; + THIS = NULL; + } + void ExPolygon::rotate(angle, center_sv) double angle; diff --git a/xs/xsp/ExPolygonCollection.xsp b/xs/xsp/ExPolygonCollection.xsp index 2adf8527..d9375db2 100644 --- a/xs/xsp/ExPolygonCollection.xsp +++ b/xs/xsp/ExPolygonCollection.xsp @@ -23,13 +23,8 @@ ExPolygonCollection::new(...) // ST(0) is class name, others are expolygons RETVAL->expolygons.resize(items-1); for (unsigned int i = 1; i < items; i++) { - if (sv_isobject(ST(i)) && (SvTYPE(SvRV(ST(i))) == SVt_PVMG)) { - // a XS ExPolygon was supplied - RETVAL->expolygons[i-1] = *(ExPolygon *)SvIV((SV*)SvRV( ST(i) )); - } else { - // a Perl arrayref was supplied - perl2expolygon(ST(i), RETVAL->expolygons[i-1]); - } + perl2expolygon_check(ST(i), RETVAL->expolygons[i-1]); + RETVAL->expolygons[i-1].in_collection = true; } OUTPUT: RETVAL @@ -41,7 +36,20 @@ ExPolygonCollection::arrayref() av_fill(av, THIS->expolygons.size()-1); int i = 0; for (ExPolygons::iterator it = THIS->expolygons.begin(); it != THIS->expolygons.end(); ++it) { - av_store(av, i++, expolygon2perl(*it)); + av_store(av, i++, (*it).to_SV(false, false)); + } + RETVAL = newRV_noinc((SV*)av); + OUTPUT: + RETVAL + +SV* +ExPolygonCollection::arrayref_pp() + CODE: + AV* av = newAV(); + av_fill(av, THIS->expolygons.size()-1); + int i = 0; + for (ExPolygons::iterator it = THIS->expolygons.begin(); it != THIS->expolygons.end(); ++it) { + av_store(av, i++, (*it).to_SV(true, true)); } RETVAL = newRV_noinc((SV*)av); OUTPUT: @@ -52,6 +60,7 @@ ExPolygonCollection::append(...) CODE: for (unsigned int i = 1; i < items; i++) { THIS->expolygons.push_back(*(ExPolygon *)SvIV((SV*)SvRV( ST(i) ))); + THIS->expolygons.back().in_collection = true; } %} diff --git a/xs/xsp/ExtrusionLoop.xsp b/xs/xsp/ExtrusionLoop.xsp index a0925725..2707dba6 100644 --- a/xs/xsp/ExtrusionLoop.xsp +++ b/xs/xsp/ExtrusionLoop.xsp @@ -8,11 +8,13 @@ %name{Slic3r::ExtrusionLoop} class ExtrusionLoop { ~ExtrusionLoop(); SV* arrayref() - %code{% RETVAL = polygon2perl(THIS->polygon); %}; + %code{% RETVAL = THIS->polygon.to_SV(true, false); %}; + SV* arrayref_pp() + %code{% RETVAL = THIS->polygon.to_SV(true, true); %}; Polygon* as_polygon() %code{% const char* CLASS = "Slic3r::Polygon::XS"; RETVAL = new Polygon(THIS->polygon); %}; void set_polygon(SV* polygon_sv) - %code{% perl2polygon_check(polygon_sv, THIS->polygon); %}; + %code{% THIS->polygon.from_SV_check(polygon_sv); %}; %{ ExtrusionLoop* @@ -24,7 +26,7 @@ _new(CLASS, polygon_sv, role, height, flow_spacing) double flow_spacing; CODE: RETVAL = new ExtrusionLoop (); - perl2polygon_check(polygon_sv, RETVAL->polygon); + RETVAL->polygon.from_SV_check(polygon_sv); RETVAL->role = role; RETVAL->height = height; RETVAL->flow_spacing = flow_spacing; diff --git a/xs/xsp/ExtrusionPath.xsp b/xs/xsp/ExtrusionPath.xsp index 9d832b56..9a9def62 100644 --- a/xs/xsp/ExtrusionPath.xsp +++ b/xs/xsp/ExtrusionPath.xsp @@ -8,11 +8,13 @@ %name{Slic3r::ExtrusionPath} class ExtrusionPath { ~ExtrusionPath(); SV* arrayref() - %code{% RETVAL = polyline2perl(THIS->polyline); %}; + %code{% RETVAL = THIS->polyline.to_SV(true, false); %}; + SV* arrayref_pp() + %code{% RETVAL = THIS->polyline.to_SV(true, true); %}; Polyline* as_polyline() %code{% const char* CLASS = "Slic3r::Polyline::XS"; RETVAL = new Polyline(THIS->polyline); %}; void set_polyline(SV* polyline_sv) - %code{% perl2polyline_check(polyline_sv, THIS->polyline); %}; + %code{% THIS->polyline.from_SV_check(polyline_sv); %}; void pop_back() %code{% THIS->polyline.points.pop_back(); %}; void reverse(); @@ -27,7 +29,7 @@ _new(CLASS, polyline_sv, role, height, flow_spacing) double flow_spacing; CODE: RETVAL = new ExtrusionPath (); - perl2polyline_check(polyline_sv, RETVAL->polyline); + RETVAL->polyline.from_SV_check(polyline_sv); RETVAL->role = role; RETVAL->height = height; RETVAL->flow_spacing = flow_spacing; diff --git a/xs/xsp/Point.xsp b/xs/xsp/Point.xsp index 7a92432d..fea86adc 100644 --- a/xs/xsp/Point.xsp +++ b/xs/xsp/Point.xsp @@ -5,15 +5,19 @@ #include "Point.hpp" %} -%name{Slic3r::Point::XS} class Point { +%name{Slic3r::Point} class Point { Point(unsigned long _x = 0, unsigned long _y = 0); ~Point(); Point* clone() - %code{% const char* CLASS = "Slic3r::Point::XS"; RETVAL = new Point(*THIS); %}; + %code{% const char* CLASS = "Slic3r::Point"; RETVAL = new Point(*THIS); %}; void scale(double factor); void translate(double x, double y); SV* arrayref() - %code{% RETVAL = point2perl(*THIS); %}; + %code{% RETVAL = THIS->to_SV(true); %}; + unsigned long x() + %code{% RETVAL = THIS->x; %}; + unsigned long y() + %code{% RETVAL = THIS->y; %}; %{ @@ -39,16 +43,3 @@ Point::coincides_with(point_sv) %} }; - -%package{Slic3r::Point::XS}; - -%{ -PROTOTYPES: DISABLE - -std::string -hello_world() - CODE: - RETVAL = "Hello world!"; - OUTPUT: - RETVAL -%} diff --git a/xs/xsp/Polygon.xsp b/xs/xsp/Polygon.xsp index daffd819..19bba68f 100644 --- a/xs/xsp/Polygon.xsp +++ b/xs/xsp/Polygon.xsp @@ -10,7 +10,9 @@ Polygon* clone() %code{% const char* CLASS = "Slic3r::Polygon::XS"; RETVAL = new Polygon(*THIS); %}; SV* arrayref() - %code{% RETVAL = polygon2perl(*THIS); %}; + %code{% RETVAL = THIS->to_SV(true, false); %}; + SV* arrayref_pp() + %code{% RETVAL = THIS->to_SV(true, true); %}; %{ Polygon* diff --git a/xs/xsp/Polyline.xsp b/xs/xsp/Polyline.xsp index 925b799d..02aad589 100644 --- a/xs/xsp/Polyline.xsp +++ b/xs/xsp/Polyline.xsp @@ -10,7 +10,9 @@ Polyline* clone() %code{% const char* CLASS = "Slic3r::Polyline::XS"; RETVAL = new Polyline(*THIS); %}; SV* arrayref() - %code{% RETVAL = polyline2perl(*THIS); %}; + %code{% RETVAL = THIS->to_SV(true, false); %}; + SV* arrayref_pp() + %code{% RETVAL = THIS->to_SV(true, true); %}; void pop_back() %code{% THIS->points.pop_back(); %}; void reverse();