Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::GCodeProcessor Class Reference

#include <src/libslic3r/GCode/GCodeProcessor.hpp>

+ Collaboration diagram for Slic3r::GCodeProcessor:

Classes

struct  CachedPosition
 
struct  CpColor
 
struct  FeedMultiply
 
struct  FeedrateProfile
 
class  OptionsZCorrector
 
class  SeamsDetector
 
struct  TimeBlock
 
struct  TimeMachine
 
struct  TimeProcessor
 
struct  Trapezoid
 
struct  UsedFilaments
 

Public Types

enum class  ETags : unsigned char {
  Role , Wipe_Start , Wipe_End , Height ,
  Width , Layer_Change , Color_Change , Pause_Print ,
  Custom_Code , First_Line_M73_Placeholder , Last_Line_M73_Placeholder , Estimated_Printing_Time_Placeholder
}
 

Public Member Functions

 GCodeProcessor ()
 
void apply_config (const PrintConfig &config)
 
void set_print (Print *print)
 
void enable_stealth_time_estimator (bool enabled)
 
bool is_stealth_time_estimator_enabled () const
 
void enable_machine_envelope_processing (bool enabled)
 
void reset ()
 
const GCodeProcessorResultget_result () const
 
GCodeProcessorResult && extract_result ()
 
void process_file (const std::string &filename, std::function< void()> cancel_callback=nullptr)
 
void initialize (const std::string &filename)
 
void initialize_result_moves ()
 
void process_buffer (const std::string &buffer)
 
void finalize (bool post_process)
 
float get_time (PrintEstimatedStatistics::ETimeMode mode) const
 
std::string get_time_dhm (PrintEstimatedStatistics::ETimeMode mode) const
 
float get_travel_time (PrintEstimatedStatistics::ETimeMode mode) const
 
std::string get_travel_time_dhm (PrintEstimatedStatistics::ETimeMode mode) const
 
std::vector< std::pair< CustomGCode::Type, std::pair< float, float > > > get_custom_gcode_times (PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const
 
std::vector< std::pair< EMoveType, float > > get_moves_time (PrintEstimatedStatistics::ETimeMode mode) const
 
std::vector< std::pair< GCodeExtrusionRole, float > > get_roles_time (PrintEstimatedStatistics::ETimeMode mode) const
 
std::vector< float > get_layers_time (PrintEstimatedStatistics::ETimeMode mode) const
 

Static Public Member Functions

static const std::string & reserved_tag (ETags tag)
 
static bool contains_reserved_tag (const std::string &gcode, std::string &found_tag)
 
static bool contains_reserved_tags (const std::string &gcode, unsigned int max_count, std::vector< std::string > &found_tag)
 

Static Public Attributes

static const float Wipe_Width = 0.05f
 
static const float Wipe_Height = 0.05f
 

Private Types

enum class  EUnits : unsigned char { Millimeters , Inches }
 
enum class  EPositioningType : unsigned char { Absolute , Relative }
 
enum class  EProducer {
  Unknown , PrusaSlicer , Slic3rPE , Slic3r ,
  SuperSlicer , Cura , Simplify3D , CraftWare ,
  ideaMaker , KissSlicer , BambuStudio
}
 
using AxisCoords = std::array< double, 4 >
 
using ExtruderColors = std::vector< unsigned char >
 
using ExtruderTemps = std::vector< float >
 

Private Member Functions

void apply_config (const DynamicPrintConfig &config)
 
void apply_config_simplify3d (const std::string &filename)
 
void apply_config_superslicer (const std::string &filename)
 
void apply_config_kissslicer (const std::string &filename)
 
void process_gcode_line (const GCodeReader::GCodeLine &line, bool producers_enabled)
 
void process_tags (const std::string_view comment, bool producers_enabled)
 
bool process_producers_tags (const std::string_view comment)
 
bool process_prusaslicer_tags (const std::string_view comment)
 
bool process_cura_tags (const std::string_view comment)
 
bool process_simplify3d_tags (const std::string_view comment)
 
bool process_craftware_tags (const std::string_view comment)
 
bool process_ideamaker_tags (const std::string_view comment)
 
bool process_kissslicer_tags (const std::string_view comment)
 
bool process_bambustudio_tags (const std::string_view comment)
 
bool detect_producer (const std::string_view comment)
 
void process_G0 (const GCodeReader::GCodeLine &line)
 
void process_G1 (const GCodeReader::GCodeLine &line)
 
void process_G1 (const std::array< std::optional< double >, 4 > &axes={ std::nullopt, std::nullopt, std::nullopt, std::nullopt }, std::optional< double > feedrate=std::nullopt, std::optional< std::string > cmt=std::nullopt)
 
void process_G2_G3 (const GCodeReader::GCodeLine &line, bool clockwise)
 
void process_G10 (const GCodeReader::GCodeLine &line)
 
void process_G11 (const GCodeReader::GCodeLine &line)
 
void process_G20 (const GCodeReader::GCodeLine &line)
 
void process_G21 (const GCodeReader::GCodeLine &line)
 
void process_G22 (const GCodeReader::GCodeLine &line)
 
void process_G23 (const GCodeReader::GCodeLine &line)
 
void process_G28 (const GCodeReader::GCodeLine &line)
 
void process_G60 (const GCodeReader::GCodeLine &line)
 
void process_G61 (const GCodeReader::GCodeLine &line)
 
void process_G90 (const GCodeReader::GCodeLine &line)
 
void process_G91 (const GCodeReader::GCodeLine &line)
 
void process_G92 (const GCodeReader::GCodeLine &line)
 
void process_M1 (const GCodeReader::GCodeLine &line)
 
void process_M82 (const GCodeReader::GCodeLine &line)
 
void process_M83 (const GCodeReader::GCodeLine &line)
 
void process_M104 (const GCodeReader::GCodeLine &line)
 
void process_M106 (const GCodeReader::GCodeLine &line)
 
void process_M107 (const GCodeReader::GCodeLine &line)
 
void process_M108 (const GCodeReader::GCodeLine &line)
 
void process_M109 (const GCodeReader::GCodeLine &line)
 
void process_M132 (const GCodeReader::GCodeLine &line)
 
void process_M135 (const GCodeReader::GCodeLine &line)
 
void process_M201 (const GCodeReader::GCodeLine &line)
 
void process_M203 (const GCodeReader::GCodeLine &line)
 
void process_M204 (const GCodeReader::GCodeLine &line)
 
void process_M205 (const GCodeReader::GCodeLine &line)
 
void process_M220 (const GCodeReader::GCodeLine &line)
 
void process_M221 (const GCodeReader::GCodeLine &line)
 
void process_M401 (const GCodeReader::GCodeLine &line)
 
void process_M402 (const GCodeReader::GCodeLine &line)
 
void process_M566 (const GCodeReader::GCodeLine &line)
 
void process_M702 (const GCodeReader::GCodeLine &line)
 
void process_T (const GCodeReader::GCodeLine &line)
 
void process_T (const std::string_view command)
 
void post_process ()
 
void store_move_vertex (EMoveType type, bool internal_only=false)
 
void set_extrusion_role (GCodeExtrusionRole role)
 
float minimum_feedrate (PrintEstimatedStatistics::ETimeMode mode, float feedrate) const
 
float minimum_travel_feedrate (PrintEstimatedStatistics::ETimeMode mode, float feedrate) const
 
float get_axis_max_feedrate (PrintEstimatedStatistics::ETimeMode mode, Axis axis) const
 
float get_axis_max_acceleration (PrintEstimatedStatistics::ETimeMode mode, Axis axis) const
 
float get_axis_max_jerk (PrintEstimatedStatistics::ETimeMode mode, Axis axis) const
 
float get_retract_acceleration (PrintEstimatedStatistics::ETimeMode mode) const
 
void set_retract_acceleration (PrintEstimatedStatistics::ETimeMode mode, float value)
 
float get_acceleration (PrintEstimatedStatistics::ETimeMode mode) const
 
void set_acceleration (PrintEstimatedStatistics::ETimeMode mode, float value)
 
float get_travel_acceleration (PrintEstimatedStatistics::ETimeMode mode) const
 
void set_travel_acceleration (PrintEstimatedStatistics::ETimeMode mode, float value)
 
float get_filament_load_time (size_t extruder_id)
 
float get_filament_unload_time (size_t extruder_id)
 
void process_custom_gcode_time (CustomGCode::Type code)
 
void process_filaments (CustomGCode::Type code)
 
void simulate_st_synchronize (float additional_time=0.0f)
 
void update_estimated_times_stats ()
 
double extract_absolute_position_on_axis (Axis axis, const GCodeReader::GCodeLine &line, double area_filament_cross_section)
 

Private Attributes

GCodeReader m_parser
 
EUnits m_units
 
EPositioningType m_global_positioning_type
 
EPositioningType m_e_local_positioning_type
 
std::vector< Vec3fm_extruder_offsets
 
GCodeFlavor m_flavor
 
AxisCoords m_start_position
 
AxisCoords m_end_position
 
AxisCoords m_saved_position
 
AxisCoords m_origin
 
CachedPosition m_cached_position
 
bool m_wiping
 
unsigned int m_line_id
 
unsigned int m_last_line_id
 
float m_feedrate
 
FeedMultiply m_feed_multiply
 
float m_width
 
float m_height
 
float m_forced_width
 
float m_forced_height
 
float m_mm3_per_mm
 
float m_fan_speed
 
float m_z_offset
 
GCodeExtrusionRole m_extrusion_role
 
unsigned char m_extruder_id
 
ExtruderColors m_extruder_colors
 
ExtruderTemps m_extruder_temps
 
ExtruderTemps m_extruder_temps_config
 
ExtruderTemps m_extruder_temps_first_layer_config
 
bool m_is_XL_printer = false
 
float m_parking_position
 
float m_extra_loading_move
 
float m_extruded_last_z
 
float m_first_layer_height
 
unsigned int m_g1_line_id
 
unsigned int m_layer_id
 
CpColor m_cp_color
 
bool m_use_volumetric_e
 
SeamsDetector m_seams_detector
 
OptionsZCorrector m_options_z_corrector
 
size_t m_last_default_color_id
 
bool m_spiral_vase_active
 
float m_kissslicer_toolchange_time_correction
 
bool m_single_extruder_multi_material
 
EProducer m_producer
 
TimeProcessor m_time_processor
 
UsedFilaments m_used_filaments
 
Printm_print { nullptr }
 
GCodeProcessorResult m_result
 

Static Private Attributes

static const std::vector< std::string > Reserved_Tags
 
static const std::vector< std::pair< GCodeProcessor::EProducer, std::string > > Producers
 
static unsigned int s_result_id = 0
 

Detailed Description


Class Documentation

◆ Slic3r::GCodeProcessor::FeedrateProfile

struct Slic3r::GCodeProcessor::FeedrateProfile
Class Members
float cruise { 0.0f }
float entry { 0.0f }
float exit { 0.0f }

Member Typedef Documentation

◆ AxisCoords

using Slic3r::GCodeProcessor::AxisCoords = std::array<double, 4>
private

◆ ExtruderColors

using Slic3r::GCodeProcessor::ExtruderColors = std::vector<unsigned char>
private

◆ ExtruderTemps

using Slic3r::GCodeProcessor::ExtruderTemps = std::vector<float>
private

Member Enumeration Documentation

◆ EPositioningType

enum class Slic3r::GCodeProcessor::EPositioningType : unsigned char
strongprivate
Enumerator
Absolute 
Relative 

◆ EProducer

◆ ETags

enum class Slic3r::GCodeProcessor::ETags : unsigned char
strong
Enumerator
Role 
Wipe_Start 
Wipe_End 
Height 
Width 
Layer_Change 
Color_Change 
Pause_Print 
Custom_Code 
First_Line_M73_Placeholder 
Last_Line_M73_Placeholder 
Estimated_Printing_Time_Placeholder 

◆ EUnits

enum class Slic3r::GCodeProcessor::EUnits : unsigned char
strongprivate
Enumerator
Millimeters 
Inches 

Constructor & Destructor Documentation

◆ GCodeProcessor()

Slic3r::GCodeProcessor::GCodeProcessor ( )
545{
546 reset();
547 m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_main_mask = "M73 P%s R%s\n";
548 m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_stop_mask = "M73 C%s\n";
549 m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_main_mask = "M73 Q%s S%s\n";
550 m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_stop_mask = "M73 D%s\n";
551}
TimeProcessor m_time_processor
Definition GCodeProcessor.hpp:606
void reset()
Definition GCodeProcessor.cpp:942
GCodeProcessorResult m_result
Definition GCodeProcessor.hpp:611
OptionsZCorrector m_options_z_corrector
Definition GCodeProcessor.hpp:579
std::array< TimeMachine, static_cast< size_t >(PrintEstimatedStatistics::ETimeMode::Count)> machines
Definition GCodeProcessor.hpp:368

References m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machines, Slic3r::PrintEstimatedStatistics::Normal, reset(), and Slic3r::PrintEstimatedStatistics::Stealth.

+ Here is the call graph for this function:

Member Function Documentation

◆ apply_config() [1/2]

void Slic3r::GCodeProcessor::apply_config ( const DynamicPrintConfig config)
private
656{
657 m_parser.apply_config(config);
658
659 const ConfigOptionEnum<GCodeFlavor>* gcode_flavor = config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor");
660 if (gcode_flavor != nullptr)
661 m_flavor = gcode_flavor->value;
662
663 const ConfigOptionPoints* bed_shape = config.option<ConfigOptionPoints>("bed_shape");
664 if (bed_shape != nullptr)
665 m_result.bed_shape = bed_shape->values;
666
667 const ConfigOptionString* print_settings_id = config.option<ConfigOptionString>("print_settings_id");
668 if (print_settings_id != nullptr)
669 m_result.settings_ids.print = print_settings_id->value;
670
671 const ConfigOptionStrings* filament_settings_id = config.option<ConfigOptionStrings>("filament_settings_id");
672 if (filament_settings_id != nullptr)
673 m_result.settings_ids.filament = filament_settings_id->values;
674
675 const ConfigOptionString* printer_settings_id = config.option<ConfigOptionString>("printer_settings_id");
676 if (printer_settings_id != nullptr)
677 m_result.settings_ids.printer = printer_settings_id->value;
678
679 m_result.extruders_count = config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
680
681 const ConfigOptionFloats* filament_diameters = config.option<ConfigOptionFloats>("filament_diameter");
682 if (filament_diameters != nullptr) {
684 m_result.filament_diameters.resize(filament_diameters->values.size());
685 for (size_t i = 0; i < filament_diameters->values.size(); ++i) {
686 m_result.filament_diameters[i] = static_cast<float>(filament_diameters->values[i]);
687 }
688 }
689
691 for (size_t i = m_result.filament_diameters.size(); i < m_result.extruders_count; ++i) {
693 }
694 }
695
696 const ConfigOptionFloats* filament_densities = config.option<ConfigOptionFloats>("filament_density");
697 if (filament_densities != nullptr) {
699 m_result.filament_densities.resize(filament_densities->values.size());
700 for (size_t i = 0; i < filament_densities->values.size(); ++i) {
701 m_result.filament_densities[i] = static_cast<float>(filament_densities->values[i]);
702 }
703 }
704
706 for (size_t i = m_result.filament_densities.size(); i < m_result.extruders_count; ++i) {
708 }
709 }
710
711 const ConfigOptionFloats* filament_cost = config.option<ConfigOptionFloats>("filament_cost");
712 if (filament_cost != nullptr) {
713 m_result.filament_cost.clear();
714 m_result.filament_cost.resize(filament_cost->values.size());
715 for (size_t i = 0; i < filament_cost->values.size(); ++i) {
716 m_result.filament_cost[i] = static_cast<float>(filament_cost->values[i]);
717 }
718 }
719
721 for (size_t i = m_result.filament_cost.size(); i < m_result.extruders_count; ++i) {
723 }
724 }
725
726 const ConfigOptionPoints* extruder_offset = config.option<ConfigOptionPoints>("extruder_offset");
727 if (extruder_offset != nullptr) {
728 m_extruder_offsets.resize(extruder_offset->values.size());
729 for (size_t i = 0; i < extruder_offset->values.size(); ++i) {
730 Vec2f offset = extruder_offset->values[i].cast<float>();
731 m_extruder_offsets[i] = { offset(0), offset(1), 0.0f };
732 }
733 }
734
736 for (size_t i = m_extruder_offsets.size(); i < m_result.extruders_count; ++i) {
738 }
739 }
740
741 const ConfigOptionStrings* extruder_colour = config.option<ConfigOptionStrings>("extruder_colour");
742 if (extruder_colour != nullptr) {
743 // takes colors from config
744 m_result.extruder_colors = extruder_colour->values;
745 // try to replace missing values with filament colors
746 const ConfigOptionStrings* filament_colour = config.option<ConfigOptionStrings>("filament_colour");
747 if (filament_colour != nullptr && filament_colour->values.size() == m_result.extruder_colors.size()) {
748 for (size_t i = 0; i < m_result.extruder_colors.size(); ++i) {
749 if (m_result.extruder_colors[i].empty())
750 m_result.extruder_colors[i] = filament_colour->values[i];
751 }
752 }
753 }
754
756 for (size_t i = m_result.extruder_colors.size(); i < m_result.extruders_count; ++i) {
757 m_result.extruder_colors.emplace_back(std::string());
758 }
759 }
760
761 // replace missing values with default
762 for (size_t i = 0; i < m_result.extruder_colors.size(); ++i) {
763 if (m_result.extruder_colors[i].empty())
764 m_result.extruder_colors[i] = "#FF8000";
765 }
766
768 for (size_t i = 0; i < m_result.extruder_colors.size(); ++i) {
769 m_extruder_colors[i] = static_cast<unsigned char>(i);
770 }
771
773
774 const ConfigOptionFloats* filament_load_time = config.option<ConfigOptionFloats>("filament_load_time");
775 if (filament_load_time != nullptr) {
776 m_time_processor.filament_load_times.resize(filament_load_time->values.size());
777 for (size_t i = 0; i < filament_load_time->values.size(); ++i) {
778 m_time_processor.filament_load_times[i] = static_cast<float>(filament_load_time->values[i]);
779 }
780 }
781
782 const ConfigOptionFloats* filament_unload_time = config.option<ConfigOptionFloats>("filament_unload_time");
783 if (filament_unload_time != nullptr) {
784 m_time_processor.filament_unload_times.resize(filament_unload_time->values.size());
785 for (size_t i = 0; i < filament_unload_time->values.size(); ++i) {
786 m_time_processor.filament_unload_times[i] = static_cast<float>(filament_unload_time->values[i]);
787 }
788 }
789
790 // With MM setups like Prusa MMU2, the filaments may be expected to be parked at the beginning.
791 // Remember the parking position so the initial load is not included in filament estimate.
792 const ConfigOptionBool* single_extruder_multi_material = config.option<ConfigOptionBool>("single_extruder_multi_material");
793 const ConfigOptionBool* wipe_tower = config.option<ConfigOptionBool>("wipe_tower");
794 const ConfigOptionFloat* parking_pos_retraction = config.option<ConfigOptionFloat>("parking_pos_retraction");
795 const ConfigOptionFloat* extra_loading_move = config.option<ConfigOptionFloat>("extra_loading_move");
796
797 m_single_extruder_multi_material = single_extruder_multi_material != nullptr && single_extruder_multi_material->value;
798
799 if (m_single_extruder_multi_material && wipe_tower != nullptr && parking_pos_retraction != nullptr && extra_loading_move != nullptr) {
800 if (m_single_extruder_multi_material && m_result.extruders_count > 1 && wipe_tower->value) {
802 m_extra_loading_move = float(extra_loading_move->value);
803 }
804 }
805
806 bool use_machine_limits = false;
808 if (machine_limits_usage != nullptr)
809 use_machine_limits = machine_limits_usage->value != MachineLimitsUsage::Ignore;
810
811 if (use_machine_limits && (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfRepRapFirmware || m_flavor == gcfKlipper)) {
812 const ConfigOptionFloats* machine_max_acceleration_x = config.option<ConfigOptionFloats>("machine_max_acceleration_x");
813 if (machine_max_acceleration_x != nullptr)
814 m_time_processor.machine_limits.machine_max_acceleration_x.values = machine_max_acceleration_x->values;
815
816 const ConfigOptionFloats* machine_max_acceleration_y = config.option<ConfigOptionFloats>("machine_max_acceleration_y");
817 if (machine_max_acceleration_y != nullptr)
818 m_time_processor.machine_limits.machine_max_acceleration_y.values = machine_max_acceleration_y->values;
819
820 const ConfigOptionFloats* machine_max_acceleration_z = config.option<ConfigOptionFloats>("machine_max_acceleration_z");
821 if (machine_max_acceleration_z != nullptr)
822 m_time_processor.machine_limits.machine_max_acceleration_z.values = machine_max_acceleration_z->values;
823
824 const ConfigOptionFloats* machine_max_acceleration_e = config.option<ConfigOptionFloats>("machine_max_acceleration_e");
825 if (machine_max_acceleration_e != nullptr)
826 m_time_processor.machine_limits.machine_max_acceleration_e.values = machine_max_acceleration_e->values;
827
828 const ConfigOptionFloats* machine_max_feedrate_x = config.option<ConfigOptionFloats>("machine_max_feedrate_x");
829 if (machine_max_feedrate_x != nullptr)
830 m_time_processor.machine_limits.machine_max_feedrate_x.values = machine_max_feedrate_x->values;
831
832 const ConfigOptionFloats* machine_max_feedrate_y = config.option<ConfigOptionFloats>("machine_max_feedrate_y");
833 if (machine_max_feedrate_y != nullptr)
834 m_time_processor.machine_limits.machine_max_feedrate_y.values = machine_max_feedrate_y->values;
835
836 const ConfigOptionFloats* machine_max_feedrate_z = config.option<ConfigOptionFloats>("machine_max_feedrate_z");
837 if (machine_max_feedrate_z != nullptr)
838 m_time_processor.machine_limits.machine_max_feedrate_z.values = machine_max_feedrate_z->values;
839
840 const ConfigOptionFloats* machine_max_feedrate_e = config.option<ConfigOptionFloats>("machine_max_feedrate_e");
841 if (machine_max_feedrate_e != nullptr)
842 m_time_processor.machine_limits.machine_max_feedrate_e.values = machine_max_feedrate_e->values;
843
844 const ConfigOptionFloats* machine_max_jerk_x = config.option<ConfigOptionFloats>("machine_max_jerk_x");
845 if (machine_max_jerk_x != nullptr)
846 m_time_processor.machine_limits.machine_max_jerk_x.values = machine_max_jerk_x->values;
847
848 const ConfigOptionFloats* machine_max_jerk_y = config.option<ConfigOptionFloats>("machine_max_jerk_y");
849 if (machine_max_jerk_y != nullptr)
850 m_time_processor.machine_limits.machine_max_jerk_y.values = machine_max_jerk_y->values;
851
852 const ConfigOptionFloats* machine_max_jerk_z = config.option<ConfigOptionFloats>("machine_max_jerkz");
853 if (machine_max_jerk_z != nullptr)
854 m_time_processor.machine_limits.machine_max_jerk_z.values = machine_max_jerk_z->values;
855
856 const ConfigOptionFloats* machine_max_jerk_e = config.option<ConfigOptionFloats>("machine_max_jerk_e");
857 if (machine_max_jerk_e != nullptr)
858 m_time_processor.machine_limits.machine_max_jerk_e.values = machine_max_jerk_e->values;
859
860 const ConfigOptionFloats* machine_max_acceleration_extruding = config.option<ConfigOptionFloats>("machine_max_acceleration_extruding");
861 if (machine_max_acceleration_extruding != nullptr)
862 m_time_processor.machine_limits.machine_max_acceleration_extruding.values = machine_max_acceleration_extruding->values;
863
864 const ConfigOptionFloats* machine_max_acceleration_retracting = config.option<ConfigOptionFloats>("machine_max_acceleration_retracting");
866 m_time_processor.machine_limits.machine_max_acceleration_retracting.values = machine_max_acceleration_retracting->values;
867
868
869 // Legacy Marlin and Klipper don't have separate travel acceleration, they use the 'extruding' value instead.
870 const ConfigOptionFloats* machine_max_acceleration_travel = config.option<ConfigOptionFloats>((m_flavor == gcfMarlinLegacy || m_flavor == gcfKlipper)
871 ? "machine_max_acceleration_extruding"
872 : "machine_max_acceleration_travel");
873 if (machine_max_acceleration_travel != nullptr)
874 m_time_processor.machine_limits.machine_max_acceleration_travel.values = machine_max_acceleration_travel->values;
875
876
877 const ConfigOptionFloats* machine_min_extruding_rate = config.option<ConfigOptionFloats>("machine_min_extruding_rate");
878 if (machine_min_extruding_rate != nullptr) {
879 m_time_processor.machine_limits.machine_min_extruding_rate.values = machine_min_extruding_rate->values;
881 // RRF does not support setting min feedrates. Set zero.
882 m_time_processor.machine_limits.machine_min_extruding_rate.values.assign(m_time_processor.machine_limits.machine_min_extruding_rate.size(), 0.);
883 }
884 }
885
886 const ConfigOptionFloats* machine_min_travel_rate = config.option<ConfigOptionFloats>("machine_min_travel_rate");
887 if (machine_min_travel_rate != nullptr) {
888 m_time_processor.machine_limits.machine_min_travel_rate.values = machine_min_travel_rate->values;
890 // RRF does not support setting min feedrates. Set zero.
891 m_time_processor.machine_limits.machine_min_travel_rate.values.assign(m_time_processor.machine_limits.machine_min_travel_rate.size(), 0.);
892 }
893 }
894 }
895
896 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
897 float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i);
898 m_time_processor.machines[i].max_acceleration = max_acceleration;
899 m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION;
900 float max_retract_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i);
901 m_time_processor.machines[i].max_retract_acceleration = max_retract_acceleration;
902 m_time_processor.machines[i].retract_acceleration = (max_retract_acceleration > 0.0f) ? max_retract_acceleration : DEFAULT_RETRACT_ACCELERATION;
903 float max_travel_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_travel, i);
904 m_time_processor.machines[i].max_travel_acceleration = max_travel_acceleration;
905 m_time_processor.machines[i].travel_acceleration = (max_travel_acceleration > 0.0f) ? max_travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
906 }
907
908 if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) { // No Klipper here, it does not support silent mode.
909 const ConfigOptionBool* silent_mode = config.option<ConfigOptionBool>("silent_mode");
910 if (silent_mode != nullptr) {
911 if (silent_mode->value && m_time_processor.machine_limits.machine_max_acceleration_x.values.size() > 1)
913 }
914 }
915
916 const ConfigOptionBool* use_volumetric_e = config.option<ConfigOptionBool>("use_volumetric_e");
917 if (use_volumetric_e != nullptr)
918 m_use_volumetric_e = use_volumetric_e->value;
919
920 const ConfigOptionFloatOrPercent* first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height");
921 if (first_layer_height != nullptr)
922 m_first_layer_height = std::abs(first_layer_height->value);
923
924 const ConfigOptionFloat* max_print_height = config.option<ConfigOptionFloat>("max_print_height");
925 if (max_print_height != nullptr)
927
928 const ConfigOptionBool* spiral_vase = config.option<ConfigOptionBool>("spiral_vase");
929 if (spiral_vase != nullptr)
930 m_spiral_vase_active = spiral_vase->value;
931
932 const ConfigOptionFloat* z_offset = config.option<ConfigOptionFloat>("z_offset");
933 if (z_offset != nullptr)
934 m_z_offset = z_offset->value;
935}
static const float DEFAULT_TRAVEL_ACCELERATION
Definition GCodeProcessor.cpp:36
static const float DEFAULT_FILAMENT_DIAMETER
Definition GCodeProcessor.cpp:39
static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET
Definition GCodeProcessor.cpp:42
static const float DEFAULT_ACCELERATION
Definition GCodeProcessor.cpp:34
static const float DEFAULT_FILAMENT_COST
Definition GCodeProcessor.cpp:41
static const float DEFAULT_FILAMENT_DENSITY
Definition GCodeProcessor.cpp:40
static const float DEFAULT_RETRACT_ACCELERATION
Definition GCodeProcessor.cpp:35
bool m_single_extruder_multi_material
Definition GCodeProcessor.hpp:586
ExtruderColors m_extruder_colors
Definition GCodeProcessor.hpp:565
float m_z_offset
Definition GCodeProcessor.hpp:562
GCodeReader m_parser
Definition GCodeProcessor.hpp:527
float m_first_layer_height
Definition GCodeProcessor.hpp:573
ExtruderTemps m_extruder_temps
Definition GCodeProcessor.hpp:566
std::vector< Vec3f > m_extruder_offsets
Definition GCodeProcessor.hpp:532
GCodeFlavor m_flavor
Definition GCodeProcessor.hpp:533
float m_parking_position
Definition GCodeProcessor.hpp:570
void enable_stealth_time_estimator(bool enabled)
Definition GCodeProcessor.cpp:937
float m_extra_loading_move
Definition GCodeProcessor.hpp:571
bool m_use_volumetric_e
Definition GCodeProcessor.hpp:577
bool m_spiral_vase_active
Definition GCodeProcessor.hpp:581
void apply_config(const GCodeConfig &config)
Definition GCodeReader.cpp:25
@ gcfMarlinFirmware
Definition PrintConfig.hpp:35
@ gcfKlipper
Definition PrintConfig.hpp:35
@ gcfRepRapFirmware
Definition PrintConfig.hpp:35
@ gcfMarlinLegacy
Definition PrintConfig.hpp:35
ConfigOptionFloat
Definition PrintConfig.hpp:570
machine_max_feedrate_y((ConfigOptionFloats, machine_max_feedrate_z))((ConfigOptionFloats
machine_max_acceleration_e((ConfigOptionFloats, machine_max_feedrate_x))((ConfigOptionFloats
machine_max_jerk_x((ConfigOptionFloats, machine_max_jerk_y))((ConfigOptionFloats
filament_cost((ConfigOptionFloats, filament_spool_weight))((ConfigOptionFloats
ConfigOptionBool
Definition PrintConfig.hpp:665
machine_min_travel_rate((ConfigOptionFloats, machine_min_extruding_rate))) PRINT_CONFIG_CLASS_DEFINE(GCodeConfig
max_print_height((ConfigOptionFloat, display_width))((ConfigOptionFloat
machine_max_acceleration_retracting((ConfigOptionFloats, machine_max_acceleration_travel))((ConfigOptionFloats
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:416
machine_limits_usage((ConfigOptionFloats, machine_max_acceleration_x))((ConfigOptionFloats
gcode_flavor((ConfigOptionBool, gcode_label_objects))((ConfigOptionStrings
parking_pos_retraction((ConfigOptionBool, remaining_times))((ConfigOptionBool
silent_mode((ConfigOptionFloat, extra_loading_move))((ConfigOptionString
Eigen::Matrix< float, 2, 1, Eigen::DontAlign > Vec2f
Definition Point.hpp:48
machine_max_acceleration_y((ConfigOptionFloats, machine_max_acceleration_z))((ConfigOptionFloats
ConfigOptionFloatsTempl< false > ConfigOptionFloats
Definition Config.hpp:716
ConfigOptionEnum< MachineLimitsUsage >
Definition PrintConfig.hpp:634
machine_max_feedrate_e((ConfigOptionFloats, machine_max_acceleration_extruding))((ConfigOptionFloats
static float get_option_value(const ConfigOptionFloats &option, size_t id)
Definition GCodeProcessor.cpp:78
machine_max_jerk_z((ConfigOptionFloats, machine_max_jerk_e))((ConfigOptionFloats
std::vector< float > filament_load_times
Definition GCodeProcessor.hpp:366
MachineEnvelopeConfig machine_limits
Definition GCodeProcessor.hpp:364
std::vector< float > filament_unload_times
Definition GCodeProcessor.hpp:367
std::string print
Definition GCodeProcessor.hpp:105
std::string printer
Definition GCodeProcessor.hpp:107
std::vector< std::string > filament
Definition GCodeProcessor.hpp:106
std::vector< float > filament_densities
Definition GCodeProcessor.hpp:149
float max_print_height
Definition GCodeProcessor.hpp:143
SettingsIds settings_ids
Definition GCodeProcessor.hpp:144
std::vector< float > filament_cost
Definition GCodeProcessor.hpp:150
std::vector< std::string > extruder_colors
Definition GCodeProcessor.hpp:147
size_t extruders_count
Definition GCodeProcessor.hpp:145
std::vector< float > filament_diameters
Definition GCodeProcessor.hpp:148
Pointfs bed_shape
Definition GCodeProcessor.hpp:142

References Slic3r::GCodeReader::apply_config(), Slic3r::GCodeProcessorResult::bed_shape, Slic3r::PrintEstimatedStatistics::Count, DEFAULT_ACCELERATION, DEFAULT_EXTRUDER_OFFSET, DEFAULT_FILAMENT_COST, DEFAULT_FILAMENT_DENSITY, DEFAULT_FILAMENT_DIAMETER, DEFAULT_RETRACT_ACCELERATION, DEFAULT_TRAVEL_ACCELERATION, enable_stealth_time_estimator(), Slic3r::GCodeProcessorResult::extruder_colors, Slic3r::GCodeProcessorResult::extruders_count, Slic3r::GCodeProcessorResult::SettingsIds::filament, Slic3r::GCodeProcessorResult::filament_cost, Slic3r::filament_cost(), Slic3r::GCodeProcessorResult::filament_densities, Slic3r::GCodeProcessorResult::filament_diameters, Slic3r::GCodeProcessor::TimeProcessor::filament_load_times, Slic3r::GCodeProcessor::TimeProcessor::filament_unload_times, Slic3r::gcfKlipper, Slic3r::gcfMarlinFirmware, Slic3r::gcfMarlinLegacy, Slic3r::gcfRepRapFirmware, Slic3r::gcode_flavor(), Slic3r::get_option_value(), Slic3r::Ignore, m_extra_loading_move, m_extruder_colors, m_extruder_offsets, m_extruder_temps, m_first_layer_height, m_flavor, m_parking_position, m_parser, m_result, m_single_extruder_multi_material, m_spiral_vase_active, m_time_processor, m_use_volumetric_e, m_z_offset, Slic3r::GCodeProcessor::TimeProcessor::machine_limits, Slic3r::machine_limits_usage(), Slic3r::machine_max_acceleration_e(), Slic3r::machine_max_acceleration_retracting(), Slic3r::machine_max_acceleration_y(), Slic3r::machine_max_feedrate_e(), Slic3r::machine_max_feedrate_y(), Slic3r::machine_max_jerk_x(), Slic3r::machine_max_jerk_z(), Slic3r::machine_min_travel_rate(), Slic3r::GCodeProcessor::TimeProcessor::machines, Slic3r::GCodeProcessorResult::max_print_height, Slic3r::max_print_height(), Slic3r::offset(), Slic3r::ConfigBase::option(), Slic3r::parking_pos_retraction(), Slic3r::GCodeProcessorResult::SettingsIds::print, Slic3r::GCodeProcessorResult::SettingsIds::printer, Slic3r::GCodeProcessorResult::settings_ids, Slic3r::silent_mode(), Slic3r::ConfigOptionVector< T >::size(), Slic3r::ConfigOptionSingle< T >::value, and Slic3r::ConfigOptionVector< T >::values.

+ Here is the call graph for this function:

◆ apply_config() [2/2]

void Slic3r::GCodeProcessor::apply_config ( const PrintConfig &  config)
554{
555 m_parser.apply_config(config);
556
558 m_flavor = config.gcode_flavor;
559
561
562 size_t extruders_count = config.nozzle_diameter.values.size();
563 m_result.extruders_count = extruders_count;
564
565 m_extruder_offsets.resize(extruders_count);
566 m_extruder_colors.resize(extruders_count);
567 m_result.filament_diameters.resize(extruders_count);
568 m_result.filament_densities.resize(extruders_count);
569 m_result.filament_cost.resize(extruders_count);
570 m_extruder_temps.resize(extruders_count);
571 m_extruder_temps_config.resize(extruders_count);
572 m_extruder_temps_first_layer_config.resize(extruders_count);
574
575 for (size_t i = 0; i < extruders_count; ++ i) {
576 m_extruder_offsets[i] = to_3d(config.extruder_offset.get_at(i).cast<float>().eval(), 0.f);
577 m_extruder_colors[i] = static_cast<unsigned char>(i);
578 m_extruder_temps_config[i] = static_cast<int>(config.temperature.get_at(i));
579 m_extruder_temps_first_layer_config[i] = static_cast<int>(config.first_layer_temperature.get_at(i));
580 m_result.filament_diameters[i] = static_cast<float>(config.filament_diameter.get_at(i));
581 m_result.filament_densities[i] = static_cast<float>(config.filament_density.get_at(i));
582 m_result.filament_cost[i] = static_cast<float>(config.filament_cost.get_at(i));
583 }
584
586 && config.machine_limits_usage.value != MachineLimitsUsage::Ignore) {
587 m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config);
589 // Legacy Marlin and Klipper don't have separate travel acceleration, they use the 'extruding' value instead.
590 m_time_processor.machine_limits.machine_max_acceleration_travel = m_time_processor.machine_limits.machine_max_acceleration_extruding;
591 }
593 // RRF does not support setting min feedrates. Set them to zero.
594 m_time_processor.machine_limits.machine_min_travel_rate.values.assign(m_time_processor.machine_limits.machine_min_travel_rate.size(), 0.);
595 m_time_processor.machine_limits.machine_min_extruding_rate.values.assign(m_time_processor.machine_limits.machine_min_extruding_rate.size(), 0.);
596 }
597 }
598
599 // Filament load / unload times are not specific to a firmware flavor. Let anybody use it if they find it useful.
600 // As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they
601 // are considered to be active for the single extruder multi-material printers only.
602 m_time_processor.filament_load_times.resize(config.filament_load_time.values.size());
603 for (size_t i = 0; i < config.filament_load_time.values.size(); ++i) {
604 m_time_processor.filament_load_times[i] = static_cast<float>(config.filament_load_time.values[i]);
605 }
606 m_time_processor.filament_unload_times.resize(config.filament_unload_time.values.size());
607 for (size_t i = 0; i < config.filament_unload_time.values.size(); ++i) {
608 m_time_processor.filament_unload_times[i] = static_cast<float>(config.filament_unload_time.values[i]);
609 }
610
611 m_single_extruder_multi_material = config.single_extruder_multi_material;
612
613 // With MM setups like Prusa MMU2, the filaments may be expected to be parked at the beginning.
614 // Remember the parking position so the initial load is not included in filament estimate.
615 if (m_single_extruder_multi_material && extruders_count > 1 && config.wipe_tower) {
616 m_parking_position = float(config.parking_pos_retraction.value);
617 m_extra_loading_move = float(config.extra_loading_move);
618 }
619
620for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
621 float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i);
622 m_time_processor.machines[i].max_acceleration = max_acceleration;
623 m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION;
624 float max_retract_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i);
625 m_time_processor.machines[i].max_retract_acceleration = max_retract_acceleration;
626 m_time_processor.machines[i].retract_acceleration = (max_retract_acceleration > 0.0f) ? max_retract_acceleration : DEFAULT_RETRACT_ACCELERATION;
627
628 float max_travel_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_travel, i);
629 if ( ! GCodeWriter::supports_separate_travel_acceleration(config.gcode_flavor.value) || config.machine_limits_usage.value != MachineLimitsUsage::EmitToGCode) {
630 // Only clamp travel acceleration when it is accessible in machine limits.
631 max_travel_acceleration = 0;
632 }
633 m_time_processor.machines[i].max_travel_acceleration = max_travel_acceleration;
634 m_time_processor.machines[i].travel_acceleration = (max_travel_acceleration > 0.0f) ? max_travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
635 }
636
637 m_time_processor.export_remaining_time_enabled = config.remaining_times.value;
638 m_use_volumetric_e = config.use_volumetric_e;
639
640 const ConfigOptionFloatOrPercent* first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height");
641 if (first_layer_height != nullptr)
642 m_first_layer_height = std::abs(first_layer_height->value);
643
644 m_result.max_print_height = config.max_print_height;
645
646 const ConfigOptionBool* spiral_vase = config.option<ConfigOptionBool>("spiral_vase");
647 if (spiral_vase != nullptr)
648 m_spiral_vase_active = spiral_vase->value;
649
650 const ConfigOptionFloat* z_offset = config.option<ConfigOptionFloat>("z_offset");
651 if (z_offset != nullptr)
652 m_z_offset = z_offset->value;
653}
EProducer m_producer
Definition GCodeProcessor.hpp:604
ExtruderTemps m_extruder_temps_config
Definition GCodeProcessor.hpp:567
bool m_is_XL_printer
Definition GCodeProcessor.hpp:569
ExtruderTemps m_extruder_temps_first_layer_config
Definition GCodeProcessor.hpp:568
static bool supports_separate_travel_acceleration(GCodeFlavor flavor)
Definition GCodeWriter.cpp:19
Eigen::Matrix< typename Derived::Scalar, 3, 1, Eigen::DontAlign > to_3d(const Eigen::MatrixBase< Derived > &pt, const typename Derived::Scalar z)
Definition Point.hpp:127
static bool is_XL_printer(const std::string &printer_notes)
Definition PrintConfig.cpp:4985
bool export_remaining_time_enabled
Definition GCodeProcessor.hpp:361
bool backtrace_enabled
Definition GCodeProcessor.hpp:146

References Slic3r::GCodeReader::apply_config(), Slic3r::GCodeProcessorResult::backtrace_enabled, Slic3r::PrintEstimatedStatistics::Count, DEFAULT_ACCELERATION, DEFAULT_RETRACT_ACCELERATION, DEFAULT_TRAVEL_ACCELERATION, Slic3r::EmitToGCode, Slic3r::GCodeProcessor::TimeProcessor::export_remaining_time_enabled, Slic3r::GCodeProcessorResult::extruders_count, Slic3r::GCodeProcessorResult::filament_cost, Slic3r::GCodeProcessorResult::filament_densities, Slic3r::GCodeProcessorResult::filament_diameters, Slic3r::GCodeProcessor::TimeProcessor::filament_load_times, Slic3r::GCodeProcessor::TimeProcessor::filament_unload_times, Slic3r::gcfKlipper, Slic3r::gcfMarlinFirmware, Slic3r::gcfMarlinLegacy, Slic3r::gcfRepRapFirmware, Slic3r::get_option_value(), Slic3r::Ignore, Slic3r::is_XL_printer(), m_extra_loading_move, m_extruder_colors, m_extruder_offsets, m_extruder_temps, m_extruder_temps_config, m_extruder_temps_first_layer_config, m_first_layer_height, m_flavor, m_is_XL_printer, m_parking_position, m_parser, m_producer, m_result, m_single_extruder_multi_material, m_spiral_vase_active, m_time_processor, m_use_volumetric_e, m_z_offset, Slic3r::GCodeProcessor::TimeProcessor::machine_limits, Slic3r::GCodeProcessor::TimeProcessor::machines, Slic3r::GCodeProcessorResult::max_print_height, PrusaSlicer, Slic3r::GCodeWriter::supports_separate_travel_acceleration(), Slic3r::to_3d(), and Slic3r::ConfigOptionSingle< T >::value.

Referenced by apply_config_superslicer(), Slic3r::DoExport::init_gcode_processor(), and process_file().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply_config_kissslicer()

void Slic3r::GCodeProcessor::apply_config_kissslicer ( const std::string &  filename)
private
1246{
1247 size_t found_counter = 0;
1248 m_parser.parse_file_raw(filename, [this, &found_counter](GCodeReader& reader, const char* begin, const char* end) {
1249 auto detect_flavor = [this](const std::string_view comment) {
1250 static const std::string search_str = "firmware_type";
1251 const size_t pos = comment.find(search_str);
1252 if (pos != comment.npos) {
1253 std::vector<std::string> elements;
1254 boost::split(elements, comment, boost::is_any_of("="));
1255 if (elements.size() == 2) {
1256 try
1257 {
1258 switch (std::stoi(elements[1]))
1259 {
1260 default: { break; }
1261 case 1:
1262 case 2:
1263 case 3: { m_flavor = gcfMarlinLegacy; break; }
1264 }
1265 return true;
1266 }
1267 catch (...)
1268 {
1269 // invalid data, do nothing
1270 }
1271 }
1272 }
1273 return false;
1274 };
1275
1276 auto detect_printer = [this](const std::string_view comment) {
1277 static const std::string search_str = "printer_name";
1278 const size_t pos = comment.find(search_str);
1279 if (pos != comment.npos) {
1280 std::vector<std::string> elements;
1281 boost::split(elements, comment, boost::is_any_of("="));
1282 if (elements.size() == 2) {
1283 elements[1] = boost::to_upper_copy(elements[1]);
1284 if (boost::contains(elements[1], "MK2.5") || boost::contains(elements[1], "MK3"))
1286 else if (boost::contains(elements[1], "MK2"))
1288 }
1289 return true;
1290 }
1291
1292 return false;
1293 };
1294
1295 begin = skip_whitespaces(begin, end);
1296 if (begin != end) {
1297 if (*begin == ';') {
1298 // Comment.
1299 begin = skip_whitespaces(++begin, end);
1300 end = remove_eols(begin, end);
1301 if (begin != end) {
1302 const std::string_view comment(begin, end - begin);
1303 if (detect_flavor(comment) || detect_printer(comment))
1304 ++found_counter;
1305 }
1306
1307 // we got the data,
1308 // force early exit to avoid parsing the entire file
1309 if (found_counter == 2)
1311 }
1312 else if (*begin == 'M' || *begin == 'G')
1313 // the header has been fully parsed, quit search
1315 }
1316 }
1317 );
1318 m_parser.reset();
1319}
float m_kissslicer_toolchange_time_correction
Definition GCodeProcessor.hpp:582
bool parse_file_raw(const std::string &file, raw_line_callback_t callback)
Definition GCodeReader.cpp:204
void quit_parsing()
Definition GCodeReader.hpp:139
void reset()
Definition GCodeReader.hpp:96
#define comment
Definition lexer.c:1004
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:14
static const char * skip_whitespaces(const char *begin, const char *end)
Definition GCodeProcessor.cpp:1013
static const char * remove_eols(const char *begin, const char *end)
Definition GCodeProcessor.cpp:1018
S::iterator begin(S &sh, const PathTag &)
Definition geometry_traits.hpp:614
S::iterator end(S &sh, const PathTag &)
Definition geometry_traits.hpp:620

References comment, Slic3r::gcfMarlinLegacy, m_flavor, m_kissslicer_toolchange_time_correction, m_parser, Slic3r::GCodeReader::parse_file_raw(), Slic3r::GCodeReader::quit_parsing(), Slic3r::remove_eols(), Slic3r::GCodeReader::reset(), and Slic3r::skip_whitespaces().

Referenced by process_file().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply_config_simplify3d()

void Slic3r::GCodeProcessor::apply_config_simplify3d ( const std::string &  filename)
private
1329{
1330 struct BedSize
1331 {
1332 double x{ 0.0 };
1333 double y{ 0.0 };
1334
1335 bool is_defined() const { return x > 0.0 && y > 0.0; }
1336 };
1337
1338 BedSize bed_size;
1339 bool producer_detected = false;
1340
1341 m_parser.parse_file_raw(filename, [this, &bed_size, &producer_detected](GCodeReader& reader, const char* begin, const char* end) {
1342
1343 auto extract_double = [](const std::string_view cmt, const std::string& key, double& out) {
1344 size_t pos = cmt.find(key);
1345 if (pos != cmt.npos) {
1346 pos = cmt.find(',', pos);
1347 if (pos != cmt.npos) {
1348 out = string_to_double_decimal_point(cmt.substr(pos+1));
1349 return true;
1350 }
1351 }
1352 return false;
1353 };
1354
1355 auto extract_floats = [](const std::string_view cmt, const std::string& key, std::vector<float>& out) {
1356 size_t pos = cmt.find(key);
1357 if (pos != cmt.npos) {
1358 pos = cmt.find(',', pos);
1359 if (pos != cmt.npos) {
1360 const std::string_view data_str = cmt.substr(pos + 1);
1361 std::vector<std::string> values_str;
1362 boost::split(values_str, data_str, boost::is_any_of("|,"), boost::token_compress_on);
1363 for (const std::string& s : values_str) {
1364 out.emplace_back(static_cast<float>(string_to_double_decimal_point(s)));
1365 }
1366 return true;
1367 }
1368 }
1369 return false;
1370 };
1371
1372 begin = skip_whitespaces(begin, end);
1373 end = remove_eols(begin, end);
1374 if (begin != end) {
1375 if (*begin == ';') {
1376 // Comment.
1377 begin = skip_whitespaces(++ begin, end);
1378 if (begin != end) {
1379 std::string_view comment(begin, end - begin);
1380 if (producer_detected) {
1381 if (bed_size.x == 0.0 && comment.find("strokeXoverride") != comment.npos)
1382 extract_double(comment, "strokeXoverride", bed_size.x);
1383 else if (bed_size.y == 0.0 && comment.find("strokeYoverride") != comment.npos)
1384 extract_double(comment, "strokeYoverride", bed_size.y);
1385 else if (comment.find("filamentDiameters") != comment.npos) {
1387 extract_floats(comment, "filamentDiameters", m_result.filament_diameters);
1388 } else if (comment.find("filamentDensities") != comment.npos) {
1390 extract_floats(comment, "filamentDensities", m_result.filament_densities);
1391 }
1392 else if (comment.find("filamentPricesPerKg") != comment.npos) {
1393 m_result.filament_cost.clear();
1394 extract_floats(comment, "filamentPricesPerKg", m_result.filament_cost);
1395 } else if (comment.find("extruderDiameter") != comment.npos) {
1396 std::vector<float> extruder_diameters;
1397 extract_floats(comment, "extruderDiameter", extruder_diameters);
1398 m_result.extruders_count = extruder_diameters.size();
1399 }
1400 } else if (boost::starts_with(comment, "G-Code generated by Simplify3D(R)"))
1401 producer_detected = true;
1402 }
1403 } else {
1404 // Some non-empty G-code line detected, stop parsing config comments.
1405 reader.quit_parsing();
1406 }
1407 }
1408 });
1409
1410 if (m_result.extruders_count == 0)
1411 m_result.extruders_count = std::max<size_t>(1, std::min(m_result.filament_diameters.size(),
1412 std::min(m_result.filament_densities.size(), m_result.filament_cost.size())));
1413
1414 if (bed_size.is_defined()) {
1416 { 0.0, 0.0 },
1417 { bed_size.x, 0.0 },
1418 { bed_size.x, bed_size.y },
1419 { 0.0, bed_size.y }
1420 };
1421 }
1422}
const Scalar & y
Definition MathFunctions.h:552
double string_to_double_decimal_point(const std::string_view str, size_t *pos)
Definition LocalesUtils.cpp:64
TCoord< P > x(const P &p)
Definition geometry_traits.hpp:297

References Slic3r::GCodeProcessorResult::bed_shape, comment, Slic3r::GCodeProcessorResult::extruders_count, Slic3r::GCodeProcessorResult::filament_cost, Slic3r::GCodeProcessorResult::filament_densities, Slic3r::GCodeProcessorResult::filament_diameters, m_parser, m_result, Slic3r::GCodeReader::parse_file_raw(), Slic3r::GCodeReader::quit_parsing(), Slic3r::remove_eols(), Slic3r::skip_whitespaces(), and Slic3r::string_to_double_decimal_point().

Referenced by process_file().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply_config_superslicer()

void Slic3r::GCodeProcessor::apply_config_superslicer ( const std::string &  filename)
private
1238{
1239 DynamicPrintConfig config;
1240 config.apply(FullPrintConfig::defaults());
1242 apply_config(config);
1243}
void apply_config(const PrintConfig &config)
Definition GCodeProcessor.cpp:553
@ EnableSilent
Definition Config.hpp:223
ConfigSubstitutions load_from_superslicer_gcode_file(const std::string &filename, DynamicPrintConfig &config, ForwardCompatibilitySubstitutionRule compatibility_rule)
Definition GCodeProcessor.cpp:1212

References Slic3r::ConfigBase::apply(), apply_config(), Slic3r::EnableSilent, and Slic3r::load_from_superslicer_gcode_file().

Referenced by process_file().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ contains_reserved_tag()

bool Slic3r::GCodeProcessor::contains_reserved_tag ( const std::string &  gcode,
std::string &  found_tag 
)
static
492{
493 bool ret = false;
494
495 GCodeReader parser;
496 parser.parse_buffer(gcode, [&ret, &found_tag](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
497 std::string comment = line.raw();
498 if (comment.length() > 2 && comment.front() == ';') {
499 comment = comment.substr(1);
500 for (const std::string& s : Reserved_Tags) {
501 if (boost::starts_with(comment, s)) {
502 ret = true;
503 found_tag = comment;
504 parser.quit_parsing();
505 return;
506 }
507 }
508 }
509 });
510
511 return ret;
512}

References comment, Slic3r::GCodeReader::parse_buffer(), and Slic3r::GCodeReader::GCodeLine::raw().

+ Here is the call graph for this function:

◆ contains_reserved_tags()

bool Slic3r::GCodeProcessor::contains_reserved_tags ( const std::string &  gcode,
unsigned int  max_count,
std::vector< std::string > &  found_tag 
)
static
515{
516 max_count = std::max(max_count, 1U);
517
518 bool ret = false;
519
520 CNumericLocalesSetter locales_setter;
521
522 GCodeReader parser;
523 parser.parse_buffer(gcode, [&ret, &found_tag, max_count](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
524 std::string comment = line.raw();
525 if (comment.length() > 2 && comment.front() == ';') {
526 comment = comment.substr(1);
527 for (const std::string& s : Reserved_Tags) {
528 if (boost::starts_with(comment, s)) {
529 ret = true;
530 found_tag.push_back(comment);
531 if (found_tag.size() == max_count) {
532 parser.quit_parsing();
533 return;
534 }
535 }
536 }
537 }
538 });
539
540 return ret;
541}

References comment, Slic3r::GCodeReader::parse_buffer(), and Slic3r::GCodeReader::GCodeLine::raw().

Referenced by Slic3r::GUI::Tab::validate_custom_gcode().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ detect_producer()

bool Slic3r::GCodeProcessor::detect_producer ( const std::string_view  comment)
private
2340{
2341 for (const auto& [id, search_string] : Producers) {
2342 const size_t pos = comment.find(search_string);
2343 if (pos != comment.npos) {
2344 m_producer = id;
2345 BOOST_LOG_TRIVIAL(info) << "Detected gcode producer: " << search_string;
2346 return true;
2347 }
2348 }
2349 return false;
2350}
static const std::vector< std::pair< GCodeProcessor::EProducer, std::string > > Producers
Definition GCodeProcessor.hpp:603

References comment, m_producer, and Producers.

Referenced by process_file().

+ Here is the caller graph for this function:

◆ enable_machine_envelope_processing()

void Slic3r::GCodeProcessor::enable_machine_envelope_processing ( bool  enabled)
inline

◆ enable_stealth_time_estimator()

void Slic3r::GCodeProcessor::enable_stealth_time_estimator ( bool  enabled)
938{
939 m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled = enabled;
940}

References m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machines, and Slic3r::PrintEstimatedStatistics::Stealth.

Referenced by apply_config(), and Slic3r::DoExport::init_gcode_processor().

+ Here is the caller graph for this function:

◆ extract_absolute_position_on_axis()

double Slic3r::GCodeProcessor::extract_absolute_position_on_axis ( Axis  axis,
const GCodeReader::GCodeLine line,
double  area_filament_cross_section 
)
private
4269{
4270 if (line.has(Slic3r::Axis(axis))) {
4272 if (axis == E)
4274
4275 const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0;
4276 double ret = line.value(Slic3r::Axis(axis)) * lengthsScaleFactor;
4277 if (axis == E && m_use_volumetric_e)
4278 ret /= area_filament_cross_section;
4279 return is_relative ? m_start_position[axis] + ret : m_origin[axis] + ret;
4280 }
4281 else
4282 return m_start_position[axis];
4283}
static const float INCHES_TO_MM
Definition GCodeProcessor.cpp:32
AxisCoords m_start_position
Definition GCodeProcessor.hpp:535
AxisCoords m_origin
Definition GCodeProcessor.hpp:538
EUnits m_units
Definition GCodeProcessor.hpp:529
EPositioningType m_global_positioning_type
Definition GCodeProcessor.hpp:530
EPositioningType m_e_local_positioning_type
Definition GCodeProcessor.hpp:531
Axis
Definition libslic3r.h:97
@ E
Definition libslic3r.h:101

References Slic3r::E, Slic3r::GCodeReader::GCodeLine::has(), Inches, INCHES_TO_MM, m_e_local_positioning_type, m_global_positioning_type, m_origin, m_start_position, m_units, m_use_volumetric_e, Relative, and Slic3r::GCodeReader::GCodeLine::value().

Referenced by process_G1(), and process_G2_G3().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ extract_result()

GCodeProcessorResult && Slic3r::GCodeProcessor::extract_result ( )
inline
634{ return std::move(m_result); }

References m_result.

Referenced by Slic3r::GCode::do_export(), and Slic3r::GUI::Plater::load_gcode().

+ Here is the caller graph for this function:

◆ finalize()

void Slic3r::GCodeProcessor::finalize ( bool  post_process)
1115{
1116 // update width/height of wipe moves
1117 for (GCodeProcessorResult::MoveVertex& move : m_result.moves) {
1118 if (move.type == EMoveType::Wipe) {
1119 move.width = Wipe_Width;
1120 move.height = Wipe_Height;
1121 }
1122 }
1123
1124 // process the time blocks
1125 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
1126 TimeMachine& machine = m_time_processor.machines[i];
1127 TimeMachine::CustomGCodeTime& gcode_time = machine.gcode_time;
1128 machine.calculate_time();
1129 if (gcode_time.needed && gcode_time.cache != 0.0f)
1130 gcode_time.times.push_back({ CustomGCode::ColorChange, gcode_time.cache });
1131 }
1132
1134
1136
1137#if ENABLE_GCODE_VIEWER_DATA_CHECKING
1138 std::cout << "\n";
1139 m_mm3_per_mm_compare.output();
1140 m_height_compare.output();
1141 m_width_compare.output();
1142#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
1143
1144 if (perform_post_process)
1145 post_process();
1146#if ENABLE_GCODE_VIEWER_STATISTICS
1147 m_result.time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - m_start_time).count();
1148#endif // ENABLE_GCODE_VIEWER_STATISTICS
1149}
void update_estimated_times_stats()
Definition GCodeProcessor.cpp:4245
static const float Wipe_Height
Definition GCodeProcessor.hpp:194
static const float Wipe_Width
Definition GCodeProcessor.hpp:193
UsedFilaments m_used_filaments
Definition GCodeProcessor.hpp:607
void post_process()
Definition GCodeProcessor.cpp:3429
@ ColorChange
Definition CustomGCode.hpp:15
void process_caches(const GCodeProcessor *processor)
Definition GCodeProcessor.cpp:432

References Slic3r::GCodeProcessor::TimeMachine::CustomGCodeTime::cache, Slic3r::GCodeProcessor::TimeMachine::calculate_time(), Slic3r::CustomGCode::ColorChange, Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeProcessor::TimeMachine::gcode_time, m_result, m_time_processor, m_used_filaments, Slic3r::GCodeProcessor::TimeProcessor::machines, Slic3r::GCodeProcessorResult::moves, Slic3r::GCodeProcessor::TimeMachine::CustomGCodeTime::needed, post_process(), Slic3r::GCodeProcessor::UsedFilaments::process_caches(), Slic3r::GCodeProcessor::TimeMachine::CustomGCodeTime::times, update_estimated_times_stats(), Slic3r::Wipe, Wipe_Height, and Wipe_Width.

Referenced by Slic3r::GCode::do_export(), and process_file().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_acceleration()

float Slic3r::GCodeProcessor::get_acceleration ( PrintEstimatedStatistics::ETimeMode  mode) const
private
4159{
4160 size_t id = static_cast<size_t>(mode);
4161 return (id < m_time_processor.machines.size()) ? m_time_processor.machines[id].acceleration : DEFAULT_ACCELERATION;
4162}
IGL_INLINE void mode(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &X, const int d, Eigen::Matrix< T, Eigen::Dynamic, 1 > &M)
Definition mode.cpp:14

References DEFAULT_ACCELERATION, m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by process_G1().

+ Here is the caller graph for this function:

◆ get_axis_max_acceleration()

float Slic3r::GCodeProcessor::get_axis_max_acceleration ( PrintEstimatedStatistics::ETimeMode  mode,
Axis  axis 
) const
private
4119{
4120 switch (axis)
4121 {
4122 case X: { return get_option_value(m_time_processor.machine_limits.machine_max_acceleration_x, static_cast<size_t>(mode)); }
4123 case Y: { return get_option_value(m_time_processor.machine_limits.machine_max_acceleration_y, static_cast<size_t>(mode)); }
4124 case Z: { return get_option_value(m_time_processor.machine_limits.machine_max_acceleration_z, static_cast<size_t>(mode)); }
4125 case E: { return get_option_value(m_time_processor.machine_limits.machine_max_acceleration_e, static_cast<size_t>(mode)); }
4126 default: { return 0.0f; }
4127 }
4128}
@ Y
Definition libslic3r.h:99
@ Z
Definition libslic3r.h:100
@ X
Definition libslic3r.h:98

References Slic3r::E, Slic3r::get_option_value(), m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machine_limits, Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by process_G1().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_axis_max_feedrate()

float Slic3r::GCodeProcessor::get_axis_max_feedrate ( PrintEstimatedStatistics::ETimeMode  mode,
Axis  axis 
) const
private
4107{
4108 switch (axis)
4109 {
4110 case X: { return get_option_value(m_time_processor.machine_limits.machine_max_feedrate_x, static_cast<size_t>(mode)); }
4111 case Y: { return get_option_value(m_time_processor.machine_limits.machine_max_feedrate_y, static_cast<size_t>(mode)); }
4112 case Z: { return get_option_value(m_time_processor.machine_limits.machine_max_feedrate_z, static_cast<size_t>(mode)); }
4113 case E: { return get_option_value(m_time_processor.machine_limits.machine_max_feedrate_e, static_cast<size_t>(mode)); }
4114 default: { return 0.0f; }
4115 }
4116}

References Slic3r::E, Slic3r::get_option_value(), m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machine_limits, Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by process_G1().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_axis_max_jerk()

float Slic3r::GCodeProcessor::get_axis_max_jerk ( PrintEstimatedStatistics::ETimeMode  mode,
Axis  axis 
) const
private
4131{
4132 switch (axis)
4133 {
4134 case X: { return get_option_value(m_time_processor.machine_limits.machine_max_jerk_x, static_cast<size_t>(mode)); }
4135 case Y: { return get_option_value(m_time_processor.machine_limits.machine_max_jerk_y, static_cast<size_t>(mode)); }
4136 case Z: { return get_option_value(m_time_processor.machine_limits.machine_max_jerk_z, static_cast<size_t>(mode)); }
4137 case E: { return get_option_value(m_time_processor.machine_limits.machine_max_jerk_e, static_cast<size_t>(mode)); }
4138 default: { return 0.0f; }
4139 }
4140}

References Slic3r::E, Slic3r::get_option_value(), m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machine_limits, Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by process_G1().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_custom_gcode_times()

std::vector< std::pair< CustomGCode::Type, std::pair< float, float > > > Slic3r::GCodeProcessor::get_custom_gcode_times ( PrintEstimatedStatistics::ETimeMode  mode,
bool  include_remaining 
) const
1172{
1173 std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> ret;
1175 const TimeMachine& machine = m_time_processor.machines[static_cast<size_t>(mode)];
1176 float total_time = 0.0f;
1177 for (const auto& [type, time] : machine.gcode_time.times) {
1178 float remaining = include_remaining ? machine.time - total_time : 0.0f;
1179 ret.push_back({ type, { time, remaining } });
1180 total_time += time;
1181 }
1182 }
1183 return ret;
1184}

References Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeProcessor::TimeMachine::gcode_time, m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machines, Slic3r::GCodeProcessor::TimeMachine::time, and Slic3r::GCodeProcessor::TimeMachine::CustomGCodeTime::times.

Referenced by update_estimated_times_stats().

+ Here is the caller graph for this function:

◆ get_filament_load_time()

float Slic3r::GCodeProcessor::get_filament_load_time ( size_t  extruder_id)
private
4191{
4192 if (m_is_XL_printer)
4193 return 4.5f; // FIXME
4195 0.0f :
4196 ((extruder_id < m_time_processor.filament_load_times.size()) ?
4197 m_time_processor.filament_load_times[extruder_id] : m_time_processor.filament_load_times.front());
4198}
TPoint< P > front(const P &p)
Definition geometry_traits.hpp:872
bool extruder_unloaded
Definition GCodeProcessor.hpp:359

References Slic3r::GCodeProcessor::TimeProcessor::extruder_unloaded, Slic3r::GCodeProcessor::TimeProcessor::filament_load_times, m_is_XL_printer, and m_time_processor.

Referenced by process_T().

+ Here is the caller graph for this function:

◆ get_filament_unload_time()

float Slic3r::GCodeProcessor::get_filament_unload_time ( size_t  extruder_id)
private
4201{
4202 if (m_is_XL_printer)
4203 return 0.f; // FIXME
4205 0.0f :
4206 ((extruder_id < m_time_processor.filament_unload_times.size()) ?
4207 m_time_processor.filament_unload_times[extruder_id] : m_time_processor.filament_unload_times.front());
4208}

References Slic3r::GCodeProcessor::TimeProcessor::extruder_unloaded, Slic3r::GCodeProcessor::TimeProcessor::filament_unload_times, m_is_XL_printer, and m_time_processor.

Referenced by process_M702(), and process_T().

+ Here is the caller graph for this function:

◆ get_layers_time()

std::vector< float > Slic3r::GCodeProcessor::get_layers_time ( PrintEstimatedStatistics::ETimeMode  mode) const
1322{
1324 m_time_processor.machines[static_cast<size_t>(mode)].layers_time :
1325 std::vector<float>();
1326}
STL namespace.

References Slic3r::PrintEstimatedStatistics::Count, m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by update_estimated_times_stats().

+ Here is the caller graph for this function:

◆ get_moves_time()

std::vector< std::pair< EMoveType, float > > Slic3r::GCodeProcessor::get_moves_time ( PrintEstimatedStatistics::ETimeMode  mode) const
1187{
1188 std::vector<std::pair<EMoveType, float>> ret;
1190 for (size_t i = 0; i < m_time_processor.machines[static_cast<size_t>(mode)].moves_time.size(); ++i) {
1191 float time = m_time_processor.machines[static_cast<size_t>(mode)].moves_time[i];
1192 if (time > 0.0f)
1193 ret.push_back({ static_cast<EMoveType>(i), time });
1194 }
1195 }
1196 return ret;
1197}
EMoveType
Definition GCodeProcessor.hpp:22

References Slic3r::PrintEstimatedStatistics::Count, m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by update_estimated_times_stats().

+ Here is the caller graph for this function:

◆ get_result()

const GCodeProcessorResult & Slic3r::GCodeProcessor::get_result ( ) const
inline
633{ return m_result; }

References m_result.

Referenced by Slic3r::DoExport::update_print_estimated_stats().

+ Here is the caller graph for this function:

◆ get_retract_acceleration()

float Slic3r::GCodeProcessor::get_retract_acceleration ( PrintEstimatedStatistics::ETimeMode  mode) const
private
4143{
4144 size_t id = static_cast<size_t>(mode);
4145 return (id < m_time_processor.machines.size()) ? m_time_processor.machines[id].retract_acceleration : DEFAULT_RETRACT_ACCELERATION;
4146}

References DEFAULT_RETRACT_ACCELERATION, m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by process_G1().

+ Here is the caller graph for this function:

◆ get_roles_time()

std::vector< std::pair< GCodeExtrusionRole, float > > Slic3r::GCodeProcessor::get_roles_time ( PrintEstimatedStatistics::ETimeMode  mode) const
1200{
1201 std::vector<std::pair<GCodeExtrusionRole, float>> ret;
1203 for (size_t i = 0; i < m_time_processor.machines[static_cast<size_t>(mode)].roles_time.size(); ++i) {
1204 float time = m_time_processor.machines[static_cast<size_t>(mode)].roles_time[i];
1205 if (time > 0.0f)
1206 ret.push_back({ static_cast<GCodeExtrusionRole>(i), time });
1207 }
1208 }
1209 return ret;
1210}
GCodeExtrusionRole
Definition ExtrusionRole.hpp:104

References Slic3r::PrintEstimatedStatistics::Count, m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by update_estimated_times_stats().

+ Here is the caller graph for this function:

◆ get_time()

float Slic3r::GCodeProcessor::get_time ( PrintEstimatedStatistics::ETimeMode  mode) const
1152{
1153 return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? m_time_processor.machines[static_cast<size_t>(mode)].time : 0.0f;
1154}

References Slic3r::PrintEstimatedStatistics::Count, m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by update_estimated_times_stats().

+ Here is the caller graph for this function:

◆ get_time_dhm()

std::string Slic3r::GCodeProcessor::get_time_dhm ( PrintEstimatedStatistics::ETimeMode  mode) const
1157{
1158 return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast<size_t>(mode)].time)) : std::string("N/A");
1159}
TOKEN * string(char *text)
Definition config.c:233
std::string short_time(const std::string &time, bool force_localization)
Definition utils.cpp:989
std::string get_time_dhms(float time_in_secs)
Definition Utils.hpp:315

References Slic3r::PrintEstimatedStatistics::Count, Slic3r::get_time_dhms(), m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machines, and Slic3r::short_time().

+ Here is the call graph for this function:

◆ get_travel_acceleration()

float Slic3r::GCodeProcessor::get_travel_acceleration ( PrintEstimatedStatistics::ETimeMode  mode) const
private
4175{
4176 size_t id = static_cast<size_t>(mode);
4177 return (id < m_time_processor.machines.size()) ? m_time_processor.machines[id].travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
4178}

References DEFAULT_TRAVEL_ACCELERATION, m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by process_G1().

+ Here is the caller graph for this function:

◆ get_travel_time()

float Slic3r::GCodeProcessor::get_travel_time ( PrintEstimatedStatistics::ETimeMode  mode) const
1162{
1163 return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? m_time_processor.machines[static_cast<size_t>(mode)].travel_time : 0.0f;
1164}

References Slic3r::PrintEstimatedStatistics::Count, m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by update_estimated_times_stats().

+ Here is the caller graph for this function:

◆ get_travel_time_dhm()

std::string Slic3r::GCodeProcessor::get_travel_time_dhm ( PrintEstimatedStatistics::ETimeMode  mode) const
1167{
1168 return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast<size_t>(mode)].travel_time)) : std::string("N/A");
1169}

References Slic3r::PrintEstimatedStatistics::Count, Slic3r::get_time_dhms(), m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machines, and Slic3r::short_time().

+ Here is the call graph for this function:

◆ initialize()

void Slic3r::GCodeProcessor::initialize ( const std::string &  filename)
1094{
1096
1097#if ENABLE_GCODE_VIEWER_STATISTICS
1098 m_start_time = std::chrono::high_resolution_clock::now();
1099#endif // ENABLE_GCODE_VIEWER_STATISTICS
1100
1101 // process gcode
1102 m_result.filename = filename;
1104}
static unsigned int s_result_id
Definition GCodeProcessor.hpp:612
bool is_decimal_separator_point()
Definition LocalesUtils.cpp:47
unsigned int id
Definition GCodeProcessor.hpp:138
std::string filename
Definition GCodeProcessor.hpp:137

References Slic3r::GCodeProcessorResult::filename, Slic3r::GCodeProcessorResult::id, Slic3r::is_decimal_separator_point(), m_result, and s_result_id.

Referenced by Slic3r::GCode::do_export().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initialize_result_moves()

void Slic3r::GCodeProcessor::initialize_result_moves ( )
inline
642 {
643 // 1st move must be a dummy move
644 assert(m_result.moves.empty());
645 m_result.moves.emplace_back(GCodeProcessorResult::MoveVertex());
646 }
std::vector< MoveVertex > moves
Definition GCodeProcessor.hpp:139

References m_result, and Slic3r::GCodeProcessorResult::moves.

Referenced by Slic3r::DoExport::init_gcode_processor(), and process_file().

+ Here is the caller graph for this function:

◆ is_stealth_time_estimator_enabled()

bool Slic3r::GCodeProcessor::is_stealth_time_estimator_enabled ( ) const
inline
627 {
629 }

References m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machines, and Slic3r::PrintEstimatedStatistics::Stealth.

Referenced by Slic3r::DoExport::update_print_estimated_stats().

+ Here is the caller graph for this function:

◆ minimum_feedrate()

float Slic3r::GCodeProcessor::minimum_feedrate ( PrintEstimatedStatistics::ETimeMode  mode,
float  feedrate 
) const
private
4091{
4092 if (m_time_processor.machine_limits.machine_min_extruding_rate.empty())
4093 return feedrate;
4094
4095 return std::max(feedrate, get_option_value(m_time_processor.machine_limits.machine_min_extruding_rate, static_cast<size_t>(mode)));
4096}

References Slic3r::get_option_value(), m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machine_limits.

Referenced by process_G1().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ minimum_travel_feedrate()

float Slic3r::GCodeProcessor::minimum_travel_feedrate ( PrintEstimatedStatistics::ETimeMode  mode,
float  feedrate 
) const
private
4099{
4100 if (m_time_processor.machine_limits.machine_min_travel_rate.empty())
4101 return feedrate;
4102
4103 return std::max(feedrate, get_option_value(m_time_processor.machine_limits.machine_min_travel_rate, static_cast<size_t>(mode)));
4104}

References Slic3r::get_option_value(), m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machine_limits.

Referenced by process_G1().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ post_process()

void Slic3r::GCodeProcessor::post_process ( )
private
3430{
3431 FilePtr in{ boost::nowide::fopen(m_result.filename.c_str(), "rb") };
3432 if (in.f == nullptr)
3433 throw Slic3r::RuntimeError(std::string("GCode processor post process export failed.\nCannot open file for reading.\n"));
3434
3435 // temporary file to contain modified gcode
3436 std::string out_path = m_result.filename + ".postprocess";
3437 FilePtr out{ boost::nowide::fopen(out_path.c_str(), "wb") };
3438 if (out.f == nullptr) {
3439 throw Slic3r::RuntimeError(std::string("GCode processor post process export failed.\nCannot open file for writing.\n"));
3440 }
3441
3442 auto time_in_minutes = [](float time_in_seconds) {
3443 assert(time_in_seconds >= 0.f);
3444 return int((time_in_seconds + 0.5f) / 60.0f);
3445 };
3446
3447 auto time_in_last_minute = [](float time_in_seconds) {
3448 assert(time_in_seconds <= 60.0f);
3449 return time_in_seconds / 60.0f;
3450 };
3451
3452 auto format_line_M73_main = [](const std::string& mask, int percent, int time) {
3453 char line_M73[64];
3454 sprintf(line_M73, mask.c_str(),
3455 std::to_string(percent).c_str(),
3456 std::to_string(time).c_str());
3457 return std::string(line_M73);
3458 };
3459
3460 auto format_line_M73_stop_int = [](const std::string& mask, int time) {
3461 char line_M73[64];
3462 sprintf(line_M73, mask.c_str(), std::to_string(time).c_str());
3463 return std::string(line_M73);
3464 };
3465
3466 auto format_time_float = [](float time) {
3468 };
3469
3470 auto format_line_M73_stop_float = [format_time_float](const std::string& mask, float time) {
3471 char line_M73[64];
3472 sprintf(line_M73, mask.c_str(), format_time_float(time).c_str());
3473 return std::string(line_M73);
3474 };
3475
3476 std::string gcode_line;
3477 size_t g1_lines_counter = 0;
3478 // keeps track of last exported pair <percent, remaining time>
3479 std::array<std::pair<int, int>, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> last_exported_main;
3480 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3481 last_exported_main[i] = { 0, time_in_minutes(m_time_processor.machines[i].time) };
3482 }
3483
3484 // keeps track of last exported remaining time to next printer stop
3485 std::array<int, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> last_exported_stop;
3486 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3487 last_exported_stop[i] = time_in_minutes(m_time_processor.machines[i].time);
3488 }
3489
3490 // Helper class to modify and export gcode to file
3491 class ExportLines
3492 {
3493 public:
3494 struct Backtrace
3495 {
3496 float time{ 60.0f };
3497 unsigned int steps{ 10 };
3498 float time_step() const { return time / float(steps); }
3499 };
3500
3501 enum class EWriteType
3502 {
3503 BySize,
3504 ByTime
3505 };
3506
3507 private:
3508 struct LineData
3509 {
3510 std::string line;
3511 float time;
3512 };
3513
3514#ifndef NDEBUG
3515 class Statistics
3516 {
3517 ExportLines& m_parent;
3518 size_t m_max_size{ 0 };
3519 size_t m_lines_count{ 0 };
3520 size_t m_max_lines_count{ 0 };
3521
3522 public:
3523 explicit Statistics(ExportLines& parent)
3524 : m_parent(parent)
3525 {}
3526
3527 void add_line(size_t line_size) {
3528 ++m_lines_count;
3529 m_max_size = std::max(m_max_size, m_parent.get_size() + line_size);
3530 m_max_lines_count = std::max(m_max_lines_count, m_lines_count);
3531 }
3532
3533 void remove_line() { --m_lines_count; }
3534 void remove_all_lines() { m_lines_count = 0; }
3535 };
3536
3537 Statistics m_statistics;
3538#endif // NDEBUG
3539
3540 EWriteType m_write_type{ EWriteType::BySize };
3541 // Time machine containing g1 times cache
3542 TimeMachine& m_machine;
3543 // Current time
3544 float m_time{ 0.0f };
3545 // Current size in bytes
3546 size_t m_size{ 0 };
3547
3548 // gcode lines cache
3549 std::deque<LineData> m_lines;
3550 size_t m_added_lines_counter{ 0 };
3551 // map of gcode line ids from original to final
3552 // used to update m_result.moves[].gcode_id
3553 std::vector<std::pair<size_t, size_t>> m_gcode_lines_map;
3554
3555 size_t m_curr_g1_id{ 0 };
3556 size_t m_out_file_pos{ 0 };
3557
3558 public:
3559 ExportLines(EWriteType type, TimeMachine& machine)
3560#ifndef NDEBUG
3561 : m_statistics(*this), m_write_type(type), m_machine(machine) {}
3562#else
3563 : m_write_type(type), m_machine(machine) {}
3564#endif // NDEBUG
3565
3566 void update(size_t lines_counter, size_t g1_lines_counter) {
3567 m_gcode_lines_map.push_back({ lines_counter, 0 });
3568
3569 if (g1_lines_counter == 0)
3570 return;
3571
3572 auto init_it = m_machine.g1_times_cache.begin() + m_curr_g1_id;
3573 auto it = init_it;
3574 while (it != m_machine.g1_times_cache.end() && it->id < g1_lines_counter + 1) {
3575 ++it;
3576 ++m_curr_g1_id;
3577 }
3578
3579 if ((it != m_machine.g1_times_cache.end() && it != init_it) || m_curr_g1_id == 0)
3580 m_time = it->elapsed_time;
3581 }
3582
3583 // add the given gcode line to the cache
3584 void append_line(const std::string& line) {
3585 m_lines.push_back({ line, m_time });
3586#ifndef NDEBUG
3587 m_statistics.add_line(line.length());
3588#endif // NDEBUG
3589 m_size += line.length();
3590 ++m_added_lines_counter;
3591 assert(!m_gcode_lines_map.empty());
3592 m_gcode_lines_map.back().second = m_added_lines_counter;
3593 }
3594
3595 // Insert the gcode lines required by the command cmd by backtracing into the cache
3596 void insert_lines(const Backtrace& backtrace, const std::string& cmd, std::function<std::string(unsigned int, float, float)> line_inserter,
3597 std::function<std::string(const std::string&)> line_replacer) {
3598 assert(!m_lines.empty());
3599 const float time_step = backtrace.time_step();
3600 size_t rev_it_dist = 0; // distance from the end of the cache of the starting point of the backtrace
3601 float last_time_insertion = 0.0f; // used to avoid inserting two lines at the same time
3602 for (unsigned int i = 0; i < backtrace.steps; ++i) {
3603 const float backtrace_time_i = (i + 1) * time_step;
3604 const float time_threshold_i = m_time - backtrace_time_i;
3605 auto rev_it = m_lines.rbegin() + rev_it_dist;
3606 auto start_rev_it = rev_it;
3607
3608 std::string curr_cmd = GCodeReader::GCodeLine::extract_cmd(rev_it->line);
3609 // backtrace into the cache to find the place where to insert the line
3610 while (rev_it != m_lines.rend() && rev_it->time > time_threshold_i && curr_cmd != cmd && curr_cmd != "G28" && curr_cmd != "G29") {
3611 rev_it->line = line_replacer(rev_it->line);
3612 ++rev_it;
3613 curr_cmd = GCodeReader::GCodeLine::extract_cmd(rev_it->line);
3614 }
3615
3616 // we met the previous evenience of cmd, or a G28/G29 command. stop inserting lines
3617 if (rev_it != m_lines.rend() && (curr_cmd == cmd || curr_cmd == "G28" || curr_cmd == "G29"))
3618 break;
3619
3620 // insert the line for the current step
3621 if (rev_it != m_lines.rend() && rev_it != start_rev_it && rev_it->time != last_time_insertion) {
3622 last_time_insertion = rev_it->time;
3623 const std::string out_line = line_inserter(i + 1, last_time_insertion, m_time - last_time_insertion);
3624 rev_it_dist = std::distance(m_lines.rbegin(), rev_it) + 1;
3625 m_lines.insert(rev_it.base(), { out_line, rev_it->time });
3626#ifndef NDEBUG
3627 m_statistics.add_line(out_line.length());
3628#endif // NDEBUG
3629 m_size += out_line.length();
3630 // synchronize gcode lines map
3631 for (auto map_it = m_gcode_lines_map.rbegin(); map_it != m_gcode_lines_map.rbegin() + rev_it_dist - 1; ++map_it) {
3632 ++map_it->second;
3633 }
3634
3635 ++m_added_lines_counter;
3636 }
3637 }
3638 }
3639
3640 // write to file:
3641 // m_write_type == EWriteType::ByTime - all lines older than m_time - backtrace_time
3642 // m_write_type == EWriteType::BySize - all lines if current size is greater than 65535 bytes
3643 void write(FilePtr& out, float backtrace_time, GCodeProcessorResult& result, const std::string& out_path) {
3644 if (m_lines.empty())
3645 return;
3646
3647 // collect lines to write into a single string
3648 std::string out_string;
3649 if (!m_lines.empty()) {
3650 if (m_write_type == EWriteType::ByTime) {
3651 while (m_lines.front().time < m_time - backtrace_time) {
3652 const LineData& data = m_lines.front();
3653 out_string += data.line;
3654 m_size -= data.line.length();
3655 m_lines.pop_front();
3656#ifndef NDEBUG
3657 m_statistics.remove_line();
3658#endif // NDEBUG
3659 }
3660 }
3661 else {
3662 if (m_size > 65535) {
3663 while (!m_lines.empty()) {
3664 out_string += m_lines.front().line;
3665 m_lines.pop_front();
3666 }
3667 m_size = 0;
3668#ifndef NDEBUG
3669 m_statistics.remove_all_lines();
3670#endif // NDEBUG
3671 }
3672 }
3673 }
3674
3675 write_to_file(out, out_string, result, out_path);
3676 }
3677
3678 // flush the current content of the cache to file
3679 void flush(FilePtr& out, GCodeProcessorResult& result, const std::string& out_path) {
3680 // collect lines to flush into a single string
3681 std::string out_string;
3682 while (!m_lines.empty()) {
3683 out_string += m_lines.front().line;
3684 m_lines.pop_front();
3685 }
3686 m_size = 0;
3687#ifndef NDEBUG
3688 m_statistics.remove_all_lines();
3689#endif // NDEBUG
3690
3691 write_to_file(out, out_string, result, out_path);
3692 }
3693
3694 void synchronize_moves(GCodeProcessorResult& result) const {
3695 auto it = m_gcode_lines_map.begin();
3696 for (GCodeProcessorResult::MoveVertex& move : result.moves) {
3697 while (it != m_gcode_lines_map.end() && it->first < move.gcode_id) {
3698 ++it;
3699 }
3700 if (it != m_gcode_lines_map.end() && it->first == move.gcode_id)
3701 move.gcode_id = it->second;
3702 }
3703 }
3704
3705 size_t get_size() const { return m_size; }
3706
3707 private:
3708 void write_to_file(FilePtr& out, const std::string& out_string, GCodeProcessorResult& result, const std::string& out_path) {
3709 if (!out_string.empty()) {
3710 fwrite((const void*)out_string.c_str(), 1, out_string.length(), out.f);
3711 if (ferror(out.f)) {
3712 out.close();
3713 boost::nowide::remove(out_path.c_str());
3714 throw Slic3r::RuntimeError(std::string("GCode processor post process export failed.\nIs the disk full?\n"));
3715 }
3716 for (size_t i = 0; i < out_string.size(); ++i) {
3717 if (out_string[i] == '\n')
3718 result.lines_ends.emplace_back(m_out_file_pos + i + 1);
3719 }
3720 m_out_file_pos += out_string.size();
3721 }
3722 }
3723 };
3724
3725 ExportLines export_lines(m_result.backtrace_enabled ? ExportLines::EWriteType::ByTime : ExportLines::EWriteType::BySize, m_time_processor.machines[0]);
3726
3727 // replace placeholder lines with the proper final value
3728 // gcode_line is in/out parameter, to reduce expensive memory allocation
3729 auto process_placeholders = [&](std::string& gcode_line) {
3730 bool processed = false;
3731
3732 // remove trailing '\n'
3733 auto line = std::string_view(gcode_line).substr(0, gcode_line.length() - 1);
3734
3735 if (line.length() > 1) {
3736 line = line.substr(1);
3739 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3740 const TimeMachine& machine = m_time_processor.machines[i];
3741 if (machine.enabled) {
3742 // export pair <percent, remaining time>
3743 export_lines.append_line(format_line_M73_main(machine.line_m73_main_mask.c_str(),
3745 (line == reserved_tag(ETags::First_Line_M73_Placeholder)) ? time_in_minutes(machine.time) : 0));
3746 processed = true;
3747
3748 // export remaining time to next printer stop
3749 if (line == reserved_tag(ETags::First_Line_M73_Placeholder) && !machine.stop_times.empty()) {
3750 const int to_export_stop = time_in_minutes(machine.stop_times.front().elapsed_time);
3751 export_lines.append_line(format_line_M73_stop_int(machine.line_m73_stop_mask.c_str(), to_export_stop));
3752 last_exported_stop[i] = to_export_stop;
3753 }
3754 }
3755 }
3756 }
3758 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3759 const TimeMachine& machine = m_time_processor.machines[i];
3761 if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
3762 char buf[128];
3763 sprintf(buf, "; estimated printing time (%s mode) = %s\n",
3764 (mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent",
3765 get_time_dhms(machine.time).c_str());
3766 export_lines.append_line(buf);
3767 processed = true;
3768 }
3769 }
3770 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3771 const TimeMachine& machine = m_time_processor.machines[i];
3773 if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
3774 char buf[128];
3775 sprintf(buf, "; estimated first layer printing time (%s mode) = %s\n",
3776 (mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent",
3777 get_time_dhms(machine.layers_time.empty() ? 0.f : machine.layers_time.front()).c_str());
3778 export_lines.append_line(buf);
3779 processed = true;
3780 }
3781 }
3782 }
3783 }
3784
3785 return processed;
3786 };
3787
3788 std::vector<double> filament_mm(m_result.extruders_count, 0.0);
3789 std::vector<double> filament_cm3(m_result.extruders_count, 0.0);
3790 std::vector<double> filament_g(m_result.extruders_count, 0.0);
3791 std::vector<double> filament_cost(m_result.extruders_count, 0.0);
3792
3793 double filament_total_g = 0.0;
3794 double filament_total_cost = 0.0;
3795
3796 for (const auto& [id, volume] : m_result.print_statistics.volumes_per_extruder) {
3797 filament_mm[id] = volume / (static_cast<double>(M_PI) * sqr(0.5 * m_result.filament_diameters[id]));
3798 filament_cm3[id] = volume * 0.001;
3799 filament_g[id] = filament_cm3[id] * double(m_result.filament_densities[id]);
3800 filament_cost[id] = filament_g[id] * double(m_result.filament_cost[id]) * 0.001;
3801 filament_total_g += filament_g[id];
3802 filament_total_cost += filament_cost[id];
3803 }
3804
3805 auto process_used_filament = [&](std::string& gcode_line) {
3806 // Prefilter for parsing speed.
3807 if (gcode_line.size() < 8 || gcode_line[0] != ';' || gcode_line[1] != ' ')
3808 return false;
3809 if (const char c = gcode_line[2]; c != 'f' && c != 't')
3810 return false;
3811 auto process_tag = [](std::string& gcode_line, const std::string_view tag, const std::vector<double>& values) {
3812 if (boost::algorithm::starts_with(gcode_line, tag)) {
3813 gcode_line = tag;
3814 char buf[1024];
3815 for (size_t i = 0; i < values.size(); ++i) {
3816 sprintf(buf, i == values.size() - 1 ? " %.2lf\n" : " %.2lf,", values[i]);
3817 gcode_line += buf;
3818 }
3819 return true;
3820 }
3821 return false;
3822 };
3823
3824 bool ret = false;
3825 ret |= process_tag(gcode_line, "; filament used [mm] =", filament_mm);
3826 ret |= process_tag(gcode_line, "; filament used [g] =", filament_g);
3827 ret |= process_tag(gcode_line, "; total filament used [g] =", { filament_total_g });
3828 ret |= process_tag(gcode_line, "; filament used [cm3] =", filament_cm3);
3829 ret |= process_tag(gcode_line, "; filament cost =", filament_cost);
3830 ret |= process_tag(gcode_line, "; total filament cost =", { filament_total_cost });
3831 return ret;
3832 };
3833
3834 // check for temporary lines
3835 auto is_temporary_decoration = [](const std::string_view gcode_line) {
3836 // remove trailing '\n'
3837 assert(!gcode_line.empty());
3838 assert(gcode_line.back() == '\n');
3839
3840 // return true for decorations which are used in processing the gcode but that should not be exported into the final gcode
3841 // i.e.:
3842 // bool ret = gcode_line.substr(0, gcode_line.length() - 1) == ";" + Layer_Change_Tag;
3843 // ...
3844 // return ret;
3845 return false;
3846 };
3847
3848 // Iterators for the normal and silent cached time estimate entry recently processed, used by process_line_G1.
3849 auto g1_times_cache_it = Slic3r::reserve_vector<std::vector<TimeMachine::G1LinesCacheItem>::const_iterator>(m_time_processor.machines.size());
3850 for (const auto& machine : m_time_processor.machines)
3851 g1_times_cache_it.emplace_back(machine.g1_times_cache.begin());
3852
3853 // add lines M73 to exported gcode
3854 auto process_line_G1 = [this,
3855 // Lambdas, mostly for string formatting, all with an empty capture block.
3856 time_in_minutes, format_time_float, format_line_M73_main, format_line_M73_stop_int, format_line_M73_stop_float, time_in_last_minute,
3857 // Caches, to be modified
3858 &g1_times_cache_it, &last_exported_main, &last_exported_stop,
3859 &export_lines]
3860 (const size_t g1_lines_counter) {
3862 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3863 const TimeMachine& machine = m_time_processor.machines[i];
3864 if (machine.enabled) {
3865 // export pair <percent, remaining time>
3866 // Skip all machine.g1_times_cache below g1_lines_counter.
3867 auto& it = g1_times_cache_it[i];
3868 while (it != machine.g1_times_cache.end() && it->id < g1_lines_counter)
3869 ++it;
3870 if (it != machine.g1_times_cache.end() && it->id == g1_lines_counter) {
3871 std::pair<int, int> to_export_main = { int(100.0f * it->elapsed_time / machine.time),
3872 time_in_minutes(machine.time - it->elapsed_time) };
3873 if (last_exported_main[i] != to_export_main) {
3874 export_lines.append_line(format_line_M73_main(machine.line_m73_main_mask.c_str(),
3875 to_export_main.first, to_export_main.second));
3876 last_exported_main[i] = to_export_main;
3877 }
3878 // export remaining time to next printer stop
3879 auto it_stop = std::upper_bound(machine.stop_times.begin(), machine.stop_times.end(), it->elapsed_time,
3880 [](float value, const TimeMachine::StopTime& t) { return value < t.elapsed_time; });
3881 if (it_stop != machine.stop_times.end()) {
3882 int to_export_stop = time_in_minutes(it_stop->elapsed_time - it->elapsed_time);
3883 if (last_exported_stop[i] != to_export_stop) {
3884 if (to_export_stop > 0) {
3885 if (last_exported_stop[i] != to_export_stop) {
3886 export_lines.append_line(format_line_M73_stop_int(machine.line_m73_stop_mask.c_str(), to_export_stop));
3887 last_exported_stop[i] = to_export_stop;
3888 }
3889 }
3890 else {
3891 bool is_last = false;
3892 auto next_it = it + 1;
3893 is_last |= (next_it == machine.g1_times_cache.end());
3894
3895 if (next_it != machine.g1_times_cache.end()) {
3896 auto next_it_stop = std::upper_bound(machine.stop_times.begin(), machine.stop_times.end(), next_it->elapsed_time,
3897 [](float value, const TimeMachine::StopTime& t) { return value < t.elapsed_time; });
3898 is_last |= (next_it_stop != it_stop);
3899
3900 std::string time_float_str = format_time_float(time_in_last_minute(it_stop->elapsed_time - it->elapsed_time));
3901 std::string next_time_float_str = format_time_float(time_in_last_minute(it_stop->elapsed_time - next_it->elapsed_time));
3902 is_last |= (string_to_double_decimal_point(time_float_str) > 0. && string_to_double_decimal_point(next_time_float_str) == 0.);
3903 }
3904
3905 if (is_last) {
3906 if (std::distance(machine.stop_times.begin(), it_stop) == static_cast<ptrdiff_t>(machine.stop_times.size() - 1))
3907 export_lines.append_line(format_line_M73_stop_int(machine.line_m73_stop_mask.c_str(), to_export_stop));
3908 else
3909 export_lines.append_line(format_line_M73_stop_float(machine.line_m73_stop_mask.c_str(), time_in_last_minute(it_stop->elapsed_time - it->elapsed_time)));
3910
3911 last_exported_stop[i] = to_export_stop;
3912 }
3913 }
3914 }
3915 }
3916 }
3917 }
3918 }
3919 }
3920 };
3921
3922 // add lines XXX to exported gcode
3923 auto process_line_T = [this, &export_lines](const std::string& gcode_line, const size_t g1_lines_counter, const ExportLines::Backtrace& backtrace) {
3924 const std::string cmd = GCodeReader::GCodeLine::extract_cmd(gcode_line);
3925 if (cmd.size() >= 2) {
3926 std::stringstream ss(cmd.substr(1));
3927 int tool_number = -1;
3928 ss >> tool_number;
3929 if (tool_number != -1) {
3930 if (tool_number < 0 || (int)m_extruder_temps_config.size() <= tool_number) {
3931 // found an invalid value, clamp it to a valid one
3932 tool_number = std::clamp<int>(0, m_extruder_temps_config.size() - 1, tool_number);
3933 // emit warning
3934 std::string warning = _u8L("GCode Post-Processor encountered an invalid toolchange, maybe from a custom gcode:");
3935 warning += "\n> ";
3936 warning += gcode_line;
3937 warning += _u8L("Generated M104 lines may be incorrect.");
3938 BOOST_LOG_TRIVIAL(error) << warning;
3939 if (m_print != nullptr)
3941 }
3942 }
3943 export_lines.insert_lines(backtrace, cmd,
3944 // line inserter
3945 [tool_number, this](unsigned int id, float time, float time_diff) {
3946 int temperature = int( m_layer_id != 1 ? m_extruder_temps_config[tool_number] : m_extruder_temps_first_layer_config[tool_number]);
3947 const std::string out = "M104 T" + std::to_string(tool_number) + " P" + std::to_string(int(std::round(time_diff))) + " S" + std::to_string(temperature) + "\n";
3948 return out;
3949 },
3950 // line replacer
3951 [this, tool_number](const std::string& line) {
3952 if (GCodeReader::GCodeLine::cmd_is(line, "M104")) {
3953 GCodeReader::GCodeLine gline;
3954 GCodeReader reader;
3955 reader.parse_line(line, [&gline](GCodeReader& reader, const GCodeReader::GCodeLine& l) { gline = l; });
3956
3957 float val;
3958 if (gline.has_value('T', val) && gline.raw().find("cooldown") != std::string::npos && m_is_XL_printer) {
3959 if (static_cast<int>(val) == tool_number)
3960 return std::string("; removed M104\n");
3961 }
3962 }
3963 return line;
3964 });
3965 }
3966 };
3967
3968 m_result.lines_ends.clear();
3969
3970 unsigned int line_id = 0;
3971 // Backtrace data for Tx gcode lines
3972 static const ExportLines::Backtrace backtrace_T = { 120.0f, 10 };
3973 // In case there are multiple sources of backtracing, keeps track of the longest backtrack time needed
3974 // to flush the backtrace cache accordingly
3975 float max_backtrace_time = 120.0f;
3976
3977 {
3978 // Read the input stream 64kB at a time, extract lines and process them.
3979 std::vector<char> buffer(65536 * 10, 0);
3980 // Line buffer.
3981 assert(gcode_line.empty());
3982 for (;;) {
3983 size_t cnt_read = ::fread(buffer.data(), 1, buffer.size(), in.f);
3984 if (::ferror(in.f))
3985 throw Slic3r::RuntimeError(std::string("GCode processor post process export failed.\nError while reading from file.\n"));
3986 bool eof = cnt_read == 0;
3987 auto it = buffer.begin();
3988 auto it_bufend = buffer.begin() + cnt_read;
3989 while (it != it_bufend || (eof && !gcode_line.empty())) {
3990 // Find end of line.
3991 bool eol = false;
3992 auto it_end = it;
3993 for (; it_end != it_bufend && !(eol = *it_end == '\r' || *it_end == '\n'); ++it_end);
3994 // End of line is indicated also if end of file was reached.
3995 eol |= eof && it_end == it_bufend;
3996 gcode_line.insert(gcode_line.end(), it, it_end);
3997 if (eol) {
3998 ++line_id;
3999 export_lines.update(line_id, g1_lines_counter);
4000
4001 gcode_line += "\n";
4002 // replace placeholder lines
4003 bool processed = process_placeholders(gcode_line);
4004 if (processed)
4005 gcode_line.clear();
4006 if (!processed)
4007 processed = process_used_filament(gcode_line);
4008 if (!processed && !is_temporary_decoration(gcode_line)) {
4009 if (GCodeReader::GCodeLine::cmd_is(gcode_line, "G1"))
4010 // add lines M73 where needed
4011 process_line_G1(g1_lines_counter++);
4013 // add lines XXX where needed
4014 process_line_T(gcode_line, g1_lines_counter, backtrace_T);
4015 max_backtrace_time = std::max(max_backtrace_time, backtrace_T.time);
4016 }
4017 }
4018
4019 if (!gcode_line.empty())
4020 export_lines.append_line(gcode_line);
4021 export_lines.write(out, 1.1f * max_backtrace_time, m_result, out_path);
4022 gcode_line.clear();
4023 }
4024 // Skip EOL.
4025 it = it_end;
4026 if (it != it_bufend && *it == '\r')
4027 ++it;
4028 if (it != it_bufend && *it == '\n')
4029 ++it;
4030 }
4031 if (eof)
4032 break;
4033 }
4034 }
4035
4036 export_lines.flush(out, m_result, out_path);
4037
4038 out.close();
4039 in.close();
4040
4041 export_lines.synchronize_moves(m_result);
4042
4043 if (rename_file(out_path, m_result.filename))
4044 throw Slic3r::RuntimeError(std::string("Failed to rename the output G-code file from ") + out_path + " to " + m_result.filename + '\n' +
4045 "Is " + out_path + " locked?" + '\n');
4046}
#define M_PI
Definition ExtrusionSimulator.cpp:20
#define _u8L(s)
macro used to mark string used at localization, return same string
Definition SLAPrint.cpp:29
Print * m_print
Definition GCodeProcessor.hpp:609
unsigned int m_layer_id
Definition GCodeProcessor.hpp:575
static const std::string & reserved_tag(ETags tag)
Definition GCodeProcessor.hpp:186
ETags
Definition GCodeProcessor.hpp:171
static bool cmd_starts_with(const std::string &gcode_line, const char *cmd_test)
Definition GCodeReader.hpp:74
static std::string extract_cmd(const std::string &gcode_line)
Definition GCodeReader.hpp:78
bool cmd_is(const char *cmd_test) const
Definition GCodeReader.hpp:50
void active_step_add_warning(PrintStateBase::WarningLevel warning_level, const std::string &message, int message_id=0)
Definition PrintBase.hpp:610
std::string float_to_string_decimal_point(double value, int precision)
Definition LocalesUtils.cpp:74
std::error_code rename_file(const std::string &from, const std::string &to)
Definition utils.cpp:468
constexpr T sqr(T x)
Definition libslic3r.h:258
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:229
constexpr auto data(C &c) -> decltype(c.data())
Definition span.hpp:195
IGL_INLINE void volume(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedT > &T, Eigen::PlainObjectBase< Derivedvol > &vol)
Definition volume.cpp:15
std::vector< size_t > lines_ends
Definition GCodeProcessor.hpp:141
ETimeMode
Definition GCodeProcessor.hpp:40
struct command cmd[]
Definition term.c:94
static char error[256]
Definition tga.cpp:50

References _u8L, Slic3r::PrintBaseWithState< PrintStepEnumType, COUNT >::active_step_add_warning(), Slic3r::GCodeProcessorResult::backtrace_enabled, Slic3r::FilePtr::close(), cmd, Slic3r::GCodeReader::GCodeLine::cmd_is(), Slic3r::GCodeReader::GCodeLine::cmd_starts_with(), Slic3r::PrintEstimatedStatistics::Count, Slic3r::PrintStateBase::CRITICAL, Slic3r::GCodeProcessor::TimeMachine::enabled, error, Estimated_Printing_Time_Placeholder, Slic3r::GCodeProcessor::TimeProcessor::export_remaining_time_enabled, Slic3r::GCodeReader::GCodeLine::extract_cmd(), Slic3r::GCodeProcessorResult::extruders_count, Slic3r::FilePtr::f, Slic3r::GCodeProcessorResult::filament_cost, Slic3r::filament_cost(), Slic3r::GCodeProcessorResult::filament_densities, Slic3r::GCodeProcessorResult::filament_diameters, Slic3r::GCodeProcessorResult::filename, First_Line_M73_Placeholder, Slic3r::float_to_string_decimal_point(), Slic3r::GCodeProcessor::TimeMachine::g1_times_cache, Slic3r::get_time_dhms(), Slic3r::GCodeReader::GCodeLine::has_value(), Last_Line_M73_Placeholder, Slic3r::GCodeProcessor::TimeMachine::layers_time, Slic3r::GCodeProcessor::TimeMachine::line_m73_main_mask, Slic3r::GCodeProcessor::TimeMachine::line_m73_stop_mask, Slic3r::GCodeProcessorResult::lines_ends, m_extruder_temps_config, m_extruder_temps_first_layer_config, m_is_XL_printer, m_layer_id, M_PI, m_print, m_result, m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machines, Slic3r::GCodeProcessorResult::moves, Slic3r::PrintEstimatedStatistics::Normal, Slic3r::GCodeReader::parse_line(), Slic3r::GCodeProcessorResult::print_statistics, Slic3r::GCodeReader::GCodeLine::raw(), Slic3r::rename_file(), reserved_tag(), Slic3r::sqr(), Slic3r::GCodeProcessor::TimeMachine::stop_times, Slic3r::string_to_double_decimal_point(), Slic3r::GCodeProcessor::TimeMachine::time, and Slic3r::PrintEstimatedStatistics::volumes_per_extruder.

Referenced by finalize().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_bambustudio_tags()

bool Slic3r::GCodeProcessor::process_bambustudio_tags ( const std::string_view  comment)
private
2284{
2285 // extrusion roles
2286
2287 std::string tag = "FEATURE: ";
2288 size_t pos = comment.find(tag);
2289 if (pos != comment.npos) {
2290 const std::string_view type = comment.substr(pos + tag.length());
2291 if (type == "Custom")
2293 else if (type == "Inner wall")
2295 else if (type == "Outer wall")
2297 else if (type == "Overhang wall")
2299 else if (type == "Gap infill")
2301 else if (type == "Bridge")
2303 else if (type == "Sparse infill")
2305 else if (type == "Internal solid infill")
2307 else if (type == "Top surface")
2309 else if (type == "Bottom surface")
2311 else if (type == "Ironing")
2313 else if (type == "Skirt")
2315 else if (type == "Brim")
2317 else if (type == "Support")
2319 else if (type == "Support interface")
2321 else if (type == "Support transition")
2323 else if (type == "Prime tower")
2325 else {
2327 BOOST_LOG_TRIVIAL(warning) << "GCodeProcessor found unknown extrusion role: " << type;
2328 }
2329
2332
2333 return true;
2334 }
2335
2336 return false;
2337}
void activate(bool active)
Definition GCodeProcessor.hpp:406
void set_extrusion_role(GCodeExtrusionRole role)
Definition GCodeProcessor.cpp:4084
SeamsDetector m_seams_detector
Definition GCodeProcessor.hpp:578
GCodeExtrusionRole m_extrusion_role
Definition GCodeProcessor.hpp:563

References Slic3r::GCodeProcessor::SeamsDetector::activate(), Slic3r::BridgeInfill, comment, Slic3r::Custom, Slic3r::ExternalPerimeter, Slic3r::GapFill, Slic3r::InternalInfill, Slic3r::Ironing, m_extrusion_role, m_seams_detector, Slic3r::None, Slic3r::OverhangPerimeter, Slic3r::Perimeter, set_extrusion_role(), Slic3r::Skirt, Slic3r::SolidInfill, Slic3r::SupportMaterial, Slic3r::SupportMaterialInterface, Slic3r::TopSolidInfill, and Slic3r::WipeTower.

Referenced by process_producers_tags().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_buffer()

void Slic3r::GCodeProcessor::process_buffer ( const std::string &  buffer)
1107{
1108 //FIXME maybe cache GCodeLine gline to be over multiple parse_buffer() invocations.
1109 m_parser.parse_buffer(buffer, [this](GCodeReader&, const GCodeReader::GCodeLine& line) {
1110 this->process_gcode_line(line, false);
1111 });
1112}
void process_gcode_line(const GCodeReader::GCodeLine &line, bool producers_enabled)
Definition GCodeProcessor.cpp:1424
void parse_buffer(const std::string &buffer, Callback callback)
Definition GCodeReader.hpp:101

References m_parser, Slic3r::GCodeReader::parse_buffer(), and process_gcode_line().

Referenced by Slic3r::GCode::GCodeOutputStream::write().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_craftware_tags()

bool Slic3r::GCodeProcessor::process_craftware_tags ( const std::string_view  comment)
private
2065{
2066 // segType -> extrusion role
2067 std::string tag = "segType:";
2068 size_t pos = comment.find(tag);
2069 if (pos != comment.npos) {
2070 const std::string_view type = comment.substr(pos + tag.length());
2071 if (type == "Skirt")
2073 else if (type == "Perimeter")
2075 else if (type == "HShell")
2076 set_extrusion_role(GCodeExtrusionRole::None); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2077 else if (type == "InnerHair")
2078 set_extrusion_role(GCodeExtrusionRole::None); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2079 else if (type == "Loop")
2080 set_extrusion_role(GCodeExtrusionRole::None); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2081 else if (type == "Infill")
2083 else if (type == "Raft")
2085 else if (type == "Support")
2087 else if (type == "SupportTouch")
2089 else if (type == "SoftSupport")
2091 else if (type == "Pillar")
2093 else {
2095 BOOST_LOG_TRIVIAL(warning) << "GCodeProcessor found unknown extrusion role: " << type;
2096 }
2097
2100
2101 return true;
2102 }
2103
2104 // layer
2105 pos = comment.find(" Layer #");
2106 if (pos == 0) {
2107 ++m_layer_id;
2108 return true;
2109 }
2110
2111 return false;
2112}

References Slic3r::GCodeProcessor::SeamsDetector::activate(), comment, Slic3r::ExternalPerimeter, Slic3r::InternalInfill, m_extrusion_role, m_layer_id, m_seams_detector, Slic3r::None, set_extrusion_role(), Slic3r::Skirt, Slic3r::SupportMaterial, Slic3r::SupportMaterialInterface, and Slic3r::WipeTower.

Referenced by process_producers_tags().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_cura_tags()

bool Slic3r::GCodeProcessor::process_cura_tags ( const std::string_view  comment)
private
1849{
1850 // TYPE -> extrusion role
1851 std::string tag = "TYPE:";
1852 size_t pos = comment.find(tag);
1853 if (pos != comment.npos) {
1854 const std::string_view type = comment.substr(pos + tag.length());
1855 if (type == "SKIRT")
1857 else if (type == "WALL-OUTER")
1859 else if (type == "WALL-INNER")
1861 else if (type == "SKIN")
1863 else if (type == "FILL")
1865 else if (type == "SUPPORT")
1867 else if (type == "SUPPORT-INTERFACE")
1869 else if (type == "PRIME-TOWER")
1871 else {
1873 BOOST_LOG_TRIVIAL(warning) << "GCodeProcessor found unknown extrusion role: " << type;
1874 }
1875
1878
1879 return true;
1880 }
1881
1882 // flavor
1883 tag = "FLAVOR:";
1884 pos = comment.find(tag);
1885 if (pos != comment.npos) {
1886 const std::string_view flavor = comment.substr(pos + tag.length());
1887 if (flavor == "BFB")
1888 m_flavor = gcfMarlinLegacy; // is this correct ?
1889 else if (flavor == "Mach3")
1891 else if (flavor == "Makerbot")
1893 else if (flavor == "UltiGCode")
1894 m_flavor = gcfMarlinLegacy; // is this correct ?
1895 else if (flavor == "Marlin(Volumetric)")
1896 m_flavor = gcfMarlinLegacy; // is this correct ?
1897 else if (flavor == "Griffin")
1898 m_flavor = gcfMarlinLegacy; // is this correct ?
1899 else if (flavor == "Repetier")
1901 else if (flavor == "RepRap")
1903 else if (flavor == "Marlin")
1905 else
1906 BOOST_LOG_TRIVIAL(warning) << "GCodeProcessor found unknown flavor: " << flavor;
1907
1908 return true;
1909 }
1910
1911 // layer
1912 tag = "LAYER:";
1913 pos = comment.find(tag);
1914 if (pos != comment.npos) {
1915 ++m_layer_id;
1916 return true;
1917 }
1918
1919 return false;
1920}
@ gcfMach3
Definition PrintConfig.hpp:35
@ gcfRepetier
Definition PrintConfig.hpp:35
@ gcfMakerWare
Definition PrintConfig.hpp:35

References Slic3r::GCodeProcessor::SeamsDetector::activate(), comment, Slic3r::ExternalPerimeter, Slic3r::gcfMach3, Slic3r::gcfMakerWare, Slic3r::gcfMarlinLegacy, Slic3r::gcfRepetier, Slic3r::gcfRepRapFirmware, Slic3r::InternalInfill, m_extrusion_role, m_flavor, m_layer_id, m_seams_detector, Slic3r::None, Slic3r::Perimeter, set_extrusion_role(), Slic3r::Skirt, Slic3r::SolidInfill, Slic3r::SupportMaterial, Slic3r::SupportMaterialInterface, and Slic3r::WipeTower.

Referenced by process_producers_tags().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_custom_gcode_time()

void Slic3r::GCodeProcessor::process_custom_gcode_time ( CustomGCode::Type  code)
private
4211{
4212 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
4213 TimeMachine& machine = m_time_processor.machines[i];
4214 if (!machine.enabled)
4215 continue;
4216
4217 TimeMachine::CustomGCodeTime& gcode_time = machine.gcode_time;
4218 gcode_time.needed = true;
4219 //FIXME this simulates st_synchronize! is it correct?
4220 // The estimated time may be longer than the real print time.
4221 machine.simulate_st_synchronize();
4222 if (gcode_time.cache != 0.0f) {
4223 gcode_time.times.push_back({ code, gcode_time.cache });
4224 gcode_time.cache = 0.0f;
4225 }
4226 }
4227}

References Slic3r::GCodeProcessor::TimeMachine::CustomGCodeTime::cache, Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeProcessor::TimeMachine::enabled, Slic3r::GCodeProcessor::TimeMachine::gcode_time, m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machines, Slic3r::GCodeProcessor::TimeMachine::CustomGCodeTime::needed, Slic3r::GCodeProcessor::TimeMachine::simulate_st_synchronize(), and Slic3r::GCodeProcessor::TimeMachine::CustomGCodeTime::times.

Referenced by process_tags().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_filaments()

void Slic3r::GCodeProcessor::process_filaments ( CustomGCode::Type  code)
private
4230{
4231 if (code == CustomGCode::ColorChange)
4233
4234 if (code == CustomGCode::ToolChange)
4236}
unsigned char m_extruder_id
Definition GCodeProcessor.hpp:564
@ ToolChange
Definition CustomGCode.hpp:17
void process_extruder_cache(unsigned char extruder_id)
Definition GCodeProcessor.cpp:403
void process_color_change_cache()
Definition GCodeProcessor.cpp:395

References Slic3r::CustomGCode::ColorChange, m_extruder_id, m_used_filaments, Slic3r::GCodeProcessor::UsedFilaments::process_color_change_cache(), Slic3r::GCodeProcessor::UsedFilaments::process_extruder_cache(), and Slic3r::CustomGCode::ToolChange.

Referenced by process_T(), and process_tags().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_file()

void Slic3r::GCodeProcessor::process_file ( const std::string &  filename,
std::function< void()>  cancel_callback = nullptr 
)
1026{
1027 CNumericLocalesSetter locales_setter;
1028
1029#if ENABLE_GCODE_VIEWER_STATISTICS
1030 m_start_time = std::chrono::high_resolution_clock::now();
1031#endif // ENABLE_GCODE_VIEWER_STATISTICS
1032
1033 // pre-processing
1034 // parse the gcode file to detect its producer
1035 {
1036 m_parser.parse_file_raw(filename, [this](GCodeReader& reader, const char *begin, const char *end) {
1037 begin = skip_whitespaces(begin, end);
1038 if (begin != end && *begin == ';') {
1039 // Comment.
1040 begin = skip_whitespaces(++ begin, end);
1041 end = remove_eols(begin, end);
1042 if (begin != end && detect_producer(std::string_view(begin, end - begin)))
1044 }
1045 });
1046 m_parser.reset();
1047
1048 // if the gcode was produced by PrusaSlicer,
1049 // extract the config from it
1051 DynamicPrintConfig config;
1052 config.apply(FullPrintConfig::defaults());
1053 // Silently substitute unknown values by new ones for loading configurations from PrusaSlicer's own G-code.
1054 // Showing substitution log or errors may make sense, but we are not really reading many values from the G-code config,
1055 // thus a probability of incorrect substitution is low and the G-code viewer is a consumer-only anyways.
1056 config.load_from_gcode_file(filename, ForwardCompatibilitySubstitutionRule::EnableSilent);
1057 apply_config(config);
1058 }
1059 else {
1061
1063 apply_config_simplify3d(filename);
1065 apply_config_superslicer(filename);
1067 apply_config_kissslicer(filename);
1068
1069 if (m_result.extruders_count == 0)
1071 }
1072 }
1073
1074 // process gcode
1075 m_result.filename = filename;
1078 size_t parse_line_callback_cntr = 10000;
1079 m_parser.parse_file(filename, [this, cancel_callback, &parse_line_callback_cntr](GCodeReader& reader, const GCodeReader::GCodeLine& line) {
1080 if (-- parse_line_callback_cntr == 0) {
1081 // Don't call the cancel_callback() too often, do it every at every 10000'th line.
1082 parse_line_callback_cntr = 10000;
1083 if (cancel_callback)
1084 cancel_callback();
1085 }
1086 this->process_gcode_line(line, true);
1087 }, m_result.lines_ends);
1088
1089 // Don't post-process the G-code to update time stamps.
1090 this->finalize(false);
1091}
static const size_t MIN_EXTRUDERS_COUNT
Definition GCodeProcessor.cpp:38
static const std::vector< std::string > DEFAULT_EXTRUDER_COLORS
Definition GCodeProcessor.cpp:44
bool detect_producer(const std::string_view comment)
Definition GCodeProcessor.cpp:2339
void initialize_result_moves()
Definition GCodeProcessor.hpp:642
void apply_config_superslicer(const std::string &filename)
Definition GCodeProcessor.cpp:1237
void apply_config_kissslicer(const std::string &filename)
Definition GCodeProcessor.cpp:1245
void finalize(bool post_process)
Definition GCodeProcessor.cpp:1114
void apply_config_simplify3d(const std::string &filename)
Definition GCodeProcessor.cpp:1328
bool parse_file(const std::string &file, callback_t callback)
Definition GCodeReader.cpp:193

References Slic3r::ConfigBase::apply(), apply_config(), apply_config_kissslicer(), apply_config_simplify3d(), apply_config_superslicer(), DEFAULT_EXTRUDER_COLORS, detect_producer(), Slic3r::EnableSilent, Slic3r::GCodeProcessorResult::extruder_colors, Slic3r::GCodeProcessorResult::extruders_count, Slic3r::GCodeProcessorResult::filename, finalize(), Slic3r::GCodeProcessorResult::id, initialize_result_moves(), KissSlicer, Slic3r::GCodeProcessorResult::lines_ends, Slic3r::ConfigBase::load_from_gcode_file(), m_parser, m_producer, m_result, MIN_EXTRUDERS_COUNT, Slic3r::GCodeReader::parse_file(), Slic3r::GCodeReader::parse_file_raw(), process_gcode_line(), PrusaSlicer, Slic3r::GCodeReader::quit_parsing(), Slic3r::remove_eols(), Slic3r::GCodeReader::reset(), s_result_id, Simplify3D, Slic3r::skip_whitespaces(), Slic3r, Slic3rPE, and SuperSlicer.

Referenced by Slic3r::GUI::Plater::load_gcode().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_G0()

void Slic3r::GCodeProcessor::process_G0 ( const GCodeReader::GCodeLine line)
private
2353{
2354 process_G1(line);
2355}
void process_G1(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2357

References process_G1().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_G1() [1/2]

void Slic3r::GCodeProcessor::process_G1 ( const GCodeReader::GCodeLine line)
private
2358{
2359 std::array<std::optional<double>, 4> g1_axes = { std::nullopt, std::nullopt, std::nullopt, std::nullopt };
2360 if (line.has_x()) g1_axes[X] = (double)line.x();
2361 if (line.has_y()) g1_axes[Y] = (double)line.y();
2362 if (line.has_z()) g1_axes[Z] = (double)line.z();
2363 if (line.has_e()) g1_axes[E] = (double)line.e();
2364 std::optional<double> g1_feedrate = std::nullopt;
2365 if (line.has_f()) g1_feedrate = (double)line.f();
2366 std::optional<std::string> g1_cmt = std::nullopt;
2367 if (!line.comment().empty()) g1_cmt = line.comment();
2368
2369 process_G1(g1_axes, g1_feedrate, g1_cmt);
2370}

References Slic3r::GCodeReader::GCodeLine::comment(), Slic3r::GCodeReader::GCodeLine::e(), Slic3r::E, Slic3r::GCodeReader::GCodeLine::f(), Slic3r::GCodeReader::GCodeLine::has_e(), Slic3r::GCodeReader::GCodeLine::has_f(), Slic3r::GCodeReader::GCodeLine::has_x(), Slic3r::GCodeReader::GCodeLine::has_y(), Slic3r::GCodeReader::GCodeLine::has_z(), process_G1(), Slic3r::GCodeReader::GCodeLine::x(), Slic3r::X, Slic3r::GCodeReader::GCodeLine::y(), Slic3r::Y, Slic3r::GCodeReader::GCodeLine::z(), and Slic3r::Z.

Referenced by process_G0(), process_G1(), process_G28(), process_G2_G3(), and process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_G1() [2/2]

void Slic3r::GCodeProcessor::process_G1 ( const std::array< std::optional< double >, 4 > &  axes = { std::nullopt, std::nullopt, std::nullopt, std::nullopt },
std::optional< double >  feedrate = std::nullopt,
std::optional< std::string >  cmt = std::nullopt 
)
private
2373{
2374 const float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
2375 const float filament_radius = 0.5f * filament_diameter;
2376 const float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
2377
2378 auto move_type = [this](const AxisCoords& delta_pos) {
2379 if (m_wiping)
2380 return EMoveType::Wipe;
2381 else if (delta_pos[E] < 0.0f)
2382 return (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f || delta_pos[Z] != 0.0f) ? EMoveType::Travel : EMoveType::Retract;
2383 else if (delta_pos[E] > 0.0f) {
2384 if (delta_pos[X] == 0.0f && delta_pos[Y] == 0.0f)
2385 return (delta_pos[Z] == 0.0f) ? EMoveType::Unretract : EMoveType::Travel;
2386 else if (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f)
2387 return EMoveType::Extrude;
2388 }
2389 else if (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f || delta_pos[Z] != 0.0f)
2390 return EMoveType::Travel;
2391
2392 return EMoveType::Noop;
2393 };
2394
2395 auto extract_absolute_position_on_axis = [&](Axis axis, std::optional<double> value, double area_filament_cross_section)
2396 {
2397 if (value.has_value()) {
2399 if (axis == E)
2401
2402 const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0;
2403 double ret = *value * lengthsScaleFactor;
2404 if (axis == E && m_use_volumetric_e)
2405 ret /= area_filament_cross_section;
2406 return is_relative ? m_start_position[axis] + ret : m_origin[axis] + ret;
2407 }
2408 else
2409 return m_start_position[axis];
2410 };
2411
2412 ++m_g1_line_id;
2413
2414 // enable processing of lines M201/M203/M204/M205
2416
2417 // updates axes positions from line
2418 for (unsigned char a = X; a <= E; ++a) {
2419 m_end_position[a] = extract_absolute_position_on_axis((Axis)a, axes[a], double(area_filament_cross_section));
2420 }
2421
2422 // updates feedrate from line, if present
2423 if (feedrate.has_value())
2425
2426 // calculates movement deltas
2427 AxisCoords delta_pos;
2428 for (unsigned char a = X; a <= E; ++a)
2429 delta_pos[a] = m_end_position[a] - m_start_position[a];
2430
2431 if (std::all_of(delta_pos.begin(), delta_pos.end(), [](double d) { return d == 0.; }))
2432 return;
2433
2434 const float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
2435
2436 if (volume_extruded_filament != 0.)
2437 m_used_filaments.increase_caches(volume_extruded_filament, m_extruder_id, area_filament_cross_section * m_parking_position,
2438 area_filament_cross_section * m_extra_loading_move);
2439
2440 const EMoveType type = move_type(delta_pos);
2441 if (type == EMoveType::Extrude) {
2442 const float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
2443 const float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
2444
2445 // volume extruded filament / tool displacement = area toolpath cross section
2446 m_mm3_per_mm = area_toolpath_cross_section;
2447#if ENABLE_GCODE_VIEWER_DATA_CHECKING
2448 m_mm3_per_mm_compare.update(area_toolpath_cross_section, m_extrusion_role);
2449#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
2450
2451 if (m_forced_height > 0.0f)
2453 else if (m_layer_id == 0)
2455 else if (!cmt.has_value() || *cmt != INTERNAL_G2G3_TAG) {
2456 if (m_end_position[Z] > m_extruded_last_z + EPSILON && delta_pos[Z] == 0.0)
2458 }
2459
2460 if (m_height == 0.0f)
2462
2465
2466 if (!cmt.has_value() || *cmt != INTERNAL_G2G3_TAG)
2469
2470#if ENABLE_GCODE_VIEWER_DATA_CHECKING
2471 m_height_compare.update(m_height, m_extrusion_role);
2472#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
2473
2474 if (m_forced_width > 0.0f)
2477 // cross section: rectangle
2478 m_width = delta_pos[E] * static_cast<float>(M_PI * sqr(1.05f * filament_radius)) / (delta_xyz * m_height);
2480 // cross section: circle
2481 m_width = static_cast<float>(m_result.filament_diameters[m_extruder_id]) * std::sqrt(delta_pos[E] / delta_xyz);
2482 else
2483 // cross section: rectangle + 2 semicircles
2484 m_width = delta_pos[E] * static_cast<float>(M_PI * sqr(filament_radius)) / (delta_xyz * m_height) + static_cast<float>(1.0 - 0.25 * M_PI) * m_height;
2485
2486 if (m_width == 0.0f)
2488
2489 // clamp width to avoid artifacts which may arise from wrong values of m_height
2490 m_width = std::min(m_width, std::max(2.0f, 4.0f * m_height));
2491
2492#if ENABLE_GCODE_VIEWER_DATA_CHECKING
2493 m_width_compare.update(m_width, m_extrusion_role);
2494#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
2495 }
2496
2497 // time estimate section
2498 auto move_length = [](const AxisCoords& delta_pos) {
2499 const float sq_xyz_length = sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]);
2500 return (sq_xyz_length > 0.0f) ? std::sqrt(sq_xyz_length) : std::abs(delta_pos[E]);
2501 };
2502
2503 auto is_extrusion_only_move = [](const AxisCoords& delta_pos) {
2504 return delta_pos[X] == 0.0f && delta_pos[Y] == 0.0f && delta_pos[Z] == 0.0f && delta_pos[E] != 0.0f;
2505 };
2506
2507 const float distance = move_length(delta_pos);
2508 assert(distance != 0.0f);
2509 const float inv_distance = 1.0f / distance;
2510
2511 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
2512 TimeMachine& machine = m_time_processor.machines[i];
2513 if (!machine.enabled)
2514 continue;
2515
2516 TimeMachine::State& curr = machine.curr;
2517 TimeMachine::State& prev = machine.prev;
2518 std::vector<TimeBlock>& blocks = machine.blocks;
2519
2520 curr.feedrate = (delta_pos[E] == 0.0f) ? minimum_travel_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), m_feedrate) :
2521 minimum_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), m_feedrate);
2522
2523 TimeBlock block;
2524 block.move_type = type;
2525 block.role = m_extrusion_role;
2526 block.distance = distance;
2527 block.g1_line_id = m_g1_line_id;
2528 block.layer_id = std::max<unsigned int>(1, m_layer_id);
2529
2530 // calculates block cruise feedrate
2531 float min_feedrate_factor = 1.0f;
2532 for (unsigned char a = X; a <= E; ++a) {
2533 curr.axis_feedrate[a] = curr.feedrate * delta_pos[a] * inv_distance;
2534 if (a == E)
2535 curr.axis_feedrate[a] *= machine.extrude_factor_override_percentage;
2536
2537 curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]);
2538 if (curr.abs_axis_feedrate[a] != 0.0f) {
2539 const float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
2540 if (axis_max_feedrate != 0.0f)
2541 min_feedrate_factor = std::min<float>(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
2542 }
2543 }
2544
2545 block.feedrate_profile.cruise = min_feedrate_factor * curr.feedrate;
2546
2547 if (min_feedrate_factor < 1.0f) {
2548 for (unsigned char a = X; a <= E; ++a) {
2549 curr.axis_feedrate[a] *= min_feedrate_factor;
2550 curr.abs_axis_feedrate[a] *= min_feedrate_factor;
2551 }
2552 }
2553
2554 // calculates block acceleration
2555 float acceleration = (type == EMoveType::Travel) ? get_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)) :
2556 (is_extrusion_only_move(delta_pos) ? get_retract_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)) :
2557 get_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)));
2558
2559 for (unsigned char a = X; a <= E; ++a) {
2560 const float axis_max_acceleration = get_axis_max_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
2561 if (acceleration * std::abs(delta_pos[a]) * inv_distance > axis_max_acceleration)
2562 acceleration = axis_max_acceleration;
2563 }
2564
2565 block.acceleration = acceleration;
2566
2567 // calculates block exit feedrate
2568 curr.safe_feedrate = block.feedrate_profile.cruise;
2569
2570 for (unsigned char a = X; a <= E; ++a) {
2571 const float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
2572 if (curr.abs_axis_feedrate[a] > axis_max_jerk)
2573 curr.safe_feedrate = std::min(curr.safe_feedrate, axis_max_jerk);
2574 }
2575
2576 block.feedrate_profile.exit = curr.safe_feedrate;
2577
2578 static const float PREVIOUS_FEEDRATE_THRESHOLD = 0.0001f;
2579
2580 // calculates block entry feedrate
2581 float vmax_junction = curr.safe_feedrate;
2582 if (!blocks.empty() && prev.feedrate > PREVIOUS_FEEDRATE_THRESHOLD) {
2583 const bool prev_speed_larger = prev.feedrate > block.feedrate_profile.cruise;
2584 const float smaller_speed_factor = prev_speed_larger ? (block.feedrate_profile.cruise / prev.feedrate) : (prev.feedrate / block.feedrate_profile.cruise);
2585 // Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
2586 vmax_junction = prev_speed_larger ? block.feedrate_profile.cruise : prev.feedrate;
2587
2588 float v_factor = 1.0f;
2589 bool limited = false;
2590
2591 for (unsigned char a = X; a <= E; ++a) {
2592 // Limit an axis. We have to differentiate coasting from the reversal of an axis movement, or a full stop.
2593 float v_exit = prev.axis_feedrate[a];
2594 float v_entry = curr.axis_feedrate[a];
2595
2596 if (prev_speed_larger)
2597 v_exit *= smaller_speed_factor;
2598
2599 if (limited) {
2600 v_exit *= v_factor;
2601 v_entry *= v_factor;
2602 }
2603
2604 // Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
2605 const float jerk =
2606 (v_exit > v_entry) ?
2607 ((v_entry > 0.0f || v_exit < 0.0f) ?
2608 // coasting
2609 (v_exit - v_entry) :
2610 // axis reversal
2611 std::max(v_exit, -v_entry)) :
2612 // v_exit <= v_entry
2613 ((v_entry < 0.0f || v_exit > 0.0f) ?
2614 // coasting
2615 (v_entry - v_exit) :
2616 // axis reversal
2617 std::max(-v_exit, v_entry));
2618
2619 const float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
2620 if (jerk > axis_max_jerk) {
2621 v_factor *= axis_max_jerk / jerk;
2622 limited = true;
2623 }
2624 }
2625
2626 if (limited)
2627 vmax_junction *= v_factor;
2628
2629 // Now the transition velocity is known, which maximizes the shared exit / entry velocity while
2630 // respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
2631 const float vmax_junction_threshold = vmax_junction * 0.99f;
2632
2633 // Not coasting. The machine will stop and start the movements anyway, better to start the segment from start.
2634 if (prev.safe_feedrate > vmax_junction_threshold && curr.safe_feedrate > vmax_junction_threshold)
2635 vmax_junction = curr.safe_feedrate;
2636 }
2637
2638 const float v_allowable = max_allowable_speed(-acceleration, curr.safe_feedrate, block.distance);
2639 block.feedrate_profile.entry = std::min(vmax_junction, v_allowable);
2640
2641 block.max_entry_speed = vmax_junction;
2642 block.flags.nominal_length = (block.feedrate_profile.cruise <= v_allowable);
2643 block.flags.recalculate = true;
2644 block.safe_feedrate = curr.safe_feedrate;
2645
2646 // calculates block trapezoid
2647 block.calculate_trapezoid();
2648
2649 // updates previous
2650 prev = curr;
2651
2652 blocks.push_back(block);
2653
2655 machine.calculate_time(TimeProcessor::Planner::queue_size);
2656 }
2657
2659 // check for seam starting vertex
2662 // check for seam ending vertex and store the resulting move
2664 auto set_end_position = [this](const Vec3f& pos) {
2665 m_end_position[X] = pos.x(); m_end_position[Y] = pos.y(); m_end_position[Z] = pos.z();
2666 };
2667
2668 const Vec3f curr_pos(m_end_position[X], m_end_position[Y], m_end_position[Z]);
2669 const Vec3f new_pos = m_result.moves.back().position - m_extruder_offsets[m_extruder_id];
2670 const std::optional<Vec3f> first_vertex = m_seams_detector.get_first_vertex();
2671 // the threshold value = 0.0625f == 0.25 * 0.25 is arbitrary, we may find some smarter condition later
2672
2673 if ((new_pos - *first_vertex).squaredNorm() < 0.0625f) {
2674 set_end_position(0.5f * (new_pos + *first_vertex) + m_z_offset * Vec3f::UnitZ());
2676 set_end_position(curr_pos);
2677 }
2678
2680 }
2681 }
2685 }
2686
2688 if (m_result.spiral_vase_layers.back().first == FLT_MAX && delta_pos[Z] >= 0.0)
2689 // replace layer height placeholder with correct value
2690 m_result.spiral_vase_layers.back().first = static_cast<float>(m_end_position[Z]);
2691 if (!m_result.moves.empty())
2692 m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1;
2693 }
2694
2695 // store move
2696 store_move_vertex(type, cmt.has_value() && *cmt == INTERNAL_G2G3_TAG);
2697}
EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL EIGEN_DEVICE_FUNC BlockXpr block(Index startRow, Index startCol, Index blockRows, Index blockCols)
This is the const version of block(Index,Index,Index,Index). *‍/.
Definition BlockMethods.h:64
static const float DEFAULT_TOOLPATH_HEIGHT
Definition GCodeProcessor.cpp:30
static const float DEFAULT_TOOLPATH_WIDTH
Definition GCodeProcessor.cpp:29
static const float MMMIN_TO_MMSEC
Definition GCodeProcessor.cpp:33
static const std::string INTERNAL_G2G3_TAG
Definition GCodeProcessor.cpp:46
void update(float height)
Definition GCodeProcessor.hpp:438
bool has_first_vertex() const
Definition GCodeProcessor.hpp:418
bool is_active() const
Definition GCodeProcessor.hpp:417
void set_first_vertex(const Vec3f &vertex)
Definition GCodeProcessor.hpp:415
std::optional< Vec3f > get_first_vertex() const
Definition GCodeProcessor.hpp:414
float m_width
Definition GCodeProcessor.hpp:556
float get_axis_max_feedrate(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const
Definition GCodeProcessor.cpp:4106
float get_axis_max_jerk(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const
Definition GCodeProcessor.cpp:4130
float get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
Definition GCodeProcessor.cpp:4142
float minimum_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const
Definition GCodeProcessor.cpp:4090
double extract_absolute_position_on_axis(Axis axis, const GCodeReader::GCodeLine &line, double area_filament_cross_section)
Definition GCodeProcessor.cpp:4268
FeedMultiply m_feed_multiply
Definition GCodeProcessor.hpp:555
unsigned int m_g1_line_id
Definition GCodeProcessor.hpp:574
bool m_wiping
Definition GCodeProcessor.hpp:540
float m_mm3_per_mm
Definition GCodeProcessor.hpp:560
float get_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
Definition GCodeProcessor.cpp:4174
float m_forced_width
Definition GCodeProcessor.hpp:558
float m_forced_height
Definition GCodeProcessor.hpp:559
std::array< double, 4 > AxisCoords
Definition GCodeProcessor.hpp:201
float get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
Definition GCodeProcessor.cpp:4158
float minimum_travel_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const
Definition GCodeProcessor.cpp:4098
void store_move_vertex(EMoveType type, bool internal_only=false)
Definition GCodeProcessor.cpp:4048
float m_feedrate
Definition GCodeProcessor.hpp:544
float get_axis_max_acceleration(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const
Definition GCodeProcessor.cpp:4118
float m_extruded_last_z
Definition GCodeProcessor.hpp:572
AxisCoords m_end_position
Definition GCodeProcessor.hpp:536
float m_height
Definition GCodeProcessor.hpp:557
static constexpr double EPSILON
Definition libslic3r.h:51
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half abs(const half &a)
Definition Half.h:445
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half() max(const half &a, const half &b)
Definition Half.h:516
filament_diameter((ConfigOptionFloats, filament_density))((ConfigOptionStrings
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:49
static float max_allowable_speed(float acceleration, float target_velocity, float distance)
Definition GCodeProcessor.cpp:103
double distance(const P &p1, const P &p2)
Definition geometry_traits.hpp:329
TPoint< P > back(const P &p)
Definition geometry_traits.hpp:873
float current
Definition GCodeProcessor.hpp:547
static constexpr size_t refresh_threshold
Definition GCodeProcessor.hpp:353
static constexpr size_t queue_size
Definition GCodeProcessor.hpp:350
void increase_caches(double extruded_volume, unsigned char extruder_id, double parking_volume, double extra_loading_volume)
Definition GCodeProcessor.cpp:373
std::vector< std::pair< float, std::pair< size_t, size_t > > > spiral_vase_layers
Definition GCodeProcessor.hpp:154

References Slic3r::GCodeProcessor::TimeMachine::State::abs_axis_feedrate, Slic3r::GCodeProcessor::SeamsDetector::activate(), Slic3r::GCodeProcessor::TimeMachine::State::axis_feedrate, block(), Slic3r::GCodeProcessor::TimeMachine::blocks, Slic3r::BridgeInfill, Slic3r::GCodeProcessor::TimeMachine::calculate_time(), Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeProcessor::TimeMachine::curr, Slic3r::GCodeProcessor::FeedMultiply::current, Slic3r::Custom, DEFAULT_TOOLPATH_HEIGHT, DEFAULT_TOOLPATH_WIDTH, Slic3r::E, Slic3r::GCodeProcessor::TimeMachine::enabled, EPSILON, Slic3r::ExternalPerimeter, extract_absolute_position_on_axis(), Slic3r::Extrude, Slic3r::GCodeProcessor::TimeMachine::extrude_factor_override_percentage, Slic3r::GCodeProcessor::TimeMachine::State::feedrate, Slic3r::filament_diameter(), Slic3r::GCodeProcessorResult::filament_diameters, get_acceleration(), get_axis_max_acceleration(), get_axis_max_feedrate(), get_axis_max_jerk(), Slic3r::GCodeProcessor::SeamsDetector::get_first_vertex(), get_retract_acceleration(), get_travel_acceleration(), Slic3r::GCodeProcessor::SeamsDetector::has_first_vertex(), Inches, INCHES_TO_MM, Slic3r::GCodeProcessor::UsedFilaments::increase_caches(), INTERNAL_G2G3_TAG, Slic3r::GCodeProcessor::SeamsDetector::is_active(), m_e_local_positioning_type, m_end_position, m_extra_loading_move, m_extruded_last_z, m_extruder_id, m_extruder_offsets, m_extrusion_role, m_feed_multiply, m_feedrate, m_first_layer_height, m_forced_height, m_forced_width, m_g1_line_id, m_global_positioning_type, m_height, m_layer_id, m_mm3_per_mm, m_options_z_corrector, m_origin, m_parking_position, M_PI, m_result, m_seams_detector, m_spiral_vase_active, m_start_position, m_time_processor, m_units, m_use_volumetric_e, m_used_filaments, m_width, m_wiping, m_z_offset, Slic3r::GCodeProcessor::TimeProcessor::machine_envelope_processing_enabled, Slic3r::GCodeProcessor::TimeProcessor::machines, Slic3r::max_allowable_speed(), minimum_feedrate(), minimum_travel_feedrate(), MMMIN_TO_MMSEC, Slic3r::GCodeProcessorResult::moves, Slic3r::None, Slic3r::Noop, Slic3r::OverhangPerimeter, Slic3r::GCodeProcessor::TimeMachine::prev, Slic3r::GCodeProcessor::TimeProcessor::Planner::queue_size, Slic3r::GCodeProcessor::TimeProcessor::Planner::refresh_threshold, Relative, Slic3r::Retract, Slic3r::GCodeProcessor::TimeMachine::State::safe_feedrate, Slic3r::Seam, Slic3r::GCodeProcessor::SeamsDetector::set_first_vertex(), Slic3r::GCodeProcessorResult::spiral_vase_layers, Slic3r::sqr(), store_move_vertex(), Slic3r::Travel, Slic3r::Unretract, Slic3r::GCodeProcessor::OptionsZCorrector::update(), Slic3r::Wipe, Slic3r::X, Slic3r::Y, and Slic3r::Z.

+ Here is the call graph for this function:

◆ process_G10()

void Slic3r::GCodeProcessor::process_G10 ( const GCodeReader::GCodeLine line)
private
2889{
2890 if (m_flavor == gcfRepRapFirmware) {
2891 // similar to M104/M109
2892 float new_temp;
2893 if (line.has_value('S', new_temp)) {
2894 size_t id = m_extruder_id;
2895 float val;
2896 if (line.has_value('P', val)) {
2897 const size_t eid = static_cast<size_t>(val);
2898 if (eid < m_extruder_temps.size())
2899 id = eid;
2900 }
2901
2902 m_extruder_temps[id] = new_temp;
2903 return;
2904 }
2905 }
2906
2907 // stores retract move
2909}

References Slic3r::gcfRepRapFirmware, Slic3r::GCodeReader::GCodeLine::has_value(), m_extruder_id, m_extruder_temps, m_flavor, Slic3r::Retract, and store_move_vertex().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_G11()

void Slic3r::GCodeProcessor::process_G11 ( const GCodeReader::GCodeLine line)
private
2912{
2913 // stores unretract move
2915}

References store_move_vertex(), and Slic3r::Unretract.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_G20()

void Slic3r::GCodeProcessor::process_G20 ( const GCodeReader::GCodeLine line)
private
2918{
2920}

References Inches, and m_units.

Referenced by process_gcode_line().

+ Here is the caller graph for this function:

◆ process_G21()

void Slic3r::GCodeProcessor::process_G21 ( const GCodeReader::GCodeLine line)
private
2923{
2925}

References m_units, and Millimeters.

Referenced by process_gcode_line().

+ Here is the caller graph for this function:

◆ process_G22()

void Slic3r::GCodeProcessor::process_G22 ( const GCodeReader::GCodeLine line)
private
2928{
2929 // stores retract move
2931}

References Slic3r::Retract, and store_move_vertex().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_G23()

void Slic3r::GCodeProcessor::process_G23 ( const GCodeReader::GCodeLine line)
private
2934{
2935 // stores unretract move
2937}

References store_move_vertex(), and Slic3r::Unretract.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_G28()

void Slic3r::GCodeProcessor::process_G28 ( const GCodeReader::GCodeLine line)
private
2940{
2941 std::string_view cmd = line.cmd();
2942 std::string new_line_raw = { cmd.data(), cmd.size() };
2943 bool found = false;
2944 if (line.has('X')) {
2945 new_line_raw += " X0";
2946 found = true;
2947 }
2948 if (line.has('Y')) {
2949 new_line_raw += " Y0";
2950 found = true;
2951 }
2952 if (line.has('Z')) {
2953 new_line_raw += " Z0";
2954 found = true;
2955 }
2956 if (!found)
2957 new_line_raw += " X0 Y0 Z0";
2958
2959 GCodeReader::GCodeLine new_gline;
2960 GCodeReader reader;
2961 reader.parse_line(new_line_raw, [&](GCodeReader& reader, const GCodeReader::GCodeLine& gline) { new_gline = gline; });
2962 process_G1(new_gline);
2963}

References Slic3r::GCodeReader::GCodeLine::cmd(), cmd, Slic3r::GCodeReader::GCodeLine::has(), Slic3r::GCodeReader::parse_line(), and process_G1().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_G2_G3()

void Slic3r::GCodeProcessor::process_G2_G3 ( const GCodeReader::GCodeLine line,
bool  clockwise 
)
private
2700{
2701 if (!line.has('I') || !line.has('J'))
2702 return;
2703
2704 // relative center
2705 Vec3f rel_center = Vec3f::Zero();
2706 if (!line.has_value('I', rel_center.x()) || !line.has_value('J', rel_center.y()))
2707 return;
2708
2709 // scale center, if needed
2710 if (m_units == EUnits::Inches)
2711 rel_center *= INCHES_TO_MM;
2712
2713 struct Arc
2714 {
2715 Vec3d start{ Vec3d::Zero() };
2716 Vec3d end{ Vec3d::Zero() };
2717 Vec3d center{ Vec3d::Zero() };
2718
2719 double angle{ 0.0 };
2720 double delta_x() const { return end.x() - start.x(); }
2721 double delta_y() const { return end.y() - start.y(); }
2722 double delta_z() const { return end.z() - start.z(); }
2723
2724 double length() const { return angle * start_radius(); }
2725 double travel_length() const { return std::sqrt(sqr(length()) + sqr(delta_z())); }
2726 double start_radius() const { return (start - center).norm(); }
2727 double end_radius() const { return (end - center).norm(); }
2728
2729 Vec3d relative_start() const { return start - center; }
2730 Vec3d relative_end() const { return end - center; }
2731
2732 bool is_full_circle() const { return std::abs(delta_x()) < EPSILON && std::abs(delta_y()) < EPSILON; }
2733 };
2734
2735 Arc arc;
2736
2737 // arc start endpoint
2739
2740 // arc center
2741 arc.center = arc.start + rel_center.cast<double>();
2742
2743 const float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
2744 const float filament_radius = 0.5f * filament_diameter;
2745 const float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
2746
2747 AxisCoords end_position = m_start_position;
2748 for (unsigned char a = X; a <= E; ++a) {
2749 end_position[a] = extract_absolute_position_on_axis((Axis)a, line, double(area_filament_cross_section));
2750 }
2751
2752 // arc end endpoint
2753 arc.end = Vec3d(end_position[X], end_position[Y], end_position[Z]);
2754
2755 // radii
2756 if (std::abs(arc.end_radius() - arc.start_radius()) > EPSILON) {
2757 // what to do ???
2758 }
2759
2760 // updates feedrate from line
2761 std::optional<float> feedrate;
2762 if (line.has_f())
2763 feedrate = m_feed_multiply.current * line.f() * MMMIN_TO_MMSEC;
2764
2765 // updates extrusion from line
2766 std::optional<float> extrusion;
2767 if (line.has_e())
2768 extrusion = end_position[E] - m_start_position[E];
2769
2770 // relative arc endpoints
2771 const Vec3d rel_arc_start = arc.relative_start();
2772 const Vec3d rel_arc_end = arc.relative_end();
2773
2774 // arc angle
2775 if (arc.is_full_circle())
2776 arc.angle = 2.0 * PI;
2777 else {
2778 arc.angle = std::atan2(rel_arc_start.x() * rel_arc_end.y() - rel_arc_start.y() * rel_arc_end.x(),
2779 rel_arc_start.x() * rel_arc_end.x() + rel_arc_start.y() * rel_arc_end.y());
2780 if (arc.angle < 0.0)
2781 arc.angle += 2.0 * PI;
2782 if (clockwise)
2783 arc.angle -= 2.0 * PI;
2784 }
2785
2786 const double travel_length = arc.travel_length();
2787 if (travel_length < 0.001)
2788 return;
2789
2790 auto adjust_target = [this, area_filament_cross_section](const AxisCoords& target, const AxisCoords& prev_position) {
2791 AxisCoords ret = target;
2793 for (unsigned char a = X; a <= E; ++a) {
2794 ret[a] -= prev_position[a];
2795 }
2796 }
2798 ret[E] -= prev_position[E];
2799
2801 ret[E] *= area_filament_cross_section;
2802
2803 const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0;
2804 for (unsigned char a = X; a <= E; ++a) {
2805 ret[a] /= lengthsScaleFactor;
2806 }
2807 return ret;
2808 };
2809
2810 auto internal_only_g1_line = [this](const AxisCoords& target, bool has_z, const std::optional<float>& feedrate, const std::optional<float>& extrusion) {
2811 std::array<std::optional<double>, 4> g1_axes = { target[X], target[Y], std::nullopt, std::nullopt };
2812 std::optional<double> g1_feedrate = std::nullopt;
2813 if (has_z)
2814 g1_axes[Z] = target[Z];
2815 if (feedrate.has_value())
2816 g1_feedrate = (double)*feedrate;
2817 if (extrusion.has_value())
2818 g1_axes[E] = target[E];
2819 std::optional<std::string> g1_cmt = INTERNAL_G2G3_TAG;
2820
2821 process_G1(g1_axes, g1_feedrate, g1_cmt);
2822 };
2823
2824 // calculate arc segments
2825 // reference:
2826 // Prusa-Firmware\Firmware\motion_control.cpp - mc_arc()
2827 // https://github.com/prusa3d/Prusa-Firmware/blob/MK3/Firmware/motion_control.cpp
2828
2829 // segments count
2830 static const double MM_PER_ARC_SEGMENT = 1.0;
2831 const size_t segments = std::max<size_t>(std::floor(travel_length / MM_PER_ARC_SEGMENT), 1);
2832
2833 const double inv_segment = 1.0 / double(segments);
2834 const double theta_per_segment = arc.angle * inv_segment;
2835 const double z_per_segment = arc.delta_z() * inv_segment;
2836 const double extruder_per_segment = (extrusion.has_value()) ? *extrusion * inv_segment : 0.0;
2837
2838 const double cos_T = 1.0 - 0.5 * sqr(theta_per_segment); // Small angle approximation
2839 const double sin_T = theta_per_segment;
2840
2841 AxisCoords prev_target = m_start_position;
2842 AxisCoords arc_target;
2843
2844 // Initialize the linear axis
2845 arc_target[Z] = m_start_position[Z];
2846
2847 // Initialize the extruder axis
2848 arc_target[E] = m_start_position[E];
2849
2850 static const size_t N_ARC_CORRECTION = 25;
2851 Vec3d curr_rel_arc_start = arc.relative_start();
2852 size_t count = 0;
2853
2854 for (size_t i = 1; i < segments; ++i) {
2855 if (count < N_ARC_CORRECTION) {
2856 // Apply vector rotation matrix
2857 const float r_axisi = curr_rel_arc_start.x() * sin_T + curr_rel_arc_start.y() * cos_T;
2858 curr_rel_arc_start.x() = curr_rel_arc_start.x() * cos_T - curr_rel_arc_start.y() * sin_T;
2859 curr_rel_arc_start.y() = r_axisi;
2860 ++count;
2861 }
2862 else {
2863 // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
2864 // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
2865 const double cos_Ti = ::cos(i * theta_per_segment);
2866 const double sin_Ti = ::sin(i * theta_per_segment);
2867 curr_rel_arc_start.x() = -double(rel_center.x()) * cos_Ti + double(rel_center.y()) * sin_Ti;
2868 curr_rel_arc_start.y() = -double(rel_center.x()) * sin_Ti - double(rel_center.y()) * cos_Ti;
2869 count = 0;
2870 }
2871
2872 // Update arc_target location
2873 arc_target[X] = arc.center.x() + curr_rel_arc_start.x();
2874 arc_target[Y] = arc.center.y() + curr_rel_arc_start.y();
2875 arc_target[Z] += z_per_segment;
2876 arc_target[E] += extruder_per_segment;
2877
2878 m_start_position = m_end_position; // this is required because we are skipping the call to process_gcode_line()
2879 internal_only_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, (i == 1) ? feedrate : std::nullopt, extrusion);
2880 prev_target = arc_target;
2881 }
2882
2883 // Ensure last segment arrives at target location.
2884 m_start_position = m_end_position; // this is required because we are skipping the call to process_gcode_line()
2885 internal_only_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, (segments == 1) ? feedrate : std::nullopt, extrusion);
2886}
EIGEN_DEVICE_FUNC const CosReturnType cos() const
Definition ArrayCwiseUnaryOps.h:202
EIGEN_DEVICE_FUNC const SinReturnType sin() const
Definition ArrayCwiseUnaryOps.h:220
static constexpr double PI
Definition libslic3r.h:58
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:52
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:112
double length(std::vector< SurfacePoint > &path)
Definition exact_geodesic.cpp:1682
IGL_INLINE void count(const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
Definition count.cpp:12

References Slic3r::angle(), cos(), Slic3r::GCodeProcessor::FeedMultiply::current, Slic3r::E, EPSILON, extract_absolute_position_on_axis(), Slic3r::GCodeReader::GCodeLine::f(), Slic3r::filament_diameter(), Slic3r::GCodeProcessorResult::filament_diameters, Slic3r::GCodeReader::GCodeLine::has(), Slic3r::GCodeReader::GCodeLine::has_e(), Slic3r::GCodeReader::GCodeLine::has_f(), Slic3r::GCodeReader::GCodeLine::has_value(), Inches, INCHES_TO_MM, INTERNAL_G2G3_TAG, m_e_local_positioning_type, m_end_position, m_extruder_id, m_feed_multiply, m_global_positioning_type, M_PI, m_result, m_start_position, m_units, m_use_volumetric_e, MMMIN_TO_MMSEC, PI, process_G1(), Relative, sin(), Slic3r::sqr(), Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_G60()

void Slic3r::GCodeProcessor::process_G60 ( const GCodeReader::GCodeLine line)
private
2966{
2969}
AxisCoords m_saved_position
Definition GCodeProcessor.hpp:537

References Slic3r::gcfMarlinFirmware, Slic3r::gcfMarlinLegacy, m_end_position, m_flavor, and m_saved_position.

Referenced by process_gcode_line().

+ Here is the caller graph for this function:

◆ process_G61()

void Slic3r::GCodeProcessor::process_G61 ( const GCodeReader::GCodeLine line)
private
2972{
2974 bool modified = false;
2975 if (line.has_x()) {
2977 modified = true;
2978 }
2979 if (line.has_y()) {
2981 modified = true;
2982 }
2983 if (line.has_z()) {
2985 modified = true;
2986 }
2987 if (line.has_e()) {
2989 modified = true;
2990 }
2991 if (line.has_f())
2992 m_feedrate = m_feed_multiply.current * line.f();
2993
2994 if (!modified)
2996
2997
2999 }
3000}

References Slic3r::GCodeProcessor::FeedMultiply::current, Slic3r::E, Slic3r::GCodeReader::GCodeLine::f(), Slic3r::gcfMarlinFirmware, Slic3r::gcfMarlinLegacy, Slic3r::GCodeReader::GCodeLine::has_e(), Slic3r::GCodeReader::GCodeLine::has_f(), Slic3r::GCodeReader::GCodeLine::has_x(), Slic3r::GCodeReader::GCodeLine::has_y(), Slic3r::GCodeReader::GCodeLine::has_z(), m_end_position, m_feed_multiply, m_feedrate, m_flavor, m_saved_position, store_move_vertex(), Slic3r::Travel, Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_G90()

void Slic3r::GCodeProcessor::process_G90 ( const GCodeReader::GCodeLine line)
private

References Absolute, and m_global_positioning_type.

Referenced by process_gcode_line().

+ Here is the caller graph for this function:

◆ process_G91()

void Slic3r::GCodeProcessor::process_G91 ( const GCodeReader::GCodeLine line)
private

References m_global_positioning_type, and Relative.

Referenced by process_gcode_line().

+ Here is the caller graph for this function:

◆ process_G92()

void Slic3r::GCodeProcessor::process_G92 ( const GCodeReader::GCodeLine line)
private
3013{
3014 float lengths_scale_factor = (m_units == EUnits::Inches) ? INCHES_TO_MM : 1.0f;
3015 bool any_found = false;
3016
3017 if (line.has_x()) {
3018 m_origin[X] = m_end_position[X] - line.x() * lengths_scale_factor;
3019 any_found = true;
3020 }
3021
3022 if (line.has_y()) {
3023 m_origin[Y] = m_end_position[Y] - line.y() * lengths_scale_factor;
3024 any_found = true;
3025 }
3026
3027 if (line.has_z()) {
3028 m_origin[Z] = m_end_position[Z] - line.z() * lengths_scale_factor;
3029 any_found = true;
3030 }
3031
3032 if (line.has_e()) {
3033 // extruder coordinate can grow to the point where its float representation does not allow for proper addition with small increments,
3034 // we set the value taken from the G92 line as the new current position for it
3035 m_end_position[E] = line.e() * lengths_scale_factor;
3036 any_found = true;
3037 }
3038 else
3040
3041 if (!any_found && !line.has_unknown_axis()) {
3042 // The G92 may be called for axes that PrusaSlicer does not recognize, for example see GH issue #3510,
3043 // where G92 A0 B0 is called although the extruder axis is till E.
3044 for (unsigned char a = X; a <= E; ++a) {
3046 }
3047 }
3048}
void simulate_st_synchronize(float additional_time=0.0f)
Definition GCodeProcessor.cpp:4238

References Slic3r::GCodeReader::GCodeLine::e(), Slic3r::E, Slic3r::GCodeReader::GCodeLine::has_e(), Slic3r::GCodeReader::GCodeLine::has_unknown_axis(), Slic3r::GCodeReader::GCodeLine::has_x(), Slic3r::GCodeReader::GCodeLine::has_y(), Slic3r::GCodeReader::GCodeLine::has_z(), Inches, INCHES_TO_MM, m_end_position, m_origin, m_units, simulate_st_synchronize(), Slic3r::GCodeReader::GCodeLine::x(), Slic3r::X, Slic3r::GCodeReader::GCodeLine::y(), Slic3r::Y, Slic3r::GCodeReader::GCodeLine::z(), and Slic3r::Z.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_gcode_line()

void Slic3r::GCodeProcessor::process_gcode_line ( const GCodeReader::GCodeLine line,
bool  producers_enabled 
)
private
1425{
1426/* std::cout << line.raw() << std::endl; */
1427
1428 ++m_line_id;
1429
1430 // update start position
1432
1433 const std::string_view cmd = line.cmd();
1434 if (cmd.length() > 1) {
1435 // process command lines
1436 switch (cmd[0])
1437 {
1438 case 'g':
1439 case 'G':
1440 switch (cmd.size()) {
1441 case 2:
1442 switch (cmd[1]) {
1443 case '0': { process_G0(line); break; } // Move
1444 case '1': { process_G1(line); break; } // Move
1445 case '2': { process_G2_G3(line, true); break; } // CW Arc Move
1446 case '3': { process_G2_G3(line, false); break; } // CCW Arc Move
1447 default: break;
1448 }
1449 break;
1450 case 3:
1451 switch (cmd[1]) {
1452 case '1':
1453 switch (cmd[2]) {
1454 case '0': { process_G10(line); break; } // Retract or Set tool temperature
1455 case '1': { process_G11(line); break; } // Unretract
1456 default: break;
1457 }
1458 break;
1459 case '2':
1460 switch (cmd[2]) {
1461 case '0': { process_G20(line); break; } // Set Units to Inches
1462 case '1': { process_G21(line); break; } // Set Units to Millimeters
1463 case '2': { process_G22(line); break; } // Firmware controlled retract
1464 case '3': { process_G23(line); break; } // Firmware controlled unretract
1465 case '8': { process_G28(line); break; } // Move to origin
1466 default: break;
1467 }
1468 break;
1469 case '6':
1470 switch (cmd[2]) {
1471 case '0': { process_G60(line); break; } // Save Current Position
1472 case '1': { process_G61(line); break; } // Return to Saved Position
1473 default: break;
1474 }
1475 break;
1476 case '9':
1477 switch (cmd[2]) {
1478 case '0': { process_G90(line); break; } // Set to Absolute Positioning
1479 case '1': { process_G91(line); break; } // Set to Relative Positioning
1480 case '2': { process_G92(line); break; } // Set Position
1481 default: break;
1482 }
1483 break;
1484 }
1485 break;
1486 default:
1487 break;
1488 }
1489 break;
1490 case 'm':
1491 case 'M':
1492 switch (cmd.size()) {
1493 case 2:
1494 switch (cmd[1]) {
1495 case '1': { process_M1(line); break; } // Sleep or Conditional stop
1496 default: break;
1497 }
1498 break;
1499 case 3:
1500 switch (cmd[1]) {
1501 case '8':
1502 switch (cmd[2]) {
1503 case '2': { process_M82(line); break; } // Set extruder to absolute mode
1504 case '3': { process_M83(line); break; } // Set extruder to relative mode
1505 default: break;
1506 }
1507 break;
1508 default:
1509 break;
1510 }
1511 break;
1512 case 4:
1513 switch (cmd[1]) {
1514 case '1':
1515 switch (cmd[2]) {
1516 case '0':
1517 switch (cmd[3]) {
1518 case '4': { process_M104(line); break; } // Set extruder temperature
1519 case '6': { process_M106(line); break; } // Set fan speed
1520 case '7': { process_M107(line); break; } // Disable fan
1521 case '8': { process_M108(line); break; } // Set tool (Sailfish)
1522 case '9': { process_M109(line); break; } // Set extruder temperature and wait
1523 default: break;
1524 }
1525 break;
1526 case '3':
1527 switch (cmd[3]) {
1528 case '2': { process_M132(line); break; } // Recall stored home offsets
1529 case '5': { process_M135(line); break; } // Set tool (MakerWare)
1530 default: break;
1531 }
1532 break;
1533 default:
1534 break;
1535 }
1536 break;
1537 case '2':
1538 switch (cmd[2]) {
1539 case '0':
1540 switch (cmd[3]) {
1541 case '1': { process_M201(line); break; } // Set max printing acceleration
1542 case '3': { process_M203(line); break; } // Set maximum feedrate
1543 case '4': { process_M204(line); break; } // Set default acceleration
1544 case '5': { process_M205(line); break; } // Advanced settings
1545 default: break;
1546 }
1547 break;
1548 case '2':
1549 switch (cmd[3]) {
1550 case '0': { process_M220(line); break; } // Set Feedrate Percentage
1551 case '1': { process_M221(line); break; } // Set extrude factor override percentage
1552 default: break;
1553 }
1554 break;
1555 default:
1556 break;
1557 }
1558 break;
1559 case '4':
1560 switch (cmd[2]) {
1561 case '0':
1562 switch (cmd[3]) {
1563 case '1': { process_M401(line); break; } // Repetier: Store x, y and z position
1564 case '2': { process_M402(line); break; } // Repetier: Go to stored position
1565 default: break;
1566 }
1567 break;
1568 default:
1569 break;
1570 }
1571 break;
1572 case '5':
1573 switch (cmd[2]) {
1574 case '6':
1575 switch (cmd[3]) {
1576 case '6': { process_M566(line); break; } // Set allowable instantaneous speed change
1577 default: break;
1578 }
1579 break;
1580 default:
1581 break;
1582 }
1583 break;
1584 case '7':
1585 switch (cmd[2]) {
1586 case '0':
1587 switch (cmd[3]) {
1588 case '2': { process_M702(line); break; } // Unload the current filament into the MK3 MMU2 unit at the end of print.
1589 default: break;
1590 }
1591 break;
1592 default:
1593 break;
1594 }
1595 break;
1596 default:
1597 break;
1598 }
1599 break;
1600 default:
1601 break;
1602 }
1603 break;
1604 case 't':
1605 case 'T':
1606 process_T(line); // Select Tool
1607 break;
1608 default:
1609 break;
1610 }
1611 }
1612 else {
1613 const std::string &comment = line.raw();
1614 if (comment.length() > 2 && comment.front() == ';')
1615 // Process tags embedded into comments. Tag comments always start at the start of a line
1616 // with a comment and continue with a tag without any whitespace separator.
1617 process_tags(comment.substr(1), producers_enabled);
1618 }
1619}
void process_G90(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3002
void process_M135(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3153
void process_M203(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3191
void process_M106(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3081
void process_G10(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2888
void process_G21(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2922
void process_M566(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3347
void process_M220(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3278
void process_G28(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2939
void process_M221(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3292
void process_G91(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3007
void process_G60(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2965
void process_M205(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3248
void process_M107(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3093
void process_M109(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3113
void process_G92(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3012
void process_M132(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3134
void process_M1(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3050
void process_M83(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3060
void process_M204(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3219
void process_G2_G3(const GCodeReader::GCodeLine &line, bool clockwise)
Definition GCodeProcessor.cpp:2699
void process_G22(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2927
unsigned int m_line_id
Definition GCodeProcessor.hpp:542
void process_M201(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3168
void process_M104(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3065
void process_G20(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2917
void process_T(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3375
void process_G11(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2911
void process_M82(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3055
void process_M402(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3315
void process_G23(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2933
void process_M401(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3304
void process_M702(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3364
void process_M108(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:3098
void process_G0(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2352
void process_tags(const std::string_view comment, bool producers_enabled)
Definition GCodeProcessor.cpp:1666
void process_G61(const GCodeReader::GCodeLine &line)
Definition GCodeProcessor.cpp:2971

References Slic3r::GCodeReader::GCodeLine::cmd(), cmd, comment, m_end_position, m_line_id, m_start_position, process_G0(), process_G1(), process_G10(), process_G11(), process_G20(), process_G21(), process_G22(), process_G23(), process_G28(), process_G2_G3(), process_G60(), process_G61(), process_G90(), process_G91(), process_G92(), process_M1(), process_M104(), process_M106(), process_M107(), process_M108(), process_M109(), process_M132(), process_M135(), process_M201(), process_M203(), process_M204(), process_M205(), process_M220(), process_M221(), process_M401(), process_M402(), process_M566(), process_M702(), process_M82(), process_M83(), process_T(), process_tags(), and Slic3r::GCodeReader::GCodeLine::raw().

Referenced by process_buffer(), and process_file().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_ideamaker_tags()

bool Slic3r::GCodeProcessor::process_ideamaker_tags ( const std::string_view  comment)
private
2115{
2116 // TYPE -> extrusion role
2117 std::string tag = "TYPE:";
2118 size_t pos = comment.find(tag);
2119 if (pos != comment.npos) {
2120 const std::string_view type = comment.substr(pos + tag.length());
2121 if (type == "RAFT")
2123 else if (type == "WALL-OUTER")
2125 else if (type == "WALL-INNER")
2127 else if (type == "SOLID-FILL")
2129 else if (type == "FILL")
2131 else if (type == "BRIDGE")
2133 else if (type == "SUPPORT")
2135 else {
2137 BOOST_LOG_TRIVIAL(warning) << "GCodeProcessor found unknown extrusion role: " << type;
2138 }
2139
2142
2143 return true;
2144 }
2145
2146 // geometry
2147 // width
2148 tag = "WIDTH:";
2149 pos = comment.find(tag);
2150 if (pos != comment.npos) {
2151 if (!parse_number(comment.substr(pos + tag.length()), m_forced_width))
2152 BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
2153 return true;
2154 }
2155
2156 // height
2157 tag = "HEIGHT:";
2158 pos = comment.find(tag);
2159 if (pos != comment.npos) {
2160 if (!parse_number(comment.substr(pos + tag.length()), m_forced_height))
2161 BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
2162 return true;
2163 }
2164
2165 // layer
2166 pos = comment.find("LAYER:");
2167 if (pos == 0) {
2168 ++m_layer_id;
2169 return true;
2170 }
2171
2172 return false;
2173}
static bool parse_number(const std::string_view sv, T &out)
Definition GCodeProcessor.cpp:1630

References Slic3r::GCodeProcessor::SeamsDetector::activate(), Slic3r::BridgeInfill, comment, error, Slic3r::ExternalPerimeter, Slic3r::InternalInfill, m_extrusion_role, m_forced_height, m_forced_width, m_layer_id, m_seams_detector, Slic3r::None, Slic3r::parse_number(), Slic3r::Perimeter, set_extrusion_role(), Slic3r::Skirt, Slic3r::SolidInfill, and Slic3r::SupportMaterial.

Referenced by process_producers_tags().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_kissslicer_tags()

bool Slic3r::GCodeProcessor::process_kissslicer_tags ( const std::string_view  comment)
private
2176{
2177 // extrusion roles
2178
2179 // ; 'Raft Path'
2180 size_t pos = comment.find(" 'Raft Path'");
2181 if (pos == 0) {
2183 return true;
2184 }
2185
2186 // ; 'Support Interface Path'
2187 pos = comment.find(" 'Support Interface Path'");
2188 if (pos == 0) {
2190 return true;
2191 }
2192
2193 // ; 'Travel/Ironing Path'
2194 pos = comment.find(" 'Travel/Ironing Path'");
2195 if (pos == 0) {
2197 return true;
2198 }
2199
2200 // ; 'Support (may Stack) Path'
2201 pos = comment.find(" 'Support (may Stack) Path'");
2202 if (pos == 0) {
2204 return true;
2205 }
2206
2207 // ; 'Perimeter Path'
2208 pos = comment.find(" 'Perimeter Path'");
2209 if (pos == 0) {
2212 return true;
2213 }
2214
2215 // ; 'Pillar Path'
2216 pos = comment.find(" 'Pillar Path'");
2217 if (pos == 0) {
2218 set_extrusion_role(GCodeExtrusionRole::None); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2219 return true;
2220 }
2221
2222 // ; 'Destring/Wipe/Jump Path'
2223 pos = comment.find(" 'Destring/Wipe/Jump Path'");
2224 if (pos == 0) {
2225 set_extrusion_role(GCodeExtrusionRole::None); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2226 return true;
2227 }
2228
2229 // ; 'Prime Pillar Path'
2230 pos = comment.find(" 'Prime Pillar Path'");
2231 if (pos == 0) {
2232 set_extrusion_role(GCodeExtrusionRole::None); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2233 return true;
2234 }
2235
2236 // ; 'Loop Path'
2237 pos = comment.find(" 'Loop Path'");
2238 if (pos == 0) {
2239 set_extrusion_role(GCodeExtrusionRole::None); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2240 return true;
2241 }
2242
2243 // ; 'Crown Path'
2244 pos = comment.find(" 'Crown Path'");
2245 if (pos == 0) {
2246 set_extrusion_role(GCodeExtrusionRole::None); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2247 return true;
2248 }
2249
2250 // ; 'Solid Path'
2251 pos = comment.find(" 'Solid Path'");
2252 if (pos == 0) {
2254 return true;
2255 }
2256
2257 // ; 'Stacked Sparse Infill Path'
2258 pos = comment.find(" 'Stacked Sparse Infill Path'");
2259 if (pos == 0) {
2261 return true;
2262 }
2263
2264 // ; 'Sparse Infill Path'
2265 pos = comment.find(" 'Sparse Infill Path'");
2266 if (pos == 0) {
2268 return true;
2269 }
2270
2271 // geometry
2272
2273 // layer
2274 pos = comment.find(" BEGIN_LAYER_");
2275 if (pos == 0) {
2276 ++m_layer_id;
2277 return true;
2278 }
2279
2280 return false;
2281}

References Slic3r::GCodeProcessor::SeamsDetector::activate(), comment, Slic3r::ExternalPerimeter, Slic3r::InternalInfill, Slic3r::Ironing, m_layer_id, m_seams_detector, Slic3r::None, set_extrusion_role(), Slic3r::Skirt, Slic3r::SolidInfill, Slic3r::SupportMaterial, and Slic3r::SupportMaterialInterface.

Referenced by process_producers_tags().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M1()

void Slic3r::GCodeProcessor::process_M1 ( const GCodeReader::GCodeLine line)
private
3051{
3053}

References simulate_st_synchronize().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M104()

void Slic3r::GCodeProcessor::process_M104 ( const GCodeReader::GCodeLine line)
private
3066{
3067 float new_temp;
3068 if (line.has_value('S', new_temp)) {
3069 size_t id = m_extruder_id;
3070 float val;
3071 if (line.has_value('T', val)) {
3072 const size_t eid = static_cast<size_t>(val);
3073 if (eid < m_extruder_temps.size())
3074 id = eid;
3075 }
3076
3077 m_extruder_temps[id] = new_temp;
3078 }
3079}

References Slic3r::GCodeReader::GCodeLine::has_value(), m_extruder_id, and m_extruder_temps.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M106()

void Slic3r::GCodeProcessor::process_M106 ( const GCodeReader::GCodeLine line)
private
3082{
3083 if (!line.has('P')) {
3084 // The absence of P means the print cooling fan, so ignore anything else.
3085 float new_fan_speed;
3086 if (line.has_value('S', new_fan_speed))
3087 m_fan_speed = (100.0f / 255.0f) * new_fan_speed;
3088 else
3089 m_fan_speed = 100.0f;
3090 }
3091}
float m_fan_speed
Definition GCodeProcessor.hpp:561

References Slic3r::GCodeReader::GCodeLine::has(), Slic3r::GCodeReader::GCodeLine::has_value(), and m_fan_speed.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M107()

void Slic3r::GCodeProcessor::process_M107 ( const GCodeReader::GCodeLine line)
private
3094{
3095 m_fan_speed = 0.0f;
3096}

References m_fan_speed.

Referenced by process_gcode_line().

+ Here is the caller graph for this function:

◆ process_M108()

void Slic3r::GCodeProcessor::process_M108 ( const GCodeReader::GCodeLine line)
private
3099{
3100 // These M-codes are used by Sailfish to change active tool.
3101 // They have to be processed otherwise toolchanges will be unrecognised
3102 // by the analyzer - see https://github.com/prusa3d/PrusaSlicer/issues/2566
3103
3104 if (m_flavor != gcfSailfish)
3105 return;
3106
3107 std::string cmd = line.raw();
3108 size_t pos = cmd.find("T");
3109 if (pos != std::string::npos)
3110 process_T(cmd.substr(pos));
3111}
@ gcfSailfish
Definition PrintConfig.hpp:35

References cmd, Slic3r::gcfSailfish, m_flavor, process_T(), and Slic3r::GCodeReader::GCodeLine::raw().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M109()

void Slic3r::GCodeProcessor::process_M109 ( const GCodeReader::GCodeLine line)
private
3114{
3115 float new_temp;
3116 size_t id = (size_t)-1;
3117 if (line.has_value('R', new_temp)) {
3118 float val;
3119 if (line.has_value('T', val)) {
3120 const size_t eid = static_cast<size_t>(val);
3121 if (eid < m_extruder_temps.size())
3122 id = eid;
3123 }
3124 else
3125 id = m_extruder_id;
3126 }
3127 else if (line.has_value('S', new_temp))
3128 id = m_extruder_id;
3129
3130 if (id != (size_t)-1)
3131 m_extruder_temps[id] = new_temp;
3132}

References Slic3r::GCodeReader::GCodeLine::has_value(), m_extruder_id, and m_extruder_temps.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M132()

void Slic3r::GCodeProcessor::process_M132 ( const GCodeReader::GCodeLine line)
private
3135{
3136 // This command is used by Makerbot to load the current home position from EEPROM
3137 // see: https://github.com/makerbot/s3g/blob/master/doc/GCodeProtocol.md
3138 // Using this command to reset the axis origin to zero helps in fixing: https://github.com/prusa3d/PrusaSlicer/issues/3082
3139
3140 if (line.has('X'))
3141 m_origin[X] = 0.0f;
3142
3143 if (line.has('Y'))
3144 m_origin[Y] = 0.0f;
3145
3146 if (line.has('Z'))
3147 m_origin[Z] = 0.0f;
3148
3149 if (line.has('E'))
3150 m_origin[E] = 0.0f;
3151}

References Slic3r::E, Slic3r::GCodeReader::GCodeLine::has(), m_origin, Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M135()

void Slic3r::GCodeProcessor::process_M135 ( const GCodeReader::GCodeLine line)
private
3154{
3155 // These M-codes are used by MakerWare to change active tool.
3156 // They have to be processed otherwise toolchanges will be unrecognised
3157 // by the analyzer - see https://github.com/prusa3d/PrusaSlicer/issues/2566
3158
3159 if (m_flavor != gcfMakerWare)
3160 return;
3161
3162 std::string cmd = line.raw();
3163 size_t pos = cmd.find("T");
3164 if (pos != std::string::npos)
3165 process_T(cmd.substr(pos));
3166}

References cmd, Slic3r::gcfMakerWare, m_flavor, process_T(), and Slic3r::GCodeReader::GCodeLine::raw().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M201()

void Slic3r::GCodeProcessor::process_M201 ( const GCodeReader::GCodeLine line)
private
3169{
3170 // see http://reprap.org/wiki/G-code#M201:_Set_max_printing_acceleration
3171 float factor = ((m_flavor != gcfRepRapSprinter && m_flavor != gcfRepRapFirmware) && m_units == EUnits::Inches) ? INCHES_TO_MM : 1.0f;
3172
3173 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3176 if (line.has_x())
3177 set_option_value(m_time_processor.machine_limits.machine_max_acceleration_x, i, line.x() * factor);
3178
3179 if (line.has_y())
3180 set_option_value(m_time_processor.machine_limits.machine_max_acceleration_y, i, line.y() * factor);
3181
3182 if (line.has_z())
3183 set_option_value(m_time_processor.machine_limits.machine_max_acceleration_z, i, line.z() * factor);
3184
3185 if (line.has_e())
3186 set_option_value(m_time_processor.machine_limits.machine_max_acceleration_e, i, line.e() * factor);
3187 }
3188 }
3189}
@ gcfRepRapSprinter
Definition PrintConfig.hpp:35
static void set_option_value(ConfigOptionFloats &option, size_t id, float value)
Definition GCodeProcessor.cpp:72

References Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeReader::GCodeLine::e(), Slic3r::gcfRepRapFirmware, Slic3r::gcfRepRapSprinter, Slic3r::GCodeReader::GCodeLine::has_e(), Slic3r::GCodeReader::GCodeLine::has_x(), Slic3r::GCodeReader::GCodeLine::has_y(), Slic3r::GCodeReader::GCodeLine::has_z(), Inches, INCHES_TO_MM, m_flavor, m_time_processor, m_units, Slic3r::GCodeProcessor::TimeProcessor::machine_envelope_processing_enabled, Slic3r::GCodeProcessor::TimeProcessor::machine_limits, Slic3r::PrintEstimatedStatistics::Normal, Slic3r::set_option_value(), Slic3r::GCodeReader::GCodeLine::x(), Slic3r::GCodeReader::GCodeLine::y(), and Slic3r::GCodeReader::GCodeLine::z().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M203()

void Slic3r::GCodeProcessor::process_M203 ( const GCodeReader::GCodeLine line)
private
3192{
3193 // see http://reprap.org/wiki/G-code#M203:_Set_maximum_feedrate
3194 if (m_flavor == gcfRepetier)
3195 return;
3196
3197 // see http://reprap.org/wiki/G-code#M203:_Set_maximum_feedrate
3198 // http://smoothieware.org/supported-g-codes
3199 float factor = (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfSmoothie) ? 1.0f : MMMIN_TO_MMSEC;
3200
3201 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3204 if (line.has_x())
3205 set_option_value(m_time_processor.machine_limits.machine_max_feedrate_x, i, line.x() * factor);
3206
3207 if (line.has_y())
3208 set_option_value(m_time_processor.machine_limits.machine_max_feedrate_y, i, line.y() * factor);
3209
3210 if (line.has_z())
3211 set_option_value(m_time_processor.machine_limits.machine_max_feedrate_z, i, line.z() * factor);
3212
3213 if (line.has_e())
3214 set_option_value(m_time_processor.machine_limits.machine_max_feedrate_e, i, line.e() * factor);
3215 }
3216 }
3217}
@ gcfSmoothie
Definition PrintConfig.hpp:36

References Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeReader::GCodeLine::e(), Slic3r::gcfMarlinFirmware, Slic3r::gcfMarlinLegacy, Slic3r::gcfRepetier, Slic3r::gcfSmoothie, Slic3r::GCodeReader::GCodeLine::has_e(), Slic3r::GCodeReader::GCodeLine::has_x(), Slic3r::GCodeReader::GCodeLine::has_y(), Slic3r::GCodeReader::GCodeLine::has_z(), m_flavor, m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machine_envelope_processing_enabled, Slic3r::GCodeProcessor::TimeProcessor::machine_limits, MMMIN_TO_MMSEC, Slic3r::PrintEstimatedStatistics::Normal, Slic3r::set_option_value(), Slic3r::GCodeReader::GCodeLine::x(), Slic3r::GCodeReader::GCodeLine::y(), and Slic3r::GCodeReader::GCodeLine::z().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M204()

void Slic3r::GCodeProcessor::process_M204 ( const GCodeReader::GCodeLine line)
private
3220{
3221 float value;
3222 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3225 if (line.has_value('S', value)) {
3226 // Legacy acceleration format. This format is used by the legacy Marlin, MK2 or MK3 firmware
3227 // It is also generated by PrusaSlicer to control acceleration per extrusion type
3228 // (perimeters, first layer etc) when 'Marlin (legacy)' flavor is used.
3231 if (line.has_value('T', value))
3233 }
3234 else {
3235 // New acceleration format, compatible with the upstream Marlin.
3236 if (line.has_value('P', value))
3238 if (line.has_value('R', value))
3240 if (line.has_value('T', value))
3241 // Interpret the T value as the travel acceleration in the new Marlin format.
3243 }
3244 }
3245 }
3246}
void set_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value)
Definition GCodeProcessor.cpp:4164
void set_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value)
Definition GCodeProcessor.cpp:4148
void set_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value)
Definition GCodeProcessor.cpp:4180

References Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeReader::GCodeLine::has_value(), m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machine_envelope_processing_enabled, Slic3r::PrintEstimatedStatistics::Normal, set_acceleration(), set_retract_acceleration(), and set_travel_acceleration().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M205()

void Slic3r::GCodeProcessor::process_M205 ( const GCodeReader::GCodeLine line)
private
3249{
3250 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3253 if (line.has_x()) {
3254 float max_jerk = line.x();
3255 set_option_value(m_time_processor.machine_limits.machine_max_jerk_x, i, max_jerk);
3256 set_option_value(m_time_processor.machine_limits.machine_max_jerk_y, i, max_jerk);
3257 }
3258
3259 if (line.has_y())
3260 set_option_value(m_time_processor.machine_limits.machine_max_jerk_y, i, line.y());
3261
3262 if (line.has_z())
3263 set_option_value(m_time_processor.machine_limits.machine_max_jerk_z, i, line.z());
3264
3265 if (line.has_e())
3266 set_option_value(m_time_processor.machine_limits.machine_max_jerk_e, i, line.e());
3267
3268 float value;
3269 if (line.has_value('S', value))
3270 set_option_value(m_time_processor.machine_limits.machine_min_extruding_rate, i, value);
3271
3272 if (line.has_value('T', value))
3273 set_option_value(m_time_processor.machine_limits.machine_min_travel_rate, i, value);
3274 }
3275 }
3276}

References Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeReader::GCodeLine::e(), Slic3r::GCodeReader::GCodeLine::has_e(), Slic3r::GCodeReader::GCodeLine::has_value(), Slic3r::GCodeReader::GCodeLine::has_x(), Slic3r::GCodeReader::GCodeLine::has_y(), Slic3r::GCodeReader::GCodeLine::has_z(), m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machine_envelope_processing_enabled, Slic3r::GCodeProcessor::TimeProcessor::machine_limits, Slic3r::PrintEstimatedStatistics::Normal, Slic3r::set_option_value(), Slic3r::GCodeReader::GCodeLine::x(), Slic3r::GCodeReader::GCodeLine::y(), and Slic3r::GCodeReader::GCodeLine::z().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M220()

void Slic3r::GCodeProcessor::process_M220 ( const GCodeReader::GCodeLine line)
private
3279{
3281 return;
3282
3283 if (line.has('B'))
3285 float value;
3286 if (line.has_value('S', value))
3287 m_feed_multiply.current = value * 0.01f;
3288 if (line.has('R'))
3290}
float saved
Definition GCodeProcessor.hpp:548

References Slic3r::GCodeProcessor::FeedMultiply::current, Slic3r::gcfKlipper, Slic3r::gcfMarlinFirmware, Slic3r::gcfMarlinLegacy, Slic3r::GCodeReader::GCodeLine::has(), Slic3r::GCodeReader::GCodeLine::has_value(), m_feed_multiply, m_flavor, and Slic3r::GCodeProcessor::FeedMultiply::saved.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M221()

void Slic3r::GCodeProcessor::process_M221 ( const GCodeReader::GCodeLine line)
private
3293{
3294 float value_s;
3295 float value_t;
3296 if (line.has_value('S', value_s) && !line.has_value('T', value_t)) {
3297 value_s *= 0.01f;
3298 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3299 m_time_processor.machines[i].extrude_factor_override_percentage = value_s;
3300 }
3301 }
3302}
Definition config.h:32

References Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeReader::GCodeLine::has_value(), m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M401()

void Slic3r::GCodeProcessor::process_M401 ( const GCodeReader::GCodeLine line)
private
3305{
3306 if (m_flavor != gcfRepetier)
3307 return;
3308
3309 for (unsigned char a = 0; a <= 3; ++a) {
3311 }
3313}
CachedPosition m_cached_position
Definition GCodeProcessor.hpp:539
AxisCoords position
Definition GCodeProcessor.hpp:219
float feedrate
Definition GCodeProcessor.hpp:220

References Slic3r::GCodeProcessor::CachedPosition::feedrate, Slic3r::gcfRepetier, m_cached_position, m_feedrate, m_flavor, m_start_position, and Slic3r::GCodeProcessor::CachedPosition::position.

Referenced by process_gcode_line().

+ Here is the caller graph for this function:

◆ process_M402()

void Slic3r::GCodeProcessor::process_M402 ( const GCodeReader::GCodeLine line)
private
3316{
3317 if (m_flavor != gcfRepetier)
3318 return;
3319
3320 // see for reference:
3321 // https://github.com/repetier/Repetier-Firmware/blob/master/src/ArduinoAVR/Repetier/Printer.cpp
3322 // void Printer::GoToMemoryPosition(bool x, bool y, bool z, bool e, float feed)
3323
3324 bool has_xyz = !(line.has('X') || line.has('Y') || line.has('Z'));
3325
3326 float p = FLT_MAX;
3327 for (unsigned char a = X; a <= Z; ++a) {
3328 if (has_xyz || line.has(a)) {
3330 if (p != FLT_MAX)
3331 m_start_position[a] = p;
3332 }
3333 }
3334
3336 if (p != FLT_MAX)
3337 m_start_position[E] = p;
3338
3339 p = FLT_MAX;
3340 if (!line.has_value(4, p))
3342
3343 if (p != FLT_MAX)
3344 m_feedrate = p;
3345}

References Slic3r::E, Slic3r::GCodeProcessor::CachedPosition::feedrate, Slic3r::gcfRepetier, Slic3r::GCodeReader::GCodeLine::has(), Slic3r::GCodeReader::GCodeLine::has_value(), m_cached_position, m_feedrate, m_flavor, m_start_position, Slic3r::GCodeProcessor::CachedPosition::position, Slic3r::X, and Slic3r::Z.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M566()

void Slic3r::GCodeProcessor::process_M566 ( const GCodeReader::GCodeLine line)
private
3348{
3349 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
3350 if (line.has_x())
3351 set_option_value(m_time_processor.machine_limits.machine_max_jerk_x, i, line.x() * MMMIN_TO_MMSEC);
3352
3353 if (line.has_y())
3354 set_option_value(m_time_processor.machine_limits.machine_max_jerk_y, i, line.y() * MMMIN_TO_MMSEC);
3355
3356 if (line.has_z())
3357 set_option_value(m_time_processor.machine_limits.machine_max_jerk_z, i, line.z() * MMMIN_TO_MMSEC);
3358
3359 if (line.has_e())
3360 set_option_value(m_time_processor.machine_limits.machine_max_jerk_e, i, line.e() * MMMIN_TO_MMSEC);
3361 }
3362}

References Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeReader::GCodeLine::e(), Slic3r::GCodeReader::GCodeLine::has_e(), Slic3r::GCodeReader::GCodeLine::has_x(), Slic3r::GCodeReader::GCodeLine::has_y(), Slic3r::GCodeReader::GCodeLine::has_z(), m_time_processor, Slic3r::GCodeProcessor::TimeProcessor::machine_limits, MMMIN_TO_MMSEC, Slic3r::set_option_value(), Slic3r::GCodeReader::GCodeLine::x(), Slic3r::GCodeReader::GCodeLine::y(), and Slic3r::GCodeReader::GCodeLine::z().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M702()

void Slic3r::GCodeProcessor::process_M702 ( const GCodeReader::GCodeLine line)
private
3365{
3366 if (line.has('C')) {
3367 // MK3 MMU2 specific M code:
3368 // M702 C is expected to be sent by the custom end G-code when finalizing a print.
3369 // The MK3 unit shall unload and park the active filament into the MMU2 unit.
3372 }
3373}
float get_filament_unload_time(size_t extruder_id)
Definition GCodeProcessor.cpp:4200

References Slic3r::GCodeProcessor::TimeProcessor::extruder_unloaded, get_filament_unload_time(), Slic3r::GCodeReader::GCodeLine::has(), m_extruder_id, m_time_processor, and simulate_st_synchronize().

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_M82()

void Slic3r::GCodeProcessor::process_M82 ( const GCodeReader::GCodeLine line)
private

References Absolute, and m_e_local_positioning_type.

Referenced by process_gcode_line().

+ Here is the caller graph for this function:

◆ process_M83()

void Slic3r::GCodeProcessor::process_M83 ( const GCodeReader::GCodeLine line)
private

References m_e_local_positioning_type, and Relative.

Referenced by process_gcode_line().

+ Here is the caller graph for this function:

◆ process_producers_tags()

bool Slic3r::GCodeProcessor::process_producers_tags ( const std::string_view  comment)
private
1826{
1827 switch (m_producer)
1828 {
1830 case EProducer::Slic3r:
1833 case EProducer::Cura: { return process_cura_tags(comment); }
1839 default: { return false; }
1840 }
1841}
bool process_bambustudio_tags(const std::string_view comment)
Definition GCodeProcessor.cpp:2283
bool process_cura_tags(const std::string_view comment)
Definition GCodeProcessor.cpp:1848
bool process_craftware_tags(const std::string_view comment)
Definition GCodeProcessor.cpp:2064
bool process_kissslicer_tags(const std::string_view comment)
Definition GCodeProcessor.cpp:2175
bool process_ideamaker_tags(const std::string_view comment)
Definition GCodeProcessor.cpp:2114
bool process_prusaslicer_tags(const std::string_view comment)
Definition GCodeProcessor.cpp:1843
bool process_simplify3d_tags(const std::string_view comment)
Definition GCodeProcessor.cpp:1922

References BambuStudio, comment, CraftWare, Cura, ideaMaker, KissSlicer, m_producer, process_bambustudio_tags(), process_craftware_tags(), process_cura_tags(), process_ideamaker_tags(), process_kissslicer_tags(), process_prusaslicer_tags(), process_simplify3d_tags(), PrusaSlicer, Simplify3D, Slic3r, Slic3rPE, and SuperSlicer.

Referenced by process_tags().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_prusaslicer_tags()

bool Slic3r::GCodeProcessor::process_prusaslicer_tags ( const std::string_view  comment)
private
1844{
1845 return false;
1846}

Referenced by process_producers_tags().

+ Here is the caller graph for this function:

◆ process_simplify3d_tags()

bool Slic3r::GCodeProcessor::process_simplify3d_tags ( const std::string_view  comment)
private
1923{
1924 // extrusion roles
1925
1926 // in older versions the comments did not contain the key 'feature'
1927 std::string_view cmt = comment;
1928 size_t pos = cmt.find(" feature");
1929 if (pos == 0)
1930 cmt.remove_prefix(8);
1931
1932 // ; skirt
1933 pos = cmt.find(" skirt");
1934 if (pos == 0) {
1936 return true;
1937 }
1938
1939 // ; outer perimeter
1940 pos = cmt.find(" outer perimeter");
1941 if (pos == 0) {
1944 return true;
1945 }
1946
1947 // ; inner perimeter
1948 pos = cmt.find(" inner perimeter");
1949 if (pos == 0) {
1951 return true;
1952 }
1953
1954 // ; gap fill
1955 pos = cmt.find(" gap fill");
1956 if (pos == 0) {
1958 return true;
1959 }
1960
1961 // ; infill
1962 pos = cmt.find(" infill");
1963 if (pos == 0) {
1965 return true;
1966 }
1967
1968 // ; solid layer
1969 pos = cmt.find(" solid layer");
1970 if (pos == 0) {
1972 return true;
1973 }
1974
1975 // ; bridge
1976 pos = cmt.find(" bridge");
1977 if (pos == 0) {
1979 return true;
1980 }
1981
1982 // ; support
1983 pos = cmt.find(" support");
1984 if (pos == 0) {
1986 return true;
1987 }
1988
1989 // ; dense support
1990 pos = cmt.find(" dense support");
1991 if (pos == 0) {
1993 return true;
1994 }
1995
1996 // ; prime pillar
1997 pos = cmt.find(" prime pillar");
1998 if (pos == 0) {
2000 return true;
2001 }
2002
2003 // ; ooze shield
2004 pos = cmt.find(" ooze shield");
2005 if (pos == 0) {
2006 set_extrusion_role(GCodeExtrusionRole::None); // Missing mapping
2007 return true;
2008 }
2009
2010 // ; raft
2011 pos = cmt.find(" raft");
2012 if (pos == 0) {
2014 return true;
2015 }
2016
2017 // ; internal single extrusion
2018 pos = cmt.find(" internal single extrusion");
2019 if (pos == 0) {
2020 set_extrusion_role(GCodeExtrusionRole::None); // Missing mapping
2021 return true;
2022 }
2023
2024 // geometry
2025 // ; tool
2026 std::string tag = " tool";
2027 pos = cmt.find(tag);
2028 if (pos == 0) {
2029 const std::string_view data = cmt.substr(pos + tag.length());
2030 std::string h_tag = "H";
2031 size_t h_start = data.find(h_tag);
2032 size_t h_end = data.find_first_of(' ', h_start);
2033 std::string w_tag = "W";
2034 size_t w_start = data.find(w_tag);
2035 size_t w_end = data.find_first_of(' ', w_start);
2036 if (h_start != data.npos) {
2037 if (!parse_number(data.substr(h_start + 1, (h_end != data.npos) ? h_end - h_start - 1 : h_end), m_forced_height))
2038 BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
2039 }
2040 if (w_start != data.npos) {
2041 if (!parse_number(data.substr(w_start + 1, (w_end != data.npos) ? w_end - w_start - 1 : w_end), m_forced_width))
2042 BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
2043 }
2044
2045 return true;
2046 }
2047
2048 // ; layer | ;layer
2049 tag = "layer";
2050 pos = cmt.find(tag);
2051 if (pos == 0 || pos == 1) {
2052 // skip lines "; layer end"
2053 const std::string_view data = cmt.substr(pos + tag.length());
2054 size_t end_start = data.find("end");
2055 if (end_start == data.npos)
2056 ++m_layer_id;
2057
2058 return true;
2059 }
2060
2061 return false;
2062}

References Slic3r::GCodeProcessor::SeamsDetector::activate(), Slic3r::BridgeInfill, comment, error, Slic3r::ExternalPerimeter, Slic3r::GapFill, Slic3r::InternalInfill, m_forced_height, m_forced_width, m_layer_id, m_seams_detector, Slic3r::None, Slic3r::parse_number(), Slic3r::Perimeter, set_extrusion_role(), Slic3r::Skirt, Slic3r::SolidInfill, Slic3r::SupportMaterial, Slic3r::SupportMaterialInterface, and Slic3r::WipeTower.

Referenced by process_producers_tags().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_T() [1/2]

void Slic3r::GCodeProcessor::process_T ( const GCodeReader::GCodeLine line)
private
3376{
3377 process_T(line.cmd());
3378}

References Slic3r::GCodeReader::GCodeLine::cmd(), and process_T().

Referenced by process_gcode_line(), process_M108(), process_M135(), and process_T().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ process_T() [2/2]

void Slic3r::GCodeProcessor::process_T ( const std::string_view  command)
private
3381{
3382 if (command.length() > 1) {
3383 int eid = 0;
3384 if (! parse_number(command.substr(1), eid) || eid < 0 || eid > 255) {
3385 // Specific to the MMU2 V2 (see https://www.help.prusa3d.com/en/article/prusa-specific-g-codes_112173):
3386 if ((m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) && (command == "Tx" || command == "Tc" || command == "T?"))
3387 return;
3388
3389 // T-1 is a valid gcode line for RepRap Firmwares (used to deselects all tools) see https://github.com/prusa3d/PrusaSlicer/issues/5677
3390 if ((m_flavor != gcfRepRapFirmware && m_flavor != gcfRepRapSprinter) || eid != -1)
3391 BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange (" << command << ").";
3392 }
3393 else {
3394 unsigned char id = static_cast<unsigned char>(eid);
3395 if (m_extruder_id != id) {
3398 BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange, maybe from a custom gcode (" << command << ").";
3399 else {
3400 unsigned char old_extruder_id = m_extruder_id;
3402 m_extruder_id = id;
3404 // Specific to the MK3 MMU2:
3405 // The initial value of extruder_unloaded is set to true indicating
3406 // that the filament is parked in the MMU2 unit and there is nothing to be unloaded yet.
3407 float extra_time = get_filament_unload_time(static_cast<size_t>(old_extruder_id));
3409 extra_time += get_filament_load_time(static_cast<size_t>(m_extruder_id));
3412 simulate_st_synchronize(extra_time);
3413
3414 // specific to single extruder multi material, set the new extruder temperature
3415 // to match the old one
3418
3420 }
3421
3422 // store tool change move
3424 }
3425 }
3426 }
3427}
float get_filament_load_time(size_t extruder_id)
Definition GCodeProcessor.cpp:4190
CpColor m_cp_color
Definition GCodeProcessor.hpp:576
void process_filaments(CustomGCode::Type code)
Definition GCodeProcessor.cpp:4229
unsigned char current
Definition GCodeProcessor.hpp:228
Definition term.c:39

References Slic3r::GCodeProcessor::CpColor::current, error, Slic3r::GCodeProcessorResult::extruder_colors, Slic3r::GCodeProcessor::TimeProcessor::extruder_unloaded, Slic3r::GCodeProcessorResult::extruders_count, Slic3r::gcfMarlinFirmware, Slic3r::gcfMarlinLegacy, Slic3r::gcfRepRapFirmware, Slic3r::gcfRepRapSprinter, get_filament_load_time(), get_filament_unload_time(), KissSlicer, m_cp_color, m_extruder_colors, m_extruder_id, m_extruder_temps, m_flavor, m_kissslicer_toolchange_time_correction, m_producer, m_result, m_single_extruder_multi_material, m_time_processor, Slic3r::parse_number(), process_filaments(), PrusaSlicer, simulate_st_synchronize(), Slic3r, Slic3rPE, store_move_vertex(), Slic3r::Tool_change, and Slic3r::CustomGCode::ToolChange.

+ Here is the call graph for this function:

◆ process_tags()

void Slic3r::GCodeProcessor::process_tags ( const std::string_view  comment,
bool  producers_enabled 
)
private
1667{
1668 // producers tags
1669 if (producers_enabled && process_producers_tags(comment))
1670 return;
1671
1672 // extrusion role tag
1673 if (boost::starts_with(comment, reserved_tag(ETags::Role))) {
1677 return;
1678 }
1679
1680 // wipe start tag
1681 if (boost::starts_with(comment, reserved_tag(ETags::Wipe_Start))) {
1682 m_wiping = true;
1683 return;
1684 }
1685
1686 // wipe end tag
1687 if (boost::starts_with(comment, reserved_tag(ETags::Wipe_End))) {
1688 m_wiping = false;
1689 return;
1690 }
1691
1692 if (!producers_enabled || m_producer == EProducer::PrusaSlicer) {
1693 // height tag
1694 if (boost::starts_with(comment, reserved_tag(ETags::Height))) {
1696 BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
1697 return;
1698 }
1699 // width tag
1700 if (boost::starts_with(comment, reserved_tag(ETags::Width))) {
1702 BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
1703 return;
1704 }
1705 }
1706
1707 // color change tag
1708 if (boost::starts_with(comment, reserved_tag(ETags::Color_Change))) {
1709 unsigned char extruder_id = 0;
1710 static std::vector<std::string> Default_Colors = {
1711 "#0B2C7A", // { 0.043f, 0.173f, 0.478f }, // bluish
1712 "#1C8891", // { 0.110f, 0.533f, 0.569f },
1713 "#AAF200", // { 0.667f, 0.949f, 0.000f },
1714 "#F5CE0A", // { 0.961f, 0.808f, 0.039f },
1715 "#D16830", // { 0.820f, 0.408f, 0.188f },
1716 "#942616", // { 0.581f, 0.149f, 0.087f } // reddish
1717 };
1718
1719 std::string color = Default_Colors[0];
1720 auto is_valid_color = [](const std::string& color) {
1721 auto is_hex_digit = [](char c) {
1722 return ((c >= '0' && c <= '9') ||
1723 (c >= 'A' && c <= 'F') ||
1724 (c >= 'a' && c <= 'f'));
1725 };
1726
1727 if (color[0] != '#' || color.length() != 7)
1728 return false;
1729 for (int i = 1; i <= 6; ++i) {
1730 if (!is_hex_digit(color[i]))
1731 return false;
1732 }
1733 return true;
1734 };
1735
1736 std::vector<std::string> tokens;
1737 boost::split(tokens, comment, boost::is_any_of(","), boost::token_compress_on);
1738 if (tokens.size() > 1) {
1739 if (tokens[1][0] == 'T') {
1740 int eid;
1741 if (!parse_number(tokens[1].substr(1), eid) || eid < 0 || eid > 255) {
1742 BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ").";
1743 return;
1744 }
1745 extruder_id = static_cast<unsigned char>(eid);
1746 }
1747 }
1748 if (tokens.size() > 2) {
1749 if (is_valid_color(tokens[2]))
1750 color = tokens[2];
1751 }
1752 else {
1753 color = Default_Colors[m_last_default_color_id];
1755 if (m_last_default_color_id == Default_Colors.size())
1757 }
1758
1759 if (extruder_id < m_extruder_colors.size())
1760 m_extruder_colors[extruder_id] = static_cast<unsigned char>(m_extruder_offsets.size()) + m_cp_color.counter; // color_change position in list of color for preview
1762 if (m_cp_color.counter == UCHAR_MAX)
1763 m_cp_color.counter = 0;
1764
1765 if (m_extruder_id == extruder_id) {
1766 m_cp_color.current = m_extruder_colors[extruder_id];
1768 CustomGCode::Item item = { static_cast<double>(m_end_position[2]), CustomGCode::ColorChange, extruder_id + 1, color, "" };
1769 m_result.custom_gcode_per_print_z.emplace_back(item);
1773 }
1774
1775 return;
1776 }
1777
1778 // pause print tag
1781 CustomGCode::Item item = { static_cast<double>(m_end_position[2]), CustomGCode::PausePrint, m_extruder_id + 1, "", "" };
1782 m_result.custom_gcode_per_print_z.emplace_back(item);
1785 return;
1786 }
1787
1788 // custom code tag
1791 CustomGCode::Item item = { static_cast<double>(m_end_position[2]), CustomGCode::Custom, m_extruder_id + 1, "", "" };
1792 m_result.custom_gcode_per_print_z.emplace_back(item);
1794 return;
1795 }
1796
1797 // layer change tag
1799 ++m_layer_id;
1801 if (m_result.moves.empty() || m_result.spiral_vase_layers.empty())
1802 // add a placeholder for layer height. the actual value will be set inside process_G1() method
1803 m_result.spiral_vase_layers.push_back({ FLT_MAX, { 0, 0 } });
1804 else {
1805 const size_t move_id = m_result.moves.size() - 1;
1806 if (!m_result.spiral_vase_layers.empty())
1807 m_result.spiral_vase_layers.back().second.second = move_id;
1808 // add a placeholder for layer height. the actual value will be set inside process_G1() method
1809 m_result.spiral_vase_layers.push_back({ FLT_MAX, { move_id, move_id } });
1810 }
1811 }
1812 return;
1813 }
1814
1815#if ENABLE_GCODE_VIEWER_DATA_CHECKING
1816 // mm3_per_mm print tag
1817 if (boost::starts_with(comment, Mm3_Per_Mm_Tag)) {
1818 if (! parse_number(comment.substr(Mm3_Per_Mm_Tag.size()), m_mm3_per_mm_compare.last_tag_value))
1819 BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Mm3_Per_Mm (" << comment << ").";
1820 return;
1821 }
1822#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
1823}
void set()
Definition GCodeProcessor.hpp:433
void process_custom_gcode_time(CustomGCode::Type code)
Definition GCodeProcessor.cpp:4210
size_t m_last_default_color_id
Definition GCodeProcessor.hpp:580
bool process_producers_tags(const std::string_view comment)
Definition GCodeProcessor.cpp:1825
@ PausePrint
Definition CustomGCode.hpp:16
@ Custom
Definition CustomGCode.hpp:19
double length(const Points &pts)
Definition MultiPoint.hpp:116
GCodeExtrusionRole string_to_gcode_extrusion_role(const std::string_view role)
Definition ExtrusionRole.cpp:57
constexpr auto size(const C &c) -> decltype(c.size())
Definition span.hpp:183
unsigned char counter
Definition GCodeProcessor.hpp:227
std::vector< CustomGCode::Item > custom_gcode_per_print_z
Definition GCodeProcessor.hpp:153

References Slic3r::GCodeProcessor::SeamsDetector::activate(), Slic3r::Color_change, Color_Change, Slic3r::CustomGCode::ColorChange, comment, Slic3r::GCodeProcessor::CpColor::counter, Slic3r::GCodeProcessor::CpColor::current, Slic3r::CustomGCode::Custom, Custom_Code, Slic3r::Custom_GCode, Slic3r::GCodeProcessorResult::custom_gcode_per_print_z, error, Slic3r::ExternalPerimeter, Height, Layer_Change, Slic3r::length(), m_cp_color, m_end_position, m_extruder_colors, m_extruder_id, m_extruder_offsets, m_extrusion_role, m_forced_height, m_forced_width, m_last_default_color_id, m_layer_id, m_options_z_corrector, m_producer, m_result, m_seams_detector, m_spiral_vase_active, m_wiping, Slic3r::GCodeProcessorResult::moves, Slic3r::parse_number(), Slic3r::Pause_Print, Pause_Print, Slic3r::CustomGCode::PausePrint, process_custom_gcode_time(), process_filaments(), process_producers_tags(), PrusaSlicer, reserved_tag(), Role, Slic3r::GCodeProcessor::OptionsZCorrector::set(), set_extrusion_role(), Slic3r::GCodeProcessorResult::spiral_vase_layers, store_move_vertex(), Slic3r::string_to_gcode_extrusion_role(), Width, Wipe_End, and Wipe_Start.

Referenced by process_gcode_line().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reserved_tag()

static const std::string & Slic3r::GCodeProcessor::reserved_tag ( ETags  tag)
inlinestatic
186{ return Reserved_Tags[static_cast<unsigned char>(tag)]; }
static const std::vector< std::string > Reserved_Tags
Definition GCodeProcessor.hpp:167

References Reserved_Tags.

Referenced by Slic3r::WipeTowerWriter::WipeTowerWriter(), Slic3r::GCode::_do_export(), Slic3r::GCode::_extrude(), Slic3r::WipeTowerWriter::change_analyzer_line_width(), Slic3r::ProcessLayer::emit_custom_gcode_per_print_z(), post_process(), Slic3r::GCode::process_layer(), process_tags(), and Slic3r::Wipe::wipe().

+ Here is the caller graph for this function:

◆ reset()

void Slic3r::GCodeProcessor::reset ( )
943{
947 m_extruder_offsets = std::vector<Vec3f>(MIN_EXTRUDERS_COUNT, Vec3f::Zero());
949
950 m_start_position = { 0.0f, 0.0f, 0.0f, 0.0f };
951 m_end_position = { 0.0f, 0.0f, 0.0f, 0.0f };
952 m_saved_position = { 0.0f, 0.0f, 0.0f, 0.0f };
953 m_origin = { 0.0f, 0.0f, 0.0f, 0.0f };
955 m_wiping = false;
956
957 m_line_id = 0;
958 m_last_line_id = 0;
959 m_feedrate = 0.0f;
961 m_width = 0.0f;
962 m_height = 0.0f;
963 m_forced_width = 0.0f;
964 m_forced_height = 0.0f;
965 m_mm3_per_mm = 0.0f;
966 m_fan_speed = 0.0f;
967 m_z_offset = 0.0f;
968
970 m_extruder_id = 0;
972 for (size_t i = 0; i < MIN_EXTRUDERS_COUNT; ++i) {
973 m_extruder_colors[i] = static_cast<unsigned char>(i);
974 }
976 for (size_t i = 0; i < MIN_EXTRUDERS_COUNT; ++i) {
977 m_extruder_temps[i] = 0.0f;
978 }
979
980 m_parking_position = 0.f;
982 m_extruded_last_z = 0.0f;
984 m_g1_line_id = 0;
985 m_layer_id = 0;
987
989
992
993 m_result.reset();
995
996 m_use_volumetric_e = false;
998
1000
1001 m_spiral_vase_active = false;
1003
1005
1006#if ENABLE_GCODE_VIEWER_DATA_CHECKING
1007 m_mm3_per_mm_compare.reset();
1008 m_height_compare.reset();
1009 m_width_compare.reset();
1010#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
1011}
void reset()
Definition GCodeProcessor.hpp:452
unsigned int m_last_line_id
Definition GCodeProcessor.hpp:543
void reset()
Definition GCodeProcessor.cpp:115
void reset()
Definition GCodeProcessor.cpp:121
void reset()
Definition GCodeProcessor.hpp:550
void reset()
Definition GCodeProcessor.cpp:345
void reset()
Definition GCodeProcessor.cpp:359
void reset()
Definition GCodeProcessor.cpp:457

References Absolute, Slic3r::gcfRepRapSprinter, Slic3r::GCodeProcessorResult::id, m_cached_position, m_cp_color, m_e_local_positioning_type, m_end_position, m_extra_loading_move, m_extruded_last_z, m_extruder_colors, m_extruder_id, m_extruder_offsets, m_extruder_temps, m_extrusion_role, m_fan_speed, m_feed_multiply, m_feedrate, m_first_layer_height, m_flavor, m_forced_height, m_forced_width, m_g1_line_id, m_global_positioning_type, m_height, m_kissslicer_toolchange_time_correction, m_last_default_color_id, m_last_line_id, m_layer_id, m_line_id, m_mm3_per_mm, m_options_z_corrector, m_origin, m_parking_position, m_producer, m_result, m_saved_position, m_single_extruder_multi_material, m_spiral_vase_active, m_start_position, m_time_processor, m_units, m_use_volumetric_e, m_used_filaments, m_width, m_wiping, m_z_offset, Millimeters, MIN_EXTRUDERS_COUNT, Slic3r::None, Slic3r::GCodeProcessorResult::reset(), Slic3r::GCodeProcessor::CachedPosition::reset(), Slic3r::GCodeProcessor::CpColor::reset(), Slic3r::GCodeProcessor::TimeProcessor::reset(), Slic3r::GCodeProcessor::UsedFilaments::reset(), Slic3r::GCodeProcessor::OptionsZCorrector::reset(), Slic3r::GCodeProcessor::FeedMultiply::reset(), s_result_id, and Unknown.

Referenced by GCodeProcessor(), Slic3r::DoExport::init_gcode_processor(), and update_estimated_times_stats().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_acceleration()

void Slic3r::GCodeProcessor::set_acceleration ( PrintEstimatedStatistics::ETimeMode  mode,
float  value 
)
private
4165{
4166 size_t id = static_cast<size_t>(mode);
4167 if (id < m_time_processor.machines.size()) {
4168 m_time_processor.machines[id].acceleration = (m_time_processor.machines[id].max_acceleration == 0.0f) ? value :
4169 // Clamp the acceleration with the maximum.
4170 std::min(value, m_time_processor.machines[id].max_acceleration);
4171 }
4172}
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half() min(const half &a, const half &b)
Definition Half.h:507

References m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by process_M204().

+ Here is the caller graph for this function:

◆ set_extrusion_role()

void Slic3r::GCodeProcessor::set_extrusion_role ( GCodeExtrusionRole  role)
private
4085{
4087 m_extrusion_role = role;
4088}
void process_role_cache(const GCodeProcessor *processor)
Definition GCodeProcessor.cpp:412

References m_extrusion_role, m_used_filaments, and Slic3r::GCodeProcessor::UsedFilaments::process_role_cache().

Referenced by process_bambustudio_tags(), process_craftware_tags(), process_cura_tags(), process_ideamaker_tags(), process_kissslicer_tags(), process_simplify3d_tags(), and process_tags().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_print()

void Slic3r::GCodeProcessor::set_print ( Print print)
inline
624{ m_print = print; }

References m_print.

Referenced by Slic3r::GCode::do_export().

+ Here is the caller graph for this function:

◆ set_retract_acceleration()

void Slic3r::GCodeProcessor::set_retract_acceleration ( PrintEstimatedStatistics::ETimeMode  mode,
float  value 
)
private
4149{
4150 size_t id = static_cast<size_t>(mode);
4151 if (id < m_time_processor.machines.size()) {
4152 m_time_processor.machines[id].retract_acceleration = (m_time_processor.machines[id].max_retract_acceleration == 0.0f) ? value :
4153 // Clamp the acceleration with the maximum.
4154 std::min(value, m_time_processor.machines[id].max_retract_acceleration);
4155 }
4156}

References m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by process_M204().

+ Here is the caller graph for this function:

◆ set_travel_acceleration()

void Slic3r::GCodeProcessor::set_travel_acceleration ( PrintEstimatedStatistics::ETimeMode  mode,
float  value 
)
private
4181{
4182 size_t id = static_cast<size_t>(mode);
4183 if (id < m_time_processor.machines.size()) {
4184 m_time_processor.machines[id].travel_acceleration = (m_time_processor.machines[id].max_travel_acceleration == 0.0f) ? value :
4185 // Clamp the acceleration with the maximum.
4186 std::min(value, m_time_processor.machines[id].max_travel_acceleration);
4187 }
4188}

References m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by process_M204().

+ Here is the caller graph for this function:

◆ simulate_st_synchronize()

void Slic3r::GCodeProcessor::simulate_st_synchronize ( float  additional_time = 0.0f)
private
4239{
4240 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
4241 m_time_processor.machines[i].simulate_st_synchronize(additional_time);
4242 }
4243}

References Slic3r::PrintEstimatedStatistics::Count, m_time_processor, and Slic3r::GCodeProcessor::TimeProcessor::machines.

Referenced by process_G92(), process_M1(), process_M702(), and process_T().

+ Here is the caller graph for this function:

◆ store_move_vertex()

void Slic3r::GCodeProcessor::store_move_vertex ( EMoveType  type,
bool  internal_only = false 
)
private
4049{
4051 m_line_id + 1 :
4052 ((type == EMoveType::Seam) ? m_last_line_id : m_line_id);
4053
4054 m_result.moves.push_back({
4056 type,
4061 static_cast<float>(m_end_position[E] - m_start_position[E]),
4062 m_feedrate,
4063 m_width,
4064 m_height,
4068 static_cast<float>(m_result.moves.size()),
4069 internal_only
4070 });
4071
4072 // stores stop time placeholders for later use
4073 if (type == EMoveType::Color_change || type == EMoveType::Pause_Print) {
4074 for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
4075 TimeMachine& machine = m_time_processor.machines[i];
4076 if (!machine.enabled)
4077 continue;
4078
4079 machine.stop_times.push_back({ m_g1_line_id, 0.0f });
4080 }
4081 }
4082}

References Slic3r::Color_change, Slic3r::PrintEstimatedStatistics::Count, Slic3r::GCodeProcessor::CpColor::current, Slic3r::Custom_GCode, Slic3r::E, Slic3r::GCodeProcessor::TimeMachine::enabled, m_cp_color, m_end_position, m_extruder_id, m_extruder_offsets, m_extruder_temps, m_extrusion_role, m_fan_speed, m_feedrate, m_g1_line_id, m_height, m_last_line_id, m_line_id, m_mm3_per_mm, m_result, m_start_position, m_time_processor, m_width, m_z_offset, Slic3r::GCodeProcessor::TimeProcessor::machines, Slic3r::GCodeProcessorResult::moves, Slic3r::Pause_Print, Slic3r::Seam, Slic3r::GCodeProcessor::TimeMachine::stop_times, Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by process_G1(), process_G10(), process_G11(), process_G22(), process_G23(), process_G61(), process_T(), and process_tags().

+ Here is the caller graph for this function:

◆ update_estimated_times_stats()

void Slic3r::GCodeProcessor::update_estimated_times_stats ( )
private
4246{
4247 auto update_mode = [this](PrintEstimatedStatistics::ETimeMode mode) {
4248 PrintEstimatedStatistics::Mode& data = m_result.print_statistics.modes[static_cast<size_t>(mode)];
4249 data.time = get_time(mode);
4250 data.travel_time = get_travel_time(mode);
4251 data.custom_gcode_times = get_custom_gcode_times(mode, true);
4252 data.moves_times = get_moves_time(mode);
4253 data.roles_times = get_roles_time(mode);
4254 data.layers_times = get_layers_time(mode);
4255 };
4256
4260 else
4262
4266}
float get_travel_time(PrintEstimatedStatistics::ETimeMode mode) const
Definition GCodeProcessor.cpp:1161
std::vector< std::pair< GCodeExtrusionRole, float > > get_roles_time(PrintEstimatedStatistics::ETimeMode mode) const
Definition GCodeProcessor.cpp:1199
std::vector< float > get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const
Definition GCodeProcessor.cpp:1321
float get_time(PrintEstimatedStatistics::ETimeMode mode) const
Definition GCodeProcessor.cpp:1151
std::vector< std::pair< CustomGCode::Type, std::pair< float, float > > > get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const
Definition GCodeProcessor.cpp:1171
std::vector< std::pair< EMoveType, float > > get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const
Definition GCodeProcessor.cpp:1186
std::map< size_t, double > volumes_per_extruder
Definition GCodeProcessor.hpp:381
std::vector< double > volumes_per_color_change
Definition GCodeProcessor.hpp:378
std::map< GCodeExtrusionRole, std::pair< double, double > > filaments_per_role
Definition GCodeProcessor.hpp:384
PrintEstimatedStatistics print_statistics
Definition GCodeProcessor.hpp:152
std::map< size_t, double > volumes_per_extruder
Definition GCodeProcessor.hpp:66
std::map< GCodeExtrusionRole, std::pair< double, double > > used_filaments_per_role
Definition GCodeProcessor.hpp:67
std::vector< double > volumes_per_color_change
Definition GCodeProcessor.hpp:65
std::array< Mode, static_cast< size_t >(ETimeMode::Count)> modes
Definition GCodeProcessor.hpp:70

References Slic3r::GCodeProcessor::UsedFilaments::filaments_per_role, get_custom_gcode_times(), get_layers_time(), get_moves_time(), get_roles_time(), get_time(), get_travel_time(), m_result, m_time_processor, m_used_filaments, Slic3r::GCodeProcessor::TimeProcessor::machines, Slic3r::PrintEstimatedStatistics::modes, Slic3r::PrintEstimatedStatistics::Normal, Slic3r::GCodeProcessorResult::print_statistics, reset(), Slic3r::PrintEstimatedStatistics::Stealth, Slic3r::PrintEstimatedStatistics::used_filaments_per_role, Slic3r::PrintEstimatedStatistics::volumes_per_color_change, Slic3r::GCodeProcessor::UsedFilaments::volumes_per_color_change, Slic3r::PrintEstimatedStatistics::volumes_per_extruder, and Slic3r::GCodeProcessor::UsedFilaments::volumes_per_extruder.

Referenced by finalize().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ m_cached_position

CachedPosition Slic3r::GCodeProcessor::m_cached_position
private

Referenced by process_M401(), process_M402(), and reset().

◆ m_cp_color

CpColor Slic3r::GCodeProcessor::m_cp_color
private

◆ m_e_local_positioning_type

EPositioningType Slic3r::GCodeProcessor::m_e_local_positioning_type
private

◆ m_end_position

◆ m_extra_loading_move

float Slic3r::GCodeProcessor::m_extra_loading_move
private

◆ m_extruded_last_z

float Slic3r::GCodeProcessor::m_extruded_last_z
private

Referenced by process_G1(), and reset().

◆ m_extruder_colors

ExtruderColors Slic3r::GCodeProcessor::m_extruder_colors
private

◆ m_extruder_id

◆ m_extruder_offsets

std::vector<Vec3f> Slic3r::GCodeProcessor::m_extruder_offsets
private

◆ m_extruder_temps

ExtruderTemps Slic3r::GCodeProcessor::m_extruder_temps
private

◆ m_extruder_temps_config

ExtruderTemps Slic3r::GCodeProcessor::m_extruder_temps_config
private

Referenced by apply_config(), and post_process().

◆ m_extruder_temps_first_layer_config

ExtruderTemps Slic3r::GCodeProcessor::m_extruder_temps_first_layer_config
private

Referenced by apply_config(), and post_process().

◆ m_extrusion_role

◆ m_fan_speed

float Slic3r::GCodeProcessor::m_fan_speed
private

◆ m_feed_multiply

FeedMultiply Slic3r::GCodeProcessor::m_feed_multiply
private

◆ m_feedrate

float Slic3r::GCodeProcessor::m_feedrate
private

◆ m_first_layer_height

float Slic3r::GCodeProcessor::m_first_layer_height
private

◆ m_flavor

◆ m_forced_height

float Slic3r::GCodeProcessor::m_forced_height
private

◆ m_forced_width

float Slic3r::GCodeProcessor::m_forced_width
private

◆ m_g1_line_id

unsigned int Slic3r::GCodeProcessor::m_g1_line_id
private

◆ m_global_positioning_type

EPositioningType Slic3r::GCodeProcessor::m_global_positioning_type
private

◆ m_height

float Slic3r::GCodeProcessor::m_height
private

◆ m_is_XL_printer

bool Slic3r::GCodeProcessor::m_is_XL_printer = false
private

◆ m_kissslicer_toolchange_time_correction

float Slic3r::GCodeProcessor::m_kissslicer_toolchange_time_correction
private

◆ m_last_default_color_id

size_t Slic3r::GCodeProcessor::m_last_default_color_id
private

Referenced by process_tags(), and reset().

◆ m_last_line_id

unsigned int Slic3r::GCodeProcessor::m_last_line_id
private

Referenced by reset(), and store_move_vertex().

◆ m_layer_id

◆ m_line_id

unsigned int Slic3r::GCodeProcessor::m_line_id
private

◆ m_mm3_per_mm

float Slic3r::GCodeProcessor::m_mm3_per_mm
private

◆ m_options_z_corrector

OptionsZCorrector Slic3r::GCodeProcessor::m_options_z_corrector
private

Referenced by process_G1(), process_tags(), and reset().

◆ m_origin

AxisCoords Slic3r::GCodeProcessor::m_origin
private

◆ m_parking_position

float Slic3r::GCodeProcessor::m_parking_position
private

◆ m_parser

◆ m_print

Print* Slic3r::GCodeProcessor::m_print { nullptr }
private

Referenced by post_process(), and set_print().

◆ m_producer

EProducer Slic3r::GCodeProcessor::m_producer
private

◆ m_result

◆ m_saved_position

AxisCoords Slic3r::GCodeProcessor::m_saved_position
private

Referenced by process_G60(), process_G61(), and reset().

◆ m_seams_detector

◆ m_single_extruder_multi_material

bool Slic3r::GCodeProcessor::m_single_extruder_multi_material
private

◆ m_spiral_vase_active

bool Slic3r::GCodeProcessor::m_spiral_vase_active
private

◆ m_start_position

◆ m_time_processor

◆ m_units

◆ m_use_volumetric_e

bool Slic3r::GCodeProcessor::m_use_volumetric_e
private

◆ m_used_filaments

UsedFilaments Slic3r::GCodeProcessor::m_used_filaments
private

◆ m_width

float Slic3r::GCodeProcessor::m_width
private

◆ m_wiping

bool Slic3r::GCodeProcessor::m_wiping
private

Referenced by process_G1(), process_tags(), and reset().

◆ m_z_offset

float Slic3r::GCodeProcessor::m_z_offset
private

◆ Producers

const std::vector< std::pair< GCodeProcessor::EProducer, std::string > > Slic3r::GCodeProcessor::Producers
staticprivate
Initial value:
= {
{ EProducer::PrusaSlicer, "generated by PrusaSlicer" },
{ EProducer::Slic3rPE, "generated by Slic3r Prusa Edition" },
{ EProducer::Slic3r, "generated by Slic3r" },
{ EProducer::SuperSlicer, "generated by SuperSlicer" },
{ EProducer::Cura, "Cura_SteamEngine" },
{ EProducer::Simplify3D, "generated by Simplify3D(R)" },
{ EProducer::CraftWare, "CraftWare" },
{ EProducer::ideaMaker, "ideaMaker" },
{ EProducer::KissSlicer, "KISSlicer" },
{ EProducer::BambuStudio, "BambuStudio" }
}

Referenced by detect_producer().

◆ Reserved_Tags

const std::vector< std::string > Slic3r::GCodeProcessor::Reserved_Tags
staticprivate
Initial value:
= {
"TYPE:",
"WIPE_START",
"WIPE_END",
"HEIGHT:",
"WIDTH:",
"LAYER_CHANGE",
"COLOR_CHANGE",
"PAUSE_PRINT",
"CUSTOM_GCODE",
"_GP_FIRST_LINE_M73_PLACEHOLDER",
"_GP_LAST_LINE_M73_PLACEHOLDER",
"_GP_ESTIMATED_PRINTING_TIME_PLACEHOLDER"
}

Referenced by reserved_tag().

◆ s_result_id

unsigned int Slic3r::GCodeProcessor::s_result_id = 0
staticprivate

Referenced by initialize(), process_file(), and reset().

◆ Wipe_Height

const float Slic3r::GCodeProcessor::Wipe_Height = 0.05f
static

◆ Wipe_Width

const float Slic3r::GCodeProcessor::Wipe_Width = 0.05f
static

Referenced by finalize().


The documentation for this class was generated from the following files: