Ported PrintObject::bridge_over_infill() to XS
This commit is contained in:
parent
ea40c4d1b0
commit
4848cb7606
8 changed files with 130 additions and 76 deletions
|
@ -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) = @_;
|
||||
|
||||
|
|
|
@ -425,6 +425,18 @@ template void diff<Slic3r::Polygons, Slic3r::Polylines>(const Slic3r::Polygons &
|
|||
template void diff<Slic3r::Polylines, Slic3r::Polylines>(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_);
|
||||
template void diff<Slic3r::Lines, Slic3r::Lines>(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_);
|
||||
|
||||
template <class SubjectType, class ResultType>
|
||||
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<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_);
|
||||
|
||||
template <class SubjectType, class ResultType>
|
||||
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_)
|
||||
{
|
||||
|
|
|
@ -83,6 +83,9 @@ void _clipper(ClipperLib::ClipType clipType, const Slic3r::Lines &subject,
|
|||
template <class SubjectType, class ResultType>
|
||||
void diff(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false);
|
||||
|
||||
template <class SubjectType, class ResultType>
|
||||
void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_ = false);
|
||||
|
||||
template <class SubjectType, class ResultType>
|
||||
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -80,6 +80,27 @@ SurfaceCollection::any_internal_contains(const T &item) const
|
|||
template bool SurfaceCollection::any_internal_contains<Line>(const Line &item) const;
|
||||
template bool SurfaceCollection::any_internal_contains<Polyline>(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
|
||||
|
|
|
@ -16,6 +16,8 @@ class SurfaceCollection
|
|||
void simplify(double tolerance);
|
||||
void group(std::vector<SurfacesPtr> *retval);
|
||||
template <class T> bool any_internal_contains(const T &item) const;
|
||||
SurfacesPtr filter_by_type(SurfaceType type);
|
||||
void filter_by_type(SurfaceType type, Polygons* polygons);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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; %};
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue