make_skirt ported to C++
This commit is contained in:
parent
90028e47e9
commit
3d11d1aebf
@ -209,112 +209,9 @@ sub make_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, 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->_make_skirt();
|
||||
$self->set_step_done(STEP_SKIRT);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "Print.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Extruder.hpp"
|
||||
#include "Flow.hpp"
|
||||
#include "Geometry.hpp"
|
||||
#include "SupportMaterial.hpp"
|
||||
@ -839,9 +840,137 @@ Print::auto_assign_extruders(ModelObject* model_object) const
|
||||
//FIXME Vojtech: This assigns an extruder ID even to a modifier volume, if it has a material assigned.
|
||||
size_t extruder_id = (v - model_object->volumes.begin()) + 1;
|
||||
if (!(*v)->config.has("extruder"))
|
||||
(*v)->config.opt<ConfigOptionInt>("extruder", true)->value = extruder_id;
|
||||
(*v)->config.opt<ConfigOptionInt>("extruder", true)->value = int(extruder_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Print::_make_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.
|
||||
coordf_t skirt_height_z = 0.;
|
||||
for (const PrintObject *object : this->objects) {
|
||||
size_t skirt_layers = this->has_infinite_skirt() ?
|
||||
object->layer_count() :
|
||||
std::min(size_t(this->config.skirt_height.value), object->layer_count());
|
||||
skirt_height_z = std::max(skirt_height_z, object->layers[skirt_layers-1]->print_z);
|
||||
}
|
||||
|
||||
// Collect points from all layers contained in skirt height.
|
||||
Points points;
|
||||
for (const PrintObject *object : this->objects) {
|
||||
Points object_points;
|
||||
// Get object layers up to skirt_height_z.
|
||||
for (const Layer *layer : object->layers) {
|
||||
if (layer->print_z > skirt_height_z)
|
||||
break;
|
||||
for (const ExPolygon &expoly : layer->slices.expolygons)
|
||||
// Collect the outer contour points only, ignore holes for the calculation of the convex hull.
|
||||
append(object_points, expoly.contour.points);
|
||||
}
|
||||
// Get support layers up to skirt_height_z.
|
||||
for (const SupportLayer *layer : object->support_layers) {
|
||||
if (layer->print_z > skirt_height_z)
|
||||
break;
|
||||
for (const ExtrusionEntity *extrusion_entity : layer->support_fills.entities)
|
||||
append(object_points, extrusion_entity->as_polyline().points);
|
||||
for (const ExtrusionEntity *extrusion_entity : layer->support_interface_fills.entities)
|
||||
append(object_points, extrusion_entity->as_polyline().points);
|
||||
}
|
||||
// Repeat points for each object copy.
|
||||
for (const Point &shift : object->_shifted_copies) {
|
||||
Points copy_points = object_points;
|
||||
for (Point &pt : copy_points)
|
||||
pt.translate(shift);
|
||||
append(points, copy_points);
|
||||
}
|
||||
}
|
||||
|
||||
if (points.size() < 3)
|
||||
// At least three points required for a convex hull.
|
||||
return;
|
||||
|
||||
Polygon convex_hull = Slic3r::Geometry::convex_hull(points);
|
||||
|
||||
// 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
|
||||
double first_layer_height = this->skirt_first_layer_height();
|
||||
Flow flow = this->skirt_flow();
|
||||
float spacing = flow.spacing();
|
||||
double mm3_per_mm = flow.mm3_per_mm();
|
||||
|
||||
std::vector<size_t> extruders;
|
||||
std::vector<double> extruders_e_per_mm;
|
||||
{
|
||||
auto set_extruders = this->extruders();
|
||||
extruders.reserve(set_extruders.size());
|
||||
extruders_e_per_mm.reserve(set_extruders.size());
|
||||
for (auto &extruder_id : set_extruders) {
|
||||
extruders.push_back(extruder_id);
|
||||
GCodeConfig config;
|
||||
config.apply(this->config, true);
|
||||
extruders_e_per_mm.push_back(Extruder((unsigned int)extruder_id, &config).e_per_mm(mm3_per_mm));
|
||||
}
|
||||
}
|
||||
|
||||
// Number of skirt loops per skirt layer.
|
||||
int n_skirts = this->config.skirts.value;
|
||||
if (this->has_infinite_skirt() && n_skirts == 0)
|
||||
n_skirts = 1;
|
||||
|
||||
// Initial offset of the brim inner edge from the object (possible with a support & raft).
|
||||
// The skirt will touch the brim if the brim is extruded.
|
||||
coord_t distance = scale_(std::max(this->config.skirt_distance.value, this->config.brim_width.value));
|
||||
// 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.
|
||||
std::vector<coordf_t> extruded_length(extruders.size(), 0.);
|
||||
for (int i = n_skirts, extruder_idx = 0; i > 0; -- i) {
|
||||
// Offset the skirt outside.
|
||||
distance += coord_t(scale_(spacing));
|
||||
// Generate the skirt centerline.
|
||||
Polygon loop = offset(convex_hull, distance, ClipperLib::jtRound, scale_(0.1)).front();
|
||||
// Extrude the skirt loop.
|
||||
ExtrusionLoop eloop(elrSkirt);
|
||||
eloop.paths.emplace_back(ExtrusionPath(
|
||||
ExtrusionPath(
|
||||
erSkirt,
|
||||
mm3_per_mm, // this will be overridden at G-code export time
|
||||
flow.width,
|
||||
first_layer_height // this will be overridden at G-code export time
|
||||
)));
|
||||
eloop.paths.back().polyline = loop.split_at_first_point();
|
||||
this->skirt.append(eloop);
|
||||
if (this->config.min_skirt_length.value > 0) {
|
||||
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
|
||||
extruded_length[extruder_idx] += unscale(loop.length()) * extruders_e_per_mm[extruder_idx];
|
||||
if (extruded_length[extruder_idx] < this->config.min_skirt_length.value) {
|
||||
// Not extruded enough yet with the current extruder. Add another loop.
|
||||
if (i == 1)
|
||||
++ i;
|
||||
} else {
|
||||
assert(extruded_length[extruder_idx] >= this->config.min_skirt_length.value);
|
||||
// Enough extruded with the current extruder. Extrude with the next one,
|
||||
// until the prescribed number of skirt loops is extruded.
|
||||
if (extruder_idx + 1 < extruders.size())
|
||||
++ extruder_idx;
|
||||
}
|
||||
} else {
|
||||
// The skirt lenght is not limited, extrude the skirt with the 1st extruder only.
|
||||
}
|
||||
}
|
||||
// Brims were generated inside out, reverse to print the outmost contour first.
|
||||
this->skirt.reverse();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -251,6 +251,8 @@ class Print
|
||||
double max_allowed_layer_height() const;
|
||||
bool has_support_material() const;
|
||||
void auto_assign_extruders(ModelObject* model_object) const;
|
||||
|
||||
void _make_skirt();
|
||||
|
||||
private:
|
||||
void clear_regions();
|
||||
|
@ -270,6 +270,8 @@ _constant()
|
||||
double skirt_first_layer_height();
|
||||
Clone<Flow> brim_flow();
|
||||
Clone<Flow> skirt_flow();
|
||||
|
||||
void _make_skirt();
|
||||
%{
|
||||
|
||||
double
|
||||
|
Loading…
Reference in New Issue
Block a user