diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index 5ea7b2a8c..b8d464af6 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -28,17 +28,6 @@ sub print { return $_[0]->layer->print; } sub config { return $_[0]->region->config; } -sub merge_slices { - my ($self) = @_; - - my $expolygons = union_ex([ map $_->p, @{$self->slices} ]); - $self->slices->clear; - $self->slices->append(Slic3r::Surface->new( - expolygon => $_, - surface_type => S_TYPE_INTERNAL, - )) for @$expolygons; -} - sub make_perimeters { my ($self, $slices, $fill_surfaces) = @_; @@ -177,7 +166,7 @@ sub make_perimeters { ); foreach my $gap_size (@gap_sizes) { my @gap_fill = $self->_fill_gaps(@$gap_size, \@gaps); - $self->thin_fills->append(@gap_fill); + $self->thin_fills->append($_) for @gap_fill; # Make sure we don't infill narrow parts that are already gap-filled # (we only consider this surface's gaps to reduce the diff() complexity). @@ -199,14 +188,13 @@ sub make_perimeters { # and then we offset back and forth by half the infill spacing to only consider the # non-collapsing regions my $min_perimeter_infill_spacing = $ispacing * (1 - &Slic3r::INSET_OVERLAP_TOLERANCE); - $fill_surfaces->append( - map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_INTERNAL), # use a bogus surface type - @{offset2_ex( - [ map @{$_->simplify_p(&Slic3r::SCALED_RESOLUTION)}, @{union_ex(\@last)} ], - -($pspacing/2 + $min_perimeter_infill_spacing/2), - +$min_perimeter_infill_spacing/2, - )} - ); + $fill_surfaces->append($_) + for map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_INTERNAL), # use a bogus surface type + @{offset2_ex( + [ map @{$_->simplify_p(&Slic3r::SCALED_RESOLUTION)}, @{union_ex(\@last)} ], + -($pspacing/2 + $min_perimeter_infill_spacing/2), + +$min_perimeter_infill_spacing/2, + )}; } @@ -245,9 +233,8 @@ sub make_perimeters { # lower layer, so we take lower slices and offset them by half the nozzle diameter used # in the current layer my $nozzle_diameter = $self->layer->print->config->get_at('nozzle_diameter', $self->region->config->perimeter_extruder-1); - $lower_slices->append( - @{offset_ex([ map @$_, @{$self->layer->lower_layer->slices} ], scale +$nozzle_diameter/2)}, - ); + $lower_slices->append($_) + for @{offset_ex([ map @$_, @{$self->layer->lower_layer->slices} ], scale +$nozzle_diameter/2)}; } my $lower_slices_p = $lower_slices->polygons; @@ -418,7 +405,7 @@ sub make_perimeters { || ($self->layer->id == 0 && $self->print->config->brim_width > 0); # append perimeters - $self->perimeters->append(@loops); + $self->perimeters->append($_) for @loops; } sub _fill_gaps { @@ -508,8 +495,8 @@ sub process_external_surfaces { $angle = $bridge_detector->detect_angle; if (defined $angle && $self->object->config->support_material) { - $self->bridged->append(@{ $bridge_detector->coverage($angle) }); - $self->unsupported_bridge_edges->append(@{ $bridge_detector->unsupported_edges }); + $self->bridged->append($_) for @{ $bridge_detector->coverage($angle) }; + $self->unsupported_bridge_edges->append($_) for @{ $bridge_detector->unsupported_edges }; } } @@ -553,7 +540,7 @@ sub process_external_surfaces { )}; } $self->fill_surfaces->clear; - $self->fill_surfaces->append(@new_surfaces); + $self->fill_surfaces->append($_) for @new_surfaces; } 1; diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 3948f1ca6..584ed11b6 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -315,11 +315,10 @@ sub slice { ); $layerm->slices->clear; - $layerm->slices->append( - map Slic3r::Surface->new + $layerm->slices->append($_) + for map Slic3r::Surface->new (expolygon => $_, surface_type => S_TYPE_INTERNAL), - @$diff - ); + @$diff; } # update layer slices after repairing the single regions @@ -542,14 +541,14 @@ sub infill { my ($i, $region_id) = @$obj_layer; my $layerm = $self->get_layer($i)->regions->[$region_id]; $layerm->fills->clear; - $layerm->fills->append( $self->fill_maker->make_fill($layerm) ); + $layerm->fills->append($_) for $self->fill_maker->make_fill($layerm); } }, collect_cb => sub {}, no_threads_cb => sub { foreach my $layerm (map @{$_->regions}, @{$self->layers}) { $layerm->fills->clear; - $layerm->fills->append($self->fill_maker->make_fill($layerm)); + $layerm->fills->append($_) for $self->fill_maker->make_fill($layerm); } }, ); @@ -705,7 +704,7 @@ sub detect_surfaces_type { # save surfaces to layer $layerm->slices->clear; - $layerm->slices->append(@bottom, @top, @internal); + $layerm->slices->append($_) for (@bottom, @top, @internal); Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n", $layerm->id, scalar(@bottom), scalar(@top), scalar(@internal) if $Slic3r::debug; @@ -725,9 +724,9 @@ sub detect_surfaces_type { [ $surface->p ], $fill_boundaries, ); - $layerm->fill_surfaces->append(map Slic3r::Surface->new - (expolygon => $_, surface_type => $surface->surface_type), - @$intersection); + $layerm->fill_surfaces->append($_) + for map Slic3r::Surface->new(expolygon => $_, surface_type => $surface->surface_type), + @$intersection; } } } @@ -772,7 +771,7 @@ sub clip_fill_surfaces { )}; $layerm->fill_surfaces->clear; - $layerm->fill_surfaces->append(@new, @other); + $layerm->fill_surfaces->append($_) for (@new, @other); } # get this layer's overhangs defined as the full slice minus the internal infill @@ -827,7 +826,7 @@ sub bridge_over_infill { 1, )}; $layerm->fill_surfaces->clear; - $layerm->fill_surfaces->append(@new_surfaces); + $layerm->fill_surfaces->append($_) for @new_surfaces; } # exclude infill from the layers below if needed @@ -855,7 +854,7 @@ sub bridge_over_infill { )}; } $lower_layerm->fill_surfaces->clear; - $lower_layerm->fill_surfaces->append(@new_surfaces); + $lower_layerm->fill_surfaces->append($_) for @new_surfaces; } $excess -= $self->get_layer($i)->height; @@ -1001,12 +1000,14 @@ sub discover_horizontal_shells { # assign resulting internal surfaces to layer $neighbor_fill_surfaces->clear; - $neighbor_fill_surfaces->append(map Slic3r::Surface->new - (expolygon => $_, surface_type => S_TYPE_INTERNAL), @$internal); + $neighbor_fill_surfaces->append($_) + for map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_INTERNAL), + @$internal; # assign new internal-solid surfaces to layer - $neighbor_fill_surfaces->append(map Slic3r::Surface->new - (expolygon => $_, surface_type => S_TYPE_INTERNALSOLID), @$internal_solid); + $neighbor_fill_surfaces->append($_) + for map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_INTERNALSOLID), + @$internal_solid; # assign top and bottom surfaces to layer foreach my $s (@{Slic3r::Surface::Collection->new(grep { ($_->surface_type == S_TYPE_TOP) || $_->is_bottom } @neighbor_fill_surfaces)->group}) { @@ -1015,7 +1016,8 @@ sub discover_horizontal_shells { [ map @$_, @$internal_solid, @$internal ], 1, ); - $neighbor_fill_surfaces->append(map $s->[0]->clone(expolygon => $_), @$solid_surfaces); + $neighbor_fill_surfaces->append($_) + for map $s->[0]->clone(expolygon => $_), @$solid_surfaces; } } } @@ -1129,7 +1131,7 @@ sub combine_infill { } $layerm->fill_surfaces->clear; - $layerm->fill_surfaces->append(@new_this_type, @other_types); + $layerm->fill_surfaces->append($_) for (@new_this_type, @other_types); } } } diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index a1f4a02b8..4e112eda4 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -178,6 +178,14 @@ use overload '@{}' => sub { $_[0]->arrayref }, 'fallback' => 1; +sub new { + my ($class, @surfaces) = @_; + + my $self = $class->_new; + $self->append($_) for @surfaces; + return $self; +} + package main; for my $class (qw( Slic3r::Config diff --git a/xs/src/libslic3r/Layer.hpp b/xs/src/libslic3r/Layer.hpp index cea1535b0..cd0250089 100644 --- a/xs/src/libslic3r/Layer.hpp +++ b/xs/src/libslic3r/Layer.hpp @@ -52,6 +52,7 @@ class LayerRegion ExtrusionEntityCollection fills; Flow flow(FlowRole role, bool bridge = false, double width = -1) const; + void merge_slices(); private: Layer *_layer; diff --git a/xs/src/libslic3r/LayerRegion.cpp b/xs/src/libslic3r/LayerRegion.cpp index cb92c4ee3..49521ff88 100644 --- a/xs/src/libslic3r/LayerRegion.cpp +++ b/xs/src/libslic3r/LayerRegion.cpp @@ -1,5 +1,7 @@ #include "Layer.hpp" +#include "ClipperUtils.hpp" #include "Print.hpp" +#include "Surface.hpp" namespace Slic3r { @@ -38,6 +40,18 @@ LayerRegion::flow(FlowRole role, bool bridge, double width) const ); } +void +LayerRegion::merge_slices() +{ + ExPolygons expp; + union_(this->slices, expp); + this->slices.surfaces.clear(); + this->slices.surfaces.reserve(expp.size()); + + for (ExPolygons::const_iterator expoly = expp.begin(); expoly != expp.end(); ++expoly) + this->slices.surfaces.push_back(Surface(stInternal, *expoly)); +} + #ifdef SLIC3RXS REGISTER_CLASS(LayerRegion, "Layer::Region"); #endif diff --git a/xs/src/libslic3r/Surface.hpp b/xs/src/libslic3r/Surface.hpp index ce0f02477..c98567cf0 100644 --- a/xs/src/libslic3r/Surface.hpp +++ b/xs/src/libslic3r/Surface.hpp @@ -10,12 +10,17 @@ enum SurfaceType { stTop, stBottom, stBottomBridge, stInternal, stInternalSolid, class Surface { public: - ExPolygon expolygon; SurfaceType surface_type; + ExPolygon expolygon; double thickness; // in mm unsigned short thickness_layers; // in layers double bridge_angle; // in radians, ccw, 0 = East, only 0+ (negative means undefined) unsigned short extra_perimeters; + + Surface(SurfaceType _surface_type, const ExPolygon &_expolygon) + : surface_type(_surface_type), expolygon(_expolygon), + thickness(-1), thickness_layers(1), bridge_angle(-1), extra_perimeters(0) + {}; double area() const; bool is_solid() const; bool is_external() const; diff --git a/xs/t/05_surface.t b/xs/t/05_surface.t index 9c3e7dc95..34feb4734 100644 --- a/xs/t/05_surface.t +++ b/xs/t/05_surface.t @@ -48,7 +48,8 @@ is $surface->extra_perimeters, 2, 'extra_perimeters'; } { - my $collection = Slic3r::Surface::Collection->new($surface, $surface->clone); + my $collection = Slic3r::Surface::Collection->new; + $collection->append($_) for $surface, $surface->clone; is scalar(@$collection), 2, 'collection has the right number of items'; is_deeply $collection->[0]->expolygon->pp, [$square, $hole_in_square], 'collection returns a correct surface expolygon'; @@ -64,12 +65,11 @@ is $surface->extra_perimeters, 2, 'extra_perimeters'; } { - my @surfaces = ( + my $collection = Slic3r::Surface::Collection->new; + $collection->append($_) for Slic3r::Surface->new(expolygon => $expolygon, surface_type => Slic3r::Surface::S_TYPE_BOTTOM), Slic3r::Surface->new(expolygon => $expolygon, surface_type => Slic3r::Surface::S_TYPE_BOTTOM), - Slic3r::Surface->new(expolygon => $expolygon, surface_type => Slic3r::Surface::S_TYPE_TOP), - ); - my $collection = Slic3r::Surface::Collection->new(@surfaces); + Slic3r::Surface->new(expolygon => $expolygon, surface_type => Slic3r::Surface::S_TYPE_TOP); is scalar(@{$collection->group}), 2, 'group() returns correct number of groups'; } diff --git a/xs/xsp/Layer.xsp b/xs/xsp/Layer.xsp index b758989e6..2d6ec99e2 100644 --- a/xs/xsp/Layer.xsp +++ b/xs/xsp/Layer.xsp @@ -28,6 +28,7 @@ Flow* flow(FlowRole role, bool bridge = false, double width = -1) %code%{ RETVAL = new Flow(THIS->flow(role, bridge, width)); %}; + void merge_slices(); }; %name{Slic3r::Layer} class Layer { diff --git a/xs/xsp/Surface.xsp b/xs/xsp/Surface.xsp index 11c7ec744..e2f5112e2 100644 --- a/xs/xsp/Surface.xsp +++ b/xs/xsp/Surface.xsp @@ -31,9 +31,7 @@ _new(CLASS, expolygon, surface_type, thickness, thickness_layers, bridge_angle, double bridge_angle; unsigned short extra_perimeters; CODE: - RETVAL = new Surface (); - RETVAL->expolygon = *expolygon; - RETVAL->surface_type = surface_type; + RETVAL = new Surface (surface_type, *expolygon); RETVAL->thickness = thickness; RETVAL->thickness_layers = thickness_layers; RETVAL->bridge_angle = bridge_angle; diff --git a/xs/xsp/SurfaceCollection.xsp b/xs/xsp/SurfaceCollection.xsp index ea6a6b7bf..b07bdb3a2 100644 --- a/xs/xsp/SurfaceCollection.xsp +++ b/xs/xsp/SurfaceCollection.xsp @@ -6,27 +6,17 @@ %} %name{Slic3r::Surface::Collection} class SurfaceCollection { + %name{_new} SurfaceCollection(); ~SurfaceCollection(); void clear() %code{% THIS->surfaces.clear(); %}; + void append(Surface* surface) + %code{% THIS->surfaces.push_back(*surface); %}; int count() %code{% RETVAL = THIS->surfaces.size(); %}; void simplify(double tolerance); %{ -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++) { - // Note: a COPY of the input is stored - RETVAL->surfaces[i-1].from_SV_check(ST(i)); - } - OUTPUT: - RETVAL - SV* SurfaceCollection::arrayref() CODE: @@ -52,15 +42,6 @@ SurfaceCollection::filter_by_type(surface_type) OUTPUT: RETVAL -void -SurfaceCollection::append(...) - CODE: - for (unsigned int i = 1; i < items; i++) { - Surface surface; - surface.from_SV_check( ST(i) ); - THIS->surfaces.push_back(surface); - } - void SurfaceCollection::replace(index, surface) int index diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index 87283debf..01718a8cb 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -83,6 +83,10 @@ %typemap{Ref}{simple}; %typemap{Clone}{simple}; +%typemap{Surface*}; +%typemap{Ref}{simple}; +%typemap{Clone}{simple}; + %typemap{PrintState*}; %typemap{Ref}{simple};