Improved G-code generator for multi-material prints

to minimize tool switches.
This commit is contained in:
bubnikv 2017-05-10 11:25:57 +02:00
parent 18bb3c3244
commit 2f57ee60d1
4 changed files with 553 additions and 378 deletions

View file

@ -205,6 +205,8 @@ sub gcode {
# Write the resulting G-code into a temporary file.
my $gcode_temp_path = abs_path($0) . '.gcode.temp';
# Remove the existing temp file.
unlink $gcode_temp_path;
$print->process;
$print->export_gcode(output_file => $gcode_temp_path, quiet => 1);
# Read the temoprary G-code file.

File diff suppressed because it is too large Load diff

View file

@ -81,14 +81,13 @@ public:
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()))
m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max()))
{}
~GCode() {}
@ -114,34 +113,64 @@ public:
void apply_print_config(const PrintConfig &print_config);
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; }
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);
std::string change_layer(coordf_t print_z);
std::string extrude_entity(const ExtrusionEntity &entity, 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_multi_path(ExtrusionMultiPath multipath, 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 {
ExtrusionEntityCollection perimeters;
ExtrusionEntityCollection infills;
ObjectByExtruder() : support(nullptr), support_extrusion_role(erNone) {}
const ExtrusionEntityCollection *support;
// 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_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 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<ObjectByExtruder::Island::Region> &by_region);
std::string extrude_support(const ExtrusionEntityCollection &support_fills);
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 unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string set_extruder(unsigned int extruder_id);
/* 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.
const Layer* m_layer;
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.
// 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.
@ -195,18 +220,32 @@ private:
std::unique_ptr<PressureEqualizer> m_pressure_equalizer;
// 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.
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;
// Index of a last object copy extruded.
std::pair<const PrintObject*, 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);
// 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);
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);
};
}

View file

@ -37,9 +37,15 @@ class Point
static Point new_scale(coordf_t x, coordf_t 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 == rhs); }
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 dump_perl() const;
void scale(double factor);
@ -184,7 +190,7 @@ std::ostream& operator<<(std::ostream &stm, const Pointf &pointf);
class Pointf
{
public:
public:
coordf_t x;
coordf_t 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 &center);
Pointf negative() 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); }