From c030e389086017ae806161e0f516f3e19d83e084 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 18 Jul 2013 19:09:07 +0200 Subject: [PATCH] Ported ExtrusionPath::Collection --- lib/Slic3r/ExtrusionPath/Collection.pm | 17 +++----- lib/Slic3r/Fill.pm | 33 +++++++------- lib/Slic3r/GCode.pm | 8 ++-- lib/Slic3r/Layer/Region.pm | 4 +- xs/lib/Slic3r/XS.pm | 5 +++ xs/src/ExPolygon.hpp | 1 + xs/src/ExPolygonCollection.cpp | 12 +++--- xs/src/ExPolygonCollection.hpp | 3 +- xs/src/ExtrusionEntity.hpp | 3 ++ xs/src/ExtrusionEntityCollection.hpp | 18 ++++++++ xs/src/Surface.hpp | 3 ++ xs/src/SurfaceCollection.hpp | 5 +-- xs/t/12_extrusionpathcollection.t | 37 ++++++++++++++++ xs/xsp/ExPolygonCollection.xsp | 19 +++++---- xs/xsp/ExtrusionEntityCollection.xsp | 59 ++++++++++++++++++++++++++ xs/xsp/SurfaceCollection.xsp | 12 +++--- xs/xsp/my.map | 1 + xs/xsp/typemap.xspt | 1 + 18 files changed, 181 insertions(+), 60 deletions(-) create mode 100644 xs/src/ExtrusionEntityCollection.hpp create mode 100644 xs/t/12_extrusionpathcollection.t create mode 100644 xs/xsp/ExtrusionEntityCollection.xsp diff --git a/lib/Slic3r/ExtrusionPath/Collection.pm b/lib/Slic3r/ExtrusionPath/Collection.pm index bb81381d6..4577d3b7b 100644 --- a/lib/Slic3r/ExtrusionPath/Collection.pm +++ b/lib/Slic3r/ExtrusionPath/Collection.pm @@ -1,25 +1,19 @@ package Slic3r::ExtrusionPath::Collection; -use Moo; - -has 'paths' => (is => 'rw', default => sub { [] }); -has 'no_sort' => (is => 'rw'); - -# no-op -sub unpack { $_[0] } +use strict; +use warnings; sub first_point { my $self = shift; - return $self->paths->[0]->polyline->[0]; + return $self->[0]->[0]; } -# Note that our paths will be reversed in place when necessary. # (Same algorithm as Polyline::Collection) sub chained_path { my $self = shift; my ($start_near, $no_reverse) = @_; - return @{$self->paths} if $self->no_sort; - my @my_paths = @{$self->paths}; + my @my_paths = @$self; + return @my_paths if $self->no_sort; my @paths = (); my $start_at; @@ -34,6 +28,7 @@ sub chained_path { my $path_index = int($start_index/2); if ($start_index % 2 && !$no_reverse) { # index is end so reverse to make it the start + # path is reversed in place, but we got a copy from XS $my_paths[$path_index]->reverse; } push @paths, splice @my_paths, $path_index, 1; diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index f1144c38f..cf122c212 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -170,29 +170,28 @@ sub make_fill { $params->{flow_spacing} = $layerm->extruders->{infill}->bridge_flow->width if $is_bridge; # save into layer - push @fills, Slic3r::ExtrusionPath::Collection->new( - no_sort => $params->{no_sort}, - paths => [ - map Slic3r::ExtrusionPath->new( - polyline => Slic3r::Polyline->new(@$_), - role => ($surface->surface_type == S_TYPE_INTERNALBRIDGE - ? EXTR_ROLE_INTERNALBRIDGE - : $is_bridge - ? EXTR_ROLE_BRIDGE - : $is_solid - ? (($surface->surface_type == S_TYPE_TOP) ? EXTR_ROLE_TOPSOLIDFILL : EXTR_ROLE_SOLIDFILL) - : EXTR_ROLE_FILL), - height => $surface->thickness, - flow_spacing => $params->{flow_spacing} || (warn "Warning: no flow_spacing was returned by the infill engine, please report this to the developer\n"), - ), @polylines, - ], + push @fills, my $collection = Slic3r::ExtrusionPath::Collection->new; + $collection->no_sort($params->{no_sort}); + $collection->append( + map Slic3r::ExtrusionPath->new( + polyline => Slic3r::Polyline->new(@$_), + role => ($surface->surface_type == S_TYPE_INTERNALBRIDGE + ? EXTR_ROLE_INTERNALBRIDGE + : $is_bridge + ? EXTR_ROLE_BRIDGE + : $is_solid + ? (($surface->surface_type == S_TYPE_TOP) ? EXTR_ROLE_TOPSOLIDFILL : EXTR_ROLE_SOLIDFILL) + : EXTR_ROLE_FILL), + height => $surface->thickness, + flow_spacing => $params->{flow_spacing} || (warn "Warning: no flow_spacing was returned by the infill engine, please report this to the developer\n"), + ), @polylines, ); push @fills_ordering_points, $polylines[0][0]; } # add thin fill regions push @fills, @{$layerm->thin_fills}; - push @fills_ordering_points, map $_->points->[0], @{$layerm->thin_fills}; + push @fills_ordering_points, map $_->[0], @{$layerm->thin_fills}; # organize infill paths using a nearest-neighbor search @fills = @fills[ chained_path(\@fills_ordering_points) ]; diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 3e11db93b..94762a7cc 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -211,9 +211,11 @@ sub extrude_loop { $extrusion_path->intersect_expolygons($self->_layer_overhangs); # reapply the nearest point search for starting point - @paths = Slic3r::ExtrusionPath::Collection - ->new(paths => [@paths]) - ->chained_path($start_at, 1); + { + my $collection = Slic3r::ExtrusionPath::Collection->new; + $collection->append(@paths); + @paths = $collection->chained_path($start_at, 1); + } } else { push @paths, $extrusion_path; } diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index 0751838ae..3b70e3f25 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -281,7 +281,7 @@ sub make_perimeters { push @{ $self->perimeters }, @loops; # add thin walls as perimeters - push @{ $self->perimeters }, Slic3r::ExtrusionPath::Collection->new(paths => [ + push @{ $self->perimeters }, Slic3r::ExtrusionPath::Collection->new( map { Slic3r::ExtrusionPath->new( polyline => ($_->isa('Slic3r::Polygon') ? $_->split_at_first_point : $_), @@ -289,7 +289,7 @@ sub make_perimeters { flow_spacing => $self->perimeter_flow->spacing, ); } @{ $self->thin_walls } - ])->chained_path; + )->chained_path; } sub _fill_gaps { diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index fcf7054b0..174e72e44 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -38,6 +38,11 @@ use overload '@{}' => sub { $_[0]->arrayref }, 'fallback' => 1; +package Slic3r::ExtrusionPath::Collection; +use overload + '@{}' => sub { $_[0]->arrayref }, + 'fallback' => 1; + package Slic3r::ExtrusionLoop; use overload '@{}' => sub { $_[0]->arrayref }, diff --git a/xs/src/ExPolygon.hpp b/xs/src/ExPolygon.hpp index 4c927f8b7..481d56c79 100644 --- a/xs/src/ExPolygon.hpp +++ b/xs/src/ExPolygon.hpp @@ -23,6 +23,7 @@ class ExPolygon }; typedef std::vector ExPolygons; +typedef std::vector ExPolygonsPtr; } diff --git a/xs/src/ExPolygonCollection.cpp b/xs/src/ExPolygonCollection.cpp index d0f84990c..dca86e05b 100644 --- a/xs/src/ExPolygonCollection.cpp +++ b/xs/src/ExPolygonCollection.cpp @@ -5,24 +5,24 @@ namespace Slic3r { void ExPolygonCollection::scale(double factor) { - for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { - (*it).scale(factor); + for (ExPolygonsPtr::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { + (**it).scale(factor); } } void ExPolygonCollection::translate(double x, double y) { - for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { - (*it).translate(x, y); + for (ExPolygonsPtr::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { + (**it).translate(x, y); } } void ExPolygonCollection::rotate(double angle, Point* center) { - for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { - (*it).rotate(angle, center); + for (ExPolygonsPtr::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { + (**it).rotate(angle, center); } } diff --git a/xs/src/ExPolygonCollection.hpp b/xs/src/ExPolygonCollection.hpp index 2cfd4bbc8..b428fcbea 100644 --- a/xs/src/ExPolygonCollection.hpp +++ b/xs/src/ExPolygonCollection.hpp @@ -9,8 +9,7 @@ namespace Slic3r { class ExPolygonCollection { public: - ExPolygons expolygons; - SV* arrayref(); + ExPolygonsPtr expolygons; void scale(double factor); void translate(double x, double y); void rotate(double angle, Point* center); diff --git a/xs/src/ExtrusionEntity.hpp b/xs/src/ExtrusionEntity.hpp index dd6a48c6b..5cf37cc24 100644 --- a/xs/src/ExtrusionEntity.hpp +++ b/xs/src/ExtrusionEntity.hpp @@ -25,11 +25,14 @@ enum ExtrusionRole { class ExtrusionEntity { public: + virtual ~ExtrusionEntity() {}; ExtrusionRole role; double height; // vertical thickness of the extrusion expressed in mm double flow_spacing; }; +typedef std::vector ExtrusionEntitiesPtr; + class ExtrusionPath : public ExtrusionEntity { public: diff --git a/xs/src/ExtrusionEntityCollection.hpp b/xs/src/ExtrusionEntityCollection.hpp new file mode 100644 index 000000000..ef36cd136 --- /dev/null +++ b/xs/src/ExtrusionEntityCollection.hpp @@ -0,0 +1,18 @@ +#ifndef slic3r_ExtrusionEntityCollection_hpp_ +#define slic3r_ExtrusionEntityCollection_hpp_ + +#include +#include "ExtrusionEntity.hpp" + +namespace Slic3r { + +class ExtrusionEntityCollection +{ + public: + ExtrusionEntitiesPtr entities; + bool no_sort; +}; + +} + +#endif diff --git a/xs/src/Surface.hpp b/xs/src/Surface.hpp index 32981df04..ef1ae543a 100644 --- a/xs/src/Surface.hpp +++ b/xs/src/Surface.hpp @@ -19,6 +19,9 @@ class Surface bool in_collection; }; +typedef std::vector Surfaces; +typedef std::vector SurfacesPtr; + } #endif diff --git a/xs/src/SurfaceCollection.hpp b/xs/src/SurfaceCollection.hpp index 091918c34..600d43c37 100644 --- a/xs/src/SurfaceCollection.hpp +++ b/xs/src/SurfaceCollection.hpp @@ -5,13 +5,10 @@ namespace Slic3r { -typedef std::vector Surfaces; - class SurfaceCollection { public: - Surfaces surfaces; - SV* arrayref(); + SurfacesPtr surfaces; }; } diff --git a/xs/t/12_extrusionpathcollection.t b/xs/t/12_extrusionpathcollection.t new file mode 100644 index 000000000..97be65772 --- /dev/null +++ b/xs/t/12_extrusionpathcollection.t @@ -0,0 +1,37 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Slic3r::XS; +use Test::More tests => 5; + +my $points = [ + [100, 100], + [200, 100], + [200, 200], +]; + +my $path = Slic3r::ExtrusionPath->new( + polyline => Slic3r::Polyline->new(@$points), + role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, +); + +my $loop = Slic3r::ExtrusionLoop->new( + polygon => Slic3r::Polygon->new(@$points), + role => Slic3r::ExtrusionPath::EXTR_ROLE_FILL, +); + +my $collection = Slic3r::ExtrusionPath::Collection->new; +isa_ok $collection, 'Slic3r::ExtrusionPath::Collection', 'collection object'; + +$collection->append($path); +is scalar(@$collection), 1, 'append ExtrusionPath'; + +$collection->append($loop); +is scalar(@$collection), 2, 'append ExtrusionLoop'; + +isa_ok $collection->[0], 'Slic3r::ExtrusionPath', 'correct object returned for path'; +isa_ok $collection->[1], 'Slic3r::ExtrusionLoop', 'correct object returned for loop'; + +__END__ diff --git a/xs/xsp/ExPolygonCollection.xsp b/xs/xsp/ExPolygonCollection.xsp index a8eafa541..253a83266 100644 --- a/xs/xsp/ExPolygonCollection.xsp +++ b/xs/xsp/ExPolygonCollection.xsp @@ -24,8 +24,9 @@ ExPolygonCollection::new(...) RETVAL->expolygons.resize(items-1); for (unsigned int i = 1; i < items; i++) { // Note: a COPY of the input is stored - RETVAL->expolygons[i-1].from_SV_check(ST(i)); - RETVAL->expolygons[i-1].in_collection = true; + RETVAL->expolygons[i-1] = new ExPolygon; + RETVAL->expolygons[i-1]->from_SV_check(ST(i)); + RETVAL->expolygons[i-1]->in_collection = true; } OUTPUT: RETVAL @@ -36,9 +37,9 @@ ExPolygonCollection::arrayref() AV* av = newAV(); av_fill(av, THIS->expolygons.size()-1); int i = 0; - for (ExPolygons::iterator it = THIS->expolygons.begin(); it != THIS->expolygons.end(); ++it) { + for (ExPolygonsPtr::iterator it = THIS->expolygons.begin(); it != THIS->expolygons.end(); ++it) { SV* sv = newSV(0); - sv_setref_pv( sv, "Slic3r::ExPolygon", &*it ); + sv_setref_pv( sv, "Slic3r::ExPolygon", *it ); av_store(av, i++, sv); } RETVAL = newRV_noinc((SV*)av); @@ -51,8 +52,8 @@ ExPolygonCollection::pp() AV* av = newAV(); av_fill(av, THIS->expolygons.size()-1); int i = 0; - for (ExPolygons::iterator it = THIS->expolygons.begin(); it != THIS->expolygons.end(); ++it) { - av_store(av, i++, (*it).to_SV_pureperl()); + for (ExPolygonsPtr::iterator it = THIS->expolygons.begin(); it != THIS->expolygons.end(); ++it) { + av_store(av, i++, (*it)->to_SV_pureperl()); } RETVAL = newRV_noinc((SV*)av); OUTPUT: @@ -62,9 +63,9 @@ void ExPolygonCollection::append(...) CODE: for (unsigned int i = 1; i < items; i++) { - ExPolygon expolygon; - expolygon.from_SV_check( ST(i) ); - expolygon.in_collection = true; + ExPolygon* expolygon = new ExPolygon; + expolygon->from_SV_check( ST(i) ); + expolygon->in_collection = true; THIS->expolygons.push_back(expolygon); } diff --git a/xs/xsp/ExtrusionEntityCollection.xsp b/xs/xsp/ExtrusionEntityCollection.xsp new file mode 100644 index 000000000..5715f1899 --- /dev/null +++ b/xs/xsp/ExtrusionEntityCollection.xsp @@ -0,0 +1,59 @@ +%module{Slic3r::XS}; + +%{ +#include +#include "ExtrusionEntityCollection.hpp" +%} + +%name{Slic3r::ExtrusionPath::Collection} class ExtrusionEntityCollection { + ExtrusionEntityCollection(); + ~ExtrusionEntityCollection(); + void clear() + %code{% THIS->entities.clear(); %}; +%{ + +SV* +ExtrusionEntityCollection::arrayref() + CODE: + AV* av = newAV(); + av_fill(av, THIS->entities.size()-1); + int i = 0; + for (ExtrusionEntitiesPtr::iterator it = THIS->entities.begin(); it != THIS->entities.end(); ++it) { + SV* sv = newSV(0); + // return COPIES + if (ExtrusionPath* path = dynamic_cast(*it)) { + sv_setref_pv( sv, "Slic3r::ExtrusionPath", new ExtrusionPath(*(ExtrusionPath*)*it) ); + } else { + sv_setref_pv( sv, "Slic3r::ExtrusionLoop", new ExtrusionLoop(*(ExtrusionLoop*)*it) ); + } + av_store(av, i++, sv); + } + RETVAL = newRV_noinc((SV*)av); + OUTPUT: + RETVAL + +void +ExtrusionEntityCollection::append(...) + CODE: + for (unsigned int i = 1; i < items; i++) { + ExtrusionEntity* entity = (ExtrusionEntity *)SvIV((SV*)SvRV( ST(i) )); + // append COPIES + if (ExtrusionPath* path = dynamic_cast(entity)) { + THIS->entities.push_back( new ExtrusionPath(*path) ); + } else { + THIS->entities.push_back( new ExtrusionLoop(*(ExtrusionLoop*)entity) ); + } + } + +bool +ExtrusionEntityCollection::no_sort(...) + CODE: + if (items > 1) { + THIS->no_sort = SvTRUE(ST(1)); + } + RETVAL = THIS->no_sort; + OUTPUT: + RETVAL + +%} +}; diff --git a/xs/xsp/SurfaceCollection.xsp b/xs/xsp/SurfaceCollection.xsp index 42f59815a..6cea6af1e 100644 --- a/xs/xsp/SurfaceCollection.xsp +++ b/xs/xsp/SurfaceCollection.xsp @@ -19,8 +19,8 @@ SurfaceCollection::new(...) RETVAL->surfaces.resize(items-1); for (unsigned int i = 1; i < items; i++) { // Note: a COPY of the input is stored - RETVAL->surfaces[i-1] = *(Surface *)SvIV((SV*)SvRV( ST(i) )); - RETVAL->surfaces[i-1].in_collection = true; + RETVAL->surfaces[i-1] = (Surface *)SvIV((SV*)SvRV( ST(i) )); + RETVAL->surfaces[i-1]->in_collection = true; } OUTPUT: RETVAL @@ -31,9 +31,9 @@ SurfaceCollection::arrayref() 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) { + for (SurfacesPtr::iterator it = THIS->surfaces.begin(); it != THIS->surfaces.end(); ++it) { SV* sv = newSV(0); - sv_setref_pv( sv, "Slic3r::Surface", &*it ); + sv_setref_pv( sv, "Slic3r::Surface", *it ); av_store(av, i++, sv); } RETVAL = newRV_noinc((SV*)av); @@ -44,8 +44,8 @@ void SurfaceCollection::append(...) CODE: for (unsigned int i = 1; i < items; i++) { - THIS->surfaces.push_back(*(Surface *)SvIV((SV*)SvRV( ST(i) ))); - THIS->surfaces.back().in_collection = true; + THIS->surfaces.push_back((Surface *)SvIV((SV*)SvRV( ST(i) ))); + THIS->surfaces.back()->in_collection = true; } %} diff --git a/xs/xsp/my.map b/xs/xsp/my.map index d26060ede..dd4c63704 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -6,6 +6,7 @@ Polyline* O_OBJECT Polygon* O_OBJECT ExPolygon* O_OBJECT ExPolygonCollection* O_OBJECT +ExtrusionEntityCollection* O_OBJECT ExtrusionPath* O_OBJECT ExtrusionLoop* O_OBJECT Surface* O_OBJECT diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index adaf0c17e..a4ac930d7 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -7,6 +7,7 @@ %typemap{ExPolygon*}; %typemap{Polyline*}; %typemap{Polygon*}; +%typemap{ExtrusionEntityCollection*}; %typemap{ExtrusionPath*}; %typemap{ExtrusionLoop*}; %typemap{Lines};