Ported GCode::extrude_path() to XS (speed boost!)
This commit is contained in:
parent
b025efe729
commit
fbd640fdc5
@ -151,7 +151,7 @@ sub extrude_loop {
|
||||
}
|
||||
|
||||
# extrude along the path
|
||||
my $gcode = join '', map $self->_extrude_path($_, $description, $speed), @paths;
|
||||
my $gcode = join '', map $self->_extrude_path($_, $description // "", $speed // -1), @paths;
|
||||
|
||||
# reset acceleration
|
||||
$gcode .= $self->writer->set_acceleration($self->config->default_acceleration);
|
||||
@ -185,115 +185,4 @@ sub extrude_loop {
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
sub extrude_path {
|
||||
my ($self, $path, $description, $speed) = @_;
|
||||
|
||||
my $gcode = $self->_extrude_path($path, $description, $speed);
|
||||
|
||||
# reset acceleration
|
||||
$gcode .= $self->writer->set_acceleration($self->config->default_acceleration);
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
sub _extrude_path {
|
||||
my ($self, $path, $description, $speed) = @_;
|
||||
|
||||
$path->simplify(&Slic3r::SCALED_RESOLUTION);
|
||||
|
||||
# go to first point of extrusion path
|
||||
my $gcode = "";
|
||||
{
|
||||
my $first_point = $path->first_point;
|
||||
$gcode .= $self->travel_to($first_point, $path->role, "move to first $description point")
|
||||
if !$self->last_pos_defined || !$self->last_pos->coincides_with($first_point);
|
||||
}
|
||||
|
||||
# compensate retraction
|
||||
$gcode .= $self->unretract;
|
||||
|
||||
# adjust acceleration
|
||||
{
|
||||
my $acceleration;
|
||||
if ($self->config->first_layer_acceleration && $self->first_layer) {
|
||||
$acceleration = $self->config->first_layer_acceleration;
|
||||
} elsif ($self->config->perimeter_acceleration && $path->is_perimeter) {
|
||||
$acceleration = $self->config->perimeter_acceleration;
|
||||
} elsif ($self->config->bridge_acceleration && $path->is_bridge) {
|
||||
$acceleration = $self->config->bridge_acceleration;
|
||||
} elsif ($self->config->infill_acceleration && $path->is_infill) {
|
||||
$acceleration = $self->config->infill_acceleration;
|
||||
} else {
|
||||
$acceleration = $self->config->default_acceleration;
|
||||
}
|
||||
$gcode .= $self->writer->set_acceleration($acceleration);
|
||||
}
|
||||
|
||||
# calculate extrusion length per distance unit
|
||||
my $e_per_mm = $self->writer->extruder->e_per_mm3 * $path->mm3_per_mm;
|
||||
$e_per_mm = 0 if !$self->writer->extrusion_axis;
|
||||
|
||||
# set speed
|
||||
$speed //= -1;
|
||||
if ($speed == -1) {
|
||||
if ($path->role == EXTR_ROLE_PERIMETER) {
|
||||
$speed = $self->config->get_abs_value('perimeter_speed');
|
||||
} elsif ($path->role == EXTR_ROLE_EXTERNAL_PERIMETER) {
|
||||
$speed = $self->config->get_abs_value('external_perimeter_speed');
|
||||
} elsif ($path->role == EXTR_ROLE_OVERHANG_PERIMETER || $path->role == EXTR_ROLE_BRIDGE) {
|
||||
$speed = $self->config->get_abs_value('bridge_speed');
|
||||
} elsif ($path->role == EXTR_ROLE_FILL) {
|
||||
$speed = $self->config->get_abs_value('infill_speed');
|
||||
} elsif ($path->role == EXTR_ROLE_SOLIDFILL) {
|
||||
$speed = $self->config->get_abs_value('solid_infill_speed');
|
||||
} elsif ($path->role == EXTR_ROLE_TOPSOLIDFILL) {
|
||||
$speed = $self->config->get_abs_value('top_solid_infill_speed');
|
||||
} elsif ($path->role == EXTR_ROLE_GAPFILL) {
|
||||
$speed = $self->config->get_abs_value('gap_fill_speed');
|
||||
} else {
|
||||
die "Invalid speed";
|
||||
}
|
||||
}
|
||||
if ($self->first_layer) {
|
||||
$speed = $self->config->get_abs_value_over('first_layer_speed', $speed);
|
||||
}
|
||||
if ($self->volumetric_speed != 0) {
|
||||
$speed ||= $self->volumetric_speed / $path->mm3_per_mm;
|
||||
}
|
||||
if ($self->config->max_volumetric_speed > 0) {
|
||||
# Cap speed with max_volumetric_speed anyway (even if user is not using autospeed)
|
||||
$speed = min(
|
||||
$speed,
|
||||
$self->config->max_volumetric_speed / $path->mm3_per_mm,
|
||||
);
|
||||
}
|
||||
my $F = $speed * 60; # convert mm/sec to mm/min
|
||||
|
||||
# extrude arc or line
|
||||
$gcode .= ";_BRIDGE_FAN_START\n" if $path->is_bridge && $self->enable_cooling_markers;
|
||||
my $path_length = unscale $path->length;
|
||||
{
|
||||
my $extruder_offset = $self->config->get_at('extruder_offset', $self->writer->extruder->id);
|
||||
$gcode .= $path->gcode($self->writer->extruder, $e_per_mm, $F,
|
||||
$self->origin->x - $extruder_offset->x,
|
||||
$self->origin->y - $extruder_offset->y, #-
|
||||
$self->writer->extrusion_axis,
|
||||
$self->config->gcode_comments ? " ; $description" : "");
|
||||
|
||||
if ($self->wipe->enable) {
|
||||
$self->wipe->set_path($path->polyline->clone);
|
||||
$self->wipe->path->reverse;
|
||||
}
|
||||
}
|
||||
$gcode .= ";_BRIDGE_FAN_END\n" if $path->is_bridge && $self->enable_cooling_markers;
|
||||
$self->set_last_pos($path->last_point);
|
||||
|
||||
if ($self->config->cooling) {
|
||||
my $path_time = $path_length / $F * 60;
|
||||
$self->set_elapsed_time($self->elapsed_time + $path_time);
|
||||
}
|
||||
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -16,6 +16,7 @@ has '_second_layer_things_done' => (is => 'rw');
|
||||
has '_last_obj_copy' => (is => 'rw');
|
||||
|
||||
use List::Util qw(first sum min max);
|
||||
use Slic3r::ExtrusionPath ':roles';
|
||||
use Slic3r::Flow ':roles';
|
||||
use Slic3r::Geometry qw(X Y scale unscale chained_path convex_hull);
|
||||
use Slic3r::Geometry::Clipper qw(JT_SQUARE union_ex offset);
|
||||
@ -251,7 +252,7 @@ sub export {
|
||||
print $fh $gcodegen->retract;
|
||||
print $fh $gcodegen->travel_to(
|
||||
Slic3r::Point->new(0,0),
|
||||
undef,
|
||||
EXTR_ROLE_NONE,
|
||||
'move to origin position for next object',
|
||||
);
|
||||
$gcodegen->set_enable_cooling_markers(1);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "GCode.hpp"
|
||||
#include "ExtrusionEntity.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -267,13 +268,126 @@ GCode::preamble()
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string
|
||||
GCode::extrude_path(const ExtrusionPath &path, std::string description, double speed)
|
||||
{
|
||||
std::string gcode = this->_extrude_path(path, description, speed);
|
||||
|
||||
// reset acceleration
|
||||
gcode += this->writer.set_acceleration(this->config.default_acceleration.value);
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string
|
||||
GCode::_extrude_path(ExtrusionPath path, std::string description, double speed)
|
||||
{
|
||||
path.simplify(SCALED_RESOLUTION);
|
||||
|
||||
std::string gcode;
|
||||
|
||||
// go to first point of extrusion path
|
||||
if (!this->_last_pos_defined || !this->_last_pos.coincides_with(path.first_point())) {
|
||||
gcode += this->travel_to(
|
||||
path.first_point(),
|
||||
path.role,
|
||||
"move to first " + description + " point"
|
||||
);
|
||||
}
|
||||
|
||||
// compensate retraction
|
||||
gcode += this->unretract();
|
||||
|
||||
// adjust acceleration
|
||||
{
|
||||
double acceleration;
|
||||
if (this->config.first_layer_acceleration.value > 0 && this->first_layer) {
|
||||
acceleration = this->config.first_layer_acceleration.value;
|
||||
} else if (this->config.perimeter_acceleration.value > 0 && path.is_perimeter()) {
|
||||
acceleration = this->config.perimeter_acceleration.value;
|
||||
} else if (this->config.bridge_acceleration.value > 0 && path.is_bridge()) {
|
||||
acceleration = this->config.bridge_acceleration.value;
|
||||
} else if (this->config.infill_acceleration.value > 0 && path.is_infill()) {
|
||||
acceleration = this->config.infill_acceleration.value;
|
||||
} else {
|
||||
acceleration = this->config.default_acceleration.value;
|
||||
}
|
||||
gcode += this->writer.set_acceleration(acceleration);
|
||||
}
|
||||
|
||||
// calculate extrusion length per distance unit
|
||||
double e_per_mm = this->writer.extruder()->e_per_mm3 * path.mm3_per_mm;
|
||||
if (this->writer.extrusion_axis().empty()) e_per_mm = 0;
|
||||
|
||||
// set speed
|
||||
if (speed == -1) {
|
||||
if (path.role == erPerimeter) {
|
||||
speed = this->config.get_abs_value("perimeter_speed");
|
||||
} else if (path.role == erExternalPerimeter) {
|
||||
speed = this->config.get_abs_value("external_perimeter_speed");
|
||||
} else if (path.role == erOverhangPerimeter || path.role == erBridgeInfill) {
|
||||
speed = this->config.get_abs_value("bridge_speed");
|
||||
} else if (path.role == erInternalInfill) {
|
||||
speed = this->config.get_abs_value("infill_speed");
|
||||
} else if (path.role == erSolidInfill) {
|
||||
speed = this->config.get_abs_value("solid_infill_speed");
|
||||
} else if (path.role == erTopSolidInfill) {
|
||||
speed = this->config.get_abs_value("top_solid_infill_speed");
|
||||
} else if (path.role == erGapFill) {
|
||||
speed = this->config.get_abs_value("gap_fill_speed");
|
||||
} else {
|
||||
CONFESS("Invalid speed");
|
||||
}
|
||||
}
|
||||
if (this->first_layer) {
|
||||
speed = this->config.get_abs_value("first_layer_speed", speed);
|
||||
}
|
||||
if (this->volumetric_speed != 0 && speed == 0) {
|
||||
speed = this->volumetric_speed / path.mm3_per_mm;
|
||||
}
|
||||
if (this->config.max_volumetric_speed.value > 0) {
|
||||
// cap speed with max_volumetric_speed anyway (even if user is not using autospeed)
|
||||
speed = std::min(
|
||||
speed,
|
||||
this->config.max_volumetric_speed.value / path.mm3_per_mm
|
||||
);
|
||||
}
|
||||
double F = speed * 60; // convert mm/sec to mm/min
|
||||
|
||||
// extrude arc or line
|
||||
if (path.is_bridge() && this->enable_cooling_markers)
|
||||
gcode += ";_BRIDGE_FAN_START\n";
|
||||
double path_length = unscale(path.length());
|
||||
{
|
||||
Pointf extruder_offset = EXTRUDER_CONFIG(extruder_offset);
|
||||
gcode += path.gcode(this->writer.extruder(), e_per_mm, F,
|
||||
this->origin.x - extruder_offset.x,
|
||||
this->origin.y - extruder_offset.y,
|
||||
this->writer.extrusion_axis(),
|
||||
this->config.gcode_comments ? (" ; " + description) : "");
|
||||
|
||||
if (this->wipe.enable) {
|
||||
this->wipe.path = path.polyline;
|
||||
this->wipe.path.reverse();
|
||||
}
|
||||
}
|
||||
if (path.is_bridge() && this->enable_cooling_markers)
|
||||
gcode += ";_BRIDGE_FAN_END\n";
|
||||
this->set_last_pos(path.last_point());
|
||||
|
||||
if (this->config.cooling)
|
||||
this->elapsed_time += path_length / F * 60;
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
// This method accepts &point in print coordinates.
|
||||
std::string
|
||||
GCode::travel_to(const Point &point, ExtrusionRole role, std::string comment)
|
||||
{
|
||||
/* Define the travel move as a line between current position and the taget point.
|
||||
This is expressed in print coordinates, so it will need to be translated by
|
||||
$self->origin in order to get G-code coordinates. */
|
||||
this->origin in order to get G-code coordinates. */
|
||||
Polyline travel;
|
||||
travel.append(this->last_pos());
|
||||
travel.append(point);
|
||||
|
@ -92,6 +92,8 @@ class GCode {
|
||||
void apply_print_config(const PrintConfig &print_config);
|
||||
void set_origin(const Pointf &pointf);
|
||||
std::string preamble();
|
||||
std::string extrude_path(const ExtrusionPath &path, std::string description = "", double speed = -1);
|
||||
std::string _extrude_path(ExtrusionPath path, std::string description = "", double speed = -1);
|
||||
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
|
||||
bool needs_retraction(const Polyline &travel, ExtrusionRole role = erNone);
|
||||
std::string retract(bool toolchange = false);
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#define EPSILON 1e-4
|
||||
#define SCALING_FACTOR 0.000001
|
||||
#define RESOLUTION 0.0125
|
||||
#define SCALED_RESOLUTION (RESOLUTION / SCALING_FACTOR)
|
||||
#define PI 3.141592653589793238
|
||||
#define scale_(val) (val / SCALING_FACTOR)
|
||||
#define unscale(val) (val * SCALING_FACTOR)
|
||||
|
@ -157,6 +157,10 @@
|
||||
void set_origin(Pointf* pointf)
|
||||
%code{% THIS->set_origin(*pointf); %};
|
||||
std::string preamble();
|
||||
std::string extrude_path(ExtrusionPath* path, std::string description = "", double speed = -1)
|
||||
%code{% RETVAL = THIS->extrude_path(*path, description, speed); %};
|
||||
std::string _extrude_path(ExtrusionPath* path, std::string description = "", double speed = -1)
|
||||
%code{% RETVAL = THIS->_extrude_path(*path, description, speed); %};
|
||||
std::string travel_to(Point* point, ExtrusionRole role, std::string comment)
|
||||
%code{% RETVAL = THIS->travel_to(*point, role, comment); %};
|
||||
bool needs_retraction(Polyline* travel, ExtrusionRole role = erNone)
|
||||
|
Loading…
Reference in New Issue
Block a user