diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 0f6636a6c..93b69a0fa 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -760,82 +760,6 @@ sub clip_fill_surfaces { } } -sub bridge_over_infill { - my $self = shift; - - for my $region_id (0..($self->print->region_count - 1)) { - my $fill_density = $self->print->regions->[$region_id]->config->fill_density; - next if $fill_density == 100 || $fill_density == 0; - - for my $layer_id (1..($self->layer_count - 1)) { - my $layer = $self->get_layer($layer_id); - my $layerm = $layer->regions->[$region_id]; - my $lower_layer = $self->get_layer($layer_id-1); - - # compute the areas needing bridge math - my @internal_solid = @{$layerm->fill_surfaces->filter_by_type(S_TYPE_INTERNALSOLID)}; - my @lower_internal = map @{$_->fill_surfaces->filter_by_type(S_TYPE_INTERNAL)}, @{$lower_layer->regions}; - my $to_bridge = intersection_ex( - [ map $_->p, @internal_solid ], - [ map $_->p, @lower_internal ], - ); - next unless @$to_bridge; - Slic3r::debugf "Bridging %d internal areas at layer %d\n", scalar(@$to_bridge), $layer_id; - - # build the new collection of fill_surfaces - { - my @new_surfaces = map $_->clone, grep $_->surface_type != S_TYPE_INTERNALSOLID, @{$layerm->fill_surfaces}; - push @new_surfaces, map Slic3r::Surface->new( - expolygon => $_, - surface_type => S_TYPE_INTERNALBRIDGE, - ), @$to_bridge; - push @new_surfaces, map Slic3r::Surface->new( - expolygon => $_, - surface_type => S_TYPE_INTERNALSOLID, - ), @{diff_ex( - [ map $_->p, @internal_solid ], - [ map @$_, @$to_bridge ], - 1, - )}; - $layerm->fill_surfaces->clear; - $layerm->fill_surfaces->append($_) for @new_surfaces; - } - - # exclude infill from the layers below if needed - # see discussion at https://github.com/alexrj/Slic3r/issues/240 - # Update: do not exclude any infill. Sparse infill is able to absorb the excess material. - if (0) { - my $excess = $layerm->extruders->{infill}->bridge_flow->width - $layerm->height; - for (my $i = $layer_id-1; $excess >= $self->get_layer($i)->height; $i--) { - Slic3r::debugf " skipping infill below those areas at layer %d\n", $i; - foreach my $lower_layerm (@{$self->get_layer($i)->regions}) { - my @new_surfaces = (); - # subtract the area from all types of surfaces - foreach my $group (@{$lower_layerm->fill_surfaces->group}) { - push @new_surfaces, map $group->[0]->clone(expolygon => $_), - @{diff_ex( - [ map $_->p, @$group ], - [ map @$_, @$to_bridge ], - )}; - push @new_surfaces, map Slic3r::Surface->new( - expolygon => $_, - surface_type => S_TYPE_INTERNALVOID, - ), @{intersection_ex( - [ map $_->p, @$group ], - [ map @$_, @$to_bridge ], - )}; - } - $lower_layerm->fill_surfaces->clear; - $lower_layerm->fill_surfaces->append($_) for @new_surfaces; - } - - $excess -= $self->get_layer($i)->height; - } - } - } - } -} - sub process_external_surfaces { my ($self) = @_; diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp index 2a86f2a26..ba243ee82 100644 --- a/xs/src/libslic3r/ClipperUtils.cpp +++ b/xs/src/libslic3r/ClipperUtils.cpp @@ -425,6 +425,18 @@ template void diff(const Slic3r::Polygons & template void diff(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); template void diff(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_); +template +void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_) +{ + Slic3r::Polygons pp; + for (Slic3r::ExPolygons::const_iterator ex = clip.begin(); ex != clip.end(); ++ex) { + Slic3r::Polygons ppp = *ex; + pp.insert(pp.end(), ppp.begin(), ppp.end()); + } + diff(subject, pp, retval, safety_offset_); +} +template void diff(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_); + template void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_) { diff --git a/xs/src/libslic3r/ClipperUtils.hpp b/xs/src/libslic3r/ClipperUtils.hpp index 5b9d356b9..ab144f202 100644 --- a/xs/src/libslic3r/ClipperUtils.hpp +++ b/xs/src/libslic3r/ClipperUtils.hpp @@ -83,6 +83,9 @@ void _clipper(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, template void diff(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false); +template +void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_ = false); + template void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false); diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index de93385f6..f0c1454fc 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -132,6 +132,8 @@ class PrintObject bool invalidate_step(PrintObjectStep step); bool invalidate_all_steps(); + void bridge_over_infill(); + private: Print* _print; ModelObject* _model_object; diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index da7e25a48..5fbca0c6d 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -1,5 +1,6 @@ #include "Print.hpp" #include "BoundingBox.hpp" +#include "ClipperUtils.hpp" #include "Geometry.hpp" namespace Slic3r { @@ -338,6 +339,93 @@ PrintObject::invalidate_all_steps() return invalidated; } +void +PrintObject::bridge_over_infill() +{ + FOREACH_REGION(this->_print, region) { + size_t region_id = region - this->_print->regions.begin(); + + double fill_density = (*region)->config.fill_density.value; + if (fill_density == 100 || fill_density == 0) continue; + + FOREACH_LAYER(this, layer_it) { + if (layer_it == this->layers.begin()) continue; + + Layer* layer = *layer_it; + Layer* lower_layer = *(layer_it - 1); + LayerRegion* layerm = layer->get_region(region_id); + + // compute the areas needing bridge math + Polygons internal_solid, lower_internal; + layerm->fill_surfaces.filter_by_type(stInternalSolid, &internal_solid); + FOREACH_LAYERREGION(lower_layer, lower_layerm_it) + (*lower_layerm_it)->fill_surfaces.filter_by_type(stInternal, &lower_internal); + + ExPolygons to_bridge; + intersection(internal_solid, lower_internal, &to_bridge); + if (to_bridge.empty()) continue; + + ExPolygons not_to_bridge; + diff(internal_solid, to_bridge, ¬_to_bridge, true); + + #ifdef SLIC3R_DEBUG + printf "Bridging %d internal areas at layer %d\n", scalar(@$to_bridge), $layer_id; + #endif + + // build the new collection of fill_surfaces + { + Surfaces new_surfaces; + for (Surfaces::const_iterator surface = layerm->fill_surfaces.surfaces.begin(); surface != layerm->fill_surfaces.surfaces.end(); ++surface) { + if (surface->surface_type != stInternalSolid) + new_surfaces.push_back(*surface); + } + + for (ExPolygons::const_iterator ex = to_bridge.begin(); ex != to_bridge.end(); ++ex) + new_surfaces.push_back(Surface(stInternalBridge, *ex)); + + for (ExPolygons::const_iterator ex = not_to_bridge.begin(); ex != not_to_bridge.end(); ++ex) + new_surfaces.push_back(Surface(stInternalSolid, *ex)); + + layerm->fill_surfaces.surfaces = new_surfaces; + } + + /* + # exclude infill from the layers below if needed + # see discussion at https://github.com/alexrj/Slic3r/issues/240 + # Update: do not exclude any infill. Sparse infill is able to absorb the excess material. + if (0) { + my $excess = $layerm->extruders->{infill}->bridge_flow->width - $layerm->height; + for (my $i = $layer_id-1; $excess >= $self->get_layer($i)->height; $i--) { + Slic3r::debugf " skipping infill below those areas at layer %d\n", $i; + foreach my $lower_layerm (@{$self->get_layer($i)->regions}) { + my @new_surfaces = (); + # subtract the area from all types of surfaces + foreach my $group (@{$lower_layerm->fill_surfaces->group}) { + push @new_surfaces, map $group->[0]->clone(expolygon => $_), + @{diff_ex( + [ map $_->p, @$group ], + [ map @$_, @$to_bridge ], + )}; + push @new_surfaces, map Slic3r::Surface->new( + expolygon => $_, + surface_type => S_TYPE_INTERNALVOID, + ), @{intersection_ex( + [ map $_->p, @$group ], + [ map @$_, @$to_bridge ], + )}; + } + $lower_layerm->fill_surfaces->clear; + $lower_layerm->fill_surfaces->append($_) for @new_surfaces; + } + + $excess -= $self->get_layer($i)->height; + } + } + */ + } + } +} + #ifdef SLIC3RXS REGISTER_CLASS(PrintObject, "Print::Object"); diff --git a/xs/src/libslic3r/SurfaceCollection.cpp b/xs/src/libslic3r/SurfaceCollection.cpp index 027138818..ccf1eaa4e 100644 --- a/xs/src/libslic3r/SurfaceCollection.cpp +++ b/xs/src/libslic3r/SurfaceCollection.cpp @@ -80,6 +80,27 @@ SurfaceCollection::any_internal_contains(const T &item) const template bool SurfaceCollection::any_internal_contains(const Line &item) const; template bool SurfaceCollection::any_internal_contains(const Polyline &item) const; +SurfacesPtr +SurfaceCollection::filter_by_type(SurfaceType type) +{ + SurfacesPtr ss; + for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) { + if (surface->surface_type == type) ss.push_back(&*surface); + } + return ss; +} + +void +SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons) +{ + for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) { + if (surface->surface_type == type) { + Polygons pp = surface->expolygon; + polygons->insert(polygons->end(), pp.begin(), pp.end()); + } + } +} + #ifdef SLIC3RXS REGISTER_CLASS(SurfaceCollection, "Surface::Collection"); #endif diff --git a/xs/src/libslic3r/SurfaceCollection.hpp b/xs/src/libslic3r/SurfaceCollection.hpp index 494bb1a21..09a46449e 100644 --- a/xs/src/libslic3r/SurfaceCollection.hpp +++ b/xs/src/libslic3r/SurfaceCollection.hpp @@ -16,6 +16,8 @@ class SurfaceCollection void simplify(double tolerance); void group(std::vector *retval); template bool any_internal_contains(const T &item) const; + SurfacesPtr filter_by_type(SurfaceType type); + void filter_by_type(SurfaceType type, Polygons* polygons); }; } diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index baf0a59ed..c3c9a97c5 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -112,6 +112,8 @@ _constant() void set_step_started(PrintObjectStep step) %code%{ THIS->state.set_started(step); %}; + void bridge_over_infill(); + int ptr() %code%{ RETVAL = (int)(intptr_t)THIS; %}; };