Improved G-code generator for multi-material prints
to minimize tool switches.
This commit is contained in:
parent
18bb3c3244
commit
2f57ee60d1
4 changed files with 553 additions and 378 deletions
|
@ -205,6 +205,8 @@ sub gcode {
|
||||||
|
|
||||||
# Write the resulting G-code into a temporary file.
|
# Write the resulting G-code into a temporary file.
|
||||||
my $gcode_temp_path = abs_path($0) . '.gcode.temp';
|
my $gcode_temp_path = abs_path($0) . '.gcode.temp';
|
||||||
|
# Remove the existing temp file.
|
||||||
|
unlink $gcode_temp_path;
|
||||||
$print->process;
|
$print->process;
|
||||||
$print->export_gcode(output_file => $gcode_temp_path, quiet => 1);
|
$print->export_gcode(output_file => $gcode_temp_path, quiet => 1);
|
||||||
# Read the temoprary G-code file.
|
# Read the temoprary G-code file.
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -81,14 +81,13 @@ public:
|
||||||
m_layer_count(0),
|
m_layer_count(0),
|
||||||
m_layer_index(-1),
|
m_layer_index(-1),
|
||||||
m_layer(nullptr),
|
m_layer(nullptr),
|
||||||
m_first_layer(false),
|
|
||||||
m_elapsed_time(0.0),
|
m_elapsed_time(0.0),
|
||||||
m_volumetric_speed(0),
|
m_volumetric_speed(0),
|
||||||
m_last_pos_defined(false),
|
m_last_pos_defined(false),
|
||||||
m_last_extrusion_role(erNone),
|
m_last_extrusion_role(erNone),
|
||||||
m_brim_done(false),
|
m_brim_done(false),
|
||||||
m_second_layer_things_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()))
|
m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max()))
|
||||||
{}
|
{}
|
||||||
~GCode() {}
|
~GCode() {}
|
||||||
|
|
||||||
|
@ -114,34 +113,64 @@ public:
|
||||||
void apply_print_config(const PrintConfig &print_config);
|
void apply_print_config(const PrintConfig &print_config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void process_layer(FILE *file, const Print &print, const Layer &layer, const Points &object_copies);
|
// Object and support extrusions of the same PrintObject at the same print_z.
|
||||||
|
struct LayerToPrint
|
||||||
|
{
|
||||||
|
LayerToPrint() : object_layer(nullptr), support_layer(nullptr) {}
|
||||||
|
const Layer *object_layer;
|
||||||
|
const SupportLayer *support_layer;
|
||||||
|
const Layer* layer() const { return (object_layer != nullptr) ? object_layer : support_layer; }
|
||||||
|
const PrintObject* object() const { return (this->layer() != nullptr) ? this->layer()->object() : nullptr; }
|
||||||
|
coordf_t print_z() const { return this->layer()->print_z; }
|
||||||
|
};
|
||||||
|
void process_layer(
|
||||||
|
// Write into the output file.
|
||||||
|
FILE *file,
|
||||||
|
const Print &print,
|
||||||
|
// Set of object & print layers of the same PrintObject and with the same print_z.
|
||||||
|
const std::vector<LayerToPrint> &layers,
|
||||||
|
// If set to size_t(-1), then print all copies of all objects.
|
||||||
|
// Otherwise print a single copy of a single object.
|
||||||
|
const size_t single_object_idx = size_t(-1));
|
||||||
|
|
||||||
void set_last_pos(const Point &pos) { m_last_pos = pos; m_last_pos_defined = true; }
|
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; }
|
bool last_pos_defined() const { return m_last_pos_defined; }
|
||||||
void set_extruders(const std::vector<unsigned int> &extruder_ids);
|
void set_extruders(const std::vector<unsigned int> &extruder_ids);
|
||||||
std::string preamble();
|
std::string preamble();
|
||||||
std::string change_layer(const Layer &layer);
|
std::string change_layer(coordf_t print_z);
|
||||||
std::string extrude(const ExtrusionEntity &entity, std::string description = "", double speed = -1);
|
std::string extrude_entity(const ExtrusionEntity &entity, std::string description = "", double speed = -1.);
|
||||||
std::string extrude(ExtrusionLoop loop, std::string description = "", double speed = -1);
|
std::string extrude_loop(ExtrusionLoop loop, std::string description, double speed = -1., std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid = nullptr);
|
||||||
std::string extrude(ExtrusionMultiPath multipath, std::string description = "", double speed = -1);
|
std::string extrude_multi_path(ExtrusionMultiPath multipath, std::string description = "", double speed = -1.);
|
||||||
std::string extrude(ExtrusionPath path, std::string description = "", double speed = -1);
|
std::string extrude_path(ExtrusionPath path, std::string description = "", double speed = -1.);
|
||||||
|
|
||||||
struct ByExtruder
|
// Extruding multiple objects with soluble / non-soluble / combined supports
|
||||||
|
// on a multi-material printer, trying to minimize tool switches.
|
||||||
|
// Following structures sort extrusions by the extruder ID, by an order of objects and object islands.
|
||||||
|
struct ObjectByExtruder
|
||||||
{
|
{
|
||||||
struct ToExtrude {
|
ObjectByExtruder() : support(nullptr), support_extrusion_role(erNone) {}
|
||||||
ExtrusionEntityCollection perimeters;
|
const ExtrusionEntityCollection *support;
|
||||||
ExtrusionEntityCollection infills;
|
// erSupportMaterial / erSupportMaterialInterface or erMixed.
|
||||||
|
ExtrusionRole support_extrusion_role;
|
||||||
|
|
||||||
|
struct Island
|
||||||
|
{
|
||||||
|
struct Region {
|
||||||
|
ExtrusionEntityCollection perimeters;
|
||||||
|
ExtrusionEntityCollection infills;
|
||||||
|
};
|
||||||
|
std::vector<Region> by_region;
|
||||||
};
|
};
|
||||||
std::vector<ToExtrude> by_region;
|
std::vector<Island> islands;
|
||||||
};
|
};
|
||||||
std::string extrude_perimeters(const Print &print, const std::vector<ByExtruder::ToExtrude> &by_region);
|
std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, std::unique_ptr<EdgeGrid::Grid> &lower_layer_edge_grid);
|
||||||
std::string extrude_infill(const Print &print, const std::vector<ByExtruder::ToExtrude> &by_region);
|
std::string extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region);
|
||||||
std::string extrude_support(const ExtrusionEntityCollection &support_fills, unsigned int extruder_id);
|
std::string extrude_support(const ExtrusionEntityCollection &support_fills);
|
||||||
|
|
||||||
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
|
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
|
||||||
bool needs_retraction(const Polyline &travel, ExtrusionRole role = erNone);
|
bool needs_retraction(const Polyline &travel, ExtrusionRole role = erNone);
|
||||||
std::string retract(bool toolchange = false);
|
std::string retract(bool toolchange = false);
|
||||||
std::string unretract();
|
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
|
||||||
std::string set_extruder(unsigned int extruder_id);
|
std::string set_extruder(unsigned int extruder_id);
|
||||||
|
|
||||||
/* Origin of print coordinates expressed in unscaled G-code coordinates.
|
/* Origin of print coordinates expressed in unscaled G-code coordinates.
|
||||||
|
@ -174,10 +203,6 @@ private:
|
||||||
// In non-sequential mode, all its copies will be printed.
|
// In non-sequential mode, all its copies will be printed.
|
||||||
const Layer* m_layer;
|
const Layer* m_layer;
|
||||||
std::map<const PrintObject*,Point> m_seam_position;
|
std::map<const PrintObject*,Point> m_seam_position;
|
||||||
// Distance Field structure to
|
|
||||||
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.
|
// 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,
|
// 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.
|
// it does not account for wipe, retract / unretract moves.
|
||||||
|
@ -195,18 +220,32 @@ private:
|
||||||
std::unique_ptr<PressureEqualizer> m_pressure_equalizer;
|
std::unique_ptr<PressureEqualizer> m_pressure_equalizer;
|
||||||
|
|
||||||
// Heights at which the skirt has already been extruded.
|
// Heights at which the skirt has already been extruded.
|
||||||
std::set<coordf_t> m_skirt_done;
|
std::vector<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.
|
// Has the brim been extruded already? Brim is being extruded only for the first object of a multi-object print.
|
||||||
bool m_brim_done;
|
bool m_brim_done;
|
||||||
// Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed.
|
// Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed.
|
||||||
bool m_second_layer_things_done;
|
bool m_second_layer_things_done;
|
||||||
// Index of a last object copy extruded. -1 for not set yet.
|
// Index of a last object copy extruded.
|
||||||
Point m_last_obj_copy;
|
std::pair<const PrintObject*, Point> m_last_obj_copy;
|
||||||
|
|
||||||
std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1);
|
std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1);
|
||||||
void _print_first_layer_extruder_temperatures(FILE *file, Print &print, bool wait);
|
void _print_first_layer_extruder_temperatures(FILE *file, Print &print, bool wait);
|
||||||
|
// this flag triggers first layer speeds
|
||||||
|
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; }
|
||||||
|
|
||||||
std::string filter(std::string &&gcode, bool flush);
|
std::string filter(std::string &&gcode, bool flush);
|
||||||
|
|
||||||
|
friend ObjectByExtruder& object_by_extruder(
|
||||||
|
std::map<unsigned int, std::vector<ObjectByExtruder>> &by_extruder,
|
||||||
|
unsigned int extruder_id,
|
||||||
|
size_t object_idx,
|
||||||
|
size_t num_objects);
|
||||||
|
friend std::vector<ObjectByExtruder::Island>& object_islands_by_extruder(
|
||||||
|
std::map<unsigned int, std::vector<ObjectByExtruder>> &by_extruder,
|
||||||
|
unsigned int extruder_id,
|
||||||
|
size_t object_idx,
|
||||||
|
size_t num_objects,
|
||||||
|
size_t num_islands);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,15 @@ class Point
|
||||||
static Point new_scale(coordf_t x, coordf_t y) {
|
static Point new_scale(coordf_t x, coordf_t y) {
|
||||||
return Point(scale_(x), scale_(y));
|
return Point(scale_(x), scale_(y));
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator==(const Point& rhs) const { return this->x == rhs.x && this->y == rhs.y; }
|
bool operator==(const Point& rhs) const { return this->x == rhs.x && this->y == rhs.y; }
|
||||||
bool operator!=(const Point& rhs) const { return ! (*this == rhs); }
|
bool operator!=(const Point& rhs) const { return ! (*this == rhs); }
|
||||||
bool operator<(const Point& rhs) const { return this->x < rhs.x || (this->x == rhs.x && this->y < rhs.y); }
|
bool operator<(const Point& rhs) const { return this->x < rhs.x || (this->x == rhs.x && this->y < rhs.y); }
|
||||||
|
|
||||||
|
Point& operator+=(const Point& rhs) { this->x += rhs.x; this->y += rhs.y; return *this; }
|
||||||
|
Point& operator-=(const Point& rhs) { this->x -= rhs.x; this->y -= rhs.y; return *this; }
|
||||||
|
Point& operator*=(const coord_t& rhs) { this->x *= rhs; this->y *= rhs; return *this; }
|
||||||
|
|
||||||
std::string wkt() const;
|
std::string wkt() const;
|
||||||
std::string dump_perl() const;
|
std::string dump_perl() const;
|
||||||
void scale(double factor);
|
void scale(double factor);
|
||||||
|
@ -184,7 +190,7 @@ std::ostream& operator<<(std::ostream &stm, const Pointf &pointf);
|
||||||
|
|
||||||
class Pointf
|
class Pointf
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
coordf_t x;
|
coordf_t x;
|
||||||
coordf_t y;
|
coordf_t y;
|
||||||
explicit Pointf(coordf_t _x = 0, coordf_t _y = 0): x(_x), y(_y) {};
|
explicit Pointf(coordf_t _x = 0, coordf_t _y = 0): x(_x), y(_y) {};
|
||||||
|
@ -203,6 +209,10 @@ class Pointf
|
||||||
void rotate(double angle, const Pointf ¢er);
|
void rotate(double angle, const Pointf ¢er);
|
||||||
Pointf negative() const;
|
Pointf negative() const;
|
||||||
Vectorf vector_to(const Pointf &point) const;
|
Vectorf vector_to(const Pointf &point) const;
|
||||||
|
|
||||||
|
Pointf& operator+=(const Pointf& rhs) { this->x += rhs.x; this->y += rhs.y; return *this; }
|
||||||
|
Pointf& operator-=(const Pointf& rhs) { this->x -= rhs.x; this->y -= rhs.y; return *this; }
|
||||||
|
Pointf& operator*=(const coordf_t& rhs) { this->x *= rhs; this->y *= rhs; return *this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Pointf operator+(const Pointf& point1, const Pointf& point2) { return Pointf(point1.x + point2.x, point1.y + point2.y); }
|
inline Pointf operator+(const Pointf& point1, const Pointf& point2) { return Pointf(point1.x + point2.x, point1.y + point2.y); }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue