diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 39fa85ab1..999e450bb 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -140,6 +140,7 @@ sub thread_cleanup { *Slic3r::Config::PrintRegion::DESTROY = sub {}; *Slic3r::ExPolygon::DESTROY = sub {}; *Slic3r::ExPolygon::Collection::DESTROY = sub {}; + *Slic3r::Extruder::DESTROY = sub {}; *Slic3r::ExtrusionLoop::DESTROY = sub {}; *Slic3r::ExtrusionPath::DESTROY = sub {}; *Slic3r::ExtrusionPath::Collection::DESTROY = sub {}; diff --git a/lib/Slic3r/Extruder.pm b/lib/Slic3r/Extruder.pm index e2334c65e..51e7ad2a6 100644 --- a/lib/Slic3r/Extruder.pm +++ b/lib/Slic3r/Extruder.pm @@ -1,5 +1,6 @@ package Slic3r::Extruder; -use Moo; +use strict; +use warnings; require Exporter; our @ISA = qw(Exporter); @@ -9,61 +10,25 @@ our %EXPORT_TAGS = (roles => \@EXPORT_OK); use Slic3r::Geometry qw(PI scale); -use constant OPTIONS => [qw( - extruder_offset - nozzle_diameter filament_diameter extrusion_multiplier temperature first_layer_temperature - retract_length retract_lift retract_speed retract_restart_extra retract_before_travel - retract_layer_change retract_length_toolchange retract_restart_extra_toolchange wipe -)]; - -has 'id' => (is => 'rw', required => 1); -has $_ => (is => 'ro', required => 1) for @{&OPTIONS}; -has 'use_relative_e_distances' => (is => 'ro', default => sub {0}); - -has 'E' => (is => 'rw', default => sub {0} ); -has 'absolute_E' => (is => 'rw', default => sub {0} ); -has 'retracted' => (is => 'rw', default => sub {0} ); -has 'restart_extra' => (is => 'rw', default => sub {0} ); -has 'e_per_mm3' => (is => 'lazy'); -has 'retract_speed_mm_min' => (is => 'lazy'); +# has 'e_per_mm3' => (is => 'lazy'); +# has 'retract_speed_mm_min' => (is => 'lazy'); use constant EXTRUDER_ROLE_PERIMETER => 1; use constant EXTRUDER_ROLE_INFILL => 2; use constant EXTRUDER_ROLE_SUPPORT_MATERIAL => 3; use constant EXTRUDER_ROLE_SUPPORT_MATERIAL_INTERFACE => 4; -sub new_from_config { - my ($class, $config, $extruder_id) = @_; - - my %conf = ( - id => $extruder_id, - use_relative_e_distances => $config->use_relative_e_distances, - ); - foreach my $opt_key (@{&OPTIONS}) { - $conf{$opt_key} = $config->get_at($opt_key, $extruder_id); - } - return $class->new(%conf); -} -sub _build_e_per_mm3 { +sub e_per_mm3 { my $self = shift; return $self->extrusion_multiplier * (4 / (($self->filament_diameter ** 2) * PI)); } -sub _build_retract_speed_mm_min { +sub retract_speed_mm_min { my $self = shift; return $self->retract_speed * 60; } -sub reset { - my ($self) = @_; - - $self->E(0); - $self->absolute_E(0); - $self->retracted(0); - $self->restart_extra(0); -} - sub scaled_wipe_distance { my ($self, $travel_speed) = @_; @@ -74,14 +39,6 @@ sub scaled_wipe_distance { return scale($self->retract_length / $self->retract_speed * $travel_speed * 0.8); } -sub extrude { - my ($self, $E) = @_; - - $self->E(0) if $self->use_relative_e_distances; - $self->absolute_E($self->absolute_E + $E); - return $self->E($self->E + $E); -} - sub extruded_volume { my ($self, $E) = @_; return $E * ($self->filament_diameter**2) * PI/4; diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 564266dc0..37eed4797 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -53,7 +53,7 @@ sub set_extruders { my ($self, $extruder_ids) = @_; foreach my $i (@$extruder_ids) { - $self->extruders->{$i} = my $e = Slic3r::Extruder->new_from_config($self->print_config, $i); + $self->extruders->{$i} = my $e = Slic3r::Extruder->new($i, $self->print_config); $self->enable_wipe(1) if $e->wipe; } @@ -508,8 +508,8 @@ sub retract { $gcode .= $self->G1(@$lift); } } - $self->extruder->retracted($self->extruder->retracted + $length); - $self->extruder->restart_extra($restart_extra); + $self->extruder->set_retracted($self->extruder->retracted + $length); + $self->extruder->set_restart_extra($restart_extra); $self->lifted($self->_retract_lift) if $lift; # reset extrusion distance during retracts @@ -547,8 +547,8 @@ sub unretract { $gcode .= " ; compensate retraction" if $self->print_config->gcode_comments; $gcode .= "\n"; } - $self->extruder->retracted(0); - $self->extruder->restart_extra(0); + $self->extruder->set_retracted(0); + $self->extruder->set_restart_extra(0); } return $gcode; @@ -558,7 +558,7 @@ sub reset_e { my ($self) = @_; return "" if $self->print_config->gcode_flavor =~ /^(?:mach3|makerware|sailfish)$/; - $self->extruder->E(0) if $self->extruder; + $self->extruder->set_E(0) if $self->extruder; return sprintf "G92 %s0%s\n", $self->_extrusion_axis, ($self->print_config->gcode_comments ? ' ; reset extrusion distance' : '') if $self->_extrusion_axis && !$self->print_config->use_relative_e_distances; } @@ -587,7 +587,7 @@ sub _G0_G1 { if ($point) { $gcode .= sprintf " X%.3f Y%.3f", - ($point->x * &Slic3r::SCALING_FACTOR) + $self->shift_x - $self->extruder->extruder_offset->[X], + ($point->x * &Slic3r::SCALING_FACTOR) + $self->shift_x - $self->extruder->extruder_offset->[X], ($point->y * &Slic3r::SCALING_FACTOR) + $self->shift_y - $self->extruder->extruder_offset->[Y]; #** $self->last_pos($point->clone); } diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 34216271b..18678e391 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -714,7 +714,7 @@ sub make_skirt { if ($self->config->min_skirt_length > 0) { $extruded_length[$extruder_idx] ||= 0; if (!$extruders_e_per_mm[$extruder_idx]) { - my $extruder = Slic3r::Extruder->new_from_config($self->config, $extruder_idx); + my $extruder = Slic3r::Extruder->new($extruder_idx, $self->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]; diff --git a/xs/MANIFEST b/xs/MANIFEST index 0ad4cd8c1..0381ee4e6 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -1660,6 +1660,8 @@ src/ExPolygon.cpp src/ExPolygon.hpp src/ExPolygonCollection.cpp src/ExPolygonCollection.hpp +src/Extruder.cpp +src/Extruder.hpp src/ExtrusionEntity.cpp src/ExtrusionEntity.hpp src/ExtrusionEntityCollection.cpp @@ -1721,6 +1723,7 @@ xsp/Clipper.xsp xsp/Config.xsp xsp/ExPolygon.xsp xsp/ExPolygonCollection.xsp +xsp/Extruder.xsp xsp/ExtrusionEntityCollection.xsp xsp/ExtrusionLoop.xsp xsp/ExtrusionPath.xsp diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index 6188a8bef..d30f84299 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -28,6 +28,11 @@ our @ISA = 'Slic3r::Point'; sub DESTROY {} +package Slic3r::Pointf; +use overload + '@{}' => sub { [ $_[0]->x, $_[0]->y ] }, #, + 'fallback' => 1; + package Slic3r::Pointf3; use overload '@{}' => sub { [ $_[0]->x, $_[0]->y, $_[0]->z ] }, #, @@ -221,4 +226,9 @@ use overload '@{}' => sub { $_[0]->arrayref }, 'fallback' => 1; +package Slic3r::Config::Print::Ref; +our @ISA = 'Slic3r::Config::Print'; + +sub DESTROY {} + 1; diff --git a/xs/src/Config.hpp b/xs/src/Config.hpp index 4d6446dc9..452f602d4 100644 --- a/xs/src/Config.hpp +++ b/xs/src/Config.hpp @@ -33,7 +33,7 @@ class ConfigOptionVector virtual ~ConfigOptionVector() {}; std::vector values; - T get_at(size_t i) { + T get_at(size_t i) const { try { return this->values.at(i); } catch (const std::out_of_range& oor) { diff --git a/xs/src/Extruder.cpp b/xs/src/Extruder.cpp new file mode 100644 index 000000000..c7a04941f --- /dev/null +++ b/xs/src/Extruder.cpp @@ -0,0 +1,153 @@ +#include "Extruder.hpp" +#ifdef SLIC3RXS +#include "perlglue.hpp" +#endif + +namespace Slic3r { + +Extruder::Extruder(int id, PrintConfig *config) +: id(id), + config(config) +{ + reset(); +} + +void +Extruder::reset() +{ + this->E = 0; + this->absolute_E = 0; + this->retracted = 0; + this->restart_extra = 0; +} + +double +Extruder::extrude(double dE) +{ + if (this->use_relative_e_distances()) { + this->E = 0; + } + + this->E += dE; + this->absolute_E += dE; + return this->E; +} + +template Val +Extruder::get_config(const char *name) const +{ + // TODO: figure out way to avoid static_cast to access hidden const method + const ConfigOption *opt = static_cast(this->config) + ->option(name); + return dynamic_cast(opt)->get_at(this->id); +} + +bool +Extruder::use_relative_e_distances() const +{ + // not using get_config because use_relative_e_distances is global + // for all extruders + + // TODO: figure out way to avoid static_cast to access hidden const method + const ConfigOption *opt = static_cast(this->config) + ->option("use_relative_e_distances"); + return *static_cast(opt); +} + +Pointf +Extruder::extruder_offset() const +{ + return get_config("extruder_offset"); +} + +double +Extruder::nozzle_diameter() const +{ + return get_config("nozzle_diameter"); +} + +double +Extruder::filament_diameter() const +{ + return get_config("filament_diameter"); +} + +double +Extruder::extrusion_multiplier() const +{ + return get_config("extrusion_multiplier"); +} + +int +Extruder::temperature() const +{ + return get_config("temperature"); +} + +int +Extruder::first_layer_temperature() const +{ + return get_config("first_layer_temperature"); +} + +double +Extruder::retract_length() const +{ + return get_config("retract_length"); +} + +double +Extruder::retract_lift() const +{ + return get_config("retract_lift"); +} + +int +Extruder::retract_speed() const +{ + return get_config("retract_speed"); +} + +double +Extruder::retract_restart_extra() const +{ + return get_config("retract_restart_extra"); +} + +double +Extruder::retract_before_travel() const +{ + return get_config("retract_before_travel"); +} + +bool +Extruder::retract_layer_change() const +{ + return get_config("retract_layer_change"); +} + +double +Extruder::retract_length_toolchange() const +{ + return get_config("retract_length_toolchange"); +} + +double +Extruder::retract_restart_extra_toolchange() const +{ + return get_config( + "retract_restart_extra_toolchange"); +} + +bool +Extruder::wipe() const +{ + return get_config("wipe"); +} + + +#ifdef SLIC3RXS +REGISTER_CLASS(Extruder, "Extruder"); +#endif + +} diff --git a/xs/src/Extruder.hpp b/xs/src/Extruder.hpp new file mode 100644 index 000000000..7302e42a3 --- /dev/null +++ b/xs/src/Extruder.hpp @@ -0,0 +1,54 @@ +#ifndef slic3r_Extruder_hpp_ +#define slic3r_Extruder_hpp_ + +#include +#include "Point.hpp" +#include "PrintConfig.hpp" + +namespace Slic3r { + +class Extruder +{ + public: + Extruder(int id, PrintConfig *config); + virtual ~Extruder() {} + void reset(); + double extrude(double dE); + + + bool use_relative_e_distances() const; + Pointf extruder_offset() const; + double nozzle_diameter() const; + double filament_diameter() const; + double extrusion_multiplier() const; + int temperature() const; + int first_layer_temperature() const; + double retract_length() const; + double retract_lift() const; + int retract_speed() const; + double retract_restart_extra() const; + double retract_before_travel() const; + bool retract_layer_change() const; + double retract_length_toolchange() const; + double retract_restart_extra_toolchange() const; + bool wipe() const; + + int id; + double E; + double absolute_E; + double retracted; + double restart_extra; + + PrintConfig *config; + + + private: + + // get value from a ConfigOptionVector subtype, indexed by extruder id + template + Val get_config(const char *name) const; +}; + +} + +#endif diff --git a/xs/src/ExtrusionEntity.cpp b/xs/src/ExtrusionEntity.cpp index 3865df877..0e023577e 100644 --- a/xs/src/ExtrusionEntity.cpp +++ b/xs/src/ExtrusionEntity.cpp @@ -2,6 +2,7 @@ #include "ExtrusionEntityCollection.hpp" #include "ExPolygonCollection.hpp" #include "ClipperUtils.hpp" +#include "Extruder.hpp" #include #ifdef SLIC3RXS #include "perlglue.hpp" @@ -109,7 +110,7 @@ ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCo REGISTER_CLASS(ExtrusionPath, "ExtrusionPath"); std::string -ExtrusionPath::gcode(SV* extruder, double e, double F, +ExtrusionPath::gcode(Extruder* extruder, double e, double F, double xofs, double yofs, std::string extrusion_axis, std::string gcode_line_suffix) const { @@ -127,19 +128,7 @@ ExtrusionPath::gcode(SV* extruder, double e, double F, const double line_length = line_it->length() * SCALING_FACTOR; // calculate extrusion length for this line - double E = 0; - if (e != 0) { - PUSHMARK(SP); - XPUSHs(extruder); - XPUSHs(sv_2mortal(newSVnv(e * line_length))); - PUTBACK; - - const int count = call_method("extrude", G_SCALAR); - SPAGAIN; - - // TODO: check that count is 1 - E = POPn; - } + double E = (e == 0) ? 0 : extruder->extrude(e * line_length); // compose G-code line diff --git a/xs/src/ExtrusionEntity.hpp b/xs/src/ExtrusionEntity.hpp index cab5be7d9..0e3c71ea7 100644 --- a/xs/src/ExtrusionEntity.hpp +++ b/xs/src/ExtrusionEntity.hpp @@ -9,6 +9,7 @@ namespace Slic3r { class ExPolygonCollection; class ExtrusionEntityCollection; +class Extruder; enum ExtrusionRole { erPerimeter, @@ -57,7 +58,7 @@ class ExtrusionPath : public ExtrusionEntity double length() const; #ifdef SLIC3RXS - std::string gcode(SV* extruder, double e, double F, + std::string gcode(Extruder* extruder, double e, double F, double xofs, double yofs, std::string extrusion_axis, std::string gcode_line_suffix) const; #endif diff --git a/xs/xsp/Extruder.xsp b/xs/xsp/Extruder.xsp new file mode 100644 index 000000000..47b5c0fa2 --- /dev/null +++ b/xs/xsp/Extruder.xsp @@ -0,0 +1,51 @@ +%module{Slic3r::XS}; + +%{ +#include +#include "Extruder.hpp" +%} + +%name{Slic3r::Extruder} class Extruder { + Extruder(int id, PrintConfig *config); + + ~Extruder(); + void reset(); + double extrude(double dE); + + int id() const + %code%{ RETVAL = THIS->id; %}; + + + double E() const + %code%{ RETVAL = THIS->E; %}; + double set_E(double val) const + %code%{ RETVAL = THIS->E = val; %}; + double absolute_E() const + %code%{ RETVAL = THIS->absolute_E; %}; + double set_absolute_E(double val) const + %code%{ RETVAL = THIS->absolute_E = val; %}; + double retracted() const + %code%{ RETVAL = THIS->retracted; %}; + double set_retracted(double val) const + %code%{ RETVAL = THIS->retracted = val; %}; + double restart_extra() const + %code%{ RETVAL = THIS->restart_extra; %}; + double set_restart_extra(double val) const + %code%{ RETVAL = THIS->restart_extra = val; %}; + + Clone extruder_offset() const; + double nozzle_diameter() const; + double filament_diameter() const; + double extrusion_multiplier() const; + int temperature() const; + int first_layer_temperature() const; + double retract_length() const; + double retract_lift() const; + int retract_speed() const; + double retract_restart_extra() const; + double retract_before_travel() const; + bool retract_layer_change() const; + double retract_length_toolchange() const; + double retract_restart_extra_toolchange() const; + bool wipe() const; +}; diff --git a/xs/xsp/ExtrusionPath.xsp b/xs/xsp/ExtrusionPath.xsp index 5c013b182..2926f2eda 100644 --- a/xs/xsp/ExtrusionPath.xsp +++ b/xs/xsp/ExtrusionPath.xsp @@ -25,7 +25,7 @@ bool is_perimeter(); bool is_fill(); bool is_bridge(); - std::string gcode(SV* extruder, double e, double F, + std::string gcode(Extruder* extruder, double e, double F, double xofs, double yofs, std::string extrusion_axis, std::string gcode_line_suffix); %{ diff --git a/xs/xsp/Point.xsp b/xs/xsp/Point.xsp index f2c1a699f..952cd161f 100644 --- a/xs/xsp/Point.xsp +++ b/xs/xsp/Point.xsp @@ -56,6 +56,17 @@ Point::coincides_with(point_sv) }; +%name{Slic3r::Pointf} class Pointf { + Pointf(double _x = 0, double _y = 0); + ~Pointf(); + Clone clone() + %code{% RETVAL = THIS; %}; + double x() + %code{% RETVAL = THIS->x; %}; + double y() + %code{% RETVAL = THIS->y; %}; +}; + %name{Slic3r::Pointf3} class Pointf3 { Pointf3(double _x = 0, double _y = 0, double _z = 0); ~Pointf3(); diff --git a/xs/xsp/my.map b/xs/xsp/my.map index 306158396..27afe53bb 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -25,6 +25,10 @@ Point* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T +Pointf* O_OBJECT_SLIC3R +Ref O_OBJECT_SLIC3R_T +Clone O_OBJECT_SLIC3R_T + Pointf3* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T @@ -77,6 +81,8 @@ Clone O_OBJECT_SLIC3R_T SurfaceCollection* O_OBJECT_SLIC3R +Extruder* O_OBJECT_SLIC3R + ExtrusionRole T_UV FlowRole T_UV PrintStep T_UV diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index 2c3667096..3aed02f7a 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -12,6 +12,9 @@ %typemap{Point*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; +%typemap{Pointf*}; +%typemap{Ref}{simple}; +%typemap{Clone}{simple}; %typemap{Pointf3*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; @@ -70,6 +73,7 @@ %typemap{Surfaces}; %typemap{Polygons*}; %typemap{TriangleMeshPtrs}; +%typemap{Extruder*}; %typemap{SurfaceType}{parsed}{ %cpp_type{SurfaceType};