Ported Layer::maker_perimeters() to XS
This commit is contained in:
parent
3a9cf91f83
commit
4f8a18bbad
8 changed files with 114 additions and 83 deletions
|
@ -2,9 +2,6 @@ package Slic3r::Layer;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
use List::Util qw(first);
|
|
||||||
use Slic3r::Geometry::Clipper qw(union_ex intersection_ex);
|
|
||||||
|
|
||||||
# the following two were previously generated by Moo
|
# the following two were previously generated by Moo
|
||||||
sub print {
|
sub print {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
@ -32,83 +29,6 @@ sub regions {
|
||||||
return [ map $self->get_region($_), 0..($self->region_count-1) ];
|
return [ map $self->get_region($_), 0..($self->region_count-1) ];
|
||||||
}
|
}
|
||||||
|
|
||||||
sub make_perimeters {
|
|
||||||
my $self = shift;
|
|
||||||
Slic3r::debugf "Making perimeters for layer %d\n", $self->id;
|
|
||||||
|
|
||||||
# keep track of regions whose perimeters we have already generated
|
|
||||||
my %done = (); # region_id => 1
|
|
||||||
|
|
||||||
for my $region_id (0..$#{$self->regions}) {
|
|
||||||
next if $done{$region_id};
|
|
||||||
my $layerm = $self->get_region($region_id);
|
|
||||||
my $config = $layerm->region->config;
|
|
||||||
$done{$region_id} = 1;
|
|
||||||
|
|
||||||
# find compatible regions
|
|
||||||
my @layerms = ($layerm);
|
|
||||||
for my $i (($region_id+1)..$#{$self->regions}) {
|
|
||||||
my $other_layerm = $self->get_region($i);
|
|
||||||
my $other_config = $other_layerm->region->config;
|
|
||||||
|
|
||||||
if ($config->perimeter_extruder == $other_config->perimeter_extruder
|
|
||||||
&& $config->perimeters == $other_config->perimeters
|
|
||||||
&& $config->perimeter_speed == $other_config->perimeter_speed
|
|
||||||
&& $config->gap_fill_speed == $other_config->gap_fill_speed
|
|
||||||
&& $config->overhangs == $other_config->overhangs
|
|
||||||
&& $config->serialize('perimeter_extrusion_width') eq $other_config->serialize('perimeter_extrusion_width')
|
|
||||||
&& $config->thin_walls == $other_config->thin_walls
|
|
||||||
&& $config->external_perimeters_first == $other_config->external_perimeters_first) {
|
|
||||||
push @layerms, $other_layerm;
|
|
||||||
$done{$i} = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (@layerms == 1) { # optimization
|
|
||||||
$layerm->fill_surfaces->clear;
|
|
||||||
$layerm->make_perimeters($layerm->slices, $layerm->fill_surfaces);
|
|
||||||
} else {
|
|
||||||
# group slices (surfaces) according to number of extra perimeters
|
|
||||||
my %slices = (); # extra_perimeters => [ surface, surface... ]
|
|
||||||
foreach my $surface (map @{$_->slices}, @layerms) {
|
|
||||||
my $extra = $surface->extra_perimeters;
|
|
||||||
$slices{$extra} ||= [];
|
|
||||||
push @{$slices{$extra}}, $surface;
|
|
||||||
}
|
|
||||||
|
|
||||||
# merge the surfaces assigned to each group
|
|
||||||
my $new_slices = Slic3r::Surface::Collection->new;
|
|
||||||
foreach my $surfaces (values %slices) {
|
|
||||||
$new_slices->append(Slic3r::Surface->new(
|
|
||||||
surface_type => $surfaces->[0]->surface_type,
|
|
||||||
extra_perimeters => $surfaces->[0]->extra_perimeters,
|
|
||||||
expolygon => $_,
|
|
||||||
)) for @{union_ex([ map $_->p, @$surfaces ], 1)};
|
|
||||||
}
|
|
||||||
|
|
||||||
# make perimeters
|
|
||||||
my $fill_surfaces = Slic3r::Surface::Collection->new;
|
|
||||||
$layerm->make_perimeters($new_slices, $fill_surfaces);
|
|
||||||
|
|
||||||
# assign fill_surfaces to each layer
|
|
||||||
if ($fill_surfaces->count > 0) {
|
|
||||||
foreach my $lm (@layerms) {
|
|
||||||
my $expolygons = intersection_ex(
|
|
||||||
[ map $_->p, @$fill_surfaces ],
|
|
||||||
[ map $_->p, @{$lm->slices} ],
|
|
||||||
);
|
|
||||||
$lm->fill_surfaces->clear;
|
|
||||||
$lm->fill_surfaces->append(Slic3r::Surface->new(
|
|
||||||
surface_type => $fill_surfaces->[0]->surface_type,
|
|
||||||
extra_perimeters => $fill_surfaces->[0]->extra_perimeters,
|
|
||||||
expolygon => $_,
|
|
||||||
)) for @$expolygons;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
package Slic3r::Layer::Support;
|
package Slic3r::Layer::Support;
|
||||||
our @ISA = qw(Slic3r::Layer);
|
our @ISA = qw(Slic3r::Layer);
|
||||||
|
|
||||||
|
|
|
@ -569,6 +569,17 @@ union_ex(const Slic3r::Polygons &subject, bool safety_offset)
|
||||||
return expp;
|
return expp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Slic3r::ExPolygons
|
||||||
|
union_ex(const Slic3r::Surfaces &subject, bool safety_offset)
|
||||||
|
{
|
||||||
|
Polygons pp;
|
||||||
|
for (Slic3r::Surfaces::const_iterator s = subject.begin(); s != subject.end(); ++s) {
|
||||||
|
Polygons spp = *s;
|
||||||
|
pp.insert(pp.end(), spp.begin(), spp.end());
|
||||||
|
}
|
||||||
|
return union_ex(pp, safety_offset);
|
||||||
|
}
|
||||||
|
|
||||||
void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, Slic3r::Polygons* retval, bool safety_offset)
|
void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, Slic3r::Polygons* retval, bool safety_offset)
|
||||||
{
|
{
|
||||||
Polygons pp = subject1;
|
Polygons pp = subject1;
|
||||||
|
|
|
@ -121,6 +121,7 @@ void union_(const Slic3r::Polygons &subject, T* retval, bool safety_offset_ = fa
|
||||||
|
|
||||||
Slic3r::Polygons union_(const Slic3r::Polygons &subject, bool safety_offset = false);
|
Slic3r::Polygons union_(const Slic3r::Polygons &subject, bool safety_offset = false);
|
||||||
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool safety_offset = false);
|
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool safety_offset = false);
|
||||||
|
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject, bool safety_offset = false);
|
||||||
|
|
||||||
void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, Slic3r::Polygons* retval, bool safety_offset = false);
|
void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, Slic3r::Polygons* retval, bool safety_offset = false);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,18 @@
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator== (const ConfigOption &a, const ConfigOption &b)
|
||||||
|
{
|
||||||
|
return a.serialize().compare(b.serialize()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator!= (const ConfigOption &a, const ConfigOption &b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ConfigBase::has(const t_config_option_key &opt_key) {
|
ConfigBase::has(const t_config_option_key &opt_key) {
|
||||||
return (this->option(opt_key, false) != NULL);
|
return (this->option(opt_key, false) != NULL);
|
||||||
|
@ -52,8 +64,8 @@ ConfigBase::diff(ConfigBase &other) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
ConfigBase::serialize(const t_config_option_key &opt_key) {
|
ConfigBase::serialize(const t_config_option_key &opt_key) const {
|
||||||
ConfigOption* opt = this->option(opt_key);
|
const ConfigOption* opt = this->option(opt_key);
|
||||||
assert(opt != NULL);
|
assert(opt != NULL);
|
||||||
return opt->serialize();
|
return opt->serialize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@ class ConfigOption {
|
||||||
virtual bool deserialize(std::string str) = 0;
|
virtual bool deserialize(std::string str) = 0;
|
||||||
virtual int getInt() const { return 0; };
|
virtual int getInt() const { return 0; };
|
||||||
virtual void setInt(int val) {};
|
virtual void setInt(int val) {};
|
||||||
|
friend bool operator== (const ConfigOption &a, const ConfigOption &b);
|
||||||
|
friend bool operator!= (const ConfigOption &a, const ConfigOption &b);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConfigOptionVectorBase : public ConfigOption {
|
class ConfigOptionVectorBase : public ConfigOption {
|
||||||
|
@ -521,7 +523,7 @@ class ConfigBase
|
||||||
void apply(const ConfigBase &other, bool ignore_nonexistent = false);
|
void apply(const ConfigBase &other, bool ignore_nonexistent = false);
|
||||||
bool equals(ConfigBase &other);
|
bool equals(ConfigBase &other);
|
||||||
t_config_option_keys diff(ConfigBase &other);
|
t_config_option_keys diff(ConfigBase &other);
|
||||||
std::string serialize(const t_config_option_key &opt_key);
|
std::string serialize(const t_config_option_key &opt_key) const;
|
||||||
bool set_deserialize(const t_config_option_key &opt_key, std::string str);
|
bool set_deserialize(const t_config_option_key &opt_key, std::string str);
|
||||||
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false);
|
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false);
|
||||||
double get_abs_value(const t_config_option_key &opt_key);
|
double get_abs_value(const t_config_option_key &opt_key);
|
||||||
|
|
|
@ -162,6 +162,89 @@ Layer::any_bottom_region_slice_contains(const T &item) const
|
||||||
}
|
}
|
||||||
template bool Layer::any_bottom_region_slice_contains<Polyline>(const Polyline &item) const;
|
template bool Layer::any_bottom_region_slice_contains<Polyline>(const Polyline &item) const;
|
||||||
|
|
||||||
|
void
|
||||||
|
Layer::make_perimeters()
|
||||||
|
{
|
||||||
|
#ifdef SLIC3R_DEBUG
|
||||||
|
printf("Making perimeters for layer %zu\n", this->id());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// keep track of regions whose perimeters we have already generated
|
||||||
|
std::set<size_t> done;
|
||||||
|
|
||||||
|
FOREACH_LAYERREGION(this, layerm) {
|
||||||
|
size_t region_id = layerm - this->regions.begin();
|
||||||
|
if (done.find(region_id) != done.end()) continue;
|
||||||
|
done.insert(region_id);
|
||||||
|
const PrintRegionConfig &config = (*layerm)->region()->config;
|
||||||
|
|
||||||
|
// find compatible regions
|
||||||
|
LayerRegionPtrs layerms;
|
||||||
|
layerms.push_back(*layerm);
|
||||||
|
for (LayerRegionPtrs::const_iterator it = layerm + 1; it != this->regions.end(); ++it) {
|
||||||
|
LayerRegion* other_layerm = *it;
|
||||||
|
const PrintRegionConfig &other_config = other_layerm->region()->config;
|
||||||
|
|
||||||
|
if (config.perimeter_extruder == other_config.perimeter_extruder
|
||||||
|
&& config.perimeters == other_config.perimeters
|
||||||
|
&& config.perimeter_speed == other_config.perimeter_speed
|
||||||
|
&& config.gap_fill_speed == other_config.gap_fill_speed
|
||||||
|
&& config.overhangs == other_config.overhangs
|
||||||
|
&& config.serialize("perimeter_extrusion_width").compare(other_config.serialize("perimeter_extrusion_width")) == 0
|
||||||
|
&& config.thin_walls == other_config.thin_walls
|
||||||
|
&& config.external_perimeters_first == other_config.external_perimeters_first) {
|
||||||
|
layerms.push_back(other_layerm);
|
||||||
|
done.insert(it - this->regions.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layerms.size() == 1) { // optimization
|
||||||
|
(*layerm)->fill_surfaces.surfaces.clear();
|
||||||
|
(*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces);
|
||||||
|
} else {
|
||||||
|
// group slices (surfaces) according to number of extra perimeters
|
||||||
|
std::map<unsigned short,Surfaces> slices; // extra_perimeters => [ surface, surface... ]
|
||||||
|
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
|
||||||
|
for (Surfaces::iterator s = (*l)->slices.surfaces.begin(); s != (*l)->slices.surfaces.end(); ++s) {
|
||||||
|
slices[s->extra_perimeters].push_back(*s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge the surfaces assigned to each group
|
||||||
|
SurfaceCollection new_slices;
|
||||||
|
for (std::map<unsigned short,Surfaces>::const_iterator it = slices.begin(); it != slices.end(); ++it) {
|
||||||
|
ExPolygons expp = union_ex(it->second, true);
|
||||||
|
for (ExPolygons::iterator ex = expp.begin(); ex != expp.end(); ++ex) {
|
||||||
|
Surface s = it->second.front(); // clone type and extra_perimeters
|
||||||
|
s.expolygon = *ex;
|
||||||
|
new_slices.surfaces.push_back(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make perimeters
|
||||||
|
SurfaceCollection fill_surfaces;
|
||||||
|
(*layerm)->make_perimeters(new_slices, &fill_surfaces);
|
||||||
|
|
||||||
|
// assign fill_surfaces to each layer
|
||||||
|
if (!fill_surfaces.surfaces.empty()) {
|
||||||
|
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
|
||||||
|
ExPolygons expp = intersection_ex(
|
||||||
|
fill_surfaces,
|
||||||
|
(*l)->slices
|
||||||
|
);
|
||||||
|
(*l)->fill_surfaces.surfaces.clear();
|
||||||
|
|
||||||
|
for (ExPolygons::iterator ex = expp.begin(); ex != expp.end(); ++ex) {
|
||||||
|
Surface s = fill_surfaces.surfaces.front(); // clone type and extra_perimeters
|
||||||
|
s.expolygon = *ex;
|
||||||
|
(*l)->fill_surfaces.surfaces.push_back(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SLIC3RXS
|
#ifdef SLIC3RXS
|
||||||
REGISTER_CLASS(Layer, "Layer");
|
REGISTER_CLASS(Layer, "Layer");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -101,6 +101,7 @@ class Layer {
|
||||||
void merge_slices();
|
void merge_slices();
|
||||||
template <class T> bool any_internal_region_slice_contains(const T &item) const;
|
template <class T> bool any_internal_region_slice_contains(const T &item) const;
|
||||||
template <class T> bool any_bottom_region_slice_contains(const T &item) const;
|
template <class T> bool any_bottom_region_slice_contains(const T &item) const;
|
||||||
|
void make_perimeters();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t _id; // sequential number of layer, 0-based
|
size_t _id; // sequential number of layer, 0-based
|
||||||
|
|
|
@ -85,6 +85,7 @@
|
||||||
%code%{ RETVAL = THIS->any_internal_region_slice_contains(*polyline); %};
|
%code%{ RETVAL = THIS->any_internal_region_slice_contains(*polyline); %};
|
||||||
bool any_bottom_region_slice_contains_polyline(Polyline* polyline)
|
bool any_bottom_region_slice_contains_polyline(Polyline* polyline)
|
||||||
%code%{ RETVAL = THIS->any_bottom_region_slice_contains(*polyline); %};
|
%code%{ RETVAL = THIS->any_bottom_region_slice_contains(*polyline); %};
|
||||||
|
void make_perimeters();
|
||||||
};
|
};
|
||||||
|
|
||||||
%name{Slic3r::Layer::Support} class SupportLayer {
|
%name{Slic3r::Layer::Support} class SupportLayer {
|
||||||
|
|
Loading…
Reference in a new issue