From 5885be881c37c7b1a98ee16f0ecb53eb3b0795d8 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 14 Jul 2013 14:56:43 +0200 Subject: [PATCH] New Slic3r::Surface::Collection class --- lib/Slic3r/Layer/Region.pm | 15 ++++++----- lib/Slic3r/Print.pm | 2 +- lib/Slic3r/Print/Object.pm | 21 ++++++++++------ xs/lib/Slic3r/XS.pm | 4 +++ xs/src/SurfaceCollection.hpp | 26 +++++++++++++++++++ xs/t/05_surface.t | 13 +++++++++- xs/xsp/SurfaceCollection.xsp | 49 ++++++++++++++++++++++++++++++++++++ xs/xsp/my.map | 1 + 8 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 xs/src/SurfaceCollection.hpp create mode 100644 xs/xsp/SurfaceCollection.xsp diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index 1d7550c44..fb6ba3450 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -36,7 +36,7 @@ has 'thin_walls' => (is => 'rw', default => sub { [] }); has 'thin_fills' => (is => 'rw', default => sub { [] }); # collection of surfaces for infill generation -has 'fill_surfaces' => (is => 'rw', default => sub { [] }); +has 'fill_surfaces' => (is => 'rw', default => sub { Slic3r::Surface::Collection->new }); # ordered collection of extrusion paths/loops to build all perimeters has 'perimeters' => (is => 'rw', default => sub { [] }); @@ -158,7 +158,7 @@ sub make_perimeters { my $gap_area_threshold = $self->perimeter_flow->scaled_width ** 2; $self->perimeters([]); - $self->fill_surfaces([]); + $self->fill_surfaces->clear; $self->thin_fills([]); my @contours = (); # array of Polygons with ccw orientation @@ -208,12 +208,14 @@ sub make_perimeters { # we offset by half the perimeter spacing (to get to the actual infill boundary) # and then we offset back and forth by the infill spacing to only consider the # non-collapsing regions - push @{ $self->fill_surfaces }, - offset2_ex( + # use a bogus surface_type + $self->fill_surfaces->append( + map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_TOP), offset2_ex( [ map $_->simplify(&Slic3r::SCALED_RESOLUTION), @last ], -($perimeter_spacing/2 + $infill_spacing), +$infill_spacing, - ); + ) + ); } $self->_fill_gaps(\@gaps); @@ -452,7 +454,8 @@ sub process_external_surfaces { [ map $_->p, @new_surfaces ], )}; } - @{$self->fill_surfaces} = @new_surfaces; + $self->fill_surfaces->clear; + $self->fill_surfaces->append(@new_surfaces); } # detect bridge direction (skip bottom layer) diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 531197582..e443f595b 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -428,7 +428,7 @@ sub export_gcode { } # free memory (note that support material needs fill_surfaces) - $_->fill_surfaces(undef) for map @{$_->regions}, map @{$_->layers}, @{$self->objects}; + $_->fill_surfaces->clear for map @{$_->regions}, map @{$_->layers}, @{$self->objects}; # make skirt $status_cb->(88, "Generating skirt"); diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index d40350bc4..c2b3cafd4 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -427,16 +427,16 @@ sub detect_surfaces_type { # clip surfaces to the fill boundaries foreach my $layer (@{$self->layers}) { my $layerm = $layer->regions->[$region_id]; - my $fill_boundaries = [ map @$_, @{$layerm->fill_surfaces} ]; - @{$layerm->fill_surfaces} = (); + my $fill_boundaries = [ map $_->p, @{$layerm->fill_surfaces} ]; + $layerm->fill_surfaces->clear; foreach my $surface (@{$layerm->slices}) { my $intersection = intersection_ex( [ $surface->p ], $fill_boundaries, ); - push @{$layerm->fill_surfaces}, map Slic3r::Surface->new + $layerm->fill_surfaces->append(map Slic3r::Surface->new (expolygon => $_, surface_type => $surface->surface_type), - @$intersection; + @$intersection); } } } @@ -465,10 +465,12 @@ sub clip_fill_surfaces { [ map @$_, @overhangs ], [ map @{$_->expolygon}, grep $_->surface_type == S_TYPE_INTERNAL, @{$layerm->fill_surfaces} ], )}; - @{$layerm->fill_surfaces} = ( + my @new_surfaces = ( @new_internal, (grep $_->surface_type != S_TYPE_INTERNAL, @{$layerm->fill_surfaces}), ); + $layerm->fill_surfaces->clear; + $layerm->fill_surfaces->append(@new_surfaces); } # get this layer's overhangs @@ -523,7 +525,8 @@ sub bridge_over_infill { [ map @$_, @$to_bridge ], 1, )}; - @{$layerm->fill_surfaces} = @new_surfaces; + $layerm->fill_surfaces->clear; + $layerm->fill_surfaces->append(@new_surfaces); } # exclude infill from the layers below if needed @@ -550,7 +553,8 @@ sub bridge_over_infill { [ map @$_, @$to_bridge ], )}; } - @{$lower_layerm->fill_surfaces} = @new_surfaces; + $lower_layerm->fill_surfaces->clear; + $lower_layerm->fill_surfaces->append(@new_surfaces); } $excess -= $self->layers->[$i]->height; @@ -779,7 +783,8 @@ sub combine_infill { )}; } - @{$layerm->fill_surfaces} = (@new_this_type, @other_types); + $layerm->fill_surfaces->clear; + $layerm->fill_surfaces->append(@new_this_type, @other_types); } } } diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index 05ef2355f..30318ce25 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -60,4 +60,8 @@ sub clone { ); } +package Slic3r::Surface::Collection; +use overload + '@{}' => sub { $_[0]->arrayref }; + 1; diff --git a/xs/src/SurfaceCollection.hpp b/xs/src/SurfaceCollection.hpp new file mode 100644 index 000000000..e9f458dfd --- /dev/null +++ b/xs/src/SurfaceCollection.hpp @@ -0,0 +1,26 @@ +#ifndef slic3r_SurfaceCollection_hpp_ +#define slic3r_SurfaceCollection_hpp_ + +extern "C" { +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#include "ppport.h" +} + +#include "Surface.hpp" + +namespace Slic3r { + +typedef std::vector Surfaces; + +class SurfaceCollection +{ + public: + Surfaces surfaces; + SV* arrayref(); +}; + +} + +#endif diff --git a/xs/t/05_surface.t b/xs/t/05_surface.t index 16232191e..a881c8198 100644 --- a/xs/t/05_surface.t +++ b/xs/t/05_surface.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 6; +use Test::More tests => 10; my $square = [ # ccw [100, 100], @@ -40,4 +40,15 @@ is $surface->bridge_angle, 30, 'bridge_angle'; $surface->extra_perimeters(2); 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], + 'collection returns a correct surface expolygon'; + $collection->clear; + is scalar(@$collection), 0, 'clear collection'; + $collection->append($surface); + is scalar(@$collection), 1, 'append to collection'; +} + __END__ diff --git a/xs/xsp/SurfaceCollection.xsp b/xs/xsp/SurfaceCollection.xsp new file mode 100644 index 000000000..ef18fff48 --- /dev/null +++ b/xs/xsp/SurfaceCollection.xsp @@ -0,0 +1,49 @@ +%module{Slic3r::XS}; + +%{ +#include +#include "SurfaceCollection.hpp" +%} + +%name{Slic3r::Surface::Collection} class SurfaceCollection { + ~SurfaceCollection(); + void clear() + %code{% THIS->surfaces.clear(); %}; +%{ + +SurfaceCollection* +SurfaceCollection::new(...) + CODE: + RETVAL = new SurfaceCollection (); + // ST(0) is class name, others are surfaces + RETVAL->surfaces.resize(items-1); + for (unsigned int i = 1; i < items; i++) { + RETVAL->surfaces[i-1] = *(Surface *)SvIV((SV*)SvRV( ST(i) )); + } + OUTPUT: + RETVAL + +SV* +SurfaceCollection::arrayref() + CODE: + AV* av = newAV(); + av_fill(av, THIS->surfaces.size()-1); + int i = 0; + for (Surfaces::iterator it = THIS->surfaces.begin(); it != THIS->surfaces.end(); ++it) { + SV* sv = newSV(0); + sv_setref_pv( sv, "Slic3r::Surface", new Surface(*it) ); + av_store(av, i++, sv); + } + RETVAL = newRV_noinc((SV*)av); + OUTPUT: + RETVAL + +void +SurfaceCollection::append(...) + CODE: + for (unsigned int i = 1; i < items; i++) { + THIS->surfaces.push_back(*(Surface *)SvIV((SV*)SvRV( ST(i) ))); + } + +%} +}; diff --git a/xs/xsp/my.map b/xs/xsp/my.map index cbdb592ae..c5476e220 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -5,3 +5,4 @@ ExPolygon* O_OBJECT ExPolygonCollection* O_OBJECT SurfaceType T_UV Surface* O_OBJECT +SurfaceCollection* O_OBJECT