Ported the G-code generator from Perl to C++.

Removed GCode.pm
Removed the Perl bindigns for AvoidCrossingPerimeters, OozePrevention, SpiralVase, Wipe
Changed the std::set of extruder IDs to vector of IDs.
Removed some MSVC compiler warnings, removed obnoxious compiler warnings when compiling the Perl bindings.
This commit is contained in:
bubnikv 2017-05-03 18:28:22 +02:00
parent 72ae3585e4
commit e90279c513
52 changed files with 1362 additions and 1632 deletions

View file

@ -514,7 +514,6 @@ xsp/Flow.xsp
xsp/GCode.xsp
xsp/GCodeSender.xsp
xsp/GCodeWriter.xsp
xsp/GCodePressureEqualizer.xsp
xsp/Geometry.xsp
xsp/GUI.xsp
xsp/GUI_3DScene.xsp

View file

@ -278,10 +278,7 @@ for my $class (qw(
Slic3r::Filler
Slic3r::Flow
Slic3r::GCode
Slic3r::GCode::AvoidCrossingPerimeters
Slic3r::GCode::OozePrevention
Slic3r::GCode::PlaceholderParser
Slic3r::GCode::Wipe
Slic3r::GCode::Writer
Slic3r::Geometry::BoundingBox
Slic3r::Geometry::BoundingBoxf

View file

@ -37,6 +37,9 @@ public:
Polylines unsupported_edges(double angle = -1) const;
private:
// Suppress warning "assignment operator could not be generated"
BridgeDetector& operator=(const BridgeDetector &);
void initialize();
struct BridgeDirection {

View file

@ -34,7 +34,7 @@ class ConfigOption {
virtual int getInt() const { return 0; };
virtual double getFloat() const { return 0; };
virtual bool getBool() const { return false; };
virtual void setInt(int val) {};
virtual void setInt(int /* val */) { };
friend bool operator== (const ConfigOption &a, const ConfigOption &b);
friend bool operator!= (const ConfigOption &a, const ConfigOption &b);
};
@ -142,7 +142,7 @@ class ConfigOptionInt : public ConfigOptionSingle<int>
{
public:
ConfigOptionInt() : ConfigOptionSingle<int>(0) {};
ConfigOptionInt(double _value) : ConfigOptionSingle<int>(_value) {};
ConfigOptionInt(double _value) : ConfigOptionSingle<int>(int(floor(_value + 0.5))) {};
int getInt() const { return this->value; };
void setInt(int val) { this->value = val; };

View file

@ -326,7 +326,7 @@ namespace boost { namespace polygon {
}
// Get the winding direction of the polygon
static inline winding_direction winding(const Slic3r::ExPolygon& t) {
static inline winding_direction winding(const Slic3r::ExPolygon& /* t */) {
return unknown_winding;
}
};
@ -391,8 +391,8 @@ namespace boost { namespace polygon {
}
//don't worry about these, just return false from them
static inline bool clean(const Slic3r::ExPolygons& polygon_set) { return false; }
static inline bool sorted(const Slic3r::ExPolygons& polygon_set) { return false; }
static inline bool clean(const Slic3r::ExPolygons& /* polygon_set */) { return false; }
static inline bool sorted(const Slic3r::ExPolygons& /* polygon_set */) { return false; }
};
template <>

View file

@ -4,12 +4,12 @@ namespace Slic3r {
Extruder::Extruder(unsigned int id, GCodeConfig *config)
: id(id),
config(config)
m_config(config)
{
reset();
// cache values that are going to be called often
if (config->use_volumetric_e) {
if (m_config->use_volumetric_e) {
this->e_per_mm3 = this->extrusion_multiplier();
} else {
this->e_per_mm3 = this->extrusion_multiplier()
@ -31,7 +31,7 @@ double
Extruder::extrude(double dE)
{
// in case of relative E distances we always reset to 0 before any output
if (this->config->use_relative_e_distances)
if (m_config->use_relative_e_distances)
this->E = 0;
this->E += dE;
@ -50,7 +50,7 @@ double
Extruder::retract(double length, double restart_extra)
{
// in case of relative E distances we always reset to 0 before any output
if (this->config->use_relative_e_distances)
if (m_config->use_relative_e_distances)
this->E = 0;
double to_retract = length - this->retracted;
@ -84,7 +84,7 @@ Extruder::e_per_mm(double mm3_per_mm) const
double
Extruder::extruded_volume() const
{
if (this->config->use_volumetric_e) {
if (m_config->use_volumetric_e) {
// Any current amount of retraction should not affect used filament, since
// it represents empty volume in the nozzle. We add it back to E.
return this->absolute_E + this->retracted;
@ -96,7 +96,7 @@ Extruder::extruded_volume() const
double
Extruder::used_filament() const
{
if (this->config->use_volumetric_e) {
if (m_config->use_volumetric_e) {
return this->extruded_volume() / (this->filament_diameter() * this->filament_diameter() * PI/4);
}
@ -108,61 +108,61 @@ Extruder::used_filament() const
double
Extruder::filament_diameter() const
{
return this->config->filament_diameter.get_at(this->id);
return m_config->filament_diameter.get_at(this->id);
}
double
Extruder::filament_density() const
{
return this->config->filament_density.get_at(this->id);
return m_config->filament_density.get_at(this->id);
}
double
Extruder::filament_cost() const
{
return this->config->filament_cost.get_at(this->id);
return m_config->filament_cost.get_at(this->id);
}
double
Extruder::extrusion_multiplier() const
{
return this->config->extrusion_multiplier.get_at(this->id);
return m_config->extrusion_multiplier.get_at(this->id);
}
double
Extruder::retract_length() const
{
return this->config->retract_length.get_at(this->id);
return m_config->retract_length.get_at(this->id);
}
double
Extruder::retract_lift() const
{
return this->config->retract_lift.get_at(this->id);
return m_config->retract_lift.get_at(this->id);
}
int
Extruder::retract_speed() const
{
return this->config->retract_speed.get_at(this->id);
return m_config->retract_speed.get_at(this->id);
}
double
Extruder::retract_restart_extra() const
{
return this->config->retract_restart_extra.get_at(this->id);
return m_config->retract_restart_extra.get_at(this->id);
}
double
Extruder::retract_length_toolchange() const
{
return this->config->retract_length_toolchange.get_at(this->id);
return m_config->retract_length_toolchange.get_at(this->id);
}
double
Extruder::retract_restart_extra_toolchange() const
{
return this->config->retract_restart_extra_toolchange.get_at(this->id);
return m_config->retract_restart_extra_toolchange.get_at(this->id);
}
}

View file

@ -9,7 +9,7 @@ namespace Slic3r {
class Extruder
{
public:
public:
unsigned int id;
double E;
double absolute_E;
@ -17,10 +17,11 @@ class Extruder
double restart_extra;
double e_per_mm3;
double retract_speed_mm_min;
Extruder(unsigned int id, GCodeConfig *config);
virtual ~Extruder() {}
void reset();
void reset();
double extrude(double dE);
double retract(double length, double restart_extra);
double unretract();
@ -34,15 +35,26 @@ class Extruder
double extrusion_multiplier() const;
double retract_length() const;
double retract_lift() const;
int retract_speed() const;
int retract_speed() const;
double retract_restart_extra() const;
double retract_length_toolchange() const;
double retract_restart_extra_toolchange() const;
private:
GCodeConfig *config;
static Extruder key(unsigned int id) { return Extruder(id); }
private:
// Private constructor to create a key for a search in std::set.
Extruder(unsigned int id) : id(id) {}
GCodeConfig *m_config;
};
// Sort Extruder objects by the extruder id by default.
inline bool operator==(const Extruder &e1, const Extruder &e2) { return e1.id == e2.id; }
inline bool operator!=(const Extruder &e1, const Extruder &e2) { return e1.id != e2.id; }
inline bool operator< (const Extruder &e1, const Extruder &e2) { return e1.id < e2.id; }
inline bool operator> (const Extruder &e1, const Extruder &e2) { return e1.id > e2.id; }
}
#endif

View file

@ -59,7 +59,7 @@ void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scale
{
// Instantiating the Flow class to get the line spacing.
// Don't know the nozzle diameter, setting to zero. It shall not matter it shall be optimized out by the compiler.
Flow flow(this->width, this->height, 0.f, this->is_bridge());
Flow flow(this->width, this->height, 0.f, is_bridge(this->role()));
polygons_append(out, offset(this->polyline, 0.5f * float(flow.scaled_spacing()) + scaled_epsilon));
}
@ -226,7 +226,7 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang)
min = dist;
path_idx = path - this->paths.begin();
}
if (prefer_non_overhang && ! path->is_bridge() && dist < min_non_overhang) {
if (prefer_non_overhang && ! is_bridge(path->role()) && dist < min_non_overhang) {
p_non_overhang = p_tmp;
min_non_overhang = dist;
path_idx_non_overhang = path - this->paths.begin();
@ -291,7 +291,7 @@ ExtrusionLoop::has_overhang_point(const Point &point) const
if (pos != -1) {
// point belongs to this path
// we consider it overhang only if it's not an endpoint
return (path->is_bridge() && pos > 0 && pos != (int)(path->polyline.points.size())-1);
return (is_bridge(path->role()) && pos > 0 && pos != (int)(path->polyline.points.size())-1);
}
}
return false;

View file

@ -29,6 +29,33 @@ enum ExtrusionRole {
erMixed,
};
inline bool is_perimeter(ExtrusionRole role)
{
return role == erPerimeter
|| role == erExternalPerimeter
|| role == erOverhangPerimeter;
}
inline bool is_infill(ExtrusionRole role)
{
return role == erBridgeInfill
|| role == erInternalInfill
|| role == erSolidInfill
|| role == erTopSolidInfill;
}
inline bool is_solid_infill(ExtrusionRole role)
{
return role == erBridgeInfill
|| role == erSolidInfill
|| role == erTopSolidInfill;
}
inline bool is_bridge(ExtrusionRole role) {
return role == erBridgeInfill
|| role == erOverhangPerimeter;
}
/* Special flags describing loop */
enum ExtrusionLoopRole {
elrDefault,
@ -101,26 +128,6 @@ public:
void simplify(double tolerance);
virtual double length() const;
virtual ExtrusionRole role() const { return m_role; }
bool is_perimeter() const {
return this->m_role == erPerimeter
|| this->m_role == erExternalPerimeter
|| this->m_role == erOverhangPerimeter;
}
bool is_infill() const {
return this->m_role == erBridgeInfill
|| this->m_role == erInternalInfill
|| this->m_role == erSolidInfill
|| this->m_role == erTopSolidInfill;
}
bool is_solid_infill() const {
return this->m_role == erBridgeInfill
|| this->m_role == erSolidInfill
|| this->m_role == erTopSolidInfill;
}
bool is_bridge() const {
return this->m_role == erBridgeInfill
|| this->m_role == erOverhangPerimeter;
}
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const;
@ -167,22 +174,6 @@ public:
Point last_point() const { return this->paths.back().polyline.points.back(); }
virtual double length() const;
virtual ExtrusionRole role() const { return this->paths.empty() ? erNone : this->paths.front().role(); }
bool is_perimeter() const {
return this->paths.front().role() == erPerimeter
|| this->paths.front().role() == erExternalPerimeter
|| this->paths.front().role() == erOverhangPerimeter;
}
bool is_infill() const {
return this->paths.front().role() == erBridgeInfill
|| this->paths.front().role() == erInternalInfill
|| this->paths.front().role() == erSolidInfill
|| this->paths.front().role() == erTopSolidInfill;
}
bool is_solid_infill() const {
return this->paths.front().role() == erBridgeInfill
|| this->paths.front().role() == erSolidInfill
|| this->paths.front().role() == erTopSolidInfill;
}
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const;
@ -230,22 +221,6 @@ public:
bool has_overhang_point(const Point &point) const;
virtual ExtrusionRole role() const { return this->paths.empty() ? erNone : this->paths.front().role(); }
ExtrusionLoopRole loop_role() const { return m_loop_role; }
bool is_perimeter() const {
return this->paths.front().role() == erPerimeter
|| this->paths.front().role() == erExternalPerimeter
|| this->paths.front().role() == erOverhangPerimeter;
}
bool is_infill() const {
return this->paths.front().role() == erBridgeInfill
|| this->paths.front().role() == erInternalInfill
|| this->paths.front().role() == erSolidInfill
|| this->paths.front().role() == erTopSolidInfill;
}
bool is_solid_infill() const {
return this->paths.front().role() == erBridgeInfill
|| this->paths.front().role() == erSolidInfill
|| this->paths.front().role() == erTopSolidInfill;
}
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const;

View file

@ -95,8 +95,14 @@ ExtrusionEntityCollection::chained_path(ExtrusionEntityCollection* retval, bool
this->chained_path_from(this->entities.front()->first_point(), retval, no_reverse, role, orig_indices);
}
void
ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEntityCollection* retval, bool no_reverse, ExtrusionRole role, std::vector<size_t>* orig_indices) const
ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(Point start_near, bool no_reverse, ExtrusionRole role) const
{
ExtrusionEntityCollection coll;
this->chained_path_from(start_near, &coll, no_reverse, role);
return coll;
}
void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEntityCollection* retval, bool no_reverse, ExtrusionRole role, std::vector<size_t>* orig_indices) const
{
if (this->no_sort) {
*retval = *this;

View file

@ -59,6 +59,7 @@ public:
void remove(size_t i);
ExtrusionEntityCollection chained_path(bool no_reverse = false, ExtrusionRole role = erMixed) const;
void chained_path(ExtrusionEntityCollection* retval, bool no_reverse = false, ExtrusionRole role = erMixed, std::vector<size_t>* orig_indices = nullptr) const;
ExtrusionEntityCollection chained_path_from(Point start_near, bool no_reverse = false, ExtrusionRole role = erMixed) const;
void chained_path_from(Point start_near, ExtrusionEntityCollection* retval, bool no_reverse = false, ExtrusionRole role = erMixed, std::vector<size_t>* orig_indices = nullptr) const;
void reverse();
Point first_point() const { return this->entities.front()->first_point(); }
@ -78,6 +79,8 @@ public:
void flatten(ExtrusionEntityCollection* retval) const;
ExtrusionEntityCollection flatten() const;
double min_mm3_per_mm() const;
// Following methods shall never be called on an ExtrusionEntityCollection.
Polyline as_polyline() const {
CONFESS("Calling as_polyline() on a ExtrusionEntityCollection");
return Polyline();

View file

@ -1,4 +1,5 @@
#include "Flow.hpp"
#include "Print.hpp"
#include <cmath>
#include <assert.h>
@ -113,4 +114,39 @@ float Flow::_width_from_spacing(float spacing, float nozzle_diameter, float heig
#endif
}
Flow support_material_flow(const PrintObject *object, float layer_height)
{
return Flow::new_from_config_width(
frSupportMaterial,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(object->config.support_material_extrusion_width.value > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
// if object->config.support_material_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
float(object->print()->config.nozzle_diameter.get_at(object->config.support_material_extruder-1)),
(layer_height > 0.f) ? layer_height : float(object->config.layer_height.value),
false);
}
Flow support_material_1st_layer_flow(const PrintObject *object, float layer_height)
{
return Flow::new_from_config_width(
frSupportMaterial,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(object->print()->config.first_layer_extrusion_width.value > 0) ? object->print()->config.first_layer_extrusion_width : object->config.support_material_extrusion_width,
float(object->print()->config.nozzle_diameter.get_at(object->config.support_material_extruder-1)),
(layer_height > 0.f) ? layer_height : object->config.first_layer_height.get_abs_value(object->config.layer_height.value),
false);
}
Flow support_material_interface_flow(const PrintObject *object, float layer_height)
{
return Flow::new_from_config_width(
frSupportMaterialInterface,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(object->config.support_material_extrusion_width > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
// if object->config.support_material_interface_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
float(object->print()->config.nozzle_diameter.get_at(object->config.support_material_interface_extruder-1)),
(layer_height > 0.f) ? layer_height : float(object->config.layer_height.value),
false);
}
}

View file

@ -7,6 +7,8 @@
namespace Slic3r {
class PrintObject;
// Extra spacing of bridge threads, in mm.
#define BRIDGE_EXTRA_SPACING 0.05
@ -59,6 +61,10 @@ public:
static float _spacing(float width, float nozzle_diameter, float height, float bridge_flow_ratio);
};
extern Flow support_material_flow(const PrintObject *object, float layer_height = 0.f);
extern Flow support_material_1st_layer_flow(const PrintObject *object, float layer_height = 0.f);
extern Flow support_material_interface_flow(const PrintObject *object, float layer_height = 0.f);
}
#endif

View file

@ -147,6 +147,9 @@ struct AMFParserContext
Instance *m_instance;
// Generic string buffer for vertices, face indices, metadata etc.
std::string m_value[3];
private:
AMFParserContext& operator=(AMFParserContext&);
};
void AMFParserContext::startElement(const char *name, const char **atts)
@ -307,7 +310,7 @@ void AMFParserContext::characters(const XML_Char *s, int len)
}
}
void AMFParserContext::endElement(const char *name)
void AMFParserContext::endElement(const char * /* name */)
{
switch (m_path.back()) {

File diff suppressed because it is too large Load diff

View file

@ -10,16 +10,20 @@
#include "PlaceholderParser.hpp"
#include "Print.hpp"
#include "PrintConfig.hpp"
#include "GCode/CoolingBuffer.hpp"
#include "GCode/PressureEqualizer.hpp"
#include "GCode/SpiralVase.hpp"
#include "EdgeGrid.hpp"
#include <string>
namespace Slic3r {
// Forward declarations.
class GCode;
namespace EdgeGrid { class Grid; }
class AvoidCrossingPerimeters {
public:
public:
// this flag triggers the use of the external configuration space
bool use_external_mp;
@ -35,7 +39,7 @@ class AvoidCrossingPerimeters {
void init_layer_mp(const ExPolygons &islands);
Polyline travel_to(GCode &gcodegen, Point point);
private:
private:
MotionPlanner* _external_mp;
MotionPlanner* _layer_mp;
};
@ -65,76 +69,141 @@ public:
};
class GCode {
public:
public:
GCode() :
m_enable_loop_clipping(true),
m_enable_cooling_markers(false),
m_enable_extrusion_role_markers(false),
m_enable_analyzer_markers(false),
m_layer_count(0),
m_layer_index(-1),
m_layer(nullptr),
m_first_layer(false),
m_elapsed_time(0.0),
m_volumetric_speed(0),
m_last_pos_defined(false),
m_last_extrusion_role(erNone),
m_brim_done(false),
m_second_layer_things_done(false),
m_last_obj_copy(Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max()))
{}
~GCode() {}
bool do_export(FILE *file, Print &print);
// Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests.
const Pointf& origin() const { return m_origin; }
void set_origin(const Pointf &pointf);
void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Pointf(x, y)); }
const Point& last_pos() const { return m_last_pos; }
Pointf point_to_gcode(const Point &point) const;
const FullPrintConfig &config() const { return m_config; }
const Layer* layer() const { return m_layer; }
GCodeWriter& writer() { return m_writer; }
bool enable_cooling_markers() const { return m_enable_cooling_markers; }
float get_reset_elapsed_time() { float t = m_elapsed_time; m_elapsed_time = 0.f; return t; }
// For Perl bindings, to be used exclusively by unit tests.
unsigned int layer_count() const { return m_layer_count; }
void set_layer_count(unsigned int value) { m_layer_count = value; }
float elapsed_time() const { return m_elapsed_time; }
void set_elapsed_time(float value) { m_elapsed_time = value; }
void apply_print_config(const PrintConfig &print_config);
private:
void process_layer(FILE *file, const Print &print, const Layer &layer, const Points &object_copies);
void set_last_pos(const Point &pos) { m_last_pos = pos; m_last_pos_defined = true; }
bool last_pos_defined() const { return m_last_pos_defined; }
void set_extruders(const std::vector<unsigned int> &extruder_ids);
std::string preamble();
std::string change_layer(const Layer &layer);
std::string extrude(const ExtrusionEntity &entity, std::string description = "", double speed = -1);
std::string extrude(ExtrusionLoop loop, std::string description = "", double speed = -1);
std::string extrude(ExtrusionMultiPath multipath, std::string description = "", double speed = -1);
std::string extrude(ExtrusionPath path, std::string description = "", double speed = -1);
struct ByExtruder
{
struct ToExtrude {
ExtrusionEntityCollection perimeters;
ExtrusionEntityCollection infills;
};
std::vector<ToExtrude> by_region;
};
std::string extrude_perimeters(const Print &print, const std::vector<ByExtruder::ToExtrude> &by_region);
std::string extrude_infill(const Print &print, const std::vector<ByExtruder::ToExtrude> &by_region);
std::string extrude_support(const ExtrusionEntityCollection &support_fills, unsigned int extruder_id);
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);
std::string unretract();
std::string set_extruder(unsigned int extruder_id);
/* Origin of print coordinates expressed in unscaled G-code coordinates.
This affects the input arguments supplied to the extrude*() and travel_to()
methods. */
Pointf origin;
FullPrintConfig config;
GCodeWriter writer;
PlaceholderParser* placeholder_parser;
OozePrevention ooze_prevention;
Wipe wipe;
AvoidCrossingPerimeters avoid_crossing_perimeters;
bool enable_loop_clipping;
Pointf m_origin;
FullPrintConfig m_config;
GCodeWriter m_writer;
PlaceholderParser m_placeholder_parser;
OozePrevention m_ooze_prevention;
Wipe m_wipe;
AvoidCrossingPerimeters m_avoid_crossing_perimeters;
bool m_enable_loop_clipping;
// If enabled, the G-code generator will put following comments at the ends
// of the G-code lines: _EXTRUDE_SET_SPEED, _WIPE, _BRIDGE_FAN_START, _BRIDGE_FAN_END
// Those comments are received and consumed (removed from the G-code) by the CoolingBuffer.pm Perl module.
bool enable_cooling_markers;
bool m_enable_cooling_markers;
// Markers for the Pressure Equalizer to recognize the extrusion type.
// The Pressure Equalizer removes the markers from the final G-code.
bool enable_extrusion_role_markers;
bool m_enable_extrusion_role_markers;
// Extended markers for the G-code Analyzer.
// The G-code Analyzer will remove these comments from the final G-code.
bool enable_analyzer_markers;
bool m_enable_analyzer_markers;
// How many times will change_layer() be called?
// change_layer() will update the progress bar.
size_t layer_count;
unsigned int m_layer_count;
// Progress bar indicator. Increments from -1 up to layer_count.
int layer_index;
int m_layer_index;
// Current layer processed. Insequential printing mode, only a single copy will be printed.
// In non-sequential mode, all its copies will be printed.
const Layer* layer;
std::map<const PrintObject*,Point> _seam_position;
const Layer* m_layer;
std::map<const PrintObject*,Point> m_seam_position;
// Distance Field structure to
EdgeGrid::Grid *_lower_layer_edge_grid;
bool first_layer; // this flag triggers first layer speeds
// Used by the CoolingBuffer.pm Perl module to calculate time spent per layer change.
std::unique_ptr<EdgeGrid::Grid> m_lower_layer_edge_grid;
// this flag triggers first layer speeds
bool m_first_layer;
// Used by the CoolingBuffer G-code filter to calculate time spent per layer change.
// This value is not quite precise. First it only accouts for extrusion moves and travel moves,
// it does not account for wipe, retract / unretract moves.
// second it does not account for the velocity profiles of the printer.
float elapsed_time; // seconds
double volumetric_speed;
float m_elapsed_time; // seconds
double m_volumetric_speed;
// Support for the extrusion role markers. Which marker is active?
ExtrusionRole _last_extrusion_role;
GCode();
~GCode();
const Point& last_pos() const;
void set_last_pos(const Point &pos);
bool last_pos_defined() const;
void apply_print_config(const PrintConfig &print_config);
void set_extruders(const std::vector<unsigned int> &extruder_ids);
void set_origin(const Pointf &pointf);
std::string preamble();
std::string change_layer(const Layer &layer);
std::string extrude(const ExtrusionEntity &entity, std::string description = "", double speed = -1);
std::string extrude(ExtrusionLoop loop, std::string description = "", double speed = -1);
std::string extrude(ExtrusionMultiPath multipath, std::string description = "", double speed = -1);
std::string extrude(ExtrusionPath path, std::string description = "", double speed = -1);
std::string extrude_support(const ExtrusionEntityCollection *support_fills, unsigned int extruder_id);
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);
std::string unretract();
std::string set_extruder(unsigned int extruder_id);
Pointf point_to_gcode(const Point &point);
private:
Point _last_pos;
bool _last_pos_defined;
ExtrusionRole m_last_extrusion_role;
Point m_last_pos;
bool m_last_pos_defined;
std::unique_ptr<CoolingBuffer> m_cooling_buffer;
std::unique_ptr<SpiralVase> m_spiral_vase;
std::unique_ptr<PressureEqualizer> m_pressure_equalizer;
// Heights at which the skirt has already been extruded.
std::set<coordf_t> m_skirt_done;
// Has the brim been extruded already? Brim is being extruded only for the first object of a multi-object print.
bool m_brim_done;
// Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed.
bool m_second_layer_things_done;
// Index of a last object copy extruded. -1 for not set yet.
Point m_last_obj_copy;
std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1);
void _print_first_layer_extruder_temperatures(FILE *file, Print &print, bool wait);
std::string filter(std::string &&gcode, bool flush);
};
}

View file

@ -90,7 +90,7 @@ static inline int parse_int(const char *&line)
char *endptr = NULL;
long result = strtol(line, &endptr, 10);
if (endptr == NULL || !is_ws_or_eol(*endptr))
throw std::runtime_error("GCodePressureEqualizer: Error parsing an int");
throw std::runtime_error("GCodeAnalyzer: Error parsing an int");
line = endptr;
return int(result);
};
@ -102,7 +102,7 @@ static inline float parse_float(const char *&line)
char *endptr = NULL;
float result = strtof(line, &endptr);
if (endptr == NULL || !is_ws_or_eol(*endptr))
throw std::runtime_error("GCodePressureEqualizer: Error parsing a float");
throw std::runtime_error("GCodeAnalyzer: Error parsing a float");
line = endptr;
return result;
};
@ -171,7 +171,7 @@ bool GCodeAnalyzer::process_line(const char *line, const size_t len)
assert(false);
}
if (i == -1)
throw std::runtime_error(std::string("GCodePressureEqualizer: Invalid axis for G0/G1: ") + axis);
throw std::runtime_error(std::string("GCodeAnalyzer: Invalid axis for G0/G1: ") + axis);
buf.pos_provided[i] = true;
new_pos[i] = parse_float(line);
if (i == 3 && m_config->use_relative_e_distances.value)
@ -235,7 +235,7 @@ bool GCodeAnalyzer::process_line(const char *line, const size_t len)
set = true;
break;
default:
throw std::runtime_error(std::string("GCodePressureEqualizer: Incorrect axis in a G92 G-code: ") + axis);
throw std::runtime_error(std::string("GCodeAnalyzer: Incorrect axis in a G92 G-code: ") + axis);
}
eatws(line);
}

View file

@ -1,3 +1,4 @@
#include "../GCode.hpp"
#include "CoolingBuffer.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
@ -5,28 +6,26 @@
namespace Slic3r {
std::string
CoolingBuffer::append(const std::string &gcode, std::string obj_id, size_t layer_id, float print_z)
std::string CoolingBuffer::append(const std::string &gcode, size_t object_id, size_t layer_id, bool is_support)
{
std::string out;
if (this->_last_z.find(obj_id) != this->_last_z.end()) {
// A layer was finished, Z of the object's layer changed. Process the layer.
size_t signature = object_id * 2 + is_support ? 1 : 0;
if (m_object_ids_visited.find(signature) != m_object_ids_visited.end())
// For a single print_z, a combination of (object_id, is_support) could repeat once only.
// If the combination of (object_id, is_support) reappears, this must be for another print_z,
// therefore a layer has to be finalized.
out = this->flush();
}
this->_layer_id = layer_id;
this->_last_z[obj_id] = print_z;
this->_gcode += gcode;
m_object_ids_visited.insert(signature);
m_layer_id = layer_id;
m_gcode += gcode;
// This is a very rough estimate of the print time,
// not taking into account the acceleration curves generated by the printer firmware.
this->_elapsed_time += this->_gcodegen->elapsed_time;
this->_gcodegen->elapsed_time = 0;
m_elapsed_time += m_gcodegen.get_reset_elapsed_time();
return out;
}
void
apply_speed_factor(std::string &line, float speed_factor, float min_print_speed)
void apply_speed_factor(std::string &line, float speed_factor, float min_print_speed)
{
// find pos of F
size_t pos = line.find_first_of('F');
@ -51,36 +50,34 @@ apply_speed_factor(std::string &line, float speed_factor, float min_print_speed)
}
}
std::string
CoolingBuffer::flush()
std::string CoolingBuffer::flush()
{
GCode &gg = *this->_gcodegen;
const FullPrintConfig &config = m_gcodegen.config();
std::string gcode = this->_gcode;
float elapsed = this->_elapsed_time;
this->_gcode = "";
this->_elapsed_time = 0;
this->_last_z.clear(); // reset the whole table otherwise we would compute overlapping times
int fan_speed = gg.config.fan_always_on ? gg.config.min_fan_speed.value : 0;
std::string gcode = m_gcode;
float elapsed = m_elapsed_time;
m_gcode.clear();
m_elapsed_time = 0.;
int fan_speed = config.fan_always_on ? config.min_fan_speed.value : 0;
float speed_factor = 1.0;
if (gg.config.cooling) {
if (config.cooling) {
#ifdef SLIC3R_DEBUG
printf("Layer %zu estimated printing time: %f seconds\n", this->_layer_id, elapsed);
printf("Layer %zu estimated printing time: %f seconds\n", m_layer_id, elapsed);
#endif
if (elapsed < (float)gg.config.slowdown_below_layer_time) {
if (elapsed < (float)config.slowdown_below_layer_time) {
// Layer time very short. Enable the fan to a full throttle and slow down the print
// (stretch the layer print time to slowdown_below_layer_time).
fan_speed = gg.config.max_fan_speed;
speed_factor = elapsed / (float)gg.config.slowdown_below_layer_time;
} else if (elapsed < (float)gg.config.fan_below_layer_time) {
fan_speed = config.max_fan_speed;
speed_factor = elapsed / (float)config.slowdown_below_layer_time;
} else if (elapsed < (float)config.fan_below_layer_time) {
// Layer time quite short. Enable the fan proportionally according to the current layer time.
fan_speed = gg.config.max_fan_speed
- (gg.config.max_fan_speed - gg.config.min_fan_speed)
* (elapsed - (float)gg.config.slowdown_below_layer_time)
/ (gg.config.fan_below_layer_time - gg.config.slowdown_below_layer_time);
fan_speed = config.max_fan_speed
- (config.max_fan_speed - config.min_fan_speed)
* (elapsed - (float)config.slowdown_below_layer_time)
/ (config.fan_below_layer_time - config.slowdown_below_layer_time);
}
#ifdef SLIC3R_DEBUG
@ -94,13 +91,14 @@ CoolingBuffer::flush()
std::string new_gcode;
std::istringstream ss(gcode);
std::string line;
bool bridge_fan_start = false;
bool bridge_fan_start = false;
float min_print_speed = float(config.min_print_speed * 60.);
while (std::getline(ss, line)) {
if (boost::starts_with(line, "G1")
&& boost::contains(line, ";_EXTRUDE_SET_SPEED")
&& !boost::contains(line, ";_WIPE")
&& !bridge_fan_start) {
apply_speed_factor(line, speed_factor, this->_min_print_speed);
apply_speed_factor(line, speed_factor, min_print_speed);
boost::replace_first(line, ";_EXTRUDE_SET_SPEED", "");
}
bridge_fan_start = boost::contains(line, ";_BRIDGE_FAN_START");
@ -109,22 +107,23 @@ CoolingBuffer::flush()
gcode = new_gcode;
}
}
if (this->_layer_id < gg.config.disable_fan_first_layers)
if (m_layer_id < config.disable_fan_first_layers)
fan_speed = 0;
gcode = gg.writer.set_fan(fan_speed) + gcode;
gcode = m_gcodegen.writer().set_fan(fan_speed) + gcode;
// bridge fan speed
if (!gg.config.cooling || gg.config.bridge_fan_speed == 0 || this->_layer_id < gg.config.disable_fan_first_layers) {
if (!config.cooling || config.bridge_fan_speed == 0 || m_layer_id < config.disable_fan_first_layers) {
boost::replace_all(gcode, ";_BRIDGE_FAN_START", "");
boost::replace_all(gcode, ";_BRIDGE_FAN_END", "");
} else {
boost::replace_all(gcode, ";_BRIDGE_FAN_START", gg.writer.set_fan(gg.config.bridge_fan_speed, true));
boost::replace_all(gcode, ";_BRIDGE_FAN_END", gg.writer.set_fan(fan_speed, true));
boost::replace_all(gcode, ";_BRIDGE_FAN_START", m_gcodegen.writer().set_fan(config.bridge_fan_speed, true));
boost::replace_all(gcode, ";_BRIDGE_FAN_END", m_gcodegen.writer().set_fan(fan_speed, true));
}
boost::replace_all(gcode, ";_WIPE", "");
boost::replace_all(gcode, ";_EXTRUDE_SET_SPEED", "");
m_object_ids_visited.clear();
return gcode;
}

View file

@ -2,12 +2,14 @@
#define slic3r_CoolingBuffer_hpp_
#include "libslic3r.h"
#include "GCode.hpp"
#include <map>
#include <string>
namespace Slic3r {
class GCode;
class Layer;
/*
A standalone G-code filter, to control cooling of the print.
The G-code is processed per layer. Once a layer is collected, fan start / stop commands are edited
@ -15,23 +17,20 @@ and the print is modified to stretch over a minimum layer time.
*/
class CoolingBuffer {
public:
CoolingBuffer(GCode &gcodegen)
: _gcodegen(&gcodegen), _elapsed_time(0.), _layer_id(0)
{
this->_min_print_speed = this->_gcodegen->config.min_print_speed * 60;
};
std::string append(const std::string &gcode, std::string obj_id, size_t layer_id, float print_z);
public:
CoolingBuffer(GCode &gcodegen) : m_gcodegen(gcodegen), m_elapsed_time(0.), m_layer_id(0) {}
std::string append(const std::string &gcode, size_t object_id, size_t layer_id, bool is_support);
std::string flush();
GCode* gcodegen() { return this->_gcodegen; };
GCode* gcodegen() { return &m_gcodegen; };
private:
GCode* _gcodegen;
std::string _gcode;
float _elapsed_time;
size_t _layer_id;
std::map<std::string,float> _last_z;
float _min_print_speed;
private:
CoolingBuffer& operator=(const CoolingBuffer&);
GCode& m_gcodegen;
std::string m_gcode;
float m_elapsed_time;
size_t m_layer_id;
std::set<size_t> m_object_ids_visited;
};
}

View file

@ -9,17 +9,17 @@
namespace Slic3r {
GCodePressureEqualizer::GCodePressureEqualizer(const Slic3r::GCodeConfig *config) :
PressureEqualizer::PressureEqualizer(const Slic3r::GCodeConfig *config) :
m_config(config)
{
reset();
}
GCodePressureEqualizer::~GCodePressureEqualizer()
PressureEqualizer::~PressureEqualizer()
{
}
void GCodePressureEqualizer::reset()
void PressureEqualizer::reset()
{
circular_buffer_pos = 0;
circular_buffer_size = 100;
@ -69,7 +69,7 @@ void GCodePressureEqualizer::reset()
line_idx = 0;
}
const char* GCodePressureEqualizer::process(const char *szGCode, bool flush)
const char* PressureEqualizer::process(const char *szGCode, bool flush)
{
// Reset length of the output_buffer.
output_buffer_length = 0;
@ -147,7 +147,7 @@ static inline int parse_int(const char *&line)
char *endptr = NULL;
long result = strtol(line, &endptr, 10);
if (endptr == NULL || !is_ws_or_eol(*endptr))
throw std::runtime_error("GCodePressureEqualizer: Error parsing an int");
throw std::runtime_error("PressureEqualizer: Error parsing an int");
line = endptr;
return int(result);
};
@ -159,13 +159,13 @@ static inline float parse_float(const char *&line)
char *endptr = NULL;
float result = strtof(line, &endptr);
if (endptr == NULL || !is_ws_or_eol(*endptr))
throw std::runtime_error("GCodePressureEqualizer: Error parsing a float");
throw std::runtime_error("PressureEqualizer: Error parsing a float");
line = endptr;
return result;
};
#define EXTRUSION_ROLE_TAG ";_EXTRUSION_ROLE:"
bool GCodePressureEqualizer::process_line(const char *line, const size_t len, GCodeLine &buf)
bool PressureEqualizer::process_line(const char *line, const size_t len, GCodeLine &buf)
{
if (strncmp(line, EXTRUSION_ROLE_TAG, strlen(EXTRUSION_ROLE_TAG)) == 0) {
line += strlen(EXTRUSION_ROLE_TAG);
@ -228,7 +228,7 @@ bool GCodePressureEqualizer::process_line(const char *line, const size_t len, GC
assert(false);
}
if (i == -1)
throw std::runtime_error(std::string("GCodePressureEqualizer: Invalid axis for G0/G1: ") + axis);
throw std::runtime_error(std::string("GCode::PressureEqualizer: Invalid axis for G0/G1: ") + axis);
buf.pos_provided[i] = true;
new_pos[i] = parse_float(line);
if (i == 3 && m_config->use_relative_e_distances.value)
@ -297,7 +297,7 @@ bool GCodePressureEqualizer::process_line(const char *line, const size_t len, GC
set = true;
break;
default:
throw std::runtime_error(std::string("GCodePressureEqualizer: Incorrect axis in a G92 G-code: ") + axis);
throw std::runtime_error(std::string("GCode::PressureEqualizer: Incorrect axis in a G92 G-code: ") + axis);
}
eatws(line);
}
@ -355,7 +355,7 @@ bool GCodePressureEqualizer::process_line(const char *line, const size_t len, GC
return true;
}
void GCodePressureEqualizer::output_gcode_line(GCodeLine &line)
void PressureEqualizer::output_gcode_line(GCodeLine &line)
{
if (! line.modified) {
push_to_output(line.raw.data(), line.raw_length, true);
@ -453,7 +453,7 @@ void GCodePressureEqualizer::output_gcode_line(GCodeLine &line)
}
}
void GCodePressureEqualizer::adjust_volumetric_rate()
void PressureEqualizer::adjust_volumetric_rate()
{
if (circular_buffer_items < 2)
return;
@ -563,7 +563,7 @@ void GCodePressureEqualizer::adjust_volumetric_rate()
}
}
void GCodePressureEqualizer::push_axis_to_output(const char axis, const float value, bool add_eol)
void PressureEqualizer::push_axis_to_output(const char axis, const float value, bool add_eol)
{
char buf[2048];
int len = sprintf(buf,
@ -572,7 +572,7 @@ void GCodePressureEqualizer::push_axis_to_output(const char axis, const float va
push_to_output(buf, len, add_eol);
}
void GCodePressureEqualizer::push_to_output(const char *text, const size_t len, bool add_eol)
void PressureEqualizer::push_to_output(const char *text, const size_t len, bool add_eol)
{
// New length of the output buffer content.
size_t len_new = output_buffer_length + len + 1;
@ -604,7 +604,7 @@ void GCodePressureEqualizer::push_to_output(const char *text, const size_t len,
output_buffer[output_buffer_length] = 0;
}
void GCodePressureEqualizer::push_line_to_output(const GCodeLine &line, const float new_feedrate, const char *comment)
void PressureEqualizer::push_line_to_output(const GCodeLine &line, const float new_feedrate, const char *comment)
{
push_to_output("G1", 2, false);
for (char i = 0; i < 3; ++ i)

View file

@ -9,11 +9,11 @@ namespace Slic3r {
// Processes a G-code. Finds changes in the volumetric extrusion speed and adjusts the transitions
// between these paths to limit fast changes in the volumetric extrusion speed.
class GCodePressureEqualizer
class PressureEqualizer
{
public:
GCodePressureEqualizer(const Slic3r::GCodeConfig *config);
~GCodePressureEqualizer();
PressureEqualizer(const Slic3r::GCodeConfig *config);
~PressureEqualizer();
void reset();

View file

@ -1,4 +1,5 @@
#include "SpiralVase.hpp"
#include "GCode.hpp"
#include <sstream>
namespace Slic3r {

View file

@ -2,7 +2,6 @@
#define slic3r_SpiralVase_hpp_
#include "libslic3r.h"
#include "GCode.hpp"
#include "GCodeReader.hpp"
namespace Slic3r {

View file

@ -23,8 +23,8 @@ GCodeWriter::apply_print_config(const PrintConfig &print_config)
void
GCodeWriter::set_extruders(const std::vector<unsigned int> &extruder_ids)
{
for (std::vector<unsigned int>::const_iterator i = extruder_ids.begin(); i != extruder_ids.end(); ++i)
this->extruders.insert( std::pair<unsigned int,Extruder>(*i, Extruder(*i, &this->config)) );
for (unsigned int extruder_id : extruder_ids)
this->extruders.insert(Extruder(extruder_id, &this->config));
/* we enable support for multiple extruder if any extruder greater than 0 is used
(even if prints only uses that one) since we need to output Tx commands
@ -194,11 +194,12 @@ GCodeWriter::reset_e(bool force)
|| FLAVOR_IS(gcfSailfish))
return "";
if (this->_extruder != NULL) {
if (this->_extruder->E == 0 && !force) return "";
this->_extruder->E = 0;
if (this->_extruder != nullptr) {
if (this->_extruder->E == 0. && ! force)
return "";
this->_extruder->E = 0.;
}
if (!this->_extrusion_axis.empty() && !this->config.use_relative_e_distances) {
std::ostringstream gcode;
gcode << "G92 " << this->_extrusion_axis << "0";
@ -226,25 +227,10 @@ GCodeWriter::update_progress(unsigned int num, unsigned int tot, bool allow_100)
return gcode.str();
}
bool
GCodeWriter::need_toolchange(unsigned int extruder_id) const
{
// return false if this extruder was already selected
return (this->_extruder == NULL) || (this->_extruder->id != extruder_id);
}
std::string
GCodeWriter::set_extruder(unsigned int extruder_id)
{
if (!this->need_toolchange(extruder_id)) return "";
return this->toolchange(extruder_id);
}
std::string
GCodeWriter::toolchange(unsigned int extruder_id)
std::string GCodeWriter::toolchange(unsigned int extruder_id)
{
// set the new extruder
this->_extruder = &this->extruders.find(extruder_id)->second;
this->_extruder = const_cast<Extruder*>(&*this->extruders.find(Extruder::key(extruder_id)));
// return the toolchange command
// if we are running a single-extruder setup, just set the extruder and return nothing

View file

@ -12,17 +12,25 @@ namespace Slic3r {
class GCodeWriter {
public:
GCodeConfig config;
std::map<unsigned int,Extruder> extruders;
std::set<Extruder> extruders;
bool multiple_extruders;
GCodeWriter()
: multiple_extruders(false), _extrusion_axis("E"), _extruder(NULL),
_last_acceleration(0), _last_fan_speed(0), _lifted(0)
{};
Extruder* extruder() const { return this->_extruder; }
GCodeWriter() :
multiple_extruders(false), _extrusion_axis("E"), _extruder(nullptr),
_last_acceleration(0), _last_fan_speed(0), _lifted(0)
{}
Extruder* extruder() { return this->_extruder; }
const Extruder* extruder() const { return this->_extruder; }
std::string extrusion_axis() const { return this->_extrusion_axis; }
void apply_print_config(const PrintConfig &print_config);
void set_extruders(const std::vector<unsigned int> &extruder_ids);
void apply_print_config(const PrintConfig &print_config);
void set_extruders(const std::vector<unsigned int> &extruder_ids);
std::vector<unsigned int> extruder_ids() const {
std::vector<unsigned int> out;
out.reserve(extruders.size());
for (const auto e : extruders)
out.push_back(e.id);
return out;
}
std::string preamble();
std::string postamble() const;
std::string set_temperature(unsigned int temperature, bool wait = false, int tool = -1) const;
@ -31,14 +39,17 @@ public:
std::string set_acceleration(unsigned int acceleration);
std::string reset_e(bool force = false);
std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const;
bool need_toolchange(unsigned int extruder_id) const;
std::string set_extruder(unsigned int extruder_id);
// return false if this extruder was already selected
bool need_toolchange(unsigned int extruder_id) const
{ return (this->_extruder == nullptr) || (this->_extruder->id != extruder_id); }
std::string set_extruder(unsigned int extruder_id)
{ return this->need_toolchange(extruder_id) ? this->toolchange(extruder_id) : ""; }
std::string toolchange(unsigned int extruder_id);
std::string set_speed(double F, const std::string &comment = std::string(), const std::string &cooling_marker = std::string()) const;
std::string travel_to_xy(const Pointf &point, const std::string &comment = std::string());
std::string travel_to_xyz(const Pointf3 &point, const std::string &comment = std::string());
std::string travel_to_z(double z, const std::string &comment = std::string());
bool will_move_z(double z) const;
bool will_move_z(double z) const;
std::string extrude_to_xy(const Pointf &point, double dE, const std::string &comment = std::string());
std::string extrude_to_xyz(const Pointf3 &point, double dE, const std::string &comment = std::string());
std::string retract();
@ -46,14 +57,15 @@ public:
std::string unretract();
std::string lift();
std::string unlift();
Pointf3 get_position() const { return this->_pos; }
Pointf3 get_position() const { return this->_pos; }
private:
std::string _extrusion_axis;
Extruder* _extruder;
unsigned int _last_acceleration;
unsigned int _last_fan_speed;
double _lifted;
Pointf3 _pos;
std::string _extrusion_axis;
Extruder* _extruder;
unsigned int _last_acceleration;
unsigned int _last_fan_speed;
double _lifted;
Pointf3 _pos;
std::string _travel_to_z(double z, const std::string &comment);
std::string _retract(double length, double restart_extra, const std::string &comment);

View file

@ -97,23 +97,34 @@ PlaceholderParser::apply_env_variables()
}
}
void
PlaceholderParser::set(const std::string &key, const std::string &value)
void PlaceholderParser::set(const std::string &key, const std::string &value)
{
this->_single[key] = value;
this->_multiple.erase(key);
}
void
PlaceholderParser::set(const std::string &key, int value)
void PlaceholderParser::set(const std::string &key, int value)
{
std::ostringstream ss;
ss << value;
this->set(key, ss.str());
}
void
PlaceholderParser::set(const std::string &key, std::vector<std::string> values)
void PlaceholderParser::set(const std::string &key, unsigned int value)
{
std::ostringstream ss;
ss << value;
this->set(key, ss.str());
}
void PlaceholderParser::set(const std::string &key, double value)
{
std::ostringstream ss;
ss << value;
this->set(key, ss.str());
}
void PlaceholderParser::set(const std::string &key, std::vector<std::string> values)
{
if (values.empty()) {
this->_multiple.erase(key);
@ -124,8 +135,7 @@ PlaceholderParser::set(const std::string &key, std::vector<std::string> values)
}
}
std::string
PlaceholderParser::process(std::string str) const
std::string PlaceholderParser::process(std::string str) const
{
// replace single options, like [foo]
for (t_strstr_map::const_iterator it = this->_single.begin(); it != this->_single.end(); ++it) {
@ -154,8 +164,7 @@ PlaceholderParser::process(std::string str) const
return str;
}
bool
PlaceholderParser::find_and_replace(std::string &source, std::string const &find, std::string const &replace) const
bool PlaceholderParser::find_and_replace(std::string &source, std::string const &find, std::string const &replace) const
{
bool found = false;
for (std::string::size_type i = 0; (i = source.find(find, i)) != std::string::npos; ) {

View file

@ -15,7 +15,7 @@ typedef std::map<std::string, std::vector<std::string> > t_strstrs_map;
class PlaceholderParser
{
public:
public:
t_strstr_map _single;
t_strstrs_map _multiple;
@ -25,10 +25,12 @@ class PlaceholderParser
void apply_env_variables();
void set(const std::string &key, const std::string &value);
void set(const std::string &key, int value);
void set(const std::string &key, unsigned int value);
void set(const std::string &key, double value);
void set(const std::string &key, std::vector<std::string> values);
std::string process(std::string str) const;
private:
private:
bool find_and_replace(std::string &source, std::string const &find, std::string const &replace) const;
};

View file

@ -32,7 +32,7 @@ class Point
coord_t y;
Point(coord_t _x = 0, coord_t _y = 0): x(_x), y(_y) {};
Point(int _x, int _y): x(_x), y(_y) {};
Point(long long _x, long long _y): x(_x), y(_y) {}; // for Clipper
Point(long long _x, long long _y): x(coord_t(_x)), y(coord_t(_y)) {}; // for Clipper
Point(double x, double y);
static Point new_scale(coordf_t x, coordf_t y) {
return Point(scale_(x), scale_(y));

View file

@ -93,6 +93,23 @@ inline void polygons_rotate(Polygons &polys, double angle)
p->rotate(angle);
}
inline Points to_points(const Polygon &poly)
{
return poly.points;
}
inline Points to_points(const Polygons &polys)
{
size_t n_points = 0;
for (size_t i = 0; i < polys.size(); ++ i)
n_points += polys[i].points.size();
Points points;
points.reserve(n_points);
for (const Polygon &poly : polys)
append(points, poly.points);
return points;
}
inline Lines to_lines(const Polygon &poly)
{
Lines lines;
@ -179,7 +196,7 @@ namespace boost { namespace polygon {
}
// Get the winding direction of the polygon
static inline winding_direction winding(const Slic3r::Polygon& t) {
static inline winding_direction winding(const Slic3r::Polygon& /* t */) {
return unknown_winding;
}
};
@ -220,8 +237,8 @@ namespace boost { namespace polygon {
}
//don't worry about these, just return false from them
static inline bool clean(const Slic3r::Polygons& polygon_set) { return false; }
static inline bool sorted(const Slic3r::Polygons& polygon_set) { return false; }
static inline bool clean(const Slic3r::Polygons& /* polygon_set */) { return false; }
static inline bool sorted(const Slic3r::Polygons& /* polygon_set */) { return false; }
};
template <>

View file

@ -30,7 +30,7 @@ Print::~Print()
void
Print::clear_objects()
{
for (int i = this->objects.size()-1; i >= 0; --i)
for (int i = int(this->objects.size())-1; i >= 0; --i)
this->delete_object(i);
this->clear_regions();
@ -255,70 +255,65 @@ Print::step_done(PrintObjectStep step) const
}
// returns 0-based indices of used extruders
std::set<size_t>
Print::object_extruders() const
std::vector<unsigned int> Print::object_extruders() const
{
std::set<size_t> extruders;
std::vector<unsigned int> extruders;
FOREACH_REGION(this, region) {
// these checks reflect the same logic used in the GUI for enabling/disabling
// extruder selection fields
if ((*region)->config.perimeters.value > 0 || this->config.brim_width.value > 0)
extruders.insert((*region)->config.perimeter_extruder - 1);
extruders.push_back((*region)->config.perimeter_extruder - 1);
if ((*region)->config.fill_density.value > 0)
extruders.insert((*region)->config.infill_extruder - 1);
extruders.push_back((*region)->config.infill_extruder - 1);
if ((*region)->config.top_solid_layers.value > 0 || (*region)->config.bottom_solid_layers.value > 0)
extruders.insert((*region)->config.solid_infill_extruder - 1);
extruders.push_back((*region)->config.solid_infill_extruder - 1);
}
std::sort(extruders.begin(), extruders.end());
extruders.erase(std::unique(extruders.begin(), extruders.end()), extruders.end());
return extruders;
}
// returns 0-based indices of used extruders
std::set<size_t>
Print::support_material_extruders() const
std::vector<unsigned int> Print::support_material_extruders() const
{
std::set<size_t> extruders;
std::vector<unsigned int> extruders;
bool support_uses_current_extruder = false;
FOREACH_OBJECT(this, object) {
if ((*object)->has_support_material()) {
if ((*object)->config.support_material_extruder == 0)
for (PrintObject *object : this->objects) {
if (object->has_support_material()) {
if (object->config.support_material_extruder == 0)
support_uses_current_extruder = true;
else
extruders.insert((*object)->config.support_material_extruder - 1);
if ((*object)->config.support_material_interface_extruder == 0)
extruders.push_back(object->config.support_material_extruder - 1);
if (object->config.support_material_interface_extruder == 0)
support_uses_current_extruder = true;
else
extruders.insert((*object)->config.support_material_interface_extruder - 1);
extruders.push_back(object->config.support_material_interface_extruder - 1);
}
}
if (support_uses_current_extruder) {
if (support_uses_current_extruder)
// Add all object extruders to the support extruders as it is not know which one will be used to print supports.
std::set<size_t> object_extruders = this->object_extruders();
extruders.insert(object_extruders.begin(), object_extruders.end());
}
append(extruders, this->object_extruders());
std::sort(extruders.begin(), extruders.end());
extruders.erase(std::unique(extruders.begin(), extruders.end()), extruders.end());
return extruders;
}
// returns 0-based indices of used extruders
std::set<size_t>
Print::extruders() const
std::vector<unsigned int> Print::extruders() const
{
std::set<size_t> extruders = this->object_extruders();
std::set<size_t> s_extruders = this->support_material_extruders();
extruders.insert(s_extruders.begin(), s_extruders.end());
std::vector<unsigned int> extruders = this->object_extruders();
append(extruders, this->support_material_extruders());
std::sort(extruders.begin(), extruders.end());
extruders.erase(std::unique(extruders.begin(), extruders.end()), extruders.end());
return extruders;
}
void
Print::_simplify_slices(double distance)
void Print::_simplify_slices(double distance)
{
FOREACH_OBJECT(this, object) {
FOREACH_LAYER(*object, layer) {
@ -330,23 +325,17 @@ Print::_simplify_slices(double distance)
}
}
double
Print::max_allowed_layer_height() const
double Print::max_allowed_layer_height() const
{
std::vector<double> nozzle_diameter;
std::set<size_t> extruders = this->extruders();
for (std::set<size_t>::const_iterator e = extruders.begin(); e != extruders.end(); ++e) {
nozzle_diameter.push_back(this->config.nozzle_diameter.get_at(*e));
}
return *std::max_element(nozzle_diameter.begin(), nozzle_diameter.end());
double nozzle_diameter_max = 0.;
for (unsigned int extruder_id : this->extruders())
nozzle_diameter_max = std::max(nozzle_diameter_max, this->config.nozzle_diameter.get_at(extruder_id));
return nozzle_diameter_max;
}
/* Caller is responsible for supplying models whose objects don't collide
and have explicit instance positions */
void
Print::add_model_object(ModelObject* model_object, int idx)
void Print::add_model_object(ModelObject* model_object, int idx)
{
DynamicPrintConfig object_config = model_object->config; // clone
object_config.normalize();
@ -617,9 +606,9 @@ Print::validate() const
convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front();
// now we check that no instance of convex_hull intersects any of the previously checked object instances
for (Points::const_iterator copy = object->_shifted_copies.begin(); copy != object->_shifted_copies.end(); ++copy) {
for (const Point &copy : object->_shifted_copies) {
Polygon p = convex_hull;
p.translate(*copy);
p.translate(copy);
if (! intersection(a, p).empty())
return "Some objects are too close; your extruder will collide with them.";
polygons_append(a, p);
@ -654,13 +643,13 @@ Print::validate() const
{
// find the smallest nozzle diameter
std::set<size_t> extruders = this->extruders();
std::vector<unsigned int> extruders = this->extruders();
if (extruders.empty())
return "The supplied settings will cause an empty print.";
std::set<double> nozzle_diameters;
for (std::set<size_t>::iterator it = extruders.begin(); it != extruders.end(); ++it)
nozzle_diameters.insert(this->config.nozzle_diameter.get_at(*it));
std::vector<double> nozzle_diameters;
for (unsigned int extruder_id : extruders)
nozzle_diameters.push_back(this->config.nozzle_diameter.get_at(extruder_id));
double min_nozzle_diameter = *std::min_element(nozzle_diameters.begin(), nozzle_diameters.end());
FOREACH_OBJECT(this, i_object) {

View file

@ -117,7 +117,7 @@ public:
ModelObject* model_object() { return this->_model_object; }
const ModelObject* model_object() const { return this->_model_object; }
Points copies() const { return this->_copies; }
const Points& copies() const { return this->_copies; }
bool add_copy(const Pointf &point);
bool delete_last_copy();
bool delete_all_copies();
@ -249,9 +249,9 @@ public:
Flow brim_flow() const;
Flow skirt_flow() const;
std::set<size_t> object_extruders() const;
std::set<size_t> support_material_extruders() const;
std::set<size_t> extruders() const;
std::vector<unsigned int> object_extruders() const;
std::vector<unsigned int> support_material_extruders() const;
std::vector<unsigned int> extruders() const;
void _simplify_slices(double distance);
double max_allowed_layer_height() const;
bool has_support_material() const;

View file

@ -44,7 +44,7 @@ SlicingParameters SlicingParameters::create_from_config(
const PrintConfig &print_config,
const PrintObjectConfig &object_config,
coordf_t object_height,
const std::set<size_t> &object_extruders)
const std::vector<unsigned int> &object_extruders)
{
coordf_t first_layer_height = (object_config.first_layer_height.value <= 0) ?
object_config.layer_height.value :
@ -84,9 +84,9 @@ SlicingParameters SlicingParameters::create_from_config(
params.min_layer_height = std::max(params.min_layer_height, min_layer_height_from_nozzle(print_config, 0));
params.max_layer_height = std::min(params.max_layer_height, max_layer_height_from_nozzle(print_config, 0));
} else {
for (std::set<size_t>::const_iterator it_extruder = object_extruders.begin(); it_extruder != object_extruders.end(); ++ it_extruder) {
params.min_layer_height = std::max(params.min_layer_height, min_layer_height_from_nozzle(print_config, *it_extruder));
params.max_layer_height = std::min(params.max_layer_height, max_layer_height_from_nozzle(print_config, *it_extruder));
for (unsigned int extruder_id : object_extruders) {
params.min_layer_height = std::max(params.min_layer_height, min_layer_height_from_nozzle(print_config, extruder_id));
params.max_layer_height = std::min(params.max_layer_height, max_layer_height_from_nozzle(print_config, extruder_id));
}
}
params.min_layer_height = std::min(params.min_layer_height, params.layer_height);
@ -113,8 +113,8 @@ SlicingParameters SlicingParameters::create_from_config(
//FIXME It is expected, that the 1st layer of the object is printed with a bridging flow over a full raft. Shall it not be vice versa?
coordf_t average_object_extruder_dmr = 0.;
if (! object_extruders.empty()) {
for (std::set<size_t>::const_iterator it_extruder = object_extruders.begin(); it_extruder != object_extruders.end(); ++ it_extruder)
average_object_extruder_dmr += print_config.nozzle_diameter.get_at(*it_extruder);
for (unsigned int extruder_id : object_extruders)
average_object_extruder_dmr += print_config.nozzle_diameter.get_at(extruder_id);
average_object_extruder_dmr /= coordf_t(object_extruders.size());
}
params.first_object_layer_height = average_object_extruder_dmr;

View file

@ -26,7 +26,7 @@ struct SlicingParameters
const PrintConfig &print_config,
const PrintObjectConfig &object_config,
coordf_t object_height,
const std::set<size_t> &object_extruders);
const std::vector<unsigned int> &object_extruders);
// Has any raft layers?
bool has_raft() const { return raft_layers() > 0; }

View file

@ -145,32 +145,10 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
m_print_config (&object->print()->config),
m_object_config (&object->config),
m_slicing_params (slicing_params),
m_first_layer_flow (Flow::new_from_config_width(
frSupportMaterial,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(object->print()->config.first_layer_extrusion_width.value > 0) ? object->print()->config.first_layer_extrusion_width : object->config.support_material_extrusion_width,
float(object->print()->config.nozzle_diameter.get_at(object->config.support_material_extruder-1)),
float(slicing_params.first_print_layer_height),
false)),
m_support_material_flow (Flow::new_from_config_width(
frSupportMaterial,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(object->config.support_material_extrusion_width.value > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
// if object->config.support_material_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
float(object->print()->config.nozzle_diameter.get_at(object->config.support_material_extruder-1)),
float(slicing_params.layer_height),
false)),
m_support_material_interface_flow(Flow::new_from_config_width(
frSupportMaterialInterface,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(object->config.support_material_extrusion_width > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
// if object->config.support_material_interface_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
float(object->print()->config.nozzle_diameter.get_at(object->config.support_material_interface_extruder-1)),
float(slicing_params.layer_height),
false)),
m_support_layer_height_min (0.01)
m_first_layer_flow (support_material_1st_layer_flow(object, float(slicing_params.first_print_layer_height))),
m_support_material_flow (support_material_flow(object, float(slicing_params.layer_height))),
m_support_material_interface_flow(support_material_interface_flow(object, float(slicing_params.layer_height))),
m_support_layer_height_min(0.01)
{
// Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um.
m_support_layer_height_min = 1000000.;

View file

@ -9,7 +9,7 @@ namespace Slic3r {
class SurfaceCollection
{
public:
public:
Surfaces surfaces;
SurfaceCollection() {};

View file

@ -14,15 +14,10 @@ REGISTER_CLASS(ExtrusionEntityCollection, "ExtrusionPath::Collection");
REGISTER_CLASS(ExtrusionSimulator, "ExtrusionSimulator");
REGISTER_CLASS(Filler, "Filler");
REGISTER_CLASS(Flow, "Flow");
REGISTER_CLASS(AvoidCrossingPerimeters, "GCode::AvoidCrossingPerimeters");
REGISTER_CLASS(CoolingBuffer, "GCode::CoolingBuffer");
REGISTER_CLASS(OozePrevention, "GCode::OozePrevention");
REGISTER_CLASS(SpiralVase, "GCode::SpiralVase");
REGISTER_CLASS(Wipe, "GCode::Wipe");
REGISTER_CLASS(GCode, "GCode");
REGISTER_CLASS(GCodeSender, "GCode::Sender");
REGISTER_CLASS(GCodeWriter, "GCode::Writer");
REGISTER_CLASS(GCodePressureEqualizer, "GCode::PressureEqualizer");
REGISTER_CLASS(Layer, "Layer");
REGISTER_CLASS(SupportLayer, "Layer::Support");
REGISTER_CLASS(LayerRegion, "Layer::Region");

View file

@ -1,6 +1,11 @@
#ifndef _xsinit_h_
#define _xsinit_h_
#ifdef _MSC_VER
// Disable some obnoxious warnings given by Visual Studio with the default warning level 4.
#pragma warning(disable: 4100 4127 4189 4244 4267 4700 4702 4800)
#endif
// undef some macros set by Perl which cause compilation errors on Win32
#undef read
#undef seekdir

View file

@ -29,9 +29,6 @@
%code{% RETVAL = THIS->has_overhang_point(*point); %};
ExtrusionRole role() const;
ExtrusionLoopRole loop_role() const;
bool is_perimeter();
bool is_infill();
bool is_solid_infill();
Polygons polygons_covered_by_width();
Polygons polygons_covered_by_spacing();
%{

View file

@ -16,9 +16,6 @@
void append(ExtrusionPath* path)
%code{% THIS->paths.push_back(*path); %};
double length();
bool is_perimeter();
bool is_infill();
bool is_solid_infill();
Polygons polygons_covered_by_width();
Polygons polygons_covered_by_spacing();
Clone<Polyline> polyline()

View file

@ -23,10 +23,8 @@
void simplify(double tolerance);
double length();
ExtrusionRole role() const;
bool is_perimeter();
bool is_infill();
bool is_solid_infill();
bool is_bridge();
bool is_bridge()
%code{% RETVAL = is_bridge(THIS->role()); %};
Polygons polygons_covered_by_width();
Polygons polygons_covered_by_spacing();
%{

View file

@ -4,176 +4,45 @@
#include <xsinit.h>
#include "libslic3r/GCode.hpp"
#include "libslic3r/GCode/CoolingBuffer.hpp"
#include "libslic3r/GCode/SpiralVase.hpp"
%}
%name{Slic3r::GCode::AvoidCrossingPerimeters} class AvoidCrossingPerimeters {
AvoidCrossingPerimeters();
~AvoidCrossingPerimeters();
void init_external_mp(ExPolygons islands);
void init_layer_mp(ExPolygons islands);
Clone<Polyline> travel_to(GCode* gcode, Point* point)
%code{% RETVAL = THIS->travel_to(*gcode, *point); %};
bool use_external_mp()
%code{% RETVAL = THIS->use_external_mp; %};
void set_use_external_mp(bool value)
%code{% THIS->use_external_mp = value; %};
bool use_external_mp_once()
%code{% RETVAL = THIS->use_external_mp_once; %};
void set_use_external_mp_once(bool value)
%code{% THIS->use_external_mp_once = value; %};
bool disable_once()
%code{% RETVAL = THIS->disable_once; %};
void set_disable_once(bool value)
%code{% THIS->disable_once = value; %};
};
%name{Slic3r::GCode::OozePrevention} class OozePrevention {
OozePrevention();
~OozePrevention();
bool enable()
%code{% RETVAL = THIS->enable; %};
void set_enable(bool value)
%code{% THIS->enable = value; %};
Points standby_points()
%code{% RETVAL = THIS->standby_points; %};
void set_standby_points(Points points)
%code{% THIS->standby_points = points; %};
std::string pre_toolchange(GCode* gcodegen)
%code{% RETVAL = THIS->pre_toolchange(*gcodegen); %};
std::string post_toolchange(GCode* gcodegen)
%code{% RETVAL = THIS->post_toolchange(*gcodegen); %};
};
%name{Slic3r::GCode::Wipe} class Wipe {
Wipe();
~Wipe();
bool has_path();
void reset_path();
std::string wipe(GCode* gcodegen, bool toolchange = false)
%code{% RETVAL = THIS->wipe(*gcodegen, toolchange); %};
bool enable()
%code{% RETVAL = THIS->enable; %};
void set_enable(bool value)
%code{% THIS->enable = value; %};
Ref<Polyline> path()
%code{% RETVAL = &(THIS->path); %};
void set_path(Polyline* value)
%code{% THIS->path = *value; %};
};
%name{Slic3r::GCode::CoolingBuffer} class CoolingBuffer {
CoolingBuffer(GCode* gcode)
%code{% RETVAL = new CoolingBuffer(*gcode); %};
~CoolingBuffer();
Ref<GCode> gcodegen();
std::string append(std::string gcode, std::string obj_id, size_t layer_id, float print_z);
std::string append(std::string gcode, size_t object_id, size_t layer_id, bool support_layer);
std::string flush();
};
%name{Slic3r::GCode::SpiralVase} class SpiralVase {
SpiralVase(StaticPrintConfig* config)
%code{% RETVAL = new SpiralVase(*dynamic_cast<PrintConfig*>(config)); %};
~SpiralVase();
bool enable()
%code{% RETVAL = THIS->enable; %};
void set_enable(bool enable)
%code{% THIS->enable = enable; %};
std::string process_layer(std::string gcode);
};
%name{Slic3r::GCode} class GCode {
GCode();
~GCode();
Ref<Pointf> origin()
%code{% RETVAL = &(THIS->origin); %};
Ref<StaticPrintConfig> config()
%code{% RETVAL = &(THIS->config); %};
Ref<GCodeWriter> writer()
%code{% RETVAL = &(THIS->writer); %};
Ref<PlaceholderParser> placeholder_parser()
%code{% RETVAL = THIS->placeholder_parser; %};
void set_placeholder_parser(PlaceholderParser* ptr)
%code{% THIS->placeholder_parser = ptr; %};
Ref<OozePrevention> ooze_prevention()
%code{% RETVAL = &(THIS->ooze_prevention); %};
Ref<Wipe> wipe()
%code{% RETVAL = &(THIS->wipe); %};
Ref<AvoidCrossingPerimeters> avoid_crossing_perimeters()
%code{% RETVAL = &(THIS->avoid_crossing_perimeters); %};
bool enable_loop_clipping()
%code{% RETVAL = THIS->enable_loop_clipping; %};
void set_enable_loop_clipping(bool value)
%code{% THIS->enable_loop_clipping = value; %};
bool enable_cooling_markers()
%code{% RETVAL = THIS->enable_cooling_markers; %};
void set_enable_cooling_markers(bool value)
%code{% THIS->enable_cooling_markers = value; %};
bool enable_extrusion_role_markers()
%code{% RETVAL = THIS->enable_extrusion_role_markers; %};
void set_enable_extrusion_role_markers(bool value)
%code{% THIS->enable_extrusion_role_markers = value; %};
std::string do_export(Print *print, const char *path)
%code{%
FILE *file = fopen(path, "wb");
if (file == nullptr) {
RETVAL = std::string("Failed to open ") + path + " for writing.";
} else {
THIS->do_export(file, *print);
fclose(file);
RETVAL = std::string();
}
%};
int layer_count()
%code{% RETVAL = THIS->layer_count; %};
void set_layer_count(int value)
%code{% THIS->layer_count = value; %};
int layer_index()
%code{% RETVAL = THIS->layer_index; %};
void set_layer_index(int value)
%code{% THIS->layer_index = value; %};
bool has_layer()
%code{% RETVAL = THIS->layer != NULL; %};
Ref<Layer> layer()
%code{% RETVAL = THIS->layer; %};
void set_layer(Layer* ptr)
%code{% THIS->layer = ptr; %};
bool first_layer()
%code{% RETVAL = THIS->first_layer; %};
void set_first_layer(bool value)
%code{% THIS->first_layer = value; %};
float elapsed_time()
%code{% RETVAL = THIS->elapsed_time; %};
void set_elapsed_time(float value)
%code{% THIS->elapsed_time = value; %};
bool last_pos_defined();
Ref<Pointf> origin()
%code{% RETVAL = &(THIS->origin()); %};
void set_origin(Pointf* pointf)
%code{% THIS->set_origin(*pointf); %};
Ref<Point> last_pos()
%code{% RETVAL = &(THIS->last_pos()); %};
void set_last_pos(Point* pos)
%code{% THIS->set_last_pos(*pos); %};
double volumetric_speed()
%code{% RETVAL = THIS->volumetric_speed; %};
void set_volumetric_speed(double value)
%code{% THIS->volumetric_speed = value; %};
unsigned int layer_count() const;
void set_layer_count(unsigned int value);
float elapsed_time() const;
void set_elapsed_time(float value);
void apply_print_config(StaticPrintConfig* print_config)
%code{%
if (const PrintConfig* config = dynamic_cast<PrintConfig*>(print_config)) {
@ -182,40 +51,7 @@
CONFESS("A PrintConfig object was not supplied to apply_print_config()");
}
%};
void set_extruders(std::vector<unsigned int> extruder_ids);
void set_origin(Pointf* pointf)
%code{% THIS->set_origin(*pointf); %};
std::string preamble();
std::string change_layer(Layer* layer)
%code{% RETVAL = THIS->change_layer(*layer); %};
%name{extrude_loop} std::string extrude(ExtrusionLoop* loop, std::string description = "", double speed = -1)
%code{% RETVAL = THIS->extrude(*loop, description, speed); %};
%name{extrude_multipath} std::string extrude(ExtrusionMultiPath* multipath, std::string description = "", double speed = -1)
%code{% RETVAL = THIS->extrude(*multipath, description, speed); %};
%name{extrude_path} std::string extrude(ExtrusionPath* path, std::string description = "", double speed = -1)
%code{% RETVAL = THIS->extrude(*path, description, speed); %};
std::string extrude_support(ExtrusionEntityCollection *support_fills, unsigned int extruder_id);
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)
%code{% RETVAL = THIS->needs_retraction(*travel, role); %};
std::string retract(bool toolchange = false);
std::string unretract();
std::string set_extruder(unsigned int extruder_id);
Clone<Pointf> point_to_gcode(Point* point)
%code{% RETVAL = THIS->point_to_gcode(*point); %};
%{
std::string
GCode::extrude(entity, description, speed)
SV* entity
std::string description;
double speed;
CODE:
ExtrusionEntity* e = (ExtrusionEntity *)SvIV((SV*)SvRV( entity ));
RETVAL = THIS->extrude(*e, description, speed);
OUTPUT:
RETVAL
%}
Ref<StaticPrintConfig> config()
%code{% RETVAL = const_cast<StaticPrintConfig*>(dynamic_cast<const StaticPrintConfig*>(&THIS->config())); %};
};

View file

@ -1,32 +0,0 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/GCode/PressureEqualizer.hpp"
%}
%name{Slic3r::GCode::PressureEqualizer} class GCodePressureEqualizer {
GCodePressureEqualizer(StaticPrintConfig* config)
%code%{ RETVAL = new GCodePressureEqualizer(dynamic_cast<GCodeConfig*>(config)); %};
~GCodePressureEqualizer();
void reset();
// Process a next batch of G-code lines. Flush the internal buffers if asked for.
// const char* process(const char *szGCode, bool flush);
// std::string process(const char *szGCode, bool flush)
// %code{% const char *out = THIS->process(szGCode, flush); RETVAL = (out == NULL) ? "" : std::string(out); %};
%{
SV*
GCodePressureEqualizer::process(const char *szGCode, bool flush)
CODE:
const char *out = THIS->process(szGCode, flush);
RETVAL = newSVpv(out, THIS->get_output_buffer_length());
OUTPUT:
RETVAL
%}
};

View file

@ -54,9 +54,8 @@ GCodeWriter::extruders()
AV* av = newAV();
av_fill(av, THIS->extruders.size()-1);
int i = 0;
for (std::map<unsigned int,Extruder>::iterator it = THIS->extruders.begin(); it != THIS->extruders.end(); ++it) {
av_store(av, i++, perl_to_SV_ref(it->second));
}
for (const Extruder &extruder : THIS->extruders)
av_store(av, i++, perl_to_SV_ref(const_cast<Extruder&>(extruder)));
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL

View file

@ -195,30 +195,6 @@ _constant()
void set_step_started(PrintStep step)
%code%{ THIS->state.set_started(step); %};
std::vector<int> object_extruders()
%code%{
std::set<size_t> extruders = THIS->object_extruders();
RETVAL.reserve(extruders.size());
for (std::set<size_t>::const_iterator e = extruders.begin(); e != extruders.end(); ++e) {
RETVAL.push_back(*e);
}
%};
std::vector<int> support_material_extruders()
%code%{
std::set<size_t> extruders = THIS->support_material_extruders();
RETVAL.reserve(extruders.size());
for (std::set<size_t>::const_iterator e = extruders.begin(); e != extruders.end(); ++e) {
RETVAL.push_back(*e);
}
%};
std::vector<int> extruders()
%code%{
std::set<size_t> extruders = THIS->extruders();
RETVAL.reserve(extruders.size());
for (std::set<size_t>::const_iterator e = extruders.begin(); e != extruders.end(); ++e) {
RETVAL.push_back(*e);
}
%};
void clear_filament_stats()
%code%{
THIS->filament_stats.clear();

View file

@ -185,26 +185,10 @@ PlaceholderParser* O_OBJECT_SLIC3R
Ref<PlaceholderParser> O_OBJECT_SLIC3R_T
Clone<PlaceholderParser> O_OBJECT_SLIC3R_T
AvoidCrossingPerimeters* O_OBJECT_SLIC3R
Ref<AvoidCrossingPerimeters> O_OBJECT_SLIC3R_T
Clone<AvoidCrossingPerimeters> O_OBJECT_SLIC3R_T
Wipe* O_OBJECT_SLIC3R
Ref<Wipe> O_OBJECT_SLIC3R_T
Clone<Wipe> O_OBJECT_SLIC3R_T
OozePrevention* O_OBJECT_SLIC3R
Ref<OozePrevention> O_OBJECT_SLIC3R_T
Clone<OozePrevention> O_OBJECT_SLIC3R_T
CoolingBuffer* O_OBJECT_SLIC3R
Ref<CoolingBuffer> O_OBJECT_SLIC3R_T
Clone<CoolingBuffer> O_OBJECT_SLIC3R_T
SpiralVase* O_OBJECT_SLIC3R
Ref<SpiralVase> O_OBJECT_SLIC3R_T
Clone<SpiralVase> O_OBJECT_SLIC3R_T
GCode* O_OBJECT_SLIC3R
Ref<GCode> O_OBJECT_SLIC3R_T
Clone<GCode> O_OBJECT_SLIC3R_T
@ -221,10 +205,6 @@ GCodeWriter* O_OBJECT_SLIC3R
Ref<GCodeWriter> O_OBJECT_SLIC3R_T
Clone<GCodeWriter> O_OBJECT_SLIC3R_T
GCodePressureEqualizer* O_OBJECT_SLIC3R
Ref<GCodePressureEqualizer> O_OBJECT_SLIC3R_T
Clone<GCodePressureEqualizer> O_OBJECT_SLIC3R_T
BridgeDetector* O_OBJECT_SLIC3R
Ref<BridgeDetector> O_OBJECT_SLIC3R_T
Clone<BridgeDetector> O_OBJECT_SLIC3R_T

View file

@ -105,9 +105,6 @@
%typemap{GCodeSender*};
%typemap{Ref<GCodeSender>}{simple};
%typemap{Clone<GCodeSender>}{simple};
%typemap{GCodePressureEqualizer*};
%typemap{Ref<GCodePressureEqualizer>}{simple};
%typemap{Clone<GCodePressureEqualizer>}{simple};
%typemap{BridgeDetector*};
%typemap{Ref<BridgeDetector>}{simple};
%typemap{Clone<BridgeDetector>}{simple};
@ -152,18 +149,6 @@
%typemap{Ref<PlaceholderParser>}{simple};
%typemap{Clone<PlaceholderParser>}{simple};
%typemap{AvoidCrossingPerimeters*};
%typemap{Ref<AvoidCrossingPerimeters>}{simple};
%typemap{Clone<AvoidCrossingPerimeters>}{simple};
%typemap{Wipe*};
%typemap{Ref<Wipe>}{simple};
%typemap{Clone<Wipe>}{simple};
%typemap{OozePrevention*};
%typemap{Ref<OozePrevention>}{simple};
%typemap{Clone<OozePrevention>}{simple};
%typemap{CoolingBuffer*};
%typemap{Ref<CoolingBuffer>}{simple};
%typemap{Clone<CoolingBuffer>}{simple};