Browse Source

Ported Slic3r::Surface to XS

Alessandro Ranellucci 11 years ago
parent
commit
399bc80899
8 changed files with 207 additions and 63 deletions
  1. 2 1
      lib/Slic3r.pm
  2. 0 61
      lib/Slic3r/Surface.pm
  3. 32 0
      xs/lib/Slic3r/XS.pm
  4. 30 0
      xs/src/Surface.hpp
  5. 43 0
      xs/t/05_surface.t
  6. 90 0
      xs/xsp/Surface.xsp
  7. 2 0
      xs/xsp/my.map
  8. 8 1
      xs/xsp/typemap.xspt

+ 2 - 1
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 {

+ 0 - 61
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 }

+ 32 - 0
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;

+ 30 - 0
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

+ 43 - 0
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__

+ 90 - 0
xs/xsp/Surface.xsp

@@ -0,0 +1,90 @@
+%module{Slic3r::XS};
+
+%{
+#include <myinit.h>
+#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
+
+%}
+

+ 2 - 0
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

+ 8 - 1
xs/xsp/typemap.xspt

@@ -2,4 +2,11 @@
 %typemap{std::vector<unsigned int>*};
 %typemap{SV*};
 %typemap{AV*};
-%typemap{Point*};
+%typemap{Point*};
+%typemap{ExPolygon*};
+%typemap{SurfaceType}{parsed}{
+  %cpp_type{SurfaceType};
+  %precall_code{%
+    $CVar = (SurfaceType)SvUV($PerlVar);
+  %};
+};