OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::CoolingBuffer Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/GCode/CoolingBuffer.hpp>

Collaboration diagram for Slic3r::CoolingBuffer:

Public Member Functions

 CoolingBuffer (GCode &gcodegen)
void reset (const Vec3d &position)
void set_current_extruder (unsigned int extruder_id, unsigned int nozzle_id)
std::string process_layer (std::string &&gcode, size_t layer_id, bool flush)

Private Member Functions

CoolingBuffer & operator= (const CoolingBuffer &)=delete
std::vector< PerExtruderAdjustments > parse_layer_gcode (const std::string &gcode, std::vector< float > &current_pos) const
float calculate_layer_slowdown (std::vector< PerExtruderAdjustments > &per_extruder_adjustments)
std::string apply_layer_cooldown (const std::string &gcode, size_t layer_id, float layer_time, std::vector< PerExtruderAdjustments > &per_extruder_adjustments)

Private Attributes

std::string m_gcode
std::vector< char > m_axis
std::vector< float > m_current_pos
int m_fan_speed
int m_additional_fan_speed
std::vector< unsigned int > m_extruder_ids
unsigned int m_num_extruders { 0 }
const std::string m_toolchange_prefix
const PrintConfig & m_config
const GCode & m_gcodegen
unsigned int m_current_extruder
unsigned int m_current_nozzle
int m_current_fan_speed
bool m_belt_band_active = false

Detailed Description

Constructor & Destructor Documentation

◆ CoolingBuffer()

Slic3r::CoolingBuffer::CoolingBuffer ( GCode & gcodegen)
40 : m_config(gcodegen.config()), m_gcodegen(gcodegen), m_toolchange_prefix(gcodegen.writer().toolchange_prefix()), m_current_extruder(0), m_current_nozzle(0)
41{
42 this->reset(gcodegen.writer().get_position());
43
44 const std::vector<Extruder> &extruders = gcodegen.writer().extruders();
45 m_extruder_ids.reserve(extruders.size());
46 for (const Extruder &ex : extruders) {
47 m_num_extruders = std::max(ex.id() + 1, m_num_extruders);
48 m_extruder_ids.emplace_back(ex.id());
49 }
50
51}
const PrintConfig & m_config
Definition CoolingBuffer.hpp:59
std::vector< unsigned int > m_extruder_ids
Definition CoolingBuffer.hpp:53
const std::string m_toolchange_prefix
Definition CoolingBuffer.hpp:56
unsigned int m_current_nozzle
Definition CoolingBuffer.hpp:63
unsigned int m_current_extruder
Definition CoolingBuffer.hpp:62
void reset(const Vec3d &position)
Definition CoolingBuffer.cpp:53
unsigned int m_num_extruders
Definition CoolingBuffer.hpp:55
const GCode & m_gcodegen
Definition CoolingBuffer.hpp:61
@ Extruder
Definition DevConfigUtil.h:34

References Slic3r::GCodeWriter::extruders(), Slic3r::GCodeWriter::get_position(), m_config, m_current_extruder, m_current_nozzle, m_extruder_ids, m_gcodegen, m_num_extruders, m_toolchange_prefix, reset(), and Slic3r::GCode::writer().

Referenced by operator=().

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

Member Function Documentation

◆ apply_layer_cooldown()

std::string Slic3r::CoolingBuffer::apply_layer_cooldown ( const std::string & gcode,
size_t layer_id,
float layer_time,
std::vector< PerExtruderAdjustments > & per_extruder_adjustments )
private
733{
734 // First sort the adjustment lines by of multiple extruders by their position in the source G-code.
735 std::vector<const CoolingLine*> lines;
736 {
737 size_t n_lines = 0;
738 for (const PerExtruderAdjustments &adj : per_extruder_adjustments)
739 n_lines += adj.lines.size();
740 lines.reserve(n_lines);
741 for (const PerExtruderAdjustments &adj : per_extruder_adjustments)
742 for (const CoolingLine &line : adj.lines)
743 lines.emplace_back(&line);
744 std::sort(lines.begin(), lines.end(), [](const CoolingLine *ln1, const CoolingLine *ln2) { return ln1->line_start < ln2->line_start; } );
745 }
746 // Second generate the adjusted G-code.
747 std::string new_gcode;
748 new_gcode.reserve(gcode.size() * 2);
749 // ORCA: per-printer minimum non-zero fan PWM. Applied at every part-cooling fan emission below so any
750 // non-zero command is raised to at least this percent (0 disables the clamp).
751 const unsigned int part_cooling_fan_min_pwm = static_cast<unsigned int>(std::max(0, m_config.part_cooling_fan_min_pwm.value));
752 bool overhang_fan_control= false;
753 int overhang_fan_speed = 0;
754 bool internal_bridge_fan_control= false; // ORCA: Add support for separate internal bridge fan speed control
755 int internal_bridge_fan_speed = 0; // ORCA: Add support for separate internal bridge fan speed control
756 bool supp_interface_fan_control= false;
757 int supp_interface_fan_speed = 0;
758 bool ironing_fan_control= false; // ORCA: Add support for ironing fan speed control
759 int ironing_fan_speed = 0; // ORCA: Add support for ironing fan speed control
760 auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, part_cooling_fan_min_pwm,
761 &overhang_fan_control, &overhang_fan_speed,
762 &internal_bridge_fan_control, &internal_bridge_fan_speed,
763 &supp_interface_fan_control, &supp_interface_fan_speed,
764 &ironing_fan_control, &ironing_fan_speed
765 ](bool immediately_apply) {
766#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
767 // The per-variant options take the extruder variant the filament prints with on this layer
768 const size_t config_index = m_gcodegen.get_filament_config_index(m_current_extruder, layer_id);
769 float fan_min_speed = m_config.fan_min_speed.get_at(config_index);
770 float fan_speed_new = EXTRUDER_CONFIG(reduce_fan_stop_start_freq) ? fan_min_speed : 0;
771 //BBS
772 int additional_fan_speed_new = m_config.additional_cooling_fan_speed.get_at(config_index);
774 // Is the fan speed ramp enabled?
776 // ORCA: explicit per-filament first-layer override (-1 = disabled, 0-100 = forced PWM percent on layer 0).
777 // The override is only honoured when the "No cooling for the first" gate is 0; otherwise the gate would
778 // force layers 1..N-1 to zero while the override sets layer 0 to a non-zero value, which is confusing
779 // and non-monotonic. The UI greys out and resets the value in that case, but we also guard here so
780 // legacy profiles loaded with both set are neutralised at the slicer level.
781 int initial_layer_fan_speed = EXTRUDER_CONFIG(initial_layer_fan_speed);
782 const bool has_initial_layer_override = initial_layer_fan_speed >= 0 && close_fan_the_first_x_layers <= 0;
783 supp_interface_fan_speed = EXTRUDER_CONFIG(support_material_interface_fan_speed);
784
785 // ORCA: previously a silent override forced `close_fan_the_first_x_layers` from 0 up to 1 whenever a ramp
786 // was configured (`full_fan_speed_layer > 0`), so the first printed layer always had the fan disabled.
787 // That hid the user's literal "no cooling for the first 0 layers" setting and produced a non-zero starting
788 // factor on the ramp denominator. The override has been removed: with N=0 and M>0 the ramp now genuinely
789 // starts on layer 0 at a factor of 1/M and reaches 100% at layer M-1, matching the intent of the option.
790 //
791 // ORCA: First-layer hard override (`initial_layer_fan_speed`). When the user has set this option to a
792 // value >= 0, layer 0 emits exactly that percentage so the entire first layer
793 // is at one stable fan speed. The override wins over the `close_fan_the_first_x_layers` gate when
794 // layer_id == 0. From layer 1 onwards the regular logic resumes.
795 if (has_initial_layer_override && layer_id == 0) {
796 fan_speed_new = initial_layer_fan_speed;
797 overhang_fan_speed = initial_layer_fan_speed;
798 overhang_fan_control = false;
799 internal_bridge_fan_speed = initial_layer_fan_speed;
800 internal_bridge_fan_control = false;
801 supp_interface_fan_speed = initial_layer_fan_speed;
802 supp_interface_fan_control = false;
803 ironing_fan_speed = initial_layer_fan_speed;
804 ironing_fan_control = false;
805 // additional_fan_speed_new is left at its configured value (auxiliary fan is independent of the
806 // part-cooling override).
807 } else if (int(layer_id) >= close_fan_the_first_x_layers) {
808 float fan_max_speed = m_config.fan_max_speed.get_at(config_index);
810 float fan_cooling_layer_time = float(EXTRUDER_CONFIG(fan_cooling_layer_time));
811 //BBS: always enable the fan speed interpolation according to layer time
812 //if (EXTRUDER_CONFIG(cooling)) {
813 if (layer_time < slow_down_layer_time) {
814 // Layer time very short. Enable the fan to a full throttle.
815 fan_speed_new = fan_max_speed;
816 } else if (layer_time < fan_cooling_layer_time) {
817 // Layer time quite short. Enable the fan proportionally according to the current layer time.
818 assert(layer_time >= slow_down_layer_time);
819 double t = (layer_time - slow_down_layer_time) / (fan_cooling_layer_time - slow_down_layer_time);
820 fan_speed_new = int(floor(t * fan_min_speed + (1. - t) * fan_max_speed) + 0.5);
821 }
822 //}
824 if (int(layer_id) >= close_fan_the_first_x_layers && int(layer_id) + 1 < full_fan_speed_layer) {
825 if (has_initial_layer_override && close_fan_the_first_x_layers == 0 && full_fan_speed_layer > 1) {
826 // ORCA: Option-B anchored ramp. When the first-layer override is configured and there's
827 // no "no cooling" gate, the ramp interpolates linearly from `initial_layer_fan_speed` on
828 // layer 0 up to the computed target on layer `full_fan_speed_layer - 1` instead of
829 // scaling the target by `factor` from zero. Layer 0 itself is handled by the override
830 // branch above; this branch only runs for layer_id >= 1, but the formula uses t = 0 at
831 // layer 0 conceptually so the curve is continuous. Guarantees a monotonic transition
832 // even when the override is larger than the natural 1/M starting value.
833 const float anchor = float(initial_layer_fan_speed);
834 const float denom = float(full_fan_speed_layer - 1);
835 const float t = float(int(layer_id)) / denom;
836 fan_speed_new = std::clamp(int(anchor + t * (float(fan_speed_new) - anchor) + 0.5f), 0, 255);
837 overhang_fan_speed = std::clamp(int(anchor + t * (float(overhang_fan_speed) - anchor) + 0.5f), 0, 255);
838 } else {
839 // Ramp up the fan speed from close_fan_the_first_x_layers to full_fan_speed_layer.
840 float factor = float(int(layer_id + 1) - close_fan_the_first_x_layers) / float(full_fan_speed_layer - close_fan_the_first_x_layers);
841 fan_speed_new = std::clamp(int(float(fan_speed_new) * factor + 0.5f), 0, 255);
842 overhang_fan_speed = std::clamp(int(float(overhang_fan_speed) * factor + 0.5f), 0, 255);
843 }
844 }
845 supp_interface_fan_speed = EXTRUDER_CONFIG(support_material_interface_fan_speed);
846 supp_interface_fan_control = supp_interface_fan_speed >= 0;
847
848 overhang_fan_control = overhang_fan_speed > fan_speed_new;
849
850 // ORCA: Add support for separate internal bridge fan speed control
851 internal_bridge_fan_speed = EXTRUDER_CONFIG(internal_bridge_fan_speed);
852 internal_bridge_fan_control = internal_bridge_fan_speed >=0;
853
854 if( internal_bridge_fan_speed < 0 ) { // ORCA: Backwards compatibility setting for Orca internal bridge fan speed setting - if set at -1 (which is the default) use the overhang fan speed settings.
855 internal_bridge_fan_speed = overhang_fan_speed;
856 internal_bridge_fan_control = overhang_fan_control;
857 }
858
859 // ORCA: Add support for ironing fan speed control
861 ironing_fan_control = ironing_fan_speed >= 0;
862#undef EXTRUDER_CONFIG
863
864 } else {
865 overhang_fan_control = false;
867 fan_speed_new = 0;
868 additional_fan_speed_new = 0;
869 supp_interface_fan_control = false;
870 supp_interface_fan_speed = 0;
871 internal_bridge_fan_control = false; // ORCA: Add support for separate internal bridge fan speed control
872 internal_bridge_fan_speed = 0; // ORCA: Add support for separate internal bridge fan speed control
873 ironing_fan_control = false; // ORCA: Add support for ironing fan speed control
874 ironing_fan_speed = 0; // ORCA: Add support for ironing fan speed control
875 }
876 // A tool change may keep the same configured base fan speed while the physical fan is
877 // still running at the previous filament's overhang speed. Restore the base speed before
878 // emitting G-code for the new tool in that case.
879 if (fan_speed_new != m_fan_speed || (immediately_apply && m_current_fan_speed != fan_speed_new)) {
880 m_fan_speed = fan_speed_new;
881 m_current_fan_speed = fan_speed_new;
882 if (immediately_apply)
884 }
885 //BBS
886 if (additional_fan_speed_new != m_additional_fan_speed) {
887 m_additional_fan_speed = additional_fan_speed_new;
888 if (immediately_apply && m_config.auxiliary_fan.value)
890 }
891 };
892
893 const char *pos = gcode.c_str();
894 int current_feedrate = 0;
895 change_extruder_set_fan(true);
896
897 // Orca: Reduce set fan commands by deferring the GCodeWriter::set_fan calls. Inspired by SuperSlicer
898 // define fan_speed_change_requests and initialize it with all possible types fan speed change requests
899 std::unordered_map<int, bool> fan_speed_change_requests = {{CoolingLine::TYPE_OVERHANG_FAN_START, false},
900 {CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START, false}, // ORCA: Add support for separate internal bridge fan speed control
902 {CoolingLine::TYPE_IRONING_FAN_START, false}, // ORCA: Add support for ironing fan speed control
904 // Belt printers: a band still open from the previous layer has to take the fan back from
905 // the layer-level speed issued just above.
906 bool need_set_fan = m_belt_band_active;
907
908 for (const CoolingLine *line : lines) {
909 const char *line_start = gcode.c_str() + line->line_start;
910 const char *line_end = gcode.c_str() + line->line_end;
911 if (line_start > pos)
912 new_gcode.append(pos, line_start - pos);
913 if (line->type & CoolingLine::TYPE_SET_TOOL) {
914 unsigned int new_extruder = 0;
915 auto ret = std::from_chars(line_start + m_toolchange_prefix.size(), line_end, new_extruder);
916 if (std::errc::invalid_argument != ret.ec) {
917 if (new_extruder != m_current_extruder) {
918 m_current_extruder = new_extruder;
919 change_extruder_set_fan(true);
921 need_set_fan = true;
922 }
923 }
924 new_gcode.append(line_start, line_end - line_start);
925 } else if (line->type & CoolingLine::TYPE_OVERHANG_FAN_START) {
926 if (overhang_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]) {
927 need_set_fan = true;
928 fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START] = true;
929 }
930 } else if (line->type & CoolingLine::TYPE_OVERHANG_FAN_END) {
931 if (overhang_fan_control && fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]) {
932 fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START] = false;
933 }
934 need_set_fan = true;
935 } else if (line->type & CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START) { // ORCA: Add support for separate internal bridge fan speed control
936 if (internal_bridge_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START]) {
937 need_set_fan = true;
938 fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START] = true;
939 }
940 } else if (line->type & CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_END) { // ORCA: Add support for separate internal bridge fan speed control
941 if (internal_bridge_fan_control && fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START]) {
942 fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START] = false;
943 }
944 need_set_fan = true;
945 } else if (line->type & CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START) {
946 if (supp_interface_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]) {
947 fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START] = true;
948 need_set_fan = true;
949 }
950 } else if (line->type & CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_END && fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]) {
951 if (supp_interface_fan_control) {
952 fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START] = false;
953 }
954 need_set_fan = true;
955 } else if (line->type & CoolingLine::TYPE_IRONING_FAN_START) {
956 if (ironing_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_IRONING_FAN_START]) {
957 fan_speed_change_requests[CoolingLine::TYPE_IRONING_FAN_START] = true;
958 need_set_fan = true;
959 }
960 } else if (line->type & CoolingLine::TYPE_IRONING_FAN_END) {
961 if (ironing_fan_control && fan_speed_change_requests[CoolingLine::TYPE_IRONING_FAN_START]) {
962 fan_speed_change_requests[CoolingLine::TYPE_IRONING_FAN_START] = false;
963 }
964 need_set_fan = true;
965 } else if (line->type & CoolingLine::TYPE_FORCE_RESUME_FAN) {
966 // check if any fan speed change request is active
967 if (m_fan_speed != -1 && !std::any_of(fan_speed_change_requests.begin(), fan_speed_change_requests.end(), [](const std::pair<int, bool>& p) { return p.second; })){
968 fan_speed_change_requests[CoolingLine::TYPE_FORCE_RESUME_FAN] = true;
969 need_set_fan = true;
970 }
971 if (m_additional_fan_speed != -1 && m_config.auxiliary_fan.value)
973 }
974 else if (line->type & CoolingLine::TYPE_BELT_BAND_START) {
975 m_belt_band_active = true;
976 need_set_fan = true;
977 } else if (line->type & CoolingLine::TYPE_BELT_BAND_END) {
978 m_belt_band_active = false;
979 need_set_fan = true;
980 }
981 else if (line->type & CoolingLine::TYPE_EXTRUDE_END) {
982 // Just remove this comment.
984 // Find the start of a comment, or roll to the end of line.
985 const char *end = line_start;
986 for (; end < line_end && *end != ';'; ++ end);
987 // Find the 'F' word.
988 const char *fpos = strstr(line_start + 2, " F") + 2;
989 int new_feedrate = current_feedrate;
990 // Modify the F word of the current G-code line.
991 bool modify = false;
992 // Remove the F word from the current G-code line.
993 bool remove = false;
994 assert(fpos != nullptr);
995 new_feedrate = line->slowdown ? int(floor(60. * line->feedrate + 0.5)) : atoi(fpos);
996 if (new_feedrate == current_feedrate) {
997 // No need to change the F value.
999 // Feedrate does not change and this line does not move the print head. Skip the complete G-code line including the G-code comment.
1000 end = line_end;
1001 else
1002 // Remove the feedrate from the G0/G1 line. The G-code line may become empty!
1003 remove = true;
1004 } else if (line->slowdown) {
1005 // The F value will be overwritten.
1006 modify = true;
1007 } else {
1008 // The F value is different from current_feedrate, but not slowed down, thus the G-code line will not be modified.
1009 // Emit the line without the comment.
1010 new_gcode.append(line_start, end - line_start);
1011 current_feedrate = new_feedrate;
1012 }
1013 if (modify || remove) {
1014 if (modify) {
1015 // Replace the feedrate.
1016 new_gcode.append(line_start, fpos - line_start);
1017 current_feedrate = new_feedrate;
1018 char buf[64];
1019 sprintf(buf, "%d", int(current_feedrate));
1020 new_gcode += buf;
1021 } else {
1022 // Remove the feedrate word.
1023 const char *f = fpos;
1024 // Roll the pointer before the 'F' word.
1025 for (f -= 2; f > line_start && (*f == ' ' || *f == '\t'); -- f);
1026
1027 if ((f - line_start == 1) && *line_start == 'G' && (*f == '1' || *f == '0')) {
1028 // BBS: only remain "G1" or "G0" of this line after remove 'F' part, don't save
1029 } else {
1030 // Append up to the F word, without the trailing whitespace.
1031 new_gcode.append(line_start, f - line_start + 1);
1032 }
1033 }
1034 // Skip the non-whitespaces of the F parameter up the comment or end of line.
1035 for (; fpos != end && *fpos != ' ' && *fpos != ';' && *fpos != '\n'; ++ fpos);
1036 // Append the rest of the line without the comment.
1037 if (fpos < end)
1038 // The G-code line is not empty yet. Emit the rest of it.
1039 new_gcode.append(fpos, end - fpos);
1040 else if (remove && new_gcode == "G1") {
1041 // The G-code line only contained the F word, now it is empty. Remove it completely including the comments.
1042 new_gcode.resize(new_gcode.size() - 2);
1043 end = line_end;
1044 }
1045 }
1046 // Process the rest of the line.
1047 if (end < line_end) {
1049 // Process comments, remove ";_EXTRUDE_SET_SPEED", ";_EXTERNAL_PERIMETER", ";_WIPE"
1050 std::string comment(end, line_end);
1051 boost::replace_all(comment, ";_EXTRUDE_SET_SPEED", "");
1052 if (line->type & CoolingLine::TYPE_EXTERNAL_PERIMETER)
1053 boost::replace_all(comment, ";_EXTERNAL_PERIMETER", "");
1054 if (line->type & CoolingLine::TYPE_WIPE)
1055 boost::replace_all(comment, ";_WIPE", "");
1056 new_gcode += comment;
1057 } else {
1058 // Just attach the rest of the source line.
1059 new_gcode.append(end, line_end - end);
1060 }
1061 }
1062 } else {
1063 new_gcode.append(line_start, line_end - line_start);
1064 }
1065
1066 if (need_set_fan) {
1067 const auto set_fan = [&](int speed) {
1068 if (m_current_fan_speed != speed) {
1069 new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, speed, part_cooling_fan_min_pwm);
1070 m_current_fan_speed = speed;
1071 }
1072 };
1073 if (m_belt_band_active) {
1074 // Belt printers: a tilted layer runs from the belt to the top of the part, so
1075 // "the first layers" are a band along the belt rather than the first slicing
1076 // layers. Extrusions GCode::_extrude() marks as inside that band print with the
1077 // fan off, whatever overhang, bridge or resume request is pending, as the first
1078 // layers of a flat bed do. Leaving the band falls through to the branches below.
1079 set_fan(0);
1080 fan_speed_change_requests[CoolingLine::TYPE_FORCE_RESUME_FAN] = false;
1081 } else if (fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]){
1082 set_fan(overhang_fan_speed);
1083 } else if (fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START]){ // ORCA: Add support for separate internal bridge fan speed control
1084 set_fan(internal_bridge_fan_speed);
1085 }
1086 else if (fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]){
1087 set_fan(supp_interface_fan_speed);
1088 }
1089 else if (fan_speed_change_requests[CoolingLine::TYPE_IRONING_FAN_START]){
1090 set_fan(ironing_fan_speed);
1091 }
1092 else if(fan_speed_change_requests[CoolingLine::TYPE_FORCE_RESUME_FAN] && m_current_fan_speed != -1){
1094 fan_speed_change_requests[CoolingLine::TYPE_FORCE_RESUME_FAN] = false;
1095 }
1096 else {
1097 set_fan(m_fan_speed);
1098 }
1099 need_set_fan = false;
1100 }
1101 pos = line_end;
1102 }
1103 const char *gcode_end = gcode.c_str() + gcode.size();
1104 if (pos < gcode_end)
1105 new_gcode.append(pos, gcode_end - pos);
1106
1107 return new_gcode;
1108}
#define EXTRUDER_CONFIG(OPT)
Definition GCode.cpp:2155
int m_additional_fan_speed
Definition CoolingBuffer.hpp:50
int m_current_fan_speed
Definition CoolingBuffer.hpp:65
bool m_belt_band_active
Definition CoolingBuffer.hpp:68
int m_fan_speed
Definition CoolingBuffer.hpp:49
static std::string set_fan(const GCodeFlavor gcode_flavor, unsigned int speed, unsigned int part_cooling_fan_min_pwm=0)
Definition GCodeWriter.cpp:1552
static std::string set_additional_fan(unsigned int speed)
Definition GCodeWriter.cpp:1599
T * end(Slic3r::Mat< N, M, T > &mat)
Definition Point.hpp:841
@ gcode
Definition Time.hpp:14
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:16
zaa_minimize_perimeter_height overhang_fan_speed((ConfigOptionEnumsGeneric, overhang_fan_threshold))((ConfigOptionEnum< PrintSequence >
zaa_minimize_perimeter_height ironing_fan_speed((ConfigOptionStrings, filament_notes))((ConfigOptionString
zaa_minimize_perimeter_height part_cooling_fan_min_pwm((ConfigOptionFloats, filament_diameter))((ConfigOptionBoolsNullable
zaa_minimize_perimeter_height fan_min_speed((ConfigOptionFloats, min_layer_height))((ConfigOptionFloat
zaa_minimize_perimeter_height support_material_interface_fan_speed((ConfigOptionInts, internal_bridge_fan_speed))((ConfigOptionInts
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:124
zaa_minimize_perimeter_height full_fan_speed_layer((ConfigOptionInts, initial_layer_fan_speed))((ConfigOptionFloats
zaa_minimize_perimeter_height close_fan_the_first_x_layers((ConfigOptionEnum< DraftShield >, draft_shield))((ConfigOptionFloat
zaa_minimize_perimeter_height slow_down_layer_time((ConfigOptionBool, spiral_mode))((ConfigOptionBool
zaa_minimize_perimeter_height fan_max_speed((ConfigOptionFloats, max_layer_height))((ConfigOptionFloats
@ TYPE_OVERHANG_FAN_END
Definition CoolingBuffer.cpp:73
@ TYPE_OVERHANG_FAN_START
Definition CoolingBuffer.cpp:72
@ TYPE_ADJUSTABLE
Definition CoolingBuffer.cpp:76
@ TYPE_IRONING_FAN_END
Definition CoolingBuffer.cpp:94
@ TYPE_WIPE
Definition CoolingBuffer.cpp:80
@ TYPE_BELT_BAND_END
Definition CoolingBuffer.cpp:97
@ TYPE_FORCE_RESUME_FAN
Definition CoolingBuffer.cpp:86
@ TYPE_HAS_F
Definition CoolingBuffer.cpp:79
@ TYPE_EXTRUDE_END
Definition CoolingBuffer.cpp:71
@ TYPE_EXTERNAL_PERIMETER
Definition CoolingBuffer.cpp:77
@ TYPE_SUPPORT_INTERFACE_FAN_END
Definition CoolingBuffer.cpp:88
@ TYPE_SUPPORT_INTERFACE_FAN_START
Definition CoolingBuffer.cpp:87
@ TYPE_INTERNAL_BRIDGE_FAN_START
Definition CoolingBuffer.cpp:90
@ TYPE_BELT_BAND_START
Definition CoolingBuffer.cpp:96
@ TYPE_INTERNAL_BRIDGE_FAN_END
Definition CoolingBuffer.cpp:91
@ TYPE_SET_TOOL
Definition CoolingBuffer.cpp:70
@ TYPE_IRONING_FAN_START
Definition CoolingBuffer.cpp:93

References Slic3r::close_fan_the_first_x_layers(), EXTRUDER_CONFIG, Slic3r::f(), Slic3r::fan_max_speed(), Slic3r::fan_min_speed(), Slic3r::full_fan_speed_layer(), Slic3r::ironing_fan_speed(), m_additional_fan_speed, m_belt_band_active, m_config, m_current_extruder, m_current_fan_speed, m_fan_speed, m_gcodegen, m_toolchange_prefix, Slic3r::overhang_fan_speed(), Slic3r::part_cooling_fan_min_pwm(), Slic3r::GCodeWriter::set_additional_fan(), Slic3r::GCodeWriter::set_fan(), Slic3r::slow_down_layer_time(), Slic3r::support_material_interface_fan_speed(), Slic3r::CoolingLine::TYPE_ADJUSTABLE, Slic3r::CoolingLine::TYPE_BELT_BAND_END, Slic3r::CoolingLine::TYPE_BELT_BAND_START, Slic3r::CoolingLine::TYPE_EXTERNAL_PERIMETER, Slic3r::CoolingLine::TYPE_EXTRUDE_END, Slic3r::CoolingLine::TYPE_FORCE_RESUME_FAN, Slic3r::CoolingLine::TYPE_HAS_F, Slic3r::CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_END, Slic3r::CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START, Slic3r::CoolingLine::TYPE_IRONING_FAN_END, Slic3r::CoolingLine::TYPE_IRONING_FAN_START, Slic3r::CoolingLine::TYPE_OVERHANG_FAN_END, Slic3r::CoolingLine::TYPE_OVERHANG_FAN_START, Slic3r::CoolingLine::TYPE_SET_TOOL, Slic3r::CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_END, Slic3r::CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START, and Slic3r::CoolingLine::TYPE_WIPE.

Referenced by process_layer().

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

◆ calculate_layer_slowdown()

float Slic3r::CoolingBuffer::calculate_layer_slowdown ( std::vector< PerExtruderAdjustments > & per_extruder_adjustments)
private
667{
668 // Sort the extruders by an increasing slow_down_layer_time.
669 // The layers with a lower slow_down_layer_time are slowed down
670 // together with all the other layers with slow_down_layer_time above.
671 std::vector<PerExtruderAdjustments*> by_slowdown_time;
672 by_slowdown_time.reserve(per_extruder_adjustments.size());
673 // Only insert entries, which are adjustable (have cooling enabled and non-zero stretchable time).
674 // Collect total print time of non-adjustable extruders.
675 float elapsed_time_total0 = 0.f;
676 for (PerExtruderAdjustments &adj : per_extruder_adjustments) {
677 // Curren total time for this extruder.
678 adj.time_total = adj.elapsed_time_total();
679 // Maximum time for this extruder, when all extrusion moves are slowed down to min_extrusion_speed.
680 adj.time_maximum = adj.maximum_time_after_slowdown(true);
681 if (adj.cooling_slow_down_enabled && adj.lines.size() > 0) {
682 by_slowdown_time.emplace_back(&adj);
683 // sorts the lines, also sets adj.time_non_adjustable
684 adj.sort_lines_by_decreasing_feedrate();
685 } else
686 elapsed_time_total0 += adj.elapsed_time_total();
687 }
688
689 std::sort(by_slowdown_time.begin(), by_slowdown_time.end(),
690 [](const PerExtruderAdjustments *adj1, const PerExtruderAdjustments *adj2)
691 { return adj1->slow_down_layer_time < adj2->slow_down_layer_time; });
692
693 for (auto cur_begin = by_slowdown_time.begin(); cur_begin != by_slowdown_time.end(); ++ cur_begin) {
694 PerExtruderAdjustments &adj = *(*cur_begin);
695 // Calculate the current adjusted elapsed_time_total over the non-finalized extruders.
696 float total = elapsed_time_total0;
697 for (auto it = cur_begin; it != by_slowdown_time.end(); ++ it)
698 total += (*it)->time_total;
699 float slow_down_layer_time = adj.slow_down_layer_time * 1.001f;
700 if (total > slow_down_layer_time) {
701 // The current total time is above the minimum threshold of the rest of the extruders, don't adjust anything.
702 } else {
703 // Adjust this and all the following (higher m_config.slow_down_layer_time) extruders.
704 // Sum maximum slow down time as if everything was slowed down including the external perimeters.
705 float max_time = elapsed_time_total0;
706 for (auto it = cur_begin; it != by_slowdown_time.end(); ++ it)
707 max_time += (*it)->time_maximum;
708 if (max_time > slow_down_layer_time) {
709 extruder_range_slow_down_non_proportional(cur_begin, by_slowdown_time.end(), slow_down_layer_time - total);
710 } else {
711 // Slow down to maximum possible.
712 for (auto it = cur_begin; it != by_slowdown_time.end(); ++ it)
713 (*it)->slowdown_to_minimum_feedrate(true);
714 }
715 }
716 elapsed_time_total0 += adj.elapsed_time_total();
717 }
718
719 return elapsed_time_total0;
720}
static void extruder_range_slow_down_non_proportional(std::vector< PerExtruderAdjustments * >::iterator it_begin, std::vector< PerExtruderAdjustments * >::iterator it_end, float time_stretch)
Definition CoolingBuffer.cpp:589

References Slic3r::PerExtruderAdjustments::elapsed_time_total(), Slic3r::extruder_range_slow_down_non_proportional(), Slic3r::PerExtruderAdjustments::slow_down_layer_time, Slic3r::slow_down_layer_time(), and Slic3r::PerExtruderAdjustments::time_total.

Referenced by process_layer().

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

◆ operator=()

CoolingBuffer & Slic3r::CoolingBuffer::operator= ( const CoolingBuffer & )
privatedelete

References CoolingBuffer().

Here is the call graph for this function:

◆ parse_layer_gcode()

std::vector< PerExtruderAdjustments > Slic3r::CoolingBuffer::parse_layer_gcode ( const std::string & gcode,
std::vector< float > & current_pos ) const
private
363{
364 std::vector<PerExtruderAdjustments> per_extruder_adjustments(m_extruder_ids.size());
365 std::vector<size_t> map_extruder_to_per_extruder_adjustment(m_num_extruders, 0);
366 for (size_t i = 0; i < m_extruder_ids.size(); ++ i) {
367 PerExtruderAdjustments &adj = per_extruder_adjustments[i];
368 unsigned int extruder_id = m_extruder_ids[i];
369 adj.extruder_id = extruder_id;
370 adj.cooling_slow_down_enabled = m_config.slow_down_for_layer_cooling.get_at(extruder_id);
371 adj.slow_down_layer_time = float(m_config.slow_down_layer_time.get_at(extruder_id));
372 adj.slow_down_min_speed = float(m_config.slow_down_min_speed.get_at(extruder_id));
373 // ORCA: To enable dont slow down external perimeters feature per filament (extruder)
374 adj.dont_slow_down_outer_wall = m_config.dont_slow_down_outer_wall.get_at(extruder_id);
375 map_extruder_to_per_extruder_adjustment[extruder_id] = i;
376 }
377
378 unsigned int current_extruder = m_current_extruder;
379 PerExtruderAdjustments *adjustment = &per_extruder_adjustments[map_extruder_to_per_extruder_adjustment[current_extruder]];
380 const char *line_start = gcode.c_str();
381 const char *line_end = line_start;
382 // Index of an existing CoolingLine of the current adjustment, which holds the feedrate setting command
383 // for a sequence of extrusion moves.
384 size_t active_speed_modifier = size_t(-1);
385
386 // Orca: Whether we had our first extrusion in this layer.
387 // Time of any other movements before the first extrusion will be excluded from the layer time.
388 bool layer_had_extrusion = false;
389
390 for (; *line_start != 0; line_start = line_end)
391 {
392 while (*line_end != '\n' && *line_end != 0)
393 ++ line_end;
394 // sline will not contain the trailing '\n'.
395 std::string sline(line_start, line_end);
396 // CoolingLine will contain the trailing '\n'.
397 if (*line_end == '\n')
398 ++ line_end;
399 CoolingLine line(0, line_start - gcode.c_str(), line_end - gcode.c_str());
400 if (boost::starts_with(sline, "G0 "))
401 line.type = CoolingLine::TYPE_G0;
402 else if (boost::starts_with(sline, "G1 "))
403 line.type = CoolingLine::TYPE_G1;
404 else if (boost::starts_with(sline, "G92 "))
405 line.type = CoolingLine::TYPE_G92;
406 else if (boost::starts_with(sline, "G2 "))
407 line.type = CoolingLine::TYPE_G2;
408 else if (boost::starts_with(sline, "G3 "))
409 line.type = CoolingLine::TYPE_G3;
410 if (line.type) {
411 // G0, G1 or G92
412 // Parse the G-code line.
413 std::vector<float> new_pos(current_pos);
414 const char *c = sline.data() + 3;
415 for (;;) {
416 // Skip whitespaces.
417 for (; *c == ' ' || *c == '\t'; ++ c);
418 if (*c == 0 || *c == ';')
419 break;
420
421 //BBS: Parse the axis.
422 size_t axis = (*c >= 'X' && *c <= 'Z') ? (*c - 'X') :
423 (*c == 'E') ? 3 : (*c == 'F') ? 4 :
424 (*c == 'I') ? 5 : (*c == 'J') ? 6 : size_t(-1);
425 if (axis != size_t(-1)) {
426 ++ c;
427 new_pos[axis] = float(atof_decimal_point(std::string_view(c, sline.data() + sline.size() - c)));
428 if (axis == 4) {
429 // Convert mm/min to mm/sec.
430 new_pos[4] /= 60.f;
431 if ((line.type & CoolingLine::TYPE_G92) == 0)
432 // This is G0 or G1 line and it sets the feedrate. This mark is used for reducing the duplicate F calls.
433 line.type |= CoolingLine::TYPE_HAS_F;
434 } else if (axis == 5 || axis == 6) {
435 // BBS: get position of arc center
436 new_pos[axis] += current_pos[axis - 5];
437 }
438 }
439 // Skip this word.
440 for (; *c != ' ' && *c != '\t' && *c != 0; ++ c);
441 }
442 bool external_perimeter = boost::contains(sline, ";_EXTERNAL_PERIMETER");
443 bool wipe = boost::contains(sline, ";_WIPE");
444 if (external_perimeter)
446 if (wipe)
447 line.type |= CoolingLine::TYPE_WIPE;
448
449 // Orca: only slow down movements since the first extrusion
450 if (boost::contains(sline, ";_EXTRUDE_SET_SPEED"))
451 layer_had_extrusion = true;
452
453 // ORCA: Dont slowdown external perimeters for layer time feature
454 // use the adjustment pointer to ensure the value for the current extruder (filament) is used.
455 bool adjust_external = true;
456 if(adjustment->dont_slow_down_outer_wall && external_perimeter) adjust_external = false;
457
458 // ORCA: Dont slowdown external perimeters for layer time works by not marking the external perimeter as adjustable,
459 // hence the slowdown algorithm ignores it.
460 if (boost::contains(sline, ";_EXTRUDE_SET_SPEED") && ! wipe && adjust_external) {
461 line.type |= CoolingLine::TYPE_ADJUSTABLE;
462 active_speed_modifier = adjustment->lines.size();
463 }
464 if ((line.type & CoolingLine::TYPE_G92) == 0) {
465 //BBS: G0, G1, G2, G3. Calculate the duration.
466 if (m_config.use_relative_e_distances.value)
467 // Reset extruder accumulator.
468 current_pos[3] = 0.f;
469 float dif[4];
470 for (size_t i = 0; i < 4; ++ i)
471 dif[i] = new_pos[i] - current_pos[i];
472 float dxy2 = 0;
473 //BBS: support to calculate length of arc
474 if (line.type & CoolingLine::TYPE_G2 || line.type & CoolingLine::TYPE_G3) {
475 Vec3f start(current_pos[0], current_pos[1], 0);
476 Vec3f end(new_pos[0], new_pos[1], 0);
477 Vec3f center(new_pos[5], new_pos[6], 0);
478 bool is_ccw = line.type & CoolingLine::TYPE_G3;
479 float dxy = ArcSegment::calc_arc_length(start, end, center, is_ccw);
480 dxy2 = dxy * dxy;
481 } else {
482 dxy2 = dif[0] * dif[0] + dif[1] * dif[1];
483 }
484 float dxyz2 = dxy2 + dif[2] * dif[2];
485 if (dxyz2 > 0.f) {
486 // Movement in xyz, calculate time from the xyz Euclidian distance.
487 line.length = sqrt(dxyz2);
488 } else if (std::abs(dif[3]) > 0.f) {
489 // Movement in the extruder axis.
490 line.length = std::abs(dif[3]);
491 }
492 line.feedrate = new_pos[4];
493 assert((line.type & CoolingLine::TYPE_ADJUSTABLE) == 0 || line.feedrate > 0.f);
494 if (line.length > 0)
495 line.time = line.length / line.feedrate;
496 line.time_max = line.time;
497 if ((line.type & CoolingLine::TYPE_ADJUSTABLE) || active_speed_modifier != size_t(-1))
498 line.time_max = (adjustment->slow_down_min_speed == 0.f) ? FLT_MAX : std::max(line.time, line.length / adjustment->slow_down_min_speed);
499 // BBS: add G2 and G3 support
500 if (active_speed_modifier < adjustment->lines.size() && ((line.type & CoolingLine::TYPE_G1) ||
501 (line.type & CoolingLine::TYPE_G2) ||
502 (line.type & CoolingLine::TYPE_G3))) {
503 // Inside the ";_EXTRUDE_SET_SPEED" blocks, there must not be a G1 Fxx entry.
504 assert((line.type & CoolingLine::TYPE_HAS_F) == 0);
505 CoolingLine &sm = adjustment->lines[active_speed_modifier];
506 assert(sm.feedrate > 0.f);
507 sm.length += line.length;
508 sm.time += line.time;
509 if (sm.time_max != FLT_MAX) {
510 if (line.time_max == FLT_MAX)
511 sm.time_max = FLT_MAX;
512 else
513 sm.time_max += line.time_max;
514 }
515 // Don't store this line.
516 line.type = 0;
517 }
518 }
519 current_pos = std::move(new_pos);
520 } else if (boost::starts_with(sline, ";_EXTRUDE_END")) {
522 active_speed_modifier = size_t(-1);
523 } else if (boost::starts_with(sline, m_toolchange_prefix)) {
524 unsigned int new_extruder = 0;
525 auto ret = std::from_chars(sline.data() + m_toolchange_prefix.size(), sline.data() + sline.size(), new_extruder);
526 if (std::errc::invalid_argument != ret.ec) {
527 // Only change extruder in case the number is meaningful. User could provide an out-of-range index through custom gcodes -
528 // those shall be ignored.
529 if (new_extruder < map_extruder_to_per_extruder_adjustment.size()) {
530 if (new_extruder != current_extruder) {
531 // Switch the tool.
532 line.type = CoolingLine::TYPE_SET_TOOL;
533 current_extruder = new_extruder;
534 adjustment = &per_extruder_adjustments[map_extruder_to_per_extruder_adjustment[current_extruder]];
535 }
536 } else {
537 // Only log the error in case of MM printer. Single extruder printers likely ignore any T anyway.
538 if (map_extruder_to_per_extruder_adjustment.size() > 1)
539 BOOST_LOG_TRIVIAL(error) << "CoolingBuffer encountered an invalid toolchange, maybe from a custom gcode: " << sline;
540 }
541 }
542 } else if (boost::starts_with(sline, ";_OVERHANG_FAN_START")) {
544 } else if (boost::starts_with(sline, ";_OVERHANG_FAN_END")) {
546 } else if (boost::starts_with(sline, ";_INTERNAL_BRIDGE_FAN_START")) { // ORCA: Add support for separate internal bridge fan speed control
548 } else if (boost::starts_with(sline, ";_INTERNAL_BRIDGE_FAN_END")) { // ORCA: Add support for separate internal bridge fan speed control
550 } else if (boost::starts_with(sline, ";_SUPP_INTERFACE_FAN_START")) {
552 } else if (boost::starts_with(sline, ";_SUPP_INTERFACE_FAN_END")) {
554 } else if (boost::starts_with(sline, ";_IRONING_FAN_START")) { // ORCA: Add support for ironing fan speed control
556 } else if (boost::starts_with(sline, ";_IRONING_FAN_END")) { // ORCA: Add support for ironing fan speed control
558 } else if (boost::starts_with(sline, ";_BELT_BAND_START")) {
560 } else if (boost::starts_with(sline, ";_BELT_BAND_END")) {
562 } else if (boost::starts_with(sline, "G4 ")) {
563 // Parse the wait time.
564 line.type = CoolingLine::TYPE_G4;
565 size_t pos_S = sline.find('S', 3);
566 size_t pos_P = sline.find('P', 3);
567 line.time = line.time_max = float(
568 (pos_S > 0) ? atof_decimal_point(sline.c_str() + pos_S + 1) :
569 (pos_P > 0) ? atof_decimal_point(sline.c_str() + pos_P + 1) * 0.001 : 0.);
570 } else if (boost::starts_with(sline, ";_FORCE_RESUME_FAN_SPEED")) {
572 }
573
574 // Orca: For any movements before this layer's first ever extrusion, we exclude them from the layer time calculation.
575 if (!layer_had_extrusion) {
576 assert((line.type & CoolingLine::TYPE_ADJUSTABLE) == 0);
577 line.time = line.time_max = 0;
578 }
579
580 if (line.type != 0)
581 adjustment->lines.emplace_back(std::move(line));
582 }
583
584 return per_extruder_adjustments;
585}
static float calc_arc_length(Vec3f start_pos, Vec3f end_pos, Vec3f center_pos, bool is_ccw)
Definition Circle.cpp:628
static bool is_ccw(const Polygon &poly)
Definition Geometry.hpp:66
double atof_decimal_point(std::string_view str)
Definition LocalesUtils.cpp:95
zaa_minimize_perimeter_height wipe((ConfigOptionInts, nozzle_temperature_range_low))((ConfigOptionInts
double length(const Points &pts)
Definition MultiPoint.hpp:181
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65
@ TYPE_G4
Definition CoolingBuffer.cpp:81
@ TYPE_G92
Definition CoolingBuffer.cpp:82
@ TYPE_G2
Definition CoolingBuffer.cpp:84
@ TYPE_G0
Definition CoolingBuffer.cpp:74
@ TYPE_G1
Definition CoolingBuffer.cpp:75
@ TYPE_G3
Definition CoolingBuffer.cpp:85

References Slic3r::atof_decimal_point(), Slic3r::ArcSegment::calc_arc_length(), Slic3r::center(), Slic3r::PerExtruderAdjustments::cooling_slow_down_enabled, Slic3r::PerExtruderAdjustments::dont_slow_down_outer_wall, Slic3r::PerExtruderAdjustments::extruder_id, Slic3r::CoolingLine::feedrate, Slic3r::Geometry::is_ccw(), Slic3r::CoolingLine::length, Slic3r::PerExtruderAdjustments::lines, m_config, m_current_extruder, m_extruder_ids, m_num_extruders, m_toolchange_prefix, Slic3r::PerExtruderAdjustments::slow_down_layer_time, Slic3r::PerExtruderAdjustments::slow_down_min_speed, Slic3r::CoolingLine::time, Slic3r::CoolingLine::time_max, Slic3r::CoolingLine::type, Slic3r::CoolingLine::TYPE_ADJUSTABLE, Slic3r::CoolingLine::TYPE_BELT_BAND_END, Slic3r::CoolingLine::TYPE_BELT_BAND_START, Slic3r::CoolingLine::TYPE_EXTERNAL_PERIMETER, Slic3r::CoolingLine::TYPE_EXTRUDE_END, Slic3r::CoolingLine::TYPE_FORCE_RESUME_FAN, Slic3r::CoolingLine::TYPE_G0, Slic3r::CoolingLine::TYPE_G1, Slic3r::CoolingLine::TYPE_G2, Slic3r::CoolingLine::TYPE_G3, Slic3r::CoolingLine::TYPE_G4, Slic3r::CoolingLine::TYPE_G92, Slic3r::CoolingLine::TYPE_HAS_F, Slic3r::CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_END, Slic3r::CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START, Slic3r::CoolingLine::TYPE_IRONING_FAN_END, Slic3r::CoolingLine::TYPE_IRONING_FAN_START, Slic3r::CoolingLine::TYPE_OVERHANG_FAN_END, Slic3r::CoolingLine::TYPE_OVERHANG_FAN_START, Slic3r::CoolingLine::TYPE_SET_TOOL, Slic3r::CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_END, Slic3r::CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START, Slic3r::CoolingLine::TYPE_WIPE, and Slic3r::wipe().

Referenced by process_layer().

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

◆ process_layer()

std::string Slic3r::CoolingBuffer::process_layer ( std::string && gcode,
size_t layer_id,
bool flush )
341{
342 // Cache the input G-code.
343 if (m_gcode.empty())
344 m_gcode = std::move(gcode);
345 else
346 m_gcode += gcode;
347
348 std::string out;
349 if (flush) {
350 // This is either an object layer or the very last print layer. Calculate cool down over the collected support layers
351 // and one object layer.
352 std::vector<PerExtruderAdjustments> per_extruder_adjustments = this->parse_layer_gcode(m_gcode, m_current_pos);
353 float layer_time_stretched = this->calculate_layer_slowdown(per_extruder_adjustments);
354 out = this->apply_layer_cooldown(m_gcode, layer_id, layer_time_stretched, per_extruder_adjustments);
355 m_gcode.clear();
356 }
357 return out;
358}
float calculate_layer_slowdown(std::vector< PerExtruderAdjustments > &per_extruder_adjustments)
Definition CoolingBuffer.cpp:666
std::vector< float > m_current_pos
Definition CoolingBuffer.hpp:47
std::string m_gcode
Definition CoolingBuffer.hpp:43
std::vector< PerExtruderAdjustments > parse_layer_gcode(const std::string &gcode, std::vector< float > &current_pos) const
Definition CoolingBuffer.cpp:362
std::string apply_layer_cooldown(const std::string &gcode, size_t layer_id, float layer_time, std::vector< PerExtruderAdjustments > &per_extruder_adjustments)
Definition CoolingBuffer.cpp:724

References apply_layer_cooldown(), calculate_layer_slowdown(), m_current_pos, m_gcode, and parse_layer_gcode().

Here is the call graph for this function:

◆ reset()

void Slic3r::CoolingBuffer::reset ( const Vec3d & position)
54{
55 m_belt_band_active = false;
56 // BBS: add I and J axis to store center of arc
57 m_current_pos.assign(7, 0.f);
58 m_current_pos[0] = float(position.x());
59 m_current_pos[1] = float(position.y());
60 m_current_pos[2] = float(position.z());
61 m_current_pos[4] = float(m_config.travel_speed.get_at(m_current_nozzle));
62 m_fan_speed = -1;
65}

References m_additional_fan_speed, m_belt_band_active, m_config, m_current_fan_speed, m_current_nozzle, m_current_pos, and m_fan_speed.

Referenced by CoolingBuffer().

Here is the caller graph for this function:

◆ set_current_extruder()

void Slic3r::CoolingBuffer::set_current_extruder ( unsigned int extruder_id,
unsigned int nozzle_id )
inline
31{ m_current_extruder = extruder_id; m_current_nozzle = nozzle_id; }

References m_current_extruder, and m_current_nozzle.

Member Data Documentation

◆ m_additional_fan_speed

int Slic3r::CoolingBuffer::m_additional_fan_speed
private

Referenced by apply_layer_cooldown(), and reset().

◆ m_axis

std::vector<char> Slic3r::CoolingBuffer::m_axis
private

◆ m_belt_band_active

bool Slic3r::CoolingBuffer::m_belt_band_active = false
private

Referenced by apply_layer_cooldown(), and reset().

◆ m_config

const PrintConfig& Slic3r::CoolingBuffer::m_config
private

◆ m_current_extruder

unsigned int Slic3r::CoolingBuffer::m_current_extruder
private

◆ m_current_fan_speed

int Slic3r::CoolingBuffer::m_current_fan_speed
private

Referenced by apply_layer_cooldown(), and reset().

◆ m_current_nozzle

unsigned int Slic3r::CoolingBuffer::m_current_nozzle
private

◆ m_current_pos

std::vector<float> Slic3r::CoolingBuffer::m_current_pos
private

Referenced by process_layer(), and reset().

◆ m_extruder_ids

std::vector<unsigned int> Slic3r::CoolingBuffer::m_extruder_ids
private

Referenced by CoolingBuffer(), and parse_layer_gcode().

◆ m_fan_speed

int Slic3r::CoolingBuffer::m_fan_speed
private

Referenced by apply_layer_cooldown(), and reset().

◆ m_gcode

std::string Slic3r::CoolingBuffer::m_gcode
private

Referenced by process_layer().

◆ m_gcodegen

const GCode& Slic3r::CoolingBuffer::m_gcodegen
private

◆ m_num_extruders

unsigned int Slic3r::CoolingBuffer::m_num_extruders { 0 }
private
55{ 0 };

Referenced by CoolingBuffer(), and parse_layer_gcode().

◆ m_toolchange_prefix

const std::string Slic3r::CoolingBuffer::m_toolchange_prefix
private

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