mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 09:17:52 -06:00
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 {
|
sub process_external_surfaces {
|
||||||
my ($self) = @_;
|
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::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 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>
|
template <class SubjectType, class ResultType>
|
||||||
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_)
|
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>
|
template <class SubjectType, class ResultType>
|
||||||
void diff(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false);
|
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>
|
template <class SubjectType, class ResultType>
|
||||||
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false);
|
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_step(PrintObjectStep step);
|
||||||
bool invalidate_all_steps();
|
bool invalidate_all_steps();
|
||||||
|
|
||||||
|
void bridge_over_infill();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Print* _print;
|
Print* _print;
|
||||||
ModelObject* _model_object;
|
ModelObject* _model_object;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "Print.hpp"
|
#include "Print.hpp"
|
||||||
#include "BoundingBox.hpp"
|
#include "BoundingBox.hpp"
|
||||||
|
#include "ClipperUtils.hpp"
|
||||||
#include "Geometry.hpp"
|
#include "Geometry.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -338,6 +339,93 @@ PrintObject::invalidate_all_steps()
|
||||||
return invalidated;
|
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
|
#ifdef SLIC3RXS
|
||||||
REGISTER_CLASS(PrintObject, "Print::Object");
|
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<Line>(const Line &item) const;
|
||||||
template bool SurfaceCollection::any_internal_contains<Polyline>(const Polyline &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
|
#ifdef SLIC3RXS
|
||||||
REGISTER_CLASS(SurfaceCollection, "Surface::Collection");
|
REGISTER_CLASS(SurfaceCollection, "Surface::Collection");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,6 +16,8 @@ class SurfaceCollection
|
||||||
void simplify(double tolerance);
|
void simplify(double tolerance);
|
||||||
void group(std::vector<SurfacesPtr> *retval);
|
void group(std::vector<SurfacesPtr> *retval);
|
||||||
template <class T> bool any_internal_contains(const T &item) const;
|
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)
|
void set_step_started(PrintObjectStep step)
|
||||||
%code%{ THIS->state.set_started(step); %};
|
%code%{ THIS->state.set_started(step); %};
|
||||||
|
|
||||||
|
void bridge_over_infill();
|
||||||
|
|
||||||
int ptr()
|
int ptr()
|
||||||
%code%{ RETVAL = (int)(intptr_t)THIS; %};
|
%code%{ RETVAL = (int)(intptr_t)THIS; %};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue