#include "WipeTower.hpp" #include #include #include #ifdef __linux #include #endif /* __linux */ #ifdef _MSC_VER #define strcasecmp _stricmp #endif namespace PrusaSingleExtruderMM { static inline std::string line_XY(float x, float y) { char buf[128]; sprintf(buf, "G1 X%.3f Y%.3f\n", x, y); return buf; } static inline std::string line_XYE(float x, float y, float e) { char buf[128]; sprintf(buf, "G1 X%.3f Y%.3f E%.4f\n", x, y, e); return buf; } static inline std::string line_XYF(float x, float y, float f) { char buf[128]; sprintf(buf, "G1 X%.3f Y%.3f F%.0f\n", x, y, f); return buf; } static inline std::string line_ZF(float z, float f) { char buf[128]; sprintf(buf, "G1 Z%.3f F%.0f\n", z, f); return buf; } static inline std::string line_F(float f) { char buf[128]; sprintf(buf, "G1 F%.0f\n", f); return buf; } static inline std::string line_XEF(float x, float e, float f) { char buf[128]; sprintf(buf, "G1 X%.3f E%.4f F%.0f\n", x, e, f); return buf; } static inline std::string line_EF(float e, float f) { char buf[128]; sprintf(buf, "G1 E%.4f F%.0f\n", e, f); return buf; } // Set extruder temperature, don't wait. static inline std::string line_M104(int temperature) { char buf[128]; sprintf(buf, "M104 S%d\n", temperature); return buf; }; // Set extruder temperature and wait. static inline std::string line_M109(int temperature) { char buf[128]; sprintf(buf, "M109 S%d\n", temperature); buf; }; // Set maximum feedrate static inline std::string line_M203(int feedrate) { char buf[128]; sprintf(buf, "M203 E%d\n", feedrate); return buf; }; // Set speed factor override percentage static inline std::string line_M220(int speed) { char buf[128]; sprintf(buf, "M220 S%d\n", speed); return buf; }; // Set digital trimpot motor static inline std::string line_M907(int current) { char buf[128]; sprintf(buf, "M907 E%d\n", current); return buf; }; // Dwell for seconds. If delay == 0, this just flushes planner queue. static inline std::string line_G4(int delay) { char buf[128]; sprintf(buf, "G4 S%d\n", delay); return buf; }; // Reset internal extruder counter. static inline std::string line_ResetE() { return "G92 E0.0\n"; }; static inline std::string line_CommentValue(const char *comment, int value) { char strvalue[15]; sprintf(strvalue, "%d", value); return std::string(";") + comment + strvalue + "\n"; }; static inline std::string line_CommentMaterial(WipeTower::material_type material) { std::string ret("; material : "); switch (material) { case WipeTower::PVA: ret += "#8 (PVA)"; break; case WipeTower::SCAFF: ret += "#5 (Scaffold)"; break; case WipeTower::FLEX: ret += "#4 (Flex)"; break; default: ret += "DEFAULT (PLA)"; break; } return ret + "\n"; }; static inline int randi(int lo, int hi) { int n = hi - lo + 1; int i = rand() % n; if (i < 0) i = -i; return lo + i; } WipeTower::material_type WipeTower::parse_material(const char *name) { if (strcasecmp(name, "PLA") == 0) return PLA; if (strcasecmp(name, "ABS") == 0) return ABS; if (strcasecmp(name, "PET") == 0) return PET; if (strcasecmp(name, "HIPS") == 0) return HIPS; if (strcasecmp(name, "FLEX") == 0) return FLEX; if (strcasecmp(name, "SCAFF") == 0) return SCAFF; if (strcasecmp(name, "EDGE") == 0) return EDGE; if (strcasecmp(name, "NGEN") == 0) return NGEN; if (strcasecmp(name, "PVA") == 0) return PVA; return INVALID; } std::string WipeTower::FirstLayer(bool sideOnly, float offset) { float _ext = extrusion_flow + ((extrusion_flow / 100) * 10); box_coordinates wipeTower_box(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_area * float(m_color_changes) - perimeterWidth / 2); std::string gcode = ";-------------------------------------\n" "; CP WIPE TOWER FIRST LAYER BRIM START\n"; gcode += line_ZF(m_z_pos + zHop, 7200); gcode += line_F(6000); gcode += line_XY( wipeTower_box.lu.x - (perimeterWidth * 10), wipeTower_box.lu.y ); gcode += line_ZF(m_z_pos, 7200); gcode += line_F(2400); gcode += line_XYE(wipeTower_box.ld.x - (perimeterWidth * 10), wipeTower_box.ld.y, retract); float _offset = 0; gcode += line_F(2100); int _per = 0; if (sideOnly) { do { _offset = _offset + perimeterWidth; gcode += line_XY(wipeTower_box.ld.x - _offset, wipeTower_box.ld.y + offset); gcode += line_XYE(wipeTower_box.lu.x - _offset, wipeTower_box.lu.y - offset, (wipeTower_box.lu.y - wipeTower_box.ld.y) * _ext); _per++; } while (_per < 4); gcode += line_F(7000); gcode += line_XY(wipeTower_box.rd.x + _offset, wipeTower_box.ld.y + offset); gcode += line_F(2100); _per = 0; _offset = 0; do { _offset = _offset + perimeterWidth; gcode += line_XY(wipeTower_box.rd.x + _offset, wipeTower_box.ld.y + offset); gcode += line_XYE(wipeTower_box.ru.x + _offset, wipeTower_box.lu.y - offset, (wipeTower_box.lu.y - wipeTower_box.ld.y) * _ext); _per++; } while (_per < 4); } else { do { _offset = _offset + perimeterWidth; float _ext_X = ((wipeTower_box.rd.x + _offset) - (wipeTower_box.ld.x - _offset))* _ext; float _ext_Y = ((wipeTower_box.lu.y + _offset) - (wipeTower_box.ld.y - _offset))* _ext; float __x0 = wipeTower_box.ld.x - _offset + (perimeterWidth / 2); float __y0 = wipeTower_box.ld.y - _offset + perimeterWidth; gcode += line_XY(__x0, __y0); float __x1 = wipeTower_box.lu.x - _offset + (perimeterWidth / 2); float __y1 = wipeTower_box.lu.y + _offset; gcode += line_XYE(__x1, __y1, _ext_Y); float __x2 = wipeTower_box.ru.x + _offset - (perimeterWidth / 2); float __y2 = wipeTower_box.ru.y + _offset; gcode += line_XYE(__x2, __y2, _ext_X); float __x3 = wipeTower_box.rd.x + _offset - (perimeterWidth / 2); float __y3 = wipeTower_box.rd.y - _offset + perimeterWidth; gcode += line_XYE(__x3, __y3, _ext_Y); float __x4 = wipeTower_box.ld.x - _offset + (perimeterWidth / 2); float __y4 = wipeTower_box.ld.y - _offset + perimeterWidth; gcode += line_XYE(__x4, __y4, _ext_X); _per++; } while (_per < 4); } gcode += line_F(7000); gcode += line_XY(wipeTower_box.ld.x, wipeTower_box.ld.y); gcode += line_XY(wipeTower_box.rd.x, wipeTower_box.ld.y); gcode += line_XY(wipeTower_box.ld.x, wipeTower_box.ld.y); gcode += "; CP WIPE TOWER FIRST LAYER BRIM END\n"; gcode += ";-----------------------------------\n"; return gcode; } std::pair WipeTower::Toolchange(int tool, material_type current_material, material_type new_material, int temperature, wipe_shape shape, int count, float spaceAvailable, float wipeStartY, bool lastInFile, bool colorInit) { box_coordinates cleaning_box( m_wipe_tower_pos.x, m_wipe_tower_pos.y + wipeStartY, //(order * _wipe_area); //wipeStartY; m_wipe_tower_width, spaceAvailable - perimeterWidth / 2); //space_available //wipe_area std::string gcode; gcode += ";--------------------\n"; gcode += "; CP TOOLCHANGE START\n"; gcode += line_CommentValue(" toolchange #", count); gcode += line_CommentMaterial(current_material); gcode += ";--------------------\n"; gcode += line_M220(100); gcode += line_ZF(m_z_pos + zHop, 7200); gcode += line_EF((retract/2)*-1, 3600); // additional retract on move to tower gcode += line_XYF(cleaning_box.ld.x + perimeterWidth, cleaning_box.ld.y + shape * perimeterWidth, 7200); gcode += line_ZF(m_z_pos, 7200); gcode += line_EF((retract / 2), 3600); // additional retract on move to tower gcode += line_EF((retract), 1500); m_y_position = (shape == NORMAL) ? cleaning_box.ld.y : cleaning_box.lu.y; gcode += line_M907(750); gcode += line_G4(0); gcode += toolchange_Unload(cleaning_box, current_material, shape, temperature); if (!lastInFile) { gcode += toolchange_Change(tool, current_material, new_material); gcode += toolchange_Load(cleaning_box, current_material, shape, colorInit); gcode += toolchange_Wipe(cleaning_box, current_material, shape); gcode += toolchange_Done(cleaning_box, current_material, shape); } gcode += line_M907(550); gcode += line_G4(0); gcode += line_ResetE(); gcode += "; CP TOOLCHANGE END\n" ";------------------\n" "\n\n"; return std::pair(gcode, (shape == NORMAL) ? cleaning_box.lu : cleaning_box.ld); } std::string WipeTower::toolchange_Unload(const box_coordinates &cleaning_box, material_type material, wipe_shape shape, int temperature) { float __xl = 0; float __xr = 0; __xl = cleaning_box.ld.x + (perimeterWidth / 2); __xr = cleaning_box.rd.x - (perimeterWidth / 2); std::string gcode = "; CP TOOLCHANGE UNLOAD"; switch (material) { case PVA: gcode += line_F(4000); m_y_position += shape * perimeterWidth * 1.2f; gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, 0); gcode += line_XYE(__xr - perimeterWidth, m_y_position, 3); gcode += line_F(4500); m_y_position += shape * perimeterWidth * 1.5f; gcode += line_XYE(__xr - perimeterWidth, m_y_position, 0); gcode += line_XYE(__xl + perimeterWidth, m_y_position, 3); gcode += line_F(4800); m_y_position += shape * perimeterWidth * 1.5f; gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, 0); gcode += line_XYE(__xr - (perimeterWidth * 2), m_y_position, 3); gcode += line_F(5000); m_y_position += shape * perimeterWidth * 1.5f; gcode += line_XYE(__xr - perimeterWidth, m_y_position, 0); gcode += line_XYE(__xl + perimeterWidth, m_y_position, 3); gcode += line_EF(-15, 5000); gcode += line_EF(-50, 5400); gcode += line_EF(-15, 3000); gcode += line_EF(-12, 2000); if (temperature != 0) { gcode += line_M104(temperature); } // cooling moves m_y_position += shape * perimeterWidth * 0.8f; gcode += line_F(1600); gcode += line_XYE(__xl, m_y_position, 3); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2000); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2200); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2400); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2400); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2400); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -3); gcode += line_G4(0); break; // end of SCAFF case SCAFF: gcode += line_F(4000); m_y_position += shape * perimeterWidth * 3.f; gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, 0); gcode += line_XYE(__xr - perimeterWidth, m_y_position, 3); gcode += line_F(4600); m_y_position += shape * perimeterWidth * 3.f; gcode += line_XYE(__xr - perimeterWidth, m_y_position, 0); gcode += line_XYE(__xl + perimeterWidth, m_y_position, 4); gcode += line_F(5200); m_y_position += shape * perimeterWidth * 3.f; gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, 0); gcode += line_XYE(__xr - (perimeterWidth * 2), m_y_position, 4.5); gcode += line_EF(-15, 5000); gcode += line_EF(-50, 5400); gcode += line_EF(-15, 3000); gcode += line_EF(-12, 2000); if (temperature != 0) { gcode += line_M104(temperature); } // cooling moves m_y_position += shape * perimeterWidth * 0.8f; gcode += line_F(1600); gcode += line_XYE(__xl, m_y_position, 3); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2000); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2200); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2200); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2400); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -3); gcode += line_G4(0); break; // end of SCAFF default: gcode += line_F(4000); m_y_position += shape * perimeterWidth * 1.2f; gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, 0); gcode += line_XYE(__xr - perimeterWidth, m_y_position, (__xr - __xl) * (extrusion_flow*(float)1.6)); gcode += line_F(4600); m_y_position += shape * perimeterWidth * 1.2f; gcode += line_XYE(__xr - perimeterWidth, m_y_position, perimeterWidth*extrusion_flow); gcode += line_XYE(__xl + perimeterWidth, m_y_position, (__xr - __xl) * (extrusion_flow*(float)1.65)); gcode += line_F(5200); m_y_position += shape * perimeterWidth * 1.2f; //1.4f gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, perimeterWidth*extrusion_flow); gcode += line_XYE(__xr - (perimeterWidth * 2), m_y_position, (__xr - __xl) * (extrusion_flow*(float)1.74)); gcode += line_EF(-15, 5000); gcode += line_EF(-50, 5400); gcode += line_EF(-15, 3000); gcode += line_EF(-12, 2000); if (temperature != 0) { gcode += line_M104(temperature); } // cooling moves m_y_position += shape * perimeterWidth * 0.8f; gcode += line_F(1600); gcode += line_XYE(__xl, m_y_position, 3); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2000); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2400); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -5); gcode += line_F(2400); gcode += line_XYE(__xl, m_y_position, 5); gcode += line_XYE(__xr, m_y_position, -3); gcode += line_G4(0); break; // end of default material } return gcode; } std::string WipeTower::toolchange_Load(const box_coordinates &cleaning_box, material_type material, wipe_shape shape, bool colorInit) { float __xl = 0; float __xr = 0; std::string gcode = "; CP TOOLCHANGE LOAD\n"; switch (material) { default: __xl = cleaning_box.ld.x + (perimeterWidth * 1); __xr = cleaning_box.rd.x - (perimeterWidth * 1); float _extrusion = (__xr - __xl) * extrusion_flow; gcode += line_XEF(__xr, 20, 1400); gcode += line_XEF(__xl, 40, 3000); gcode += line_XEF(__xr, 20, 1600); gcode += line_XEF(__xl, 10, 1000); gcode += line_F(1600); gcode += line_XYE(__xr, m_y_position, _extrusion); gcode += line_F(2200); int _pass = 2; if (colorInit) _pass = 1; for (int _i = 0; _i < _pass; _i++) { m_y_position += shape * perimeterWidth * 0.85f; gcode += line_XY(__xr, m_y_position); gcode += line_XYE(__xl, m_y_position, _extrusion); m_y_position += shape * perimeterWidth * 0.85f; gcode += line_XY(__xl, m_y_position); gcode += line_XYE(__xr, m_y_position, _extrusion); } break; } gcode += line_M907(550); return gcode; } std::string WipeTower::toolchange_Wipe(const box_coordinates &cleaning_box, material_type material, wipe_shape shape) { // wipe new filament until end of wipe area float __xl = 0; float __xr = 0; int __p = 0; float _wipespeed = 4200; float _extr = extrusion_flow; float _wipekoef = 1; std::string gcode = "; CP TOOLCHANGE WIPE\n"; // increase flow on first layer, slow down print if (int(m_z_pos * 100) < 21) { _extr = extrusion_flow + ((extrusion_flow / 100) * 18); _wipekoef = (float)0.5; } else { _extr = extrusion_flow; _wipekoef = (float)1; } switch (material) { default: __xl = cleaning_box.ld.x + (perimeterWidth*2); __xr = cleaning_box.rd.x - (perimeterWidth*2); switch (shape) { case NORMAL: do { __p++; _wipespeed = _wipespeed + 50; if (_wipespeed > 4800) { _wipespeed = 4800; } gcode += line_F(_wipespeed * _wipekoef); m_y_position += shape * perimeterWidth * 0.7f; if (__p < 2) { gcode += line_XYE(__xl - (perimeterWidth/2), m_y_position, perimeterWidth * _extr); gcode += line_XYE(__xr + (perimeterWidth), m_y_position, (__xr - __xl) * _extr); } else { gcode += line_XYE(__xl-(perimeterWidth), m_y_position, perimeterWidth * _extr); gcode += line_XYE(__xr+(perimeterWidth*2), m_y_position, (__xr - __xl) * _extr); __p = 0; } _wipespeed = _wipespeed + 50; if (_wipespeed > 4800) { _wipespeed = 4800; } gcode += line_F(_wipespeed * _wipekoef); m_y_position += shape * perimeterWidth * 0.7f; gcode += line_XYE(__xr + (perimeterWidth), m_y_position, perimeterWidth * _extr); gcode += line_XYE(__xl - (perimeterWidth), m_y_position, (__xr - __xl) * _extr); } while (m_y_position <= cleaning_box.lu.y - (perimeterWidth*1)); break; case REVERSED: do { __p++; _wipespeed = _wipespeed + 50; if (_wipespeed > 4900) { _wipespeed = 4900; } gcode += line_F(_wipespeed * _wipekoef); m_y_position += shape * perimeterWidth * 0.7f; if (__p < 2) { gcode += line_XYE(__xl - (perimeterWidth/2), m_y_position, perimeterWidth * _extr); gcode += line_XYE(__xr + (perimeterWidth), m_y_position, (__xr - __xl) * _extr); } else { gcode += line_XYE(__xl - (perimeterWidth), m_y_position, perimeterWidth * _extr); gcode += line_XYE(__xr + (perimeterWidth *2), m_y_position, (__xr - __xl) * _extr); __p = 0; } _wipespeed = _wipespeed + 50; if (_wipespeed > 4900) { _wipespeed = 4900; } gcode += line_F(_wipespeed * _wipekoef); m_y_position += shape * perimeterWidth * 0.7f; gcode += line_XYE(__xr + (perimeterWidth), m_y_position, perimeterWidth * _extr); gcode += line_XYE(__xl - (perimeterWidth), m_y_position, (__xr - __xl) * _extr); } while (m_y_position >= cleaning_box.ld.y + (perimeterWidth*1 )); break; } break; } return gcode; } std::string WipeTower::toolchange_Done(const box_coordinates &cleaning_box, material_type /* material */, wipe_shape shape) { std::string gcode; switch (shape) { case NORMAL: gcode += line_F(7000); gcode += line_XY(cleaning_box.lu.x, cleaning_box.lu.y); gcode += line_F(3200); gcode += line_XYE(cleaning_box.ld.x, cleaning_box.ld.y, (cleaning_box.lu.y - cleaning_box.ld.y)*(extrusion_flow )); gcode += line_XYE(cleaning_box.rd.x, cleaning_box.rd.y, (cleaning_box.rd.x - cleaning_box.ld.x)*(extrusion_flow )); gcode += line_XYE(cleaning_box.ru.x, cleaning_box.lu.y, (cleaning_box.lu.y - cleaning_box.ld.y)*(extrusion_flow )); gcode += line_XYE(cleaning_box.lu.x, cleaning_box.lu.y, (cleaning_box.rd.x - cleaning_box.ld.x)*(extrusion_flow )); gcode += line_F(7200); gcode += line_XY(cleaning_box.ru.x, cleaning_box.lu.y); gcode += line_XY(cleaning_box.lu.x, cleaning_box.lu.y); gcode += line_F(6000); break; case REVERSED: gcode += line_F(7000); gcode += line_XY(cleaning_box.ld.x , cleaning_box.ld.y ); gcode += line_F(3200); gcode += line_XYE(cleaning_box.rd.x , cleaning_box.rd.y, (cleaning_box.rd.x - cleaning_box.ld.x)*(extrusion_flow )); gcode += line_XYE(cleaning_box.ru.x , cleaning_box.ru.y, (cleaning_box.ru.y - cleaning_box.rd.y)*(extrusion_flow )); gcode += line_XYE(cleaning_box.lu.x , cleaning_box.lu.y, (cleaning_box.ru.x - cleaning_box.lu.x)*(extrusion_flow )); gcode += line_XYE(cleaning_box.ld.x, cleaning_box.ld.y, (cleaning_box.lu.y - cleaning_box.ld.y)*(extrusion_flow )); gcode += line_F(7200); gcode += line_XY(cleaning_box.rd.x, cleaning_box.ld.y); gcode += line_XY(cleaning_box.ld.x, cleaning_box.ld.y); gcode += line_F(6000); break; } return gcode; } std::string WipeTower::toolchange_Change(int tool, material_type /* current_material */, material_type new_material) { assert(tool >= 0 && tool < 4); std::string gcode("T0\n"); gcode[1] += char(tool); switch (new_material) { case PVA: gcode += line_M220(80); gcode += line_G4(0); break; case SCAFF: gcode += line_M220(35); gcode += line_G4(0); break; case FLEX: gcode += line_M220(35); gcode += line_G4(0); break; default: gcode += line_M220(100); gcode += line_G4(0); break; } return gcode; } std::string WipeTower::Perimeter(int order, int total, int Layer, bool afterToolchange, int firstLayerOffset) { float _speed = 1.f; std::string gcode = ";--------------------\n" "; CP EMPTY GRID START\n"; gcode += line_CommentValue(" layer #", Layer); if (Layer == 20) _speed = 2.f; box_coordinates _p = _boxForColor(order); box_coordinates _to = _boxForColor(total); _p.ld.y += firstLayerOffset; _p.rd.y += firstLayerOffset; _p.lu = _to.lu; _p.ru = _to.ru; if (!afterToolchange) { gcode += line_EF(retract*(float)-1.5, 3600); gcode += line_ZF(m_z_pos + zHop, 7200); gcode += line_XYF(_p.ld.x + randi(5, 20), _p.ld.y, 7000); gcode += line_ZF(m_z_pos, 7200); gcode += line_XEF(_p.ld.x, retract*(float)1.5, 3600); } gcode += line_F(2400 / _speed); gcode += line_XYE(_p.lu.x, _p.ru.y, (_p.ru.y - _p.ld.y) * extrusion_flow); gcode += line_XYE(_p.ru.x, _p.ru.y, (_p.ru.x - _p.lu.x) * extrusion_flow); gcode += line_XYE(_p.rd.x, _p.rd.y, (_p.ru.y - _p.ld.y) * extrusion_flow); gcode += line_XYE(_p.ld.x + (perimeterWidth / 2), _p.ld.y, (_p.ru.x - _p.lu.x) * extrusion_flow); gcode += line_F(3200 / _speed); gcode += line_XYE(_p.lu.x + (perimeterWidth / 2), _p.lu.y - (perimeterWidth / 2), (_p.ru.y - _p.ld.y) * extrusion_flow); gcode += line_XYE(_p.ru.x - (perimeterWidth / 2), _p.ru.y - (perimeterWidth / 2), (_p.ru.x - _p.lu.x) * extrusion_flow); gcode += line_XYE(_p.rd.x - (perimeterWidth / 2), _p.rd.y + (perimeterWidth / 2), (_p.ru.y - _p.ld.y) * extrusion_flow); gcode += line_XYE(_p.ld.x + perimeterWidth, _p.ld.y + (perimeterWidth / 2), (_p.ru.x - _p.lu.x) * extrusion_flow); gcode += line_XYE(_p.ld.x + perimeterWidth, _p.ld.y + perimeterWidth, perimeterWidth * extrusion_flow); gcode += line_F(2900 / _speed); gcode += line_XYE(_p.ld.x + (perimeterWidth * 3), _p.ld.y + perimeterWidth, (perimeterWidth * 3) * extrusion_flow); gcode += line_XYE(_p.lu.x + (perimeterWidth * 3), _p.lu.y - perimeterWidth, (_p.ru.y - _p.ld.y) * extrusion_flow); gcode += line_XYE(_p.lu.x + (perimeterWidth * 6), _p.lu.y - perimeterWidth, (perimeterWidth * 3) * extrusion_flow); gcode += line_XYE(_p.ld.x + (perimeterWidth * 6), _p.ld.y + perimeterWidth, (_p.ru.y - _p.ld.y) * extrusion_flow); if (_p.lu.y - _p.ld.y > 4) { gcode += line_F(3200 / _speed); float _step = (m_wipe_tower_width - (perimeterWidth * 12)) / 3; float _sx = 0; for (int _s = 0; _s < 3; _s++) { float _ext = ((_p.ru.y - _p.ld.y) / 3)*(extrusion_flow*(float)1.5); _sx = _sx + (_step / 2); gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + (_step / 4) + (_step * _s), _p.ld.y + (perimeterWidth * 8), _ext); gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + (_step / 4) + (_step * _s), _p.lu.y - (perimeterWidth * 8), _ext); gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + ((_step / 4) * 2) + (_step * _s), _p.lu.y - perimeterWidth, _ext); gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + ((_step / 4) * 3) + (_step * _s), _p.lu.y - (perimeterWidth * 8), _ext); gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + ((_step / 4) * 3) + (_step * _s), _p.ld.y + (perimeterWidth * 8), _ext); gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + (_step)+(_step * _s), _p.ld.y + perimeterWidth, _ext); } } gcode += line_F(2900 / _speed); gcode += line_XYE(_p.ru.x - (perimeterWidth * 6), _p.ru.y - perimeterWidth, (_p.ru.y - _p.ld.y) * extrusion_flow); gcode += line_XYE(_p.ru.x - (perimeterWidth * 3), _p.ru.y - perimeterWidth, (perimeterWidth * 3) * extrusion_flow); gcode += line_XYE(_p.rd.x - (perimeterWidth * 3), _p.rd.y + perimeterWidth, (_p.ru.y - _p.ld.y) * extrusion_flow); gcode += line_XYE(_p.rd.x - perimeterWidth, _p.rd.y + perimeterWidth, perimeterWidth * extrusion_flow); gcode += line_F(7200); gcode += line_XY(_p.ld.x + perimeterWidth, _p.rd.y + (perimeterWidth / 2)); gcode += line_XY(_p.rd.x - perimeterWidth, _p.ld.y + (perimeterWidth / 2)); gcode += "; CP EMPTY GRID END\n" ";------------------\n\n\n\n\n\n\n"; return gcode; } WipeTower::box_coordinates WipeTower::_boxForColor(int order) const { return box_coordinates(m_wipe_tower_pos.x, m_wipe_tower_pos.y + m_wipe_area * order - perimeterWidth / 2, m_wipe_tower_width, perimeterWidth); } }; // namespace PrusaSingleExtruderMM