mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-04-23 22:30:02 +08:00
Ported Print::make_skirt() to C++
This commit is contained in:
parent
75670c6819
commit
33b3faacfd
@ -255,134 +255,6 @@ EOF
|
|||||||
print "Done.\n" unless $params{quiet};
|
print "Done.\n" unless $params{quiet};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub make_skirt {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# prerequisites
|
|
||||||
$_->make_perimeters for @{$self->objects};
|
|
||||||
$_->infill for @{$self->objects};
|
|
||||||
$_->generate_support_material for @{$self->objects};
|
|
||||||
|
|
||||||
return if $self->step_done(STEP_SKIRT);
|
|
||||||
$self->set_step_started(STEP_SKIRT);
|
|
||||||
|
|
||||||
# since this method must be idempotent, we clear skirt paths *before*
|
|
||||||
# checking whether we need to generate them
|
|
||||||
$self->skirt->clear;
|
|
||||||
|
|
||||||
if (!$self->has_skirt) {
|
|
||||||
$self->set_step_done(STEP_SKIRT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$self->status_cb->(88, "Generating skirt");
|
|
||||||
|
|
||||||
# First off we need to decide how tall the skirt must be.
|
|
||||||
# The skirt_height option from config is expressed in layers, but our
|
|
||||||
# object might have different layer heights, so we need to find the print_z
|
|
||||||
# of the highest layer involved.
|
|
||||||
# Note that unless has_infinite_skirt() == true
|
|
||||||
# the actual skirt might not reach this $skirt_height_z value since the print
|
|
||||||
# order of objects on each layer is not guaranteed and will not generally
|
|
||||||
# include the thickest object first. It is just guaranteed that a skirt is
|
|
||||||
# prepended to the first 'n' layers (with 'n' = skirt_height).
|
|
||||||
# $skirt_height_z in this case is the highest possible skirt height for safety.
|
|
||||||
my $skirt_height_z = -1;
|
|
||||||
foreach my $object (@{$self->objects}) {
|
|
||||||
my $skirt_height = $self->has_infinite_skirt
|
|
||||||
? $object->layer_count
|
|
||||||
: min($self->config->skirt_height, $object->layer_count);
|
|
||||||
my $highest_layer = $object->get_layer($skirt_height - 1);
|
|
||||||
$skirt_height_z = max($skirt_height_z, $highest_layer->print_z);
|
|
||||||
}
|
|
||||||
|
|
||||||
# collect points from all layers contained in skirt height
|
|
||||||
my @points = ();
|
|
||||||
foreach my $object (@{$self->objects}) {
|
|
||||||
my @object_points = ();
|
|
||||||
|
|
||||||
# get object layers up to $skirt_height_z
|
|
||||||
foreach my $layer (@{$object->layers}) {
|
|
||||||
last if $layer->print_z > $skirt_height_z;
|
|
||||||
push @object_points, map @$_, map @$_, @{$layer->slices};
|
|
||||||
}
|
|
||||||
|
|
||||||
# get support layers up to $skirt_height_z
|
|
||||||
foreach my $layer (@{$object->support_layers}) {
|
|
||||||
last if $layer->print_z > $skirt_height_z;
|
|
||||||
push @object_points, map @{$_->polyline}, @{$layer->support_fills} if $layer->support_fills;
|
|
||||||
push @object_points, map @{$_->polyline}, @{$layer->support_interface_fills} if $layer->support_interface_fills;
|
|
||||||
}
|
|
||||||
|
|
||||||
# repeat points for each object copy
|
|
||||||
foreach my $copy (@{$object->_shifted_copies}) {
|
|
||||||
my @copy_points = map $_->clone, @object_points;
|
|
||||||
$_->translate(@$copy) for @copy_points;
|
|
||||||
push @points, @copy_points;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return if @points < 3; # at least three points required for a convex hull
|
|
||||||
|
|
||||||
# find out convex hull
|
|
||||||
my $convex_hull = convex_hull(\@points);
|
|
||||||
|
|
||||||
my @extruded_length = (); # for each extruder
|
|
||||||
|
|
||||||
# skirt may be printed on several layers, having distinct layer heights,
|
|
||||||
# but loops must be aligned so can't vary width/spacing
|
|
||||||
# TODO: use each extruder's own flow
|
|
||||||
my $first_layer_height = $self->skirt_first_layer_height;
|
|
||||||
my $flow = $self->skirt_flow;
|
|
||||||
my $spacing = $flow->spacing;
|
|
||||||
my $mm3_per_mm = $flow->mm3_per_mm;
|
|
||||||
|
|
||||||
my @extruders_e_per_mm = ();
|
|
||||||
my $extruder_idx = 0;
|
|
||||||
|
|
||||||
my $skirts = $self->config->skirts;
|
|
||||||
$skirts ||= 1 if $self->has_infinite_skirt;
|
|
||||||
|
|
||||||
# draw outlines from outside to inside
|
|
||||||
# loop while we have less skirts than required or any extruder hasn't reached the min length if any
|
|
||||||
my $distance = scale max($self->config->skirt_distance, $self->config->brim_width);
|
|
||||||
for (my $i = $skirts; $i > 0; $i--) {
|
|
||||||
$distance += scale $spacing;
|
|
||||||
my $loop = offset([$convex_hull], $distance, 1, JT_ROUND, scale(0.1))->[0];
|
|
||||||
my $eloop = Slic3r::ExtrusionLoop->new_from_paths(
|
|
||||||
Slic3r::ExtrusionPath->new(
|
|
||||||
polyline => Slic3r::Polygon->new(@$loop)->split_at_first_point,
|
|
||||||
role => EXTR_ROLE_SKIRT,
|
|
||||||
mm3_per_mm => $mm3_per_mm, # this will be overridden at G-code export time
|
|
||||||
width => $flow->width,
|
|
||||||
height => $first_layer_height, # this will be overridden at G-code export time
|
|
||||||
),
|
|
||||||
);
|
|
||||||
$eloop->role(EXTRL_ROLE_SKIRT);
|
|
||||||
$self->skirt->append($eloop);
|
|
||||||
|
|
||||||
if ($self->config->min_skirt_length > 0) {
|
|
||||||
$extruded_length[$extruder_idx] ||= 0;
|
|
||||||
if (!$extruders_e_per_mm[$extruder_idx]) {
|
|
||||||
my $config = Slic3r::Config::GCode->new;
|
|
||||||
$config->apply_static($self->config);
|
|
||||||
my $extruder = Slic3r::Extruder->new($extruder_idx, $config);
|
|
||||||
$extruders_e_per_mm[$extruder_idx] = $extruder->e_per_mm($mm3_per_mm);
|
|
||||||
}
|
|
||||||
$extruded_length[$extruder_idx] += unscale $loop->length * $extruders_e_per_mm[$extruder_idx];
|
|
||||||
$i++ if defined first { ($extruded_length[$_] // 0) < $self->config->min_skirt_length } 0 .. $#{$self->extruders};
|
|
||||||
if ($extruded_length[$extruder_idx] >= $self->config->min_skirt_length) {
|
|
||||||
if ($extruder_idx < $#{$self->extruders}) {
|
|
||||||
$extruder_idx++;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->skirt->reverse;
|
|
||||||
|
|
||||||
$self->set_step_done(STEP_SKIRT);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub make_brim {
|
sub make_brim {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
@ -45,6 +45,8 @@ class ExPolygonCollection
|
|||||||
size_t size() const { return expolygons.size(); }
|
size_t size() const { return expolygons.size(); }
|
||||||
ExPolygons::iterator begin() { return expolygons.begin(); }
|
ExPolygons::iterator begin() { return expolygons.begin(); }
|
||||||
ExPolygons::iterator end() { return expolygons.end(); }
|
ExPolygons::iterator end() { return expolygons.end(); }
|
||||||
|
const ExPolygons::const_iterator begin() const { return expolygons.cbegin(); }
|
||||||
|
const ExPolygons::const_iterator end() const { return expolygons.cend(); }
|
||||||
ExPolygons::const_iterator cbegin() const { return expolygons.cbegin();}
|
ExPolygons::const_iterator cbegin() const { return expolygons.cbegin();}
|
||||||
ExPolygons::const_iterator cend() const { return expolygons.cend();}
|
ExPolygons::const_iterator cend() const { return expolygons.cend();}
|
||||||
ExPolygon& at(size_t i) { return expolygons.at(i); }
|
ExPolygon& at(size_t i) { return expolygons.at(i); }
|
||||||
|
@ -74,6 +74,8 @@ class ExtrusionEntityCollection : public ExtrusionEntity
|
|||||||
|
|
||||||
ExtrusionEntitiesPtr::iterator begin() { return entities.begin(); }
|
ExtrusionEntitiesPtr::iterator begin() { return entities.begin(); }
|
||||||
ExtrusionEntitiesPtr::iterator end() { return entities.end(); }
|
ExtrusionEntitiesPtr::iterator end() { return entities.end(); }
|
||||||
|
ExtrusionEntitiesPtr::const_iterator begin() const { return entities.cbegin(); }
|
||||||
|
ExtrusionEntitiesPtr::const_iterator end() const { return entities.cend(); }
|
||||||
ExtrusionEntitiesPtr::const_iterator cbegin() const { return entities.cbegin(); }
|
ExtrusionEntitiesPtr::const_iterator cbegin() const { return entities.cbegin(); }
|
||||||
ExtrusionEntitiesPtr::const_iterator cend() const { return entities.cend(); }
|
ExtrusionEntitiesPtr::const_iterator cend() const { return entities.cend(); }
|
||||||
|
|
||||||
|
@ -140,16 +140,16 @@ Print::make_brim()
|
|||||||
void
|
void
|
||||||
Print::make_skirt()
|
Print::make_skirt()
|
||||||
{
|
{
|
||||||
|
if (this->state.is_done(psSkirt)) return;
|
||||||
|
this->state.set_started(psSkirt);
|
||||||
|
|
||||||
// prereqs
|
// prereqs
|
||||||
for(auto& obj: this->objects) {
|
for (auto* obj: this->objects) {
|
||||||
obj->make_perimeters();
|
obj->make_perimeters();
|
||||||
obj->infill();
|
obj->infill();
|
||||||
obj->generate_support_material();
|
obj->generate_support_material();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->state.is_done(psSkirt)) return;
|
|
||||||
this->state.set_started(psSkirt);
|
|
||||||
|
|
||||||
// since this method must be idempotent, we clear skirt paths *before*
|
// since this method must be idempotent, we clear skirt paths *before*
|
||||||
// checking whether we need to generate them
|
// checking whether we need to generate them
|
||||||
this->skirt.clear();
|
this->skirt.clear();
|
||||||
@ -173,10 +173,11 @@ Print::make_skirt()
|
|||||||
// prepended to the first 'n' layers (with 'n' = skirt_height).
|
// prepended to the first 'n' layers (with 'n' = skirt_height).
|
||||||
// $skirt_height_z in this case is the highest possible skirt height for safety.
|
// $skirt_height_z in this case is the highest possible skirt height for safety.
|
||||||
double skirt_height_z {-1.0};
|
double skirt_height_z {-1.0};
|
||||||
for (const auto& object : this->objects) {
|
for (const auto* object : this->objects) {
|
||||||
const size_t skirt_height {
|
const size_t skirt_height {
|
||||||
this->has_infinite_skirt() ? object->layer_count() :
|
this->has_infinite_skirt()
|
||||||
std::min(size_t(this->config.skirt_height()), object->layer_count())
|
? object->layer_count()
|
||||||
|
: std::min(size_t(this->config.skirt_height()), object->layer_count())
|
||||||
};
|
};
|
||||||
const Layer* highest_layer { object->get_layer(skirt_height - 1) };
|
const Layer* highest_layer { object->get_layer(skirt_height - 1) };
|
||||||
skirt_height_z = std::max(skirt_height_z, highest_layer->print_z);
|
skirt_height_z = std::max(skirt_height_z, highest_layer->print_z);
|
||||||
@ -184,116 +185,83 @@ Print::make_skirt()
|
|||||||
|
|
||||||
// collect points from all layers contained in skirt height
|
// collect points from all layers contained in skirt height
|
||||||
Points points;
|
Points points;
|
||||||
for(auto* object : this->objects) {
|
for (auto* object : this->objects) {
|
||||||
Points object_points;
|
Points object_points;
|
||||||
|
|
||||||
// get object layers up to skirt_height_z
|
// get object layers up to skirt_height_z
|
||||||
for(auto* layer : object->layers) {
|
for (const auto* layer : object->layers) {
|
||||||
if(layer->print_z > skirt_height_z)break;
|
if (layer->print_z > skirt_height_z) break;
|
||||||
for(ExPolygon poly : layer->slices){
|
for (const ExPolygon ex : layer->slices)
|
||||||
for(Point point : static_cast<Points>(poly)){
|
append_to(object_points, static_cast<Points>(ex));
|
||||||
object_points.push_back(point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get support layers up to $skirt_height_z
|
// get support layers up to skirt_height_z
|
||||||
for(auto* layer : object->support_layers) {
|
for (const auto* layer : object->support_layers) {
|
||||||
if(layer->print_z > skirt_height_z)break;
|
if (layer->print_z > skirt_height_z) break;
|
||||||
for(auto* ee : layer->support_fills){
|
for (auto* ee : layer->support_fills)
|
||||||
for(Point point : ee->as_polyline().points){
|
append_to(object_points, ee->as_polyline().points);
|
||||||
object_points.push_back(point);
|
for (auto* ee : layer->support_interface_fills)
|
||||||
}
|
append_to(object_points, ee->as_polyline().points);
|
||||||
}
|
|
||||||
for(auto* ee : layer->support_interface_fills){
|
|
||||||
for(Point point : ee->as_polyline().points){
|
|
||||||
object_points.push_back(point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeat points for each object copy
|
// repeat points for each object copy
|
||||||
for(auto copy : object->_shifted_copies) {
|
for (const auto& copy : object->_shifted_copies) {
|
||||||
for(Point point : object_points){
|
for (Point p : object_points) {
|
||||||
point.translate(copy);
|
p.translate(copy);
|
||||||
points.push_back(point);
|
points.push_back(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (points.size() < 3) return; // at least three points required for a convex hull
|
if (points.size() < 3) return; // at least three points required for a convex hull
|
||||||
|
|
||||||
// find out convex hull
|
// find out convex hull
|
||||||
auto convex = Geometry::convex_hull(points);
|
const Polygon convex = Geometry::convex_hull(points);
|
||||||
|
|
||||||
// skirt may be printed on several layers, having distinct layer heights,
|
// skirt may be printed on several layers, having distinct layer heights,
|
||||||
// but loops must be aligned so can't vary width/spacing
|
// but loops must be aligned so can't vary width/spacing
|
||||||
// TODO: use each extruder's own flow
|
// TODO: use each extruder's own flow
|
||||||
auto first_layer_height = this->skirt_first_layer_height();
|
const auto first_layer_height = this->skirt_first_layer_height();
|
||||||
auto flow = this->skirt_flow();
|
const auto flow = this->skirt_flow();
|
||||||
auto spacing = flow.spacing();
|
const auto spacing = flow.scaled_spacing();
|
||||||
auto mm3_per_mm = flow.mm3_per_mm();
|
const auto mm3_per_mm = flow.mm3_per_mm();
|
||||||
|
|
||||||
|
int skirts = this->config.skirts();
|
||||||
|
if (skirts == 0 && this->has_infinite_skirt())
|
||||||
|
skirts = 1;
|
||||||
|
|
||||||
auto skirts = this->config.skirts;
|
const std::set<size_t> extruders{ this->extruders() };
|
||||||
if(this->has_infinite_skirt() && skirts == 0){
|
auto extruder_it { extruders.begin() };
|
||||||
skirts = 1;
|
std::vector<float> e_per_mm{0}, extruded_length{0};
|
||||||
}
|
if (this->config.min_skirt_length() > 0)
|
||||||
|
for (auto i : extruders)
|
||||||
//my @extruded_length = (); # for each extruder
|
e_per_mm[i] = Extruder(i, &this->config).e_per_mm(mm3_per_mm);
|
||||||
//extruders_e_per_mm = ();
|
|
||||||
//size_t extruder_idx = 0;
|
|
||||||
|
|
||||||
// new to the cpp implementation
|
|
||||||
float e_per_mm {0.0}, extruded_length = 0;
|
|
||||||
size_t extruders_warm = 0;
|
|
||||||
if (this->config.min_skirt_length.getFloat() > 0) {
|
|
||||||
//my $config = Config::GCode();
|
|
||||||
//$config->apply_static($self->config);
|
|
||||||
auto extruder = Extruder(0, &this->config);
|
|
||||||
e_per_mm = extruder.e_per_mm(mm3_per_mm);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw outlines from outside to inside
|
// draw outlines from outside to inside
|
||||||
// loop while we have less skirts than required or any extruder hasn't reached the min length if any
|
// loop while we have less skirts than required or any extruder hasn't reached the min length if any
|
||||||
float distance = scale_(std::max(this->config.skirt_distance.getFloat(), this->config.brim_width.getFloat()));
|
float distance = scale_(std::max(this->config.skirt_distance(), this->config.brim_width()));
|
||||||
for (int i = skirts; i > 0; i--) {
|
for (int i = skirts; i > 0; i--) {
|
||||||
distance += scale_(spacing);
|
distance += spacing;
|
||||||
auto loop = offset(Polygons{convex}, distance, 1, jtRound, scale_(0.1)).at(0);
|
const Polygon loop = offset(Polygons{convex}, distance, 1, jtRound, scale_(0.1)).at(0);
|
||||||
auto epath = ExtrusionPath(erSkirt,
|
auto epath = ExtrusionPath(
|
||||||
mm3_per_mm, // this will be overridden at G-code export time
|
erSkirt,
|
||||||
flow.width,
|
mm3_per_mm, // this will be overridden at G-code export time
|
||||||
first_layer_height // this will be overridden at G-code export time
|
flow.width,
|
||||||
|
first_layer_height // this will be overridden at G-code export time
|
||||||
);
|
);
|
||||||
epath.polyline = loop.split_at_first_point();
|
epath.polyline = loop.split_at_first_point();
|
||||||
auto eloop = ExtrusionLoop(epath,elrSkirt);
|
auto eloop = ExtrusionLoop(epath, elrSkirt);
|
||||||
this->skirt.append(eloop);
|
this->skirt.append(eloop);
|
||||||
|
|
||||||
if (this->config.min_skirt_length.getFloat() > 0) {
|
if (this->config.min_skirt_length() > 0) {
|
||||||
// Alternative simpler method
|
extruded_length[*extruder_it] += unscale(loop.length()) * e_per_mm[*extruder_it];
|
||||||
extruded_length += unscale(loop.length()) * e_per_mm;
|
for (auto j : extruders) {
|
||||||
if(extruded_length >= this->config.min_skirt_length.getFloat()){
|
if (extruded_length[j] < this->config.min_skirt_length()) {
|
||||||
extruders_warm++;
|
++i;
|
||||||
extruded_length = 0;
|
break;
|
||||||
}
|
|
||||||
if (extruders_warm < this->extruders().size()){
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*$extruded_length[$extruder_idx] ||= 0;
|
|
||||||
if (!$extruders_e_per_mm[$extruder_idx]) {
|
|
||||||
my $config = Slic3r::Config::GCode->new;
|
|
||||||
$config->apply_static($self->config);
|
|
||||||
my $extruder = Slic3r::Extruder->new($extruder_idx, $config);
|
|
||||||
$extruders_e_per_mm[$extruder_idx] = $extruder->e_per_mm($mm3_per_mm);
|
|
||||||
}
|
|
||||||
$extruded_length[$extruder_idx] += unscale $loop->length * $extruders_e_per_mm[$extruder_idx];
|
|
||||||
$i++ if defined first { ($extruded_length[$_] // 0) < $self->config->min_skirt_length } 0 .. $#{$self->extruders};
|
|
||||||
if ($extruded_length[$extruder_idx] >= $self->config->min_skirt_length) {
|
|
||||||
if ($extruder_idx < $#{$self->extruders}) {
|
|
||||||
$extruder_idx++;
|
|
||||||
next;
|
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
if (extruded_length[*extruder_it] >= this->config.min_skirt_length() && extruder_it != extruders.end())
|
||||||
|
++extruder_it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,6 +287,7 @@ _constant()
|
|||||||
double skirt_first_layer_height();
|
double skirt_first_layer_height();
|
||||||
Clone<Flow> brim_flow();
|
Clone<Flow> brim_flow();
|
||||||
Clone<Flow> skirt_flow();
|
Clone<Flow> skirt_flow();
|
||||||
|
void make_skirt();
|
||||||
void _make_brim();
|
void _make_brim();
|
||||||
%{
|
%{
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user