New Slic3r::Surface::Collection class

This commit is contained in:
Alessandro Ranellucci 2013-07-14 14:56:43 +02:00
parent 0099218f61
commit 5885be881c
8 changed files with 115 additions and 16 deletions

View File

@ -36,7 +36,7 @@ has 'thin_walls' => (is => 'rw', default => sub { [] });
has 'thin_fills' => (is => 'rw', default => sub { [] }); has 'thin_fills' => (is => 'rw', default => sub { [] });
# collection of surfaces for infill generation # 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 # ordered collection of extrusion paths/loops to build all perimeters
has 'perimeters' => (is => 'rw', default => sub { [] }); has 'perimeters' => (is => 'rw', default => sub { [] });
@ -158,7 +158,7 @@ sub make_perimeters {
my $gap_area_threshold = $self->perimeter_flow->scaled_width ** 2; my $gap_area_threshold = $self->perimeter_flow->scaled_width ** 2;
$self->perimeters([]); $self->perimeters([]);
$self->fill_surfaces([]); $self->fill_surfaces->clear;
$self->thin_fills([]); $self->thin_fills([]);
my @contours = (); # array of Polygons with ccw orientation my @contours = (); # array of Polygons with ccw orientation
@ -208,11 +208,13 @@ sub make_perimeters {
# we offset by half the perimeter spacing (to get to the actual infill boundary) # 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 # and then we offset back and forth by the infill spacing to only consider the
# non-collapsing regions # non-collapsing regions
push @{ $self->fill_surfaces }, # use a bogus surface_type
offset2_ex( $self->fill_surfaces->append(
map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_TOP), offset2_ex(
[ map $_->simplify(&Slic3r::SCALED_RESOLUTION), @last ], [ map $_->simplify(&Slic3r::SCALED_RESOLUTION), @last ],
-($perimeter_spacing/2 + $infill_spacing), -($perimeter_spacing/2 + $infill_spacing),
+$infill_spacing, +$infill_spacing,
)
); );
} }
@ -452,7 +454,8 @@ sub process_external_surfaces {
[ map $_->p, @new_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) # detect bridge direction (skip bottom layer)

View File

@ -428,7 +428,7 @@ sub export_gcode {
} }
# free memory (note that support material needs fill_surfaces) # 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 # make skirt
$status_cb->(88, "Generating skirt"); $status_cb->(88, "Generating skirt");

View File

@ -427,16 +427,16 @@ sub detect_surfaces_type {
# clip surfaces to the fill boundaries # clip surfaces to the fill boundaries
foreach my $layer (@{$self->layers}) { foreach my $layer (@{$self->layers}) {
my $layerm = $layer->regions->[$region_id]; my $layerm = $layer->regions->[$region_id];
my $fill_boundaries = [ map @$_, @{$layerm->fill_surfaces} ]; my $fill_boundaries = [ map $_->p, @{$layerm->fill_surfaces} ];
@{$layerm->fill_surfaces} = (); $layerm->fill_surfaces->clear;
foreach my $surface (@{$layerm->slices}) { foreach my $surface (@{$layerm->slices}) {
my $intersection = intersection_ex( my $intersection = intersection_ex(
[ $surface->p ], [ $surface->p ],
$fill_boundaries, $fill_boundaries,
); );
push @{$layerm->fill_surfaces}, map Slic3r::Surface->new $layerm->fill_surfaces->append(map Slic3r::Surface->new
(expolygon => $_, surface_type => $surface->surface_type), (expolygon => $_, surface_type => $surface->surface_type),
@$intersection; @$intersection);
} }
} }
} }
@ -465,10 +465,12 @@ sub clip_fill_surfaces {
[ map @$_, @overhangs ], [ map @$_, @overhangs ],
[ map @{$_->expolygon}, grep $_->surface_type == S_TYPE_INTERNAL, @{$layerm->fill_surfaces} ], [ map @{$_->expolygon}, grep $_->surface_type == S_TYPE_INTERNAL, @{$layerm->fill_surfaces} ],
)}; )};
@{$layerm->fill_surfaces} = ( my @new_surfaces = (
@new_internal, @new_internal,
(grep $_->surface_type != S_TYPE_INTERNAL, @{$layerm->fill_surfaces}), (grep $_->surface_type != S_TYPE_INTERNAL, @{$layerm->fill_surfaces}),
); );
$layerm->fill_surfaces->clear;
$layerm->fill_surfaces->append(@new_surfaces);
} }
# get this layer's overhangs # get this layer's overhangs
@ -523,7 +525,8 @@ sub bridge_over_infill {
[ map @$_, @$to_bridge ], [ map @$_, @$to_bridge ],
1, 1,
)}; )};
@{$layerm->fill_surfaces} = @new_surfaces; $layerm->fill_surfaces->clear;
$layerm->fill_surfaces->append(@new_surfaces);
} }
# exclude infill from the layers below if needed # exclude infill from the layers below if needed
@ -550,7 +553,8 @@ sub bridge_over_infill {
[ map @$_, @$to_bridge ], [ 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; $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);
} }
} }
} }

View File

@ -60,4 +60,8 @@ sub clone {
); );
} }
package Slic3r::Surface::Collection;
use overload
'@{}' => sub { $_[0]->arrayref };
1; 1;

View File

@ -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<Surface> Surfaces;
class SurfaceCollection
{
public:
Surfaces surfaces;
SV* arrayref();
};
}
#endif

View File

@ -4,7 +4,7 @@ use strict;
use warnings; use warnings;
use Slic3r::XS; use Slic3r::XS;
use Test::More tests => 6; use Test::More tests => 10;
my $square = [ # ccw my $square = [ # ccw
[100, 100], [100, 100],
@ -40,4 +40,15 @@ is $surface->bridge_angle, 30, 'bridge_angle';
$surface->extra_perimeters(2); $surface->extra_perimeters(2);
is $surface->extra_perimeters, 2, 'extra_perimeters'; 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__ __END__

View File

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

View File

@ -5,3 +5,4 @@ ExPolygon* O_OBJECT
ExPolygonCollection* O_OBJECT ExPolygonCollection* O_OBJECT
SurfaceType T_UV SurfaceType T_UV
Surface* O_OBJECT Surface* O_OBJECT
SurfaceCollection* O_OBJECT