From 036badf932291520ca7d3f7d9f8bad1c69a947aa Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 5 Jan 2014 13:16:13 +0100 Subject: [PATCH] Ported Flow to XS --- lib/Slic3r/Flow.pm | 167 ++------------------------------------------ lib/Slic3r/GCode.pm | 2 +- xs/MANIFEST | 4 ++ xs/lib/Slic3r/XS.pm | 28 ++++++++ xs/src/Config.cpp | 32 ++++----- xs/src/Config.hpp | 36 ++++++---- xs/src/Flow.cpp | 109 +++++++++++++++++++++++++++++ xs/src/Flow.hpp | 48 +++++++++++++ xs/src/Point.cpp | 4 +- xs/src/Point.hpp | 6 +- xs/src/myinit.h | 2 + xs/t/15_config.t | 5 +- xs/t/16_flow.t | 29 ++++++++ xs/xsp/Flow.xsp | 80 +++++++++++++++++++++ xs/xsp/my.map | 2 + xs/xsp/typemap.xspt | 7 ++ 16 files changed, 360 insertions(+), 201 deletions(-) create mode 100644 xs/src/Flow.cpp create mode 100644 xs/src/Flow.hpp create mode 100644 xs/t/16_flow.t create mode 100644 xs/xsp/Flow.xsp diff --git a/lib/Slic3r/Flow.pm b/lib/Slic3r/Flow.pm index f07be98f5..a7c8312c5 100644 --- a/lib/Slic3r/Flow.pm +++ b/lib/Slic3r/Flow.pm @@ -1,165 +1,12 @@ package Slic3r::Flow; -use Moo; +use strict; +use warnings; -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw(FLOW_ROLE_PERIMETER FLOW_ROLE_INFILL FLOW_ROLE_SOLID_INFILL FLOW_ROLE_TOP_SOLID_INFILL - FLOW_ROLE_SUPPORT_MATERIAL FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE); +use parent qw(Exporter); + +our @EXPORT_OK = qw(FLOW_ROLE_PERIMETER FLOW_ROLE_INFILL FLOW_ROLE_SOLID_INFILL + FLOW_ROLE_TOP_SOLID_INFILL FLOW_ROLE_SUPPORT_MATERIAL + FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE); our %EXPORT_TAGS = (roles => \@EXPORT_OK); -use Slic3r::Geometry qw(PI); - -has 'width' => (is => 'ro', required => 1); -has 'spacing' => (is => 'ro', required => 1); -has 'nozzle_diameter' => (is => 'ro', required => 1); -has 'bridge' => (is => 'ro', default => sub {0}); -has 'scaled_width' => (is => 'lazy'); -has 'scaled_spacing' => (is => 'lazy'); - -use constant FLOW_ROLE_PERIMETER => 1; -use constant FLOW_ROLE_INFILL => 2; -use constant FLOW_ROLE_SOLID_INFILL => 3; -use constant FLOW_ROLE_TOP_SOLID_INFILL => 4; -use constant FLOW_ROLE_SUPPORT_MATERIAL => 5; -use constant FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE => 6; - -use constant BRIDGE_EXTRA_SPACING => 0.05; -use constant OVERLAP_FACTOR => 1; - -sub new_from_width { - my ($class, %args) = @_; - - if ($args{width} eq '0') { - $args{width} = _width(@args{qw(role nozzle_diameter layer_height bridge_flow_ratio)}); - } elsif ($args{width} =~ /^(\d+(?:\.\d+)?)%$/) { - $args{width} = $args{layer_height} * $1 / 100; - } - - return $class->new( - width => $args{width}, - spacing => _spacing(@args{qw(width nozzle_diameter layer_height bridge_flow_ratio)}), - nozzle_diameter => $args{nozzle_diameter}, - bridge => ($args{bridge_flow_ratio} > 0) ? 1 : 0, - ); -} - -sub new_from_spacing { - my ($class, %args) = @_; - - return $class->new( - width => _width_from_spacing(@args{qw(spacing nozzle_diameter layer_height bridge)}), - spacing => $args{spacing}, - nozzle_diameter => $args{nozzle_diameter}, - bridge => $args{bridge}, - ); -} - -sub clone { - my $self = shift; - - return (ref $self)->new( - width => $self->width, - spacing => $self->spacing, - nozzle_diameter => $self->nozzle_diameter, - bridge => $self->bridge, - ); -} - -sub mm3_per_mm { - my ($self, $h) = @_; - - my $w = $self->width; - my $s = $self->spacing; - - if ($self->bridge) { - return ($w**2) * PI/4; - } elsif ($w >= ($self->nozzle_diameter + $h)) { - # rectangle with semicircles at the ends - return $w * $h + ($h**2) / 4 * (PI - 4); - } else { - # rectangle with shrunk semicircles at the ends - return $self->nozzle_diameter * $h * (1 - PI/4) + $h * $w * PI/4; - } -} - -sub _width { - my ($role, $nozzle_diameter, $layer_height, $bridge_flow_ratio) = @_; - - if ($bridge_flow_ratio > 0) { - return sqrt($bridge_flow_ratio * ($nozzle_diameter**2)); - } - - # here we calculate a sane default by matching the flow speed (at the nozzle) and the feed rate - my $volume = ($nozzle_diameter**2) * PI/4; - my $shape_threshold = $nozzle_diameter * $layer_height + ($layer_height**2) * PI/4; - my $width; - if ($volume >= $shape_threshold) { - # rectangle with semicircles at the ends - $width = (($nozzle_diameter**2) * PI + ($layer_height**2) * (4 - PI)) / (4 * $layer_height); - } else { - # rectangle with squished semicircles at the ends - $width = $nozzle_diameter * ($nozzle_diameter/$layer_height - 4/PI + 1); - } - - my $min = $nozzle_diameter * 1.05; - my $max; - if ($role == FLOW_ROLE_PERIMETER || $role == FLOW_ROLE_SUPPORT_MATERIAL) { - $min = $max = $nozzle_diameter; - } elsif ($role != FLOW_ROLE_INFILL) { - # do not limit width for sparse infill so that we use full native flow for it - $max = $nozzle_diameter * 1.7; - } - $width = $max if defined($max) && $width > $max; - $width = $min if $width < $min; - - return $width; -} - -sub _width_from_spacing { - my ($s, $nozzle_diameter, $h, $bridge) = @_; - - if ($bridge) { - return $s - BRIDGE_EXTRA_SPACING; - } - - my $w_threshold = $h + $nozzle_diameter; - my $s_threshold = $w_threshold - OVERLAP_FACTOR * ($w_threshold - ($w_threshold - $h * (1 - PI/4))); - - if ($s >= $s_threshold) { - # rectangle with semicircles at the ends - return $s + OVERLAP_FACTOR * $h * (1 - PI/4); - } else { - # rectangle with shrunk semicircles at the ends - return ($s + $nozzle_diameter * OVERLAP_FACTOR * (PI/4 - 1)) / (1 + OVERLAP_FACTOR * (PI/4 - 1)); - } -} - -sub _spacing { - my ($width, $nozzle_diameter, $layer_height, $bridge_flow_ratio) = @_; - - if ($bridge_flow_ratio > 0) { - return $width + BRIDGE_EXTRA_SPACING; - } - use XXX; ZZZ "here" if !defined $nozzle_diameter; - my $min_flow_spacing; - if ($width >= ($nozzle_diameter + $layer_height)) { - # rectangle with semicircles at the ends - $min_flow_spacing = $width - $layer_height * (1 - PI/4); - } else { - # rectangle with shrunk semicircles at the ends - $min_flow_spacing = $nozzle_diameter * (1 - PI/4) + $width * PI/4; - } - return $width - OVERLAP_FACTOR * ($width - $min_flow_spacing); -} - -sub _build_scaled_width { - my $self = shift; - return Slic3r::Geometry::scale($self->width); -} - -sub _build_scaled_spacing { - my $self = shift; - return Slic3r::Geometry::scale($self->spacing); -} - 1; diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 78324f3bd..1d1952309 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -246,7 +246,7 @@ sub extrude_loop { foreach my $path (@{$extrusion_path->intersect_expolygons($self->_layer_overhangs)}) { $path = $path->clone; $path->role(EXTR_ROLE_OVERHANG_PERIMETER); - $path->mm3_per_mm($self->region->flow(FLOW_ROLE_PERIMETER, undef, 1)->mm3_per_mm(undef)); + $path->mm3_per_mm($self->region->flow(FLOW_ROLE_PERIMETER, -1, 1)->mm3_per_mm(-1)); push @paths, $path; } diff --git a/xs/MANIFEST b/xs/MANIFEST index ef37e40cb..fc52e2497 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -22,6 +22,8 @@ src/ExtrusionEntity.cpp src/ExtrusionEntity.hpp src/ExtrusionEntityCollection.cpp src/ExtrusionEntityCollection.hpp +src/Flow.cpp +src/Flow.hpp src/Geometry.cpp src/Geometry.hpp src/Line.cpp @@ -65,6 +67,7 @@ t/12_extrusionpathcollection.t t/13_polylinecollection.t t/14_geometry.t t/15_config.t +t/16_flow.t xsp/Clipper.xsp xsp/Config.xsp xsp/ExPolygon.xsp @@ -72,6 +75,7 @@ xsp/ExPolygonCollection.xsp xsp/ExtrusionEntityCollection.xsp xsp/ExtrusionLoop.xsp xsp/ExtrusionPath.xsp +xsp/Flow.xsp xsp/Geometry.xsp xsp/Line.xsp xsp/my.map diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index 9e0e678d8..489aeb0e8 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -146,6 +146,34 @@ our @ISA = 'Slic3r::ExtrusionPath'; sub DESTROY {} +package Slic3r::Flow; + +sub new { + my ($class, %args) = @_; + + my $self = $class->_new( + @args{qw(width spacing nozzle_diameter)}, + ); + $self->set_bridge($args{bridge} // 0); + return $self; +} + +sub new_from_width { + my ($class, %args) = @_; + + return $class->_new_from_width( + @args{qw(role width nozzle_diameter layer_height bridge_flow_ratio)}, + ); +} + +sub new_from_spacing { + my ($class, %args) = @_; + + return $class->_new_from_spacing( + @args{qw(spacing nozzle_diameter layer_height bridge)}, + ); +} + package Slic3r::Surface; sub new { diff --git a/xs/src/Config.cpp b/xs/src/Config.cpp index 32c6d6074..20be9a3c2 100644 --- a/xs/src/Config.cpp +++ b/xs/src/Config.cpp @@ -50,22 +50,18 @@ ConfigBase::set_deserialize(const t_config_option_key opt_key, std::string str) double ConfigBase::get_abs_value(const t_config_option_key opt_key) { - // get option definition - assert(this->def->count(opt_key) != 0); - ConfigOptionDef* def = &(*this->def)[opt_key]; - assert(def->type == coFloatOrPercent); - - // get stored option value - ConfigOptionFloatOrPercent* opt = dynamic_cast(this->option(opt_key)); - assert(opt != NULL); - - // compute absolute value - if (opt->percent) { - ConfigOptionFloat* optbase = dynamic_cast(this->option(def->ratio_over)); - if (optbase == NULL) throw "ratio_over option not found"; - return optbase->value * opt->value / 100; + ConfigOption* opt = this->option(opt_key, false); + if (ConfigOptionFloatOrPercent* optv = dynamic_cast(opt)) { + // get option definition + assert(this->def->count(opt_key) != 0); + ConfigOptionDef* def = &(*this->def)[opt_key]; + + // compute absolute value over the absolute value of the base option + return optv->get_abs_value(this->get_abs_value(def->ratio_over)); + } else if (ConfigOptionFloat* optv = dynamic_cast(opt)) { + return optv->value; } else { - return opt->value; + throw "Not a valid option type for get_abs_value()"; } } @@ -76,11 +72,7 @@ ConfigBase::get_abs_value(const t_config_option_key opt_key, double ratio_over) assert(opt != NULL); // compute absolute value - if (opt->percent) { - return ratio_over * opt->value / 100; - } else { - return opt->value; - } + return opt->get_abs_value(ratio_over); } #ifdef SLIC3RXS diff --git a/xs/src/Config.hpp b/xs/src/Config.hpp index 64229cb2c..71f945349 100644 --- a/xs/src/Config.hpp +++ b/xs/src/Config.hpp @@ -21,7 +21,7 @@ typedef std::vector t_config_option_keys; class ConfigOption { public: virtual ~ConfigOption() {}; - virtual std::string serialize() = 0; + virtual std::string serialize() const = 0; virtual void deserialize(std::string str) = 0; }; @@ -49,7 +49,7 @@ class ConfigOptionFloat : public ConfigOption operator double() const { return this->value; }; - std::string serialize() { + std::string serialize() const { std::ostringstream ss; ss << this->value; return ss.str(); @@ -64,7 +64,7 @@ class ConfigOptionFloats : public ConfigOption, public ConfigOptionVector::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { if (it - this->values.begin() != 0) ss << ","; @@ -91,7 +91,7 @@ class ConfigOptionInt : public ConfigOption operator int() const { return this->value; }; - std::string serialize() { + std::string serialize() const { std::ostringstream ss; ss << this->value; return ss.str(); @@ -106,7 +106,7 @@ class ConfigOptionInts : public ConfigOption, public ConfigOptionVector { public: - std::string serialize() { + std::string serialize() const { std::ostringstream ss; for (std::vector::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { if (it - this->values.begin() != 0) ss << ","; @@ -133,7 +133,7 @@ class ConfigOptionString : public ConfigOption operator std::string() const { return this->value; }; - std::string serialize() { + std::string serialize() const { std::string str = this->value; // s/\R/\\n/g @@ -163,7 +163,7 @@ class ConfigOptionStrings : public ConfigOption, public ConfigOptionVector::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { if (it - this->values.begin() != 0) ss << ";"; @@ -189,7 +189,15 @@ class ConfigOptionFloatOrPercent : public ConfigOption bool percent; ConfigOptionFloatOrPercent() : value(0), percent(false) {}; - std::string serialize() { + double get_abs_value(double ratio_over) const { + if (this->percent) { + return ratio_over * this->value / 100; + } else { + return this->value; + } + }; + + std::string serialize() const { std::ostringstream ss; ss << this->value; std::string s(ss.str()); @@ -216,7 +224,7 @@ class ConfigOptionPoint : public ConfigOption operator Pointf() const { return this->point; }; - std::string serialize() { + std::string serialize() const { std::ostringstream ss; ss << this->point.x; ss << ","; @@ -233,7 +241,7 @@ class ConfigOptionPoints : public ConfigOption, public ConfigOptionVectorvalues.begin(); it != this->values.end(); ++it) { if (it - this->values.begin() != 0) ss << ","; @@ -264,7 +272,7 @@ class ConfigOptionBool : public ConfigOption operator bool() const { return this->value; }; - std::string serialize() { + std::string serialize() const { return std::string(this->value ? "1" : "0"); }; @@ -277,7 +285,7 @@ class ConfigOptionBools : public ConfigOption, public ConfigOptionVector { public: - std::string serialize() { + std::string serialize() const { std::ostringstream ss; for (std::vector::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { if (it - this->values.begin() != 0) ss << ","; @@ -306,7 +314,7 @@ class ConfigOptionEnum : public ConfigOption operator T() const { return this->value; }; - std::string serialize() { + std::string serialize() const { t_config_enum_values enum_keys_map = ConfigOptionEnum::get_enum_values(); for (t_config_enum_values::iterator it = enum_keys_map.begin(); it != enum_keys_map.end(); ++it) { if (it->second == static_cast(this->value)) return it->first; @@ -333,7 +341,7 @@ class ConfigOptionEnumGeneric : public ConfigOption operator int() const { return this->value; }; - std::string serialize() { + std::string serialize() const { for (t_config_enum_values::iterator it = this->keys_map->begin(); it != this->keys_map->end(); ++it) { if (it->second == this->value) return it->first; } diff --git a/xs/src/Flow.cpp b/xs/src/Flow.cpp new file mode 100644 index 000000000..e5e7dc2be --- /dev/null +++ b/xs/src/Flow.cpp @@ -0,0 +1,109 @@ +#include "Flow.hpp" +#include + +namespace Slic3r { + +Flow +Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio) { + float w; + if (!width.percent && width.value == 0) { + w = Flow::_width(role, nozzle_diameter, height, bridge_flow_ratio); + } else { + w = width.get_abs_value(height); + } + + Flow flow(w, Flow::_spacing(w, nozzle_diameter, height, bridge_flow_ratio), nozzle_diameter); + if (bridge_flow_ratio > 0) flow.bridge = true; + return flow; +} + +Flow +Flow::new_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge) { + float w = Flow::_width_from_spacing(spacing, nozzle_diameter, height, bridge); + Flow flow(w, spacing, nozzle_diameter); + flow.bridge = bridge; + return flow; +} + +double +Flow::mm3_per_mm(float h) { + if (this->bridge) { + return (this->width * this->width) * PI/4.0; + } else if (this->width >= (this->nozzle_diameter + h)) { + // rectangle with semicircles at the ends + return this->width * h + (h*h) / 4.0 * (PI-4.0); + } else { + // rectangle with shrunk semicircles at the ends + return this->nozzle_diameter * h * (1 - PI/4.0) + h * this->width * PI/4.0; + } +} + +float +Flow::_width(FlowRole role, float nozzle_diameter, float height, float bridge_flow_ratio) { + if (bridge_flow_ratio > 0) { + return sqrt(bridge_flow_ratio * (nozzle_diameter*nozzle_diameter)); + } + + // here we calculate a sane default by matching the flow speed (at the nozzle) and the feed rate + float volume = (nozzle_diameter*nozzle_diameter) * PI/4.0; + float shape_threshold = nozzle_diameter * height + (height*height) * PI/4.0; + float width; + if (volume >= shape_threshold) { + // rectangle with semicircles at the ends + width = ((nozzle_diameter*nozzle_diameter) * PI + (height*height) * (4.0 - PI)) / (4.0 * height); + } else { + // rectangle with squished semicircles at the ends + width = nozzle_diameter * (nozzle_diameter/height - 4.0/PI + 1); + } + + float min = nozzle_diameter * 1.05; + float max = -1; + if (role == frPerimeter || role == frSupportMaterial) { + min = max = nozzle_diameter; + } else if (role != frInfill) { + // do not limit width for sparse infill so that we use full native flow for it + max = nozzle_diameter * 1.7; + } + if (max != -1 && width > max) width = max; + if (width < min) width = min; + + return width; +} + + +float +Flow::_width_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge) { + if (bridge) { + return spacing - BRIDGE_EXTRA_SPACING; + } + + float w_threshold = height + nozzle_diameter; + float s_threshold = w_threshold - OVERLAP_FACTOR * (w_threshold - (w_threshold - height * (1 - PI/4.0))); + + if (spacing >= s_threshold) { + // rectangle with semicircles at the ends + return spacing + OVERLAP_FACTOR * height * (1 - PI/4.0); + } else { + // rectangle with shrunk semicircles at the ends + return (spacing + nozzle_diameter * OVERLAP_FACTOR * (PI/4.0 - 1)) / (1 + OVERLAP_FACTOR * (PI/4.0 - 1)); + } +} + +float +Flow::_spacing(float width, float nozzle_diameter, float height, float bridge_flow_ratio) { + if (bridge_flow_ratio > 0) { + return width + BRIDGE_EXTRA_SPACING; + } + + float min_flow_spacing; + if (width >= (nozzle_diameter + height)) { + // rectangle with semicircles at the ends + min_flow_spacing = width - height * (1 - PI/4.0); + } else { + // rectangle with shrunk semicircles at the ends + min_flow_spacing = nozzle_diameter * (1 - PI/4.0) + width * PI/4.0; + } + return width - OVERLAP_FACTOR * (width - min_flow_spacing); +} + +} diff --git a/xs/src/Flow.hpp b/xs/src/Flow.hpp new file mode 100644 index 000000000..e98173dc9 --- /dev/null +++ b/xs/src/Flow.hpp @@ -0,0 +1,48 @@ +#ifndef slic3r_Flow_hpp_ +#define slic3r_Flow_hpp_ + +#include +#include "Config.hpp" +#include "ExtrusionEntity.hpp" + +namespace Slic3r { + +#define BRIDGE_EXTRA_SPACING 0.05 +#define OVERLAP_FACTOR 1.0 + +enum FlowRole { + frPerimeter, + frInfill, + frSolidInfill, + frTopSolidInfill, + frSupportMaterial, + frSupportMaterialInterface, +}; + +class Flow +{ + public: + float width; + float spacing; + float nozzle_diameter; + bool bridge; + coord_t scaled_width; + coord_t scaled_spacing; + + Flow(float _w, float _s, float _nd): width(_w), spacing(_s), nozzle_diameter(_nd), bridge(false) { + this->scaled_width = scale_(this->width); + this->scaled_spacing = scale_(this->spacing); + }; + double mm3_per_mm(float h); + static Flow new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio); + static Flow new_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge); + + private: + static float _width(FlowRole role, float nozzle_diameter, float height, float bridge_flow_ratio); + static float _width_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge); + static float _spacing(float width, float nozzle_diameter, float height, float bridge_flow_ratio); +}; + +} + +#endif diff --git a/xs/src/Point.cpp b/xs/src/Point.cpp index fbb3b06c6..d35b3f0f8 100644 --- a/xs/src/Point.cpp +++ b/xs/src/Point.cpp @@ -23,8 +23,8 @@ Point::rotate(double angle, Point* center) { double cur_x = (double)this->x; double cur_y = (double)this->y; - this->x = (long)round( (double)center->x + cos(angle) * (cur_x - (double)center->x) - sin(angle) * (cur_y - (double)center->y) ); - this->y = (long)round( (double)center->y + cos(angle) * (cur_y - (double)center->y) + sin(angle) * (cur_x - (double)center->x) ); + this->x = (coord_t)round( (double)center->x + cos(angle) * (cur_x - (double)center->x) - sin(angle) * (cur_y - (double)center->y) ); + this->y = (coord_t)round( (double)center->y + cos(angle) * (cur_y - (double)center->y) + sin(angle) * (cur_x - (double)center->x) ); } bool diff --git a/xs/src/Point.hpp b/xs/src/Point.hpp index 507d082c9..385f99cdb 100644 --- a/xs/src/Point.hpp +++ b/xs/src/Point.hpp @@ -17,9 +17,9 @@ typedef std::vector Pointfs; class Point { public: - long x; - long y; - explicit Point(long _x = 0, long _y = 0): x(_x), y(_y) {}; + coord_t x; + coord_t y; + explicit Point(coord_t _x = 0, coord_t _y = 0): x(_x), y(_y) {}; void scale(double factor); void translate(double x, double y); void rotate(double angle, Point* center); diff --git a/xs/src/myinit.h b/xs/src/myinit.h index 1ef522b44..fcbaca5c0 100644 --- a/xs/src/myinit.h +++ b/xs/src/myinit.h @@ -20,8 +20,10 @@ extern "C" { #define EPSILON 1e-4 #define SCALING_FACTOR 0.000001 +#define PI 3.141592653589793238 #define scale_(val) (val / SCALING_FACTOR) #define unscale(val) (val * SCALING_FACTOR) +typedef long coord_t; namespace Slic3r {} using namespace Slic3r; diff --git a/xs/t/15_config.t b/xs/t/15_config.t index c80f14408..ed60c3e6d 100644 --- a/xs/t/15_config.t +++ b/xs/t/15_config.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 88; +use Test::More tests => 89; foreach my $config (Slic3r::Config->new, Slic3r::Config::Full->new) { $config->set('layer_height', 0.3); @@ -110,6 +110,9 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Full->new) { my $config2 = Slic3r::Config->new; $config2->apply_static($config); is $config2->get('perimeters'), Slic3r::Config::print_config_def()->{perimeters}{default}, 'apply_static and print_config_def'; + + $config->set('top_solid_infill_speed', 70); + is $config->get_abs_value('top_solid_infill_speed'), 70, 'get_abs_value() works when ratio_over references a floatOrPercent option'; } { diff --git a/xs/t/16_flow.t b/xs/t/16_flow.t new file mode 100644 index 000000000..e19430200 --- /dev/null +++ b/xs/t/16_flow.t @@ -0,0 +1,29 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Slic3r::XS; +use Test::More tests => 2; + +{ + my $flow = Slic3r::Flow->new_from_width( + role => Slic3r::Flow::FLOW_ROLE_PERIMETER, + width => '1', + nozzle_diameter => 0.5, + layer_height => 0.3, + bridge_flow_ratio => 1, + ); + isa_ok $flow, 'Slic3r::Flow', 'new_from_width'; +} + +{ + my $flow = Slic3r::Flow->new( + width => 1, + spacing => 0.95, + nozzle_diameter => 0.5, + ); + isa_ok $flow, 'Slic3r::Flow', 'new'; +} + +__END__ diff --git a/xs/xsp/Flow.xsp b/xs/xsp/Flow.xsp new file mode 100644 index 000000000..4ff5427fc --- /dev/null +++ b/xs/xsp/Flow.xsp @@ -0,0 +1,80 @@ +%module{Slic3r::XS}; + +%{ +#include +#include "Flow.hpp" +%} + +%name{Slic3r::Flow} class Flow { + ~Flow(); + %name{_new} Flow(float width, float spacing, float nozzle_diameter); + void set_bridge(bool bridge) + %code{% THIS->bridge = bridge; %}; + Flow* clone() + %code{% const char* CLASS = "Slic3r::Flow"; RETVAL = new Flow(*THIS); %}; + + float width() + %code{% RETVAL = THIS->width; %}; + float spacing() + %code{% RETVAL = THIS->spacing; %}; + float nozzle_diameter() + %code{% RETVAL = THIS->nozzle_diameter; %}; + bool bridge() + %code{% RETVAL = THIS->bridge; %}; + long scaled_width() + %code{% RETVAL = THIS->scaled_width; %}; + long scaled_spacing() + %code{% RETVAL = THIS->scaled_spacing; %}; + + double mm3_per_mm(float height); +%{ + +Flow* +_new_from_width(CLASS, role, width, nozzle_diameter, height, bridge_flow_ratio) + char* CLASS; + FlowRole role; + std::string width; + float nozzle_diameter; + float height; + float bridge_flow_ratio; + CODE: + ConfigOptionFloatOrPercent optwidth; + optwidth.deserialize(width); + RETVAL = new Flow(Flow::new_from_config_width(role, optwidth, nozzle_diameter, height, bridge_flow_ratio)); + OUTPUT: + RETVAL + +Flow* +_new_from_spacing(CLASS, spacing, nozzle_diameter, height, bridge) + char* CLASS; + float spacing; + float nozzle_diameter; + float height; + bool bridge; + CODE: + RETVAL = new Flow(Flow::new_from_spacing(spacing, nozzle_diameter, height, bridge)); + OUTPUT: + RETVAL + +%} +}; + +%package{Slic3r::Flow}; +%{ + +IV +_constant() + ALIAS: + FLOW_ROLE_PERIMETER = frPerimeter + FLOW_ROLE_INFILL = frInfill + FLOW_ROLE_SOLID_INFILL = frSolidInfill + FLOW_ROLE_TOP_SOLID_INFILL = frTopSolidInfill + FLOW_ROLE_SUPPORT_MATERIAL = frSupportMaterial + FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE = frSupportMaterialInterface + PROTOTYPE: + CODE: + RETVAL = ix; + OUTPUT: RETVAL + +%} + diff --git a/xs/xsp/my.map b/xs/xsp/my.map index 666cbf616..6a02d9432 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -18,11 +18,13 @@ ExPolygonCollection* O_OBJECT ExtrusionEntityCollection* O_OBJECT ExtrusionPath* O_OBJECT ExtrusionLoop* O_OBJECT +Flow* O_OBJECT PrintState* O_OBJECT Surface* O_OBJECT SurfaceCollection* O_OBJECT ExtrusionRole T_UV +FlowRole T_UV PrintStep T_UV SurfaceType T_UV ClipperLib::JoinType T_UV diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index 25c4c4d12..46a037526 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -15,6 +15,7 @@ %typemap{FullPrintConfig*}; %typemap{ExPolygon*}; %typemap{ExPolygonCollection*}; +%typemap{Flow*}; %typemap{Line*}; %typemap{Polyline*}; %typemap{Polygon*}; @@ -43,6 +44,12 @@ $CVar = (ExtrusionRole)SvUV($PerlVar); %}; }; +%typemap{FlowRole}{parsed}{ + %cpp_type{FlowRole}; + %precall_code{% + $CVar = (FlowRole)SvUV($PerlVar); + %}; +}; %typemap{PrintStep}{parsed}{ %cpp_type{PrintStep}; %precall_code{%