From 399bc80899117ed504c81e04658a83f7cd9bc480 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 14 Jul 2013 13:05:55 +0200 Subject: [PATCH] Ported Slic3r::Surface to XS --- lib/Slic3r.pm | 3 +- lib/Slic3r/Surface.pm | 61 ----------------------------- xs/lib/Slic3r/XS.pm | 32 +++++++++++++++ xs/src/Surface.hpp | 30 +++++++++++++++ xs/t/05_surface.t | 43 +++++++++++++++++++++ xs/xsp/Surface.xsp | 90 +++++++++++++++++++++++++++++++++++++++++++ xs/xsp/my.map | 2 + xs/xsp/typemap.xspt | 9 ++++- 8 files changed, 207 insertions(+), 63 deletions(-) create mode 100644 xs/src/Surface.hpp create mode 100644 xs/t/05_surface.t create mode 100644 xs/xsp/Surface.xsp diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 2c2883574..782179da7 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -32,6 +32,7 @@ use Encode::Locale; use Boost::Geometry::Utils 0.15; use Moo 0.091009; +use Slic3r::XS; # import all symbols (constants etc.) before they get parsed use Slic3r::Config; use Slic3r::ExPolygon; use Slic3r::Extruder; @@ -65,7 +66,6 @@ use Slic3r::Print::Object; use Slic3r::Print::Region; use Slic3r::Surface; use Slic3r::TriangleMesh; -use Slic3r::XS; our $build = eval "use Slic3r::Build; 1"; use constant SCALING_FACTOR => 0.000001; @@ -113,6 +113,7 @@ sub thread_cleanup { *Slic3r::ExPolygon::Collection::DESTROY = sub {}; *Slic3r::ExPolygon::XS::DESTROY = sub {}; *Slic3r::Point::XS::DESTROY = sub {}; + *Slic3r::Surface::DESTROY = sub {}; } sub encode_path { diff --git a/lib/Slic3r/Surface.pm b/lib/Slic3r/Surface.pm index 7db4cfd27..c33e2924a 100644 --- a/lib/Slic3r/Surface.pm +++ b/lib/Slic3r/Surface.pm @@ -7,67 +7,6 @@ our @ISA = qw(Exporter); our @EXPORT_OK = qw(S_TYPE_TOP S_TYPE_BOTTOM S_TYPE_INTERNAL S_TYPE_INTERNALSOLID S_TYPE_INTERNALBRIDGE S_TYPE_INTERNALVOID); our %EXPORT_TAGS = (types => \@EXPORT_OK); -use constant S_EXPOLYGON => 0; -use constant S_SURFACE_TYPE => 1; -use constant S_THICKNESS => 2; # in mm -use constant S_THICKNESS_LAYERS => 3; # in layers -use constant S_BRIDGE_ANGLE => 4; -use constant S_EXTRA_PERIMETERS => 5; - -use constant S_TYPE_TOP => 0; -use constant S_TYPE_BOTTOM => 1; -use constant S_TYPE_INTERNAL => 2; -use constant S_TYPE_INTERNALSOLID => 3; -use constant S_TYPE_INTERNALBRIDGE => 4; -use constant S_TYPE_INTERNALVOID => 5; - -sub new { - my $class = shift; - my %args = @_; - - my $self = [ - map delete $args{$_}, qw(expolygon surface_type thickness thickness_layers bridge_angle extra_perimeters), - ]; - $self->[S_THICKNESS_LAYERS] //= 1; - - bless $self, $class; - $self; -} - -sub clone { - my $self = shift; - my %p = @_; - - return (ref $self)->new( - (map { $_ => $self->$_ } qw(surface_type thickness thickness_layers bridge_angle)), - expolygon => (defined $p{expolygon} ? delete $p{expolygon} : $self->expolygon->clone), - %p, - ); -} - -sub expolygon { $_[0][S_EXPOLYGON] } -sub surface_type { $_[0][S_SURFACE_TYPE] = $_[1] if defined $_[1]; $_[0][S_SURFACE_TYPE] } -sub thickness { $_[0][S_THICKNESS] } -sub thickness_layers { $_[0][S_THICKNESS_LAYERS] } -sub bridge_angle { $_[0][S_BRIDGE_ANGLE] = $_[1] if defined $_[1]; $_[0][S_BRIDGE_ANGLE] } -sub extra_perimeters { $_[0][S_EXTRA_PERIMETERS] = $_[1] if defined $_[1]; $_[0][S_EXTRA_PERIMETERS] } - -if (eval "use Class::XSAccessor::Array; 1") { - Class::XSAccessor::Array->import( - getters => { - expolygon => S_EXPOLYGON, - }, - accessors => { - surface_type => S_SURFACE_TYPE, - thickness => S_THICKNESS, - thickness_layers => S_THICKNESS_LAYERS, - bridge_angle => S_BRIDGE_ANGLE, - extra_perimeters => S_EXTRA_PERIMETERS, - }, - replace => 1, - ); -} - # delegate handles sub encloses_point { $_[0]->expolygon->encloses_point } sub lines { $_[0]->expolygon->lines } diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index c81690e72..cf275ae40 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -32,4 +32,36 @@ use overload sub clone { (ref $_[0])->_clone($_[0]) } +package Slic3r::Surface; + +sub new { + my ($class, %args) = @_; + + # defensive programming: make sure no negative bridge_angle is supplied + die "Error: invalid negative bridge_angle\n" + if defined $args{bridge_angle} && $args{bridge_angle} < 0; + + return $class->_new( + delete $args{expolygon}, # required + delete $args{surface_type}, # required + delete $args{thickness} // -1, + delete $args{thickness_layers} // 1, + delete $args{bridge_angle} // -1, + delete $args{extra_perimeters} // 0, + ); +} + +sub clone { + my ($self, %args) = @_; + + return (ref $self)->_new( + delete $args{expolygon} // $self->expolygon->clone, + delete $args{surface_type} // $self->surface_type, + delete $args{thickness} // $self->thickness, + delete $args{thickness_layers} // $self->thickness_layers, + delete $args{bridge_angle} // $self->bridge_angle, + delete $args{extra_perimeters} // $self->extra_perimeters, + ); +} + 1; diff --git a/xs/src/Surface.hpp b/xs/src/Surface.hpp new file mode 100644 index 000000000..291c3e850 --- /dev/null +++ b/xs/src/Surface.hpp @@ -0,0 +1,30 @@ +#ifndef slic3r_Surface_hpp_ +#define slic3r_Surface_hpp_ + +extern "C" { +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#include "ppport.h" +} + +#include "ExPolygon.hpp" + +namespace Slic3r { + +enum SurfaceType { stTop, stBottom, stInternal, stInternalSolid, stInternalBridge, stInternalVoid }; + +class Surface +{ + public: + ExPolygon expolygon; + SurfaceType surface_type; + double thickness; // in mm + unsigned short thickness_layers; // in layers + double bridge_angle; + unsigned short extra_perimeters; +}; + +} + +#endif diff --git a/xs/t/05_surface.t b/xs/t/05_surface.t new file mode 100644 index 000000000..16232191e --- /dev/null +++ b/xs/t/05_surface.t @@ -0,0 +1,43 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Slic3r::XS; +use Test::More tests => 6; + +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); +my $surface = Slic3r::Surface->new( + expolygon => $expolygon, + surface_type => Slic3r::Surface::S_TYPE_INTERNAL, +); + +$surface = $surface->clone; + +isa_ok $surface->expolygon, 'Slic3r::ExPolygon::XS', 'expolygon'; +is_deeply [ @{$surface->expolygon} ], [$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); +is $surface->surface_type, Slic3r::Surface::S_TYPE_BOTTOM, 'modify surface_type'; + +$surface->bridge_angle(30); +is $surface->bridge_angle, 30, 'bridge_angle'; + +$surface->extra_perimeters(2); +is $surface->extra_perimeters, 2, 'extra_perimeters'; + +__END__ diff --git a/xs/xsp/Surface.xsp b/xs/xsp/Surface.xsp new file mode 100644 index 000000000..173b3f260 --- /dev/null +++ b/xs/xsp/Surface.xsp @@ -0,0 +1,90 @@ +%module{Slic3r::XS}; + +%{ +#include +#include "Surface.hpp" +%} + +%name{Slic3r::Surface} class Surface { + %name{_clone} Surface(Surface& self); + ~Surface(); + ExPolygon* expolygon() + %code{% const char* CLASS = "Slic3r::ExPolygon::XS"; RETVAL = new ExPolygon(THIS->expolygon); %}; + double thickness() + %code{% RETVAL = THIS->thickness; %}; + unsigned short thickness_layers() + %code{% RETVAL = THIS->thickness_layers; %}; +%{ + +Surface* +_new(CLASS, expolygon, surface_type, thickness, thickness_layers, bridge_angle, extra_perimeters) + char* CLASS; + ExPolygon* expolygon; + SurfaceType surface_type; + double thickness; + unsigned short thickness_layers; + double bridge_angle; + unsigned short extra_perimeters; + CODE: + RETVAL = new Surface (); + RETVAL->expolygon = *expolygon; + RETVAL->surface_type = surface_type; + RETVAL->thickness = thickness; + RETVAL->thickness_layers = thickness_layers; + RETVAL->bridge_angle = bridge_angle; + RETVAL->extra_perimeters = extra_perimeters; + OUTPUT: + RETVAL + +SurfaceType +Surface::surface_type(...) + CODE: + if (items > 1) { + THIS->surface_type = (SurfaceType)SvUV(ST(1)); + } + RETVAL = THIS->surface_type; + OUTPUT: + RETVAL + +double +Surface::bridge_angle(...) + CODE: + if (items > 1) { + THIS->bridge_angle = (double)SvNV(ST(1)); + } + RETVAL = THIS->bridge_angle; + OUTPUT: + RETVAL + +unsigned short +Surface::extra_perimeters(...) + CODE: + if (items > 1) { + THIS->extra_perimeters = (double)SvUV(ST(1)); + } + RETVAL = THIS->extra_perimeters; + OUTPUT: + RETVAL + +%} +}; + +%package{Slic3r::Surface}; +%{ + +IV +_constant() + ALIAS: + S_TYPE_TOP = stTop + S_TYPE_BOTTOM = stBottom + S_TYPE_INTERNAL = stInternal + S_TYPE_INTERNALSOLID = stInternalSolid + S_TYPE_INTERNALBRIDGE = stInternalBridge + S_TYPE_INTERNALVOID = stInternalVoid + PROTOTYPE: + CODE: + RETVAL = ix; + OUTPUT: RETVAL + +%} + diff --git a/xs/xsp/my.map b/xs/xsp/my.map index 9737c8c05..cbdb592ae 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -3,3 +3,5 @@ TriangleMesh* O_OBJECT Point* O_OBJECT ExPolygon* O_OBJECT ExPolygonCollection* O_OBJECT +SurfaceType T_UV +Surface* O_OBJECT diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index b41df45dc..fc6f43631 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -2,4 +2,11 @@ %typemap{std::vector*}; %typemap{SV*}; %typemap{AV*}; -%typemap{Point*}; \ No newline at end of file +%typemap{Point*}; +%typemap{ExPolygon*}; +%typemap{SurfaceType}{parsed}{ + %cpp_type{SurfaceType}; + %precall_code{% + $CVar = (SurfaceType)SvUV($PerlVar); + %}; +}; \ No newline at end of file