diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index c128d0eb3..43a88120d 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -64,8 +64,54 @@ sub make_fill { { my @surfaces_with_bridge_angle = grep defined $_->bridge_angle, @{$layerm->fill_surfaces}; + # group surfaces by distinct properties + my @groups = @{$layerm->fill_surfaces->group}; + + # merge compatible groups (we can generate continuous infill for them) + { + # cache flow widths and patterns used for all solid groups + # (we'll use them for comparing compatible groups) + my @is_solid = my @fw = my @pattern = (); + for (my $i = 0; $i <= $#groups; $i++) { + # we can only merge solid non-bridge surfaces, so discard + # non-solid surfaces + if ($groups[$i][0]->is_solid && (!$groups[$i][0]->is_bridge || $layerm->id == 0)) { + $is_solid[$i] = 1; + $fw[$i] = ($groups[$i][0]->surface_type == S_TYPE_TOP) + ? $layerm->flow(FLOW_ROLE_TOP_SOLID_INFILL)->width + : $solid_infill_flow->width; + $pattern[$i] = $groups[$i][0]->is_external + ? $layerm->config->solid_fill_pattern + : 'rectilinear'; + } else { + $is_solid[$i] = 0; + $fw[$i] = 0; + $pattern[$i] = 'none'; + } + } + + # loop through solid groups + for (my $i = 0; $i <= $#groups; $i++) { + next if !$is_solid[$i]; + + # find compatible groups and append them to this one + for (my $j = $i+1; $j <= $#groups; $j++) { + next if !$is_solid[$j]; + + if ($fw[$i] == $fw[$j] && $pattern[$i] eq $pattern[$j]) { + # groups are compatible, merge them + push @{$groups[$i]}, @{$groups[$j]}; + splice @groups, $j, 1; + splice @is_solid, $j, 1; + splice @fw, $j, 1; + splice @pattern, $j, 1; + } + } + } + } + # give priority to bridges - my @groups = sort { defined $a->[0]->bridge_angle ? -1 : 0 } @{$layerm->fill_surfaces->group(1)}; + @groups = sort { defined $a->[0]->bridge_angle ? -1 : 0 } @groups; foreach my $group (@groups) { my $union_p = union([ map $_->p, @$group ], 1); diff --git a/xs/src/Surface.cpp b/xs/src/Surface.cpp index e82cf8079..4f3b5b96a 100644 --- a/xs/src/Surface.cpp +++ b/xs/src/Surface.cpp @@ -16,6 +16,13 @@ Surface::is_solid() const || this->surface_type == stInternalSolid; } +bool +Surface::is_external() const +{ + return this->surface_type == stTop + || this->surface_type == stBottom; +} + bool Surface::is_bridge() const { diff --git a/xs/src/Surface.hpp b/xs/src/Surface.hpp index cf89b1ac6..6d6fec1de 100644 --- a/xs/src/Surface.hpp +++ b/xs/src/Surface.hpp @@ -18,6 +18,7 @@ class Surface unsigned short extra_perimeters; double area() const; bool is_solid() const; + bool is_external() const; bool is_bridge() const; #ifdef SLIC3RXS diff --git a/xs/src/SurfaceCollection.cpp b/xs/src/SurfaceCollection.cpp index fb63d3333..16e1ee583 100644 --- a/xs/src/SurfaceCollection.cpp +++ b/xs/src/SurfaceCollection.cpp @@ -21,14 +21,14 @@ SurfaceCollection::simplify(double tolerance) /* group surfaces by common properties */ void -SurfaceCollection::group(std::vector *retval, bool merge_solid) +SurfaceCollection::group(std::vector *retval) { for (Surfaces::iterator it = this->surfaces.begin(); it != this->surfaces.end(); ++it) { // find a group with the same properties SurfacesPtr* group = NULL; for (std::vector::iterator git = retval->begin(); git != retval->end(); ++git) { Surface* gkey = git->front(); - if ((gkey->surface_type == it->surface_type || (merge_solid && gkey->is_solid() && it->is_solid())) + if ( gkey->surface_type == it->surface_type && gkey->thickness == it->thickness && gkey->thickness_layers == it->thickness_layers && gkey->bridge_angle == it->bridge_angle) { diff --git a/xs/src/SurfaceCollection.hpp b/xs/src/SurfaceCollection.hpp index dc5ebc115..cb8088c47 100644 --- a/xs/src/SurfaceCollection.hpp +++ b/xs/src/SurfaceCollection.hpp @@ -11,7 +11,7 @@ class SurfaceCollection public: Surfaces surfaces; void simplify(double tolerance); - void group(std::vector *retval, bool merge_solid = false); + void group(std::vector *retval); }; } diff --git a/xs/t/05_surface.t b/xs/t/05_surface.t index 493a74b52..9c3e7dc95 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 => 16; +use Test::More tests => 15; my $square = [ # ccw [100, 100], @@ -71,7 +71,6 @@ is $surface->extra_perimeters, 2, 'extra_perimeters'; ); my $collection = Slic3r::Surface::Collection->new(@surfaces); is scalar(@{$collection->group}), 2, 'group() returns correct number of groups'; - is scalar(@{$collection->group(1)}), 1, 'group() returns correct number of solid groups'; } __END__ diff --git a/xs/xsp/Surface.xsp b/xs/xsp/Surface.xsp index bc2367169..466ada1b7 100644 --- a/xs/xsp/Surface.xsp +++ b/xs/xsp/Surface.xsp @@ -16,6 +16,7 @@ %code{% RETVAL = THIS->thickness_layers; %}; double area(); bool is_solid() const; + bool is_external() const; bool is_bridge() const; %{ diff --git a/xs/xsp/SurfaceCollection.xsp b/xs/xsp/SurfaceCollection.xsp index 6665a0a24..4bc2fc167 100644 --- a/xs/xsp/SurfaceCollection.xsp +++ b/xs/xsp/SurfaceCollection.xsp @@ -76,12 +76,11 @@ SurfaceCollection::set_surface_type(index, surface_type) THIS->surfaces[index].surface_type = surface_type; SV* -SurfaceCollection::group(merge_solid = false) - bool merge_solid +SurfaceCollection::group() CODE: // perform grouping std::vector groups; - THIS->group(&groups, merge_solid); + THIS->group(&groups); // build return arrayref AV* av = newAV();