Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/libslic3r/GCode.hpp')
-rw-r--r--src/libslic3r/GCode.hpp365
1 files changed, 365 insertions, 0 deletions
diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp
new file mode 100644
index 000000000..45f17a68a
--- /dev/null
+++ b/src/libslic3r/GCode.hpp
@@ -0,0 +1,365 @@
+#ifndef slic3r_GCode_hpp_
+#define slic3r_GCode_hpp_
+
+#include "libslic3r.h"
+#include "ExPolygon.hpp"
+#include "GCodeWriter.hpp"
+#include "Layer.hpp"
+#include "MotionPlanner.hpp"
+#include "Point.hpp"
+#include "PlaceholderParser.hpp"
+#include "Print.hpp"
+#include "PrintConfig.hpp"
+#include "GCode/CoolingBuffer.hpp"
+#include "GCode/PressureEqualizer.hpp"
+#include "GCode/SpiralVase.hpp"
+#include "GCode/ToolOrdering.hpp"
+#include "GCode/WipeTower.hpp"
+#include "GCodeTimeEstimator.hpp"
+#include "EdgeGrid.hpp"
+#include "GCode/Analyzer.hpp"
+
+#include <memory>
+#include <string>
+
+namespace Slic3r {
+
+// Forward declarations.
+class GCode;
+class GCodePreviewData;
+
+class AvoidCrossingPerimeters {
+public:
+
+ // this flag triggers the use of the external configuration space
+ bool use_external_mp;
+ bool use_external_mp_once; // just for the next travel move
+
+ // this flag disables avoid_crossing_perimeters just for the next travel move
+ // we enable it by default for the first travel move in print
+ bool disable_once;
+
+ AvoidCrossingPerimeters() : use_external_mp(false), use_external_mp_once(false), disable_once(true) {}
+ ~AvoidCrossingPerimeters() {}
+
+ void init_external_mp(const ExPolygons &islands) { m_external_mp = Slic3r::make_unique<MotionPlanner>(islands); }
+ void init_layer_mp(const ExPolygons &islands) { m_layer_mp = Slic3r::make_unique<MotionPlanner>(islands); }
+
+ Polyline travel_to(const GCode &gcodegen, const Point &point);
+
+private:
+ std::unique_ptr<MotionPlanner> m_external_mp;
+ std::unique_ptr<MotionPlanner> m_layer_mp;
+};
+
+class OozePrevention {
+public:
+ bool enable;
+ Points standby_points;
+
+ OozePrevention() : enable(false) {}
+ std::string pre_toolchange(GCode &gcodegen);
+ std::string post_toolchange(GCode &gcodegen);
+
+private:
+ int _get_temp(GCode &gcodegen);
+};
+
+class Wipe {
+public:
+ bool enable;
+ Polyline path;
+
+ Wipe() : enable(false) {}
+ bool has_path() const { return !this->path.points.empty(); }
+ void reset_path() { this->path = Polyline(); }
+ std::string wipe(GCode &gcodegen, bool toolchange = false);
+};
+
+class WipeTowerIntegration {
+public:
+ WipeTowerIntegration(
+ const PrintConfig &print_config,
+ const WipeTower::ToolChangeResult &priming,
+ const std::vector<std::vector<WipeTower::ToolChangeResult>> &tool_changes,
+ const WipeTower::ToolChangeResult &final_purge) :
+ m_left(/*float(print_config.wipe_tower_x.value)*/ 0.f),
+ m_right(float(/*print_config.wipe_tower_x.value +*/ print_config.wipe_tower_width.value)),
+ m_wipe_tower_pos(float(print_config.wipe_tower_x.value), float(print_config.wipe_tower_y.value)),
+ m_wipe_tower_rotation(float(print_config.wipe_tower_rotation_angle)),
+ m_priming(priming),
+ m_tool_changes(tool_changes),
+ m_final_purge(final_purge),
+ m_layer_idx(-1),
+ m_tool_change_idx(0),
+ m_brim_done(false) {}
+
+ std::string prime(GCode &gcodegen);
+ void next_layer() { ++ m_layer_idx; m_tool_change_idx = 0; }
+ std::string tool_change(GCode &gcodegen, int extruder_id, bool finish_layer);
+ std::string finalize(GCode &gcodegen);
+ std::vector<float> used_filament_length() const;
+
+private:
+ WipeTowerIntegration& operator=(const WipeTowerIntegration&);
+ std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const;
+
+ // Postprocesses gcode: rotates and moves all G1 extrusions and returns result
+ std::string rotate_wipe_tower_moves(const std::string& gcode_original, const WipeTower::xy& start_pos, const WipeTower::xy& translation, float angle) const;
+
+ // Left / right edges of the wipe tower, for the planning of wipe moves.
+ const float m_left;
+ const float m_right;
+ const WipeTower::xy m_wipe_tower_pos;
+ const float m_wipe_tower_rotation;
+ // Reference to cached values at the Printer class.
+ const WipeTower::ToolChangeResult &m_priming;
+ const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes;
+ const WipeTower::ToolChangeResult &m_final_purge;
+ // Current layer index.
+ int m_layer_idx;
+ int m_tool_change_idx;
+ bool m_brim_done;
+ bool i_have_brim = false;
+};
+
+class GCode {
+public:
+ GCode() :
+ m_origin(Vec2d::Zero()),
+ m_enable_loop_clipping(true),
+ m_enable_cooling_markers(false),
+ m_enable_extrusion_role_markers(false),
+ m_enable_analyzer(false),
+ m_last_analyzer_extrusion_role(erNone),
+ m_layer_count(0),
+ m_layer_index(-1),
+ m_layer(nullptr),
+ m_volumetric_speed(0),
+ m_last_pos_defined(false),
+ m_last_extrusion_role(erNone),
+ m_last_mm3_per_mm(GCodeAnalyzer::Default_mm3_per_mm),
+ m_last_width(GCodeAnalyzer::Default_Width),
+ m_last_height(GCodeAnalyzer::Default_Height),
+ m_brim_done(false),
+ m_second_layer_things_done(false),
+ m_normal_time_estimator(GCodeTimeEstimator::Normal),
+ m_silent_time_estimator(GCodeTimeEstimator::Silent),
+ m_silent_time_estimator_enabled(false),
+ m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max()))
+ {}
+ ~GCode() {}
+
+ // throws std::runtime_exception on error,
+ // throws CanceledException through print->throw_if_canceled().
+ void do_export(Print *print, const char *path, GCodePreviewData *preview_data = nullptr);
+
+ // Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests.
+ const Vec2d& origin() const { return m_origin; }
+ void set_origin(const Vec2d &pointf);
+ void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Vec2d(x, y)); }
+ const Point& last_pos() const { return m_last_pos; }
+ Vec2d point_to_gcode(const Point &point) const;
+ Point gcode_to_point(const Vec2d &point) const;
+ const FullPrintConfig &config() const { return m_config; }
+ const Layer* layer() const { return m_layer; }
+ GCodeWriter& writer() { return m_writer; }
+ PlaceholderParser& placeholder_parser() { return m_placeholder_parser; }
+ const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; }
+ // Process a template through the placeholder parser, collect error messages to be reported
+ // inside the generated string and after the G-code export finishes.
+ std::string placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override = nullptr);
+ bool enable_cooling_markers() const { return m_enable_cooling_markers; }
+
+ // 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; }
+ void apply_print_config(const PrintConfig &print_config);
+
+ // append full config to the given string
+ static void append_full_config(const Print& print, std::string& str);
+
+protected:
+ void _do_export(Print &print, FILE *file, GCodePreviewData *preview_data);
+
+ // 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 (object_layer != nullptr && support_layer != nullptr) ? 0.5 * (object_layer->print_z + support_layer->print_z) : this->layer()->print_z; }
+ };
+ static std::vector<GCode::LayerToPrint> collect_layers_to_print(const PrintObject &object);
+ static std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> collect_layers_to_print(const Print &print);
+ 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,
+ const LayerTools &layer_tools,
+ // 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(coordf_t print_z);
+ std::string extrude_entity(const ExtrusionEntity &entity, std::string description = "", double speed = -1., std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid = nullptr);
+ 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.);
+
+ typedef std::vector<int> ExtruderPerCopy;
+ // 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
+ {
+ 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<const ExtruderPerCopy*> infills_overrides;
+ std::vector<const ExtruderPerCopy*> perimeters_overrides;
+
+ // Appends perimeter/infill entities and writes don't indices of those that are not to be extruder as part of perimeter/infill wiping
+ void append(const std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copy_extruders, unsigned int object_copies_num);
+ };
+
+ std::vector<Region> by_region; // all extrusions for this island, grouped by regions
+ const std::vector<Region>& by_region_per_copy(unsigned int copy, int extruder, bool wiping_entities = false); // returns reference to subvector of by_region
+
+ private:
+ std::vector<Region> by_region_per_copy_cache; // caches vector generated by function above to avoid copying and recalculating
+ };
+ std::vector<Island> islands;
+ };
+
+
+ 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() { 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.
+ This affects the input arguments supplied to the extrude*() and travel_to()
+ methods. */
+ Vec2d m_origin;
+ FullPrintConfig m_config;
+ GCodeWriter m_writer;
+ PlaceholderParser m_placeholder_parser;
+ // Collection of templates, on which the placeholder substitution failed.
+ std::set<std::string> m_placeholder_parser_failed_templates;
+ 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 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 m_enable_extrusion_role_markers;
+ // Enableds the G-code Analyzer.
+ // Extended markers will be added during G-code generation.
+ // The G-code Analyzer will remove these comments from the final G-code.
+ bool m_enable_analyzer;
+ ExtrusionRole m_last_analyzer_extrusion_role;
+ // How many times will change_layer() be called?
+ // change_layer() will update the progress bar.
+ unsigned int m_layer_count;
+ // Progress bar indicator. Increments from -1 up to layer_count.
+ 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* m_layer;
+ std::map<const PrintObject*,Point> m_seam_position;
+ double m_volumetric_speed;
+ // Support for the extrusion role markers. Which marker is active?
+ ExtrusionRole m_last_extrusion_role;
+ // Support for G-Code Analyzer
+ double m_last_mm3_per_mm;
+ float m_last_width;
+ float m_last_height;
+
+ 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;
+ std::unique_ptr<WipeTowerIntegration> m_wipe_tower;
+
+ // Heights at which the skirt has already been extruded.
+ 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.
+ std::pair<const PrintObject*, Point> m_last_obj_copy;
+
+ // Time estimators
+ GCodeTimeEstimator m_normal_time_estimator;
+ GCodeTimeEstimator m_silent_time_estimator;
+ bool m_silent_time_estimator_enabled;
+
+ // Analyzer
+ GCodeAnalyzer m_analyzer;
+
+ // Write a string into a file.
+ void _write(FILE* file, const std::string& what) { this->_write(file, what.c_str()); }
+ void _write(FILE* file, const char *what);
+
+ // Write a string into a file.
+ // Add a newline, if the string does not end with a newline already.
+ // Used to export a custom G-code section processed by the PlaceholderParser.
+ void _writeln(FILE* file, const std::string& what);
+
+ // Formats and write into a file the given data.
+ void _write_format(FILE* file, const char* format, ...);
+
+ std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1);
+ void print_machine_envelope(FILE *file, Print &print);
+ void _print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
+ void _print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
+ // this flag triggers first layer speeds
+ bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; }
+
+ 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);
+
+ friend class WipeTowerIntegration;
+};
+
+}
+
+#endif