2014-05-10 13:08:49 +00:00
# ifndef slic3r_GCode_hpp_
# define slic3r_GCode_hpp_
2015-12-07 23:39:54 +00:00
# include "libslic3r.h"
2015-07-01 18:14:05 +00:00
# include "ExPolygon.hpp"
2015-07-01 19:47:17 +00:00
# include "GCodeWriter.hpp"
# include "Layer.hpp"
2015-07-01 18:14:05 +00:00
# include "MotionPlanner.hpp"
2015-07-01 19:47:17 +00:00
# include "Point.hpp"
# include "PlaceholderParser.hpp"
# include "Print.hpp"
# include "PrintConfig.hpp"
2017-05-03 16:28:22 +00:00
# include "GCode/CoolingBuffer.hpp"
# include "GCode/PressureEqualizer.hpp"
# include "GCode/SpiralVase.hpp"
2017-05-16 11:45:28 +00:00
# include "GCode/ToolOrdering.hpp"
# include "GCode/WipeTower.hpp"
2017-12-11 08:06:29 +00:00
# include "GCodeTimeEstimator.hpp"
2017-05-03 16:28:22 +00:00
# include "EdgeGrid.hpp"
2018-01-08 12:44:10 +00:00
# include "GCode/Analyzer.hpp"
2017-05-03 16:28:22 +00:00
2017-05-03 16:35:55 +00:00
# include <memory>
2014-05-10 13:08:49 +00:00
# include <string>
namespace Slic3r {
2016-09-12 14:25:15 +00:00
// Forward declarations.
2015-07-01 21:00:52 +00:00
class GCode ;
2018-02-14 19:35:59 +00:00
class GCodePreviewData ;
2014-05-10 13:08:49 +00:00
2015-07-01 18:14:05 +00:00
class AvoidCrossingPerimeters {
2017-05-03 16:28:22 +00:00
public :
2014-05-10 13:08:49 +00:00
2015-07-01 18:14:05 +00:00
// 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 ;
2017-05-05 07:59:56 +00:00
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 ) ; }
2017-06-02 11:33:19 +00:00
Polyline travel_to ( const GCode & gcodegen , const Point & point ) ;
2017-05-05 07:59:56 +00:00
2017-05-03 16:28:22 +00:00
private :
2017-05-05 07:59:56 +00:00
std : : unique_ptr < MotionPlanner > m_external_mp ;
std : : unique_ptr < MotionPlanner > m_layer_mp ;
2014-05-10 13:08:49 +00:00
} ;
2015-07-01 19:01:42 +00:00
class OozePrevention {
2017-04-26 12:24:31 +00:00
public :
2015-07-01 19:01:42 +00:00
bool enable ;
Points standby_points ;
2017-04-26 12:24:31 +00:00
OozePrevention ( ) : enable ( false ) { }
2015-07-02 13:02:20 +00:00
std : : string pre_toolchange ( GCode & gcodegen ) ;
std : : string post_toolchange ( GCode & gcodegen ) ;
2017-04-26 12:24:31 +00:00
private :
2015-07-02 13:02:20 +00:00
int _get_temp ( GCode & gcodegen ) ;
2015-07-01 19:01:42 +00:00
} ;
2015-07-01 18:57:16 +00:00
class Wipe {
2017-04-26 12:24:31 +00:00
public :
2015-07-01 18:57:16 +00:00
bool enable ;
Polyline path ;
2017-04-26 12:24:31 +00:00
Wipe ( ) : enable ( false ) { }
bool has_path ( ) const { return ! this - > path . points . empty ( ) ; }
void reset_path ( ) { this - > path = Polyline ( ) ; }
2015-07-01 21:00:52 +00:00
std : : string wipe ( GCode & gcodegen , bool toolchange = false ) ;
2015-07-01 18:57:16 +00:00
} ;
2017-05-18 14:53:19 +00:00
class WipeTowerIntegration {
public :
2017-05-25 20:27:53 +00:00
WipeTowerIntegration (
const PrintConfig & print_config ,
2017-09-01 15:30:18 +00:00
const WipeTower : : ToolChangeResult & priming ,
2017-05-25 20:27:53 +00:00
const std : : vector < std : : vector < WipeTower : : ToolChangeResult > > & tool_changes ,
const WipeTower : : ToolChangeResult & final_purge ) :
m_left ( float ( print_config . wipe_tower_x . value ) ) ,
m_right ( float ( print_config . wipe_tower_x . value + print_config . wipe_tower_width . value ) ) ,
2017-09-01 15:30:18 +00:00
m_priming ( priming ) ,
2017-05-25 20:27:53 +00:00
m_tool_changes ( tool_changes ) ,
m_final_purge ( final_purge ) ,
m_layer_idx ( - 1 ) ,
m_tool_change_idx ( 0 ) ,
m_brim_done ( false ) { }
2017-09-01 15:30:18 +00:00
std : : string prime ( GCode & gcodegen ) ;
2017-05-25 20:27:53 +00:00
void next_layer ( ) { + + m_layer_idx ; m_tool_change_idx = 0 ; }
2017-05-18 14:53:19 +00:00
std : : string tool_change ( GCode & gcodegen , int extruder_id , bool finish_layer ) ;
2017-05-25 20:27:53 +00:00
std : : string finalize ( GCode & gcodegen ) ;
2017-05-18 14:53:19 +00:00
private :
2017-05-25 20:27:53 +00:00
WipeTowerIntegration & operator = ( const WipeTowerIntegration & ) ;
std : : string append_tcr ( GCode & gcodegen , const WipeTower : : ToolChangeResult & tcr , int new_extruder_id ) const ;
// Left / right edges of the wipe tower, for the planning of wipe moves.
const float m_left ;
const float m_right ;
// Reference to cached values at the Printer class.
2017-09-01 15:30:18 +00:00
const WipeTower : : ToolChangeResult & m_priming ;
2017-05-25 20:27:53 +00:00
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 ;
2017-05-18 14:53:19 +00:00
} ;
2015-07-01 19:47:17 +00:00
class GCode {
2017-05-03 16:28:22 +00:00
public :
GCode ( ) :
m_enable_loop_clipping ( true ) ,
m_enable_cooling_markers ( false ) ,
m_enable_extrusion_role_markers ( false ) ,
2018-02-14 19:35:59 +00:00
m_enable_analyzer ( false ) ,
2018-05-07 12:23:07 +00:00
m_last_analyzer_extrusion_role ( erNone ) ,
2017-05-03 16:28:22 +00:00
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 ) ,
2018-01-08 12:44:10 +00:00
m_last_mm3_per_mm ( GCodeAnalyzer : : Default_mm3_per_mm ) ,
m_last_width ( GCodeAnalyzer : : Default_Width ) ,
m_last_height ( GCodeAnalyzer : : Default_Height ) ,
2017-05-03 16:28:22 +00:00
m_brim_done ( false ) ,
m_second_layer_things_done ( false ) ,
2017-05-10 09:25:57 +00:00
m_last_obj_copy ( nullptr , Point ( std : : numeric_limits < coord_t > : : max ( ) , std : : numeric_limits < coord_t > : : max ( ) ) )
2017-05-03 16:28:22 +00:00
{ }
~ GCode ( ) { }
2017-12-05 14:54:24 +00:00
// throws std::runtime_exception
2018-02-14 19:35:59 +00:00
void do_export ( Print * print , const char * path , GCodePreviewData * preview_data = nullptr ) ;
2017-05-03 16:28:22 +00:00
// 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 ;
2017-05-18 14:53:19 +00:00
Point gcode_to_point ( const Pointf & point ) const ;
2017-05-03 16:28:22 +00:00
const FullPrintConfig & config ( ) const { return m_config ; }
const Layer * layer ( ) const { return m_layer ; }
GCodeWriter & writer ( ) { return m_writer ; }
2017-11-30 15:01:47 +00:00
PlaceholderParser & placeholder_parser ( ) { return m_placeholder_parser ; }
2017-12-05 14:54:24 +00:00
// 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 ) ;
2017-05-03 16:28:22 +00:00
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 ) ;
2018-02-13 14:19:55 +00:00
// append full config to the given string
static void append_full_config ( const Print & print , std : : string & str ) ;
2017-05-18 14:53:19 +00:00
protected :
2018-02-14 19:35:59 +00:00
void _do_export ( Print & print , FILE * file , GCodePreviewData * preview_data ) ;
2017-08-03 15:31:31 +00:00
2017-05-10 09:25:57 +00:00
// 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 ; }
2017-05-23 15:09:43 +00:00
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 ; }
2017-05-10 09:25:57 +00:00
} ;
2017-05-23 15:09:43 +00:00
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 ) ;
2017-05-10 09:25:57 +00:00
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 ,
2017-05-16 11:45:28 +00:00
const ToolOrdering : : LayerTools & layer_tools ,
2017-05-10 09:25:57 +00:00
// 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 ) ) ;
2017-05-03 16:28:22 +00:00
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 ( ) ;
2017-05-10 09:25:57 +00:00
std : : string change_layer ( coordf_t print_z ) ;
2017-05-15 09:32:59 +00:00
std : : string extrude_entity ( const ExtrusionEntity & entity , std : : string description = " " , double speed = - 1. , std : : unique_ptr < EdgeGrid : : Grid > * lower_layer_edge_grid = nullptr ) ;
2017-05-10 09:25:57 +00:00
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. ) ;
// 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
2017-05-03 16:28:22 +00:00
{
2017-05-10 09:25:57 +00:00
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 ;
2018-06-01 13:38:49 +00:00
std : : vector < std : : vector < unsigned int > > infills_per_copy_ids ; // indices of infill.entities that are not part of infill wiping (an element for each object copy)
2017-05-10 09:25:57 +00:00
} ;
std : : vector < Region > by_region ;
2018-06-01 13:38:49 +00:00
std : : vector < Region > by_region_per_copy ( unsigned int copy ) const ; // returns only extrusions that are NOT printed during wiping into infill for this copy
2017-05-03 16:28:22 +00:00
} ;
2017-05-10 09:25:57 +00:00
std : : vector < Island > islands ;
2017-05-03 16:28:22 +00:00
} ;
2018-05-31 14:21:10 +00:00
2017-05-10 09:25:57 +00:00
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 ) ;
2017-05-03 16:28:22 +00:00
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 ) ;
2017-05-10 09:25:57 +00:00
std : : string unretract ( ) { return m_writer . unlift ( ) + m_writer . unretract ( ) ; }
2017-05-03 16:28:22 +00:00
std : : string set_extruder ( unsigned int extruder_id ) ;
2015-07-01 19:47:17 +00:00
/* Origin of print coordinates expressed in unscaled G-code coordinates.
This affects the input arguments supplied to the extrude * ( ) and travel_to ( )
methods . */
2017-05-03 16:28:22 +00:00
Pointf m_origin ;
FullPrintConfig m_config ;
GCodeWriter m_writer ;
PlaceholderParser m_placeholder_parser ;
2017-12-05 14:54:24 +00:00
// Collection of templates, on which the placeholder substitution failed.
std : : set < std : : string > m_placeholder_parser_failed_templates ;
2017-05-03 16:28:22 +00:00
OozePrevention m_ooze_prevention ;
Wipe m_wipe ;
AvoidCrossingPerimeters m_avoid_crossing_perimeters ;
bool m_enable_loop_clipping ;
2016-09-13 11:30:00 +00:00
// 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.
2017-05-03 16:28:22 +00:00
bool m_enable_cooling_markers ;
2016-09-12 14:25:15 +00:00
// Markers for the Pressure Equalizer to recognize the extrusion type.
// The Pressure Equalizer removes the markers from the final G-code.
2017-05-03 16:28:22 +00:00
bool m_enable_extrusion_role_markers ;
2018-01-08 12:44:10 +00:00
// 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 ;
2018-05-07 12:23:07 +00:00
ExtrusionRole m_last_analyzer_extrusion_role ;
2016-09-26 10:52:40 +00:00
// How many times will change_layer() be called?
// change_layer() will update the progress bar.
2017-05-03 16:28:22 +00:00
unsigned int m_layer_count ;
2016-09-26 10:52:40 +00:00
// Progress bar indicator. Increments from -1 up to layer_count.
2017-05-03 16:28:22 +00:00
int m_layer_index ;
2016-09-26 10:52:40 +00:00
// Current layer processed. Insequential printing mode, only a single copy will be printed.
// In non-sequential mode, all its copies will be printed.
2017-05-03 16:28:22 +00:00
const Layer * m_layer ;
std : : map < const PrintObject * , Point > m_seam_position ;
double m_volumetric_speed ;
2016-09-12 14:25:15 +00:00
// Support for the extrusion role markers. Which marker is active?
2017-05-03 16:28:22 +00:00
ExtrusionRole m_last_extrusion_role ;
2018-01-08 12:44:10 +00:00
// Support for G-Code Analyzer
double m_last_mm3_per_mm ;
float m_last_width ;
float m_last_height ;
2017-05-03 16:28:22 +00:00
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 ;
2017-05-18 14:53:19 +00:00
std : : unique_ptr < WipeTowerIntegration > m_wipe_tower ;
2017-05-03 16:28:22 +00:00
// Heights at which the skirt has already been extruded.
2017-05-10 09:25:57 +00:00
std : : vector < coordf_t > m_skirt_done ;
2017-05-03 16:28:22 +00:00
// 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 ;
2017-05-10 09:25:57 +00:00
// Index of a last object copy extruded.
std : : pair < const PrintObject * , Point > m_last_obj_copy ;
2017-05-03 16:28:22 +00:00
2017-12-11 08:06:29 +00:00
// Time estimator
GCodeTimeEstimator m_time_estimator ;
2018-01-08 12:44:10 +00:00
// Analyzer
GCodeAnalyzer m_analyzer ;
2017-12-14 08:18:28 +00:00
// Write a string into a file.
2018-01-08 12:44:10 +00:00
void _write ( FILE * file , const std : : string & what ) { this - > _write ( file , what . c_str ( ) ) ; }
void _write ( FILE * file , const char * what ) ;
2017-12-14 08:18:28 +00:00
// 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 , . . . ) ;
2017-02-15 16:51:46 +00:00
std : : string _extrude ( const ExtrusionPath & path , std : : string description = " " , double speed = - 1 ) ;
2017-11-28 14:19:57 +00:00
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 ) ;
2017-05-10 09:25:57 +00:00
// this flag triggers first layer speeds
bool on_first_layer ( ) const { return m_layer ! = nullptr & & m_layer - > id ( ) = = 0 ; }
2017-05-03 16:28:22 +00:00
2017-05-10 09:25:57 +00:00
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 ) ;
2017-05-18 14:53:19 +00:00
friend class WipeTowerIntegration ;
2015-07-01 19:47:17 +00:00
} ;
2014-05-10 13:08:49 +00:00
}
# endif