From c9749ca3b3ec8b34a12613420702b0cac5e244b8 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 15 Jul 2013 16:04:49 +0200 Subject: [PATCH] More integration of Slic3r::Point::XS --- lib/Slic3r/GCode.pm | 2 +- lib/Slic3r/Geometry.pm | 5 ++++- lib/Slic3r/Line.pm | 1 - lib/Slic3r/Point.pm | 2 +- lib/Slic3r/Polyline.pm | 2 +- xs/src/Point.hpp | 41 +++++++++++++++++++++++++++++++++++++---- xs/src/Polyline.hpp | 6 ++---- xs/t/03_point.t | 12 +++++++++++- xs/xsp/Point.xsp | 26 +++++++++++++++++++++++--- 9 files changed, 80 insertions(+), 17 deletions(-) diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index a657dc011..e38bf4a11 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -270,7 +270,7 @@ sub extrude_path { # go to first point of extrusion path my $gcode = ""; $gcode .= $self->travel_to($path->points->[0], $path->role, "move to first $description point") - if !$self->last_pos || !$self->last_pos->coincides_with($path->points->[0]); + if !defined $self->last_pos || !$self->last_pos->coincides_with($path->points->[0]); # compensate retraction $gcode .= $self->unretract; diff --git a/lib/Slic3r/Geometry.pm b/lib/Slic3r/Geometry.pm index b082dc7b5..7f9921292 100644 --- a/lib/Slic3r/Geometry.pm +++ b/lib/Slic3r/Geometry.pm @@ -386,7 +386,10 @@ sub rotate_points { sub move_points { my ($shift, @points) = @_; - return map Slic3r::Point->new($shift->[X] + $_->[X], $shift->[Y] + $_->[Y]), @points; + return map { + my @p = @$_; + Slic3r::Point->new($shift->[X] + $p[X], $shift->[Y] + $p[Y]); + } @points; } sub move_points_3D { diff --git a/lib/Slic3r/Line.pm b/lib/Slic3r/Line.pm index 968ec1b6a..ac2227006 100644 --- a/lib/Slic3r/Line.pm +++ b/lib/Slic3r/Line.pm @@ -12,7 +12,6 @@ sub new { my $self; $self = [ @_ ]; bless $self, $class; - bless $_, 'Slic3r::Point' for @$self; return $self; } diff --git a/lib/Slic3r/Point.pm b/lib/Slic3r/Point.pm index 4e86995e1..f8567f3ed 100644 --- a/lib/Slic3r/Point.pm +++ b/lib/Slic3r/Point.pm @@ -21,7 +21,7 @@ sub new { } sub clone { - Storable::dclone($_[0]) + return Slic3r::Point::XS->new(@{$_[0]}); } sub threadsafe_clone { diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 705163761..08950355d 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -243,7 +243,7 @@ sub chained_path { : [ map { $_->[0], $_->[-1] } @my_paths ]; while (@my_paths) { # find nearest point - my $start_index = $start_near + my $start_index = defined $start_near ? Slic3r::Geometry::nearest_point_index($start_near, $endpoints) : 0; diff --git a/xs/src/Point.hpp b/xs/src/Point.hpp index d8511b4c2..9288d98fc 100644 --- a/xs/src/Point.hpp +++ b/xs/src/Point.hpp @@ -18,18 +18,41 @@ class Point long x; long y; Point(long _x = 0, long _y = 0): x(_x), y(_y) {}; + void scale(double factor); + void translate(double x, double y); void rotate(double angle, Point* center); + bool coincides_with(Point* point); }; typedef std::vector Points; +void +Point::scale(double factor) +{ + this->x *= factor; + this->y *= factor; +} + +void +Point::translate(double x, double y) +{ + this->x += x; + this->y += y; +} + void Point::rotate(double angle, Point* center) { - double cur_x = (double)x; - double cur_y = (double)y; - x = (long)( (double)center->x + cos(angle) * (cur_x - (double)center->x) - sin(angle) * (cur_y - (double)center->y) ); - y = (long)( (double)center->y + cos(angle) * (cur_y - (double)center->y) + sin(angle) * (cur_x - (double)center->x) ); + double cur_x = (double)this->x; + double cur_y = (double)this->y; + this->x = (long)( (double)center->x + cos(angle) * (cur_x - (double)center->x) - sin(angle) * (cur_y - (double)center->y) ); + this->y = (long)( (double)center->y + cos(angle) * (cur_y - (double)center->y) + sin(angle) * (cur_x - (double)center->x) ); +} + +bool +Point::coincides_with(Point* point) +{ + return this->x == point->x && this->y == point->y; } SV* @@ -48,6 +71,16 @@ perl2point(SV* point_sv, Point& point) point.y = (unsigned long)SvIV(*av_fetch(point_av, 1, 0)); } +void +perl2point_check(SV* point_sv, Point& point) +{ + if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) { + point = *(Point*)SvIV((SV*)SvRV( point_sv )); + } else { + perl2point(point_sv, point); + } +} + } #endif diff --git a/xs/src/Polyline.hpp b/xs/src/Polyline.hpp index 0941314c1..3c34d0f12 100644 --- a/xs/src/Polyline.hpp +++ b/xs/src/Polyline.hpp @@ -29,8 +29,7 @@ void Polyline::scale(double factor) { for (Points::iterator it = points.begin(); it != points.end(); ++it) { - (*it).x *= factor; - (*it).y *= factor; + (*it).scale(factor); } } @@ -38,8 +37,7 @@ void Polyline::translate(double x, double y) { for (Points::iterator it = points.begin(); it != points.end(); ++it) { - (*it).x += x; - (*it).y += y; + (*it).translate(x, y); } } diff --git a/xs/t/03_point.t b/xs/t/03_point.t index 362581147..c40641c47 100644 --- a/xs/t/03_point.t +++ b/xs/t/03_point.t @@ -4,11 +4,21 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 2; +use Test::More tests => 6; my $point = Slic3r::Point::XS->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'; + +$point2->translate(10, -15); +is_deeply [ @$point2 ], [30, 15], 'translate'; + +ok $point->coincides_with($point->clone), 'coincides_with'; +ok !$point->coincides_with($point2), 'coincides_with'; + __END__ diff --git a/xs/xsp/Point.xsp b/xs/xsp/Point.xsp index ef18931fe..7a92432de 100644 --- a/xs/xsp/Point.xsp +++ b/xs/xsp/Point.xsp @@ -8,16 +8,36 @@ %name{Slic3r::Point::XS} 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); %}; + void scale(double factor); + void translate(double x, double y); + SV* arrayref() + %code{% RETVAL = point2perl(*THIS); %}; + %{ -SV* -Point::arrayref() +void +Point::rotate(angle, center_sv) + double angle; + SV* center_sv; CODE: - RETVAL = point2perl(*THIS); + Point center; + perl2point_check(center_sv, center); + THIS->rotate(angle, ¢er); + +bool +Point::coincides_with(point_sv) + SV* point_sv; + CODE: + Point point; + perl2point_check(point_sv, point); + RETVAL = THIS->coincides_with(&point); OUTPUT: RETVAL %} + }; %package{Slic3r::Point::XS};