diff --git a/xs/MANIFEST b/xs/MANIFEST index c29ced6ef..b8232a848 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -18,6 +18,7 @@ src/admesh/stlinit.c src/admesh/stlinit.o src/admesh/util.c src/admesh/util.o +src/ExPolygon.hpp src/myinit.h src/Point.cpp src/Point.hpp @@ -30,6 +31,8 @@ src/ZTable.hpp t/01_trianglemesh.t t/02_object.t t/03_point.t +t/04_expolygon.t +xsp/ExPolygon.xsp xsp/my.map xsp/mytype.map xsp/Object.xsp diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index 1b245329a..8df63af91 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -11,4 +11,8 @@ package Slic3r::Point::XS; use overload '@{}' => sub { $_[0]->_toPerl }; +package Slic3r::ExPolygon::XS; +use overload + '@{}' => sub { $_[0]->_toPerl }; + 1; diff --git a/xs/src/ExPolygon.hpp b/xs/src/ExPolygon.hpp new file mode 100644 index 000000000..093b69167 --- /dev/null +++ b/xs/src/ExPolygon.hpp @@ -0,0 +1,52 @@ +#ifndef slic3r_ExPolygon_hpp_ +#define slic3r_ExPolygon_hpp_ + +extern "C" { +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#include "ppport.h" +} + +#include "Point.hpp" + +typedef std::vector Polygon; +typedef std::vector Polygons; + +class ExPolygon +{ + public: + Polygon contour; + Polygons holes; + SV* _toPerl(); +}; + +Polygon* +perl2polygon(SV* poly_sv) +{ + AV* poly_av = (AV*)SvRV(poly_sv); + const unsigned int num_points = av_len(poly_av)+1; + Polygon* retval = new Polygon(num_points); + + for (unsigned int i = 0; i < num_points; i++) { + SV** point_sv = av_fetch(poly_av, i, 0); + AV* point_av = (AV*)SvRV(*point_sv); + Point& p = (*retval)[i]; + p.x = (unsigned long)SvIV(*av_fetch(point_av, 0, 0)); + p.y = (unsigned long)SvIV(*av_fetch(point_av, 1, 0)); + } + return retval; +} + +SV* +polygon2perl(Polygon& poly) { + const unsigned int num_points = poly.size(); + AV* av = newAV(); + av_extend(av, num_points-1); + for (unsigned int i = 0; i < num_points; i++) { + av_store(av, i, poly[i]._toPerl()); + } + return (SV*)newRV_noinc((SV*)av); +} + +#endif diff --git a/xs/src/Point.cpp b/xs/src/Point.cpp index a4c905eae..3758cabc7 100644 --- a/xs/src/Point.cpp +++ b/xs/src/Point.cpp @@ -1,7 +1,6 @@ #include "myinit.h" #include "Point.hpp" -Point::Point(unsigned long x, unsigned long y) {} Point::~Point() {} diff --git a/xs/src/Point.hpp b/xs/src/Point.hpp index 3b7a5e5dd..eedd73fde 100644 --- a/xs/src/Point.hpp +++ b/xs/src/Point.hpp @@ -13,7 +13,7 @@ class Point public: unsigned long x; unsigned long y; - Point(unsigned long _x, unsigned long _y): x(_x), y(_y) {}; + Point(unsigned long _x = 0, unsigned long _y = 0): x(_x), y(_y) {}; ~Point(); SV* _toPerl(); }; diff --git a/xs/t/04_expolygon.t b/xs/t/04_expolygon.t new file mode 100644 index 000000000..0fe27640c --- /dev/null +++ b/xs/t/04_expolygon.t @@ -0,0 +1,25 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Slic3r::XS; +use Test::More tests => 1; + +my $square = [ # ccw + [100, 100], + [200, 100], + [200, 200], + [100, 200], +]; +my $hole_in_square = [ # cw + [140, 140], + [140, 160], + [160, 160], + [160, 140], +]; + +my $expolygon = Slic3r::ExPolygon::XS->new($square, $hole_in_square); +is_deeply [ @$expolygon ], [$square, $hole_in_square], 'expolygon roundtrip'; + +__END__ diff --git a/xs/xsp/ExPolygon.xsp b/xs/xsp/ExPolygon.xsp new file mode 100644 index 000000000..0c8bdbf9e --- /dev/null +++ b/xs/xsp/ExPolygon.xsp @@ -0,0 +1,51 @@ +%module{Slic3r::XS}; + +%{ +#include +#include "ExPolygon.hpp" +%} + +%name{Slic3r::ExPolygon::XS} class ExPolygon { +%{ + +ExPolygon* +ExPolygon::new(...) + CODE: + RETVAL = new ExPolygon (); + // ST(0) is class name, ST(1) is contour and others are holes + RETVAL->contour = *perl2polygon(ST(1)); + for (unsigned int i = 2; i < items; i++) { + RETVAL->holes.push_back(*perl2polygon(ST(i))); + } + OUTPUT: + RETVAL + +SV* +ExPolygon::_toPerl() + CODE: + const unsigned int num_holes = THIS->holes.size(); + AV* av = newAV(); + av_fill(av, num_holes); // -1 +1 + av_store(av, 0, polygon2perl(THIS->contour)); + for (unsigned int i = 0; i < num_holes; i++) { + av_store(av, i+1, polygon2perl(THIS->holes[i])); + } + RETVAL = (SV*)newRV_noinc((SV*)av); + OUTPUT: + RETVAL + +%} +}; + +%package{Slic3r::ExPolygon::XS}; + +%{ +PROTOTYPES: DISABLE + +std::string +hello_world() + CODE: + RETVAL = "Hello world!"; + OUTPUT: + RETVAL +%} diff --git a/xs/xsp/Point.xsp b/xs/xsp/Point.xsp index db810068b..9756a4b31 100644 --- a/xs/xsp/Point.xsp +++ b/xs/xsp/Point.xsp @@ -6,7 +6,7 @@ %} %name{Slic3r::Point::XS} class Point { - Point(unsigned long _x, unsigned long _y); + Point(unsigned long _x = 0, unsigned long _y = 0); ~Point(); SV* _toPerl(); }; diff --git a/xs/xsp/my.map b/xs/xsp/my.map index 46a311676..329d75e4d 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -1,4 +1,5 @@ ZTable* O_OBJECT TriangleMesh* O_OBJECT Point* O_OBJECT +ExPolygon* O_OBJECT std::vector< unsigned int >* T_STD_VECTOR_UINT_PTR