1103 {
1104 if (new_filament_id != -1 && new_filament_id != tcr.new_tool)
1105 throw Slic3r::InvalidArgument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect.");
1106
1107 const std::optional<GCode::ToolchangePositionState> position_before_toolchange =
1108 gcodegen.capture_toolchange_position();
1109
1111
1112
1113 auto group_result = gcodegen.m_print->get_layered_nozzle_group_result();
1114
1115 bool is_nozzle_change = !tcr.nozzle_change_result.gcode.empty() && (gcodegen.config().
nozzle_diameter.size() > 1);
1116
1118
1119
1120
1122
1123 auto transform_wt_pt = [&alpha,
this](
const Vec2f& pt) ->
Vec2f {
1124 Vec2f out = Eigen::Rotation2Df(alpha) * pt;
1126 return out;
1127 };
1128
1129 Vec2f start_pos = tcr.start_pos;
1130 Vec2f end_pos = tcr.end_pos;
1131 Vec2f tool_change_start_pos = start_pos;
1132 if (tcr.is_tool_change)
1133 tool_change_start_pos = tcr.tool_change_start_pos;
1134 if (!tcr.priming) {
1135 start_pos = transform_wt_pt(start_pos);
1136 end_pos = transform_wt_pt(end_pos);
1137 tool_change_start_pos = transform_wt_pt(tool_change_start_pos);
1138 }
1139
1141 float wipe_tower_rotation = tcr.priming ? 0.f : alpha;
1142
1144
1145
1147
1148
1149
1150
1151 if (!tcr.priming && tcr.is_finish_first) {
1152
1153 gcode += gcodegen.retract();
1154 gcodegen.m_avoid_crossing_perimeters.use_external_mp_once();
1156 "Travel to a Wipe Tower");
1157 gcode += gcodegen.unretract();
1158 }
1159
1160
1161 double current_z = gcodegen.writer().get_position().z();
1162 if (z == -1.)
1163 z = current_z;
1164
1165
1166
1167
1168
1170 && !tcr.priming && !tcr.is_finish_first && (current_z - z) >
EPSILON;
1171 if (!
is_approx(z, current_z) && !defer_compacted_descend) {
1172 gcode += gcodegen.writer().retract();
1173 gcode += gcodegen.writer().travel_to_z(z,
"Travel down to the last wipe tower layer.");
1174 gcode += gcodegen.writer().unretract();
1175 }
1176
1177
1179
1180
1181 bool add_change_filament_624 = false;
1182 std::string end_filament_gcode_str;
1183 if (gcodegen.writer().filament() != nullptr) {
1184
1185 unsigned int old_filament_id = gcodegen.writer().filament()->id();
1186 const std::string& filament_end_gcode = gcodegen.config().filament_end_gcode.get_at(old_filament_id);
1187 if (gcodegen.writer().filament() != nullptr && !filament_end_gcode.empty()) {
1188 DynamicConfig config;
1189 config.set_key_value("filament_extruder_id", new ConfigOptionInt((int) old_filament_id));
1190 config.set_key_value("current_filament_id", new ConfigOptionInt((int) old_filament_id));
1194 config.set_key_value("layer_num", new ConfigOptionInt(gcodegen.m_layer_index));
1196 config.set_key_value(
"max_layer_z",
new ConfigOptionFloat(gcodegen.m_max_layer_z));
1197 if (!gcodegen.m_filament_instances_code.empty()) {
1198 end_filament_gcode_str += ("M624 " + gcodegen.m_filament_instances_code + "\n");
1199 gcodegen.m_filament_instances_code = "";
1200 add_change_filament_624 = true;
1201 }
1202 end_filament_gcode_str += gcodegen.placeholder_parser_process("filament_end_gcode", filament_end_gcode, old_filament_id, &config);
1204 }
1205 }
1206
1207 std::string toolchange_gcode_str;
1208
1209 ZHopType z_hope_type =
ZHopType(gcodegen.config().z_hop_types.get_at(gcodegen.get_filament_config_index((
int)gcodegen.writer().filament()->id())));
1213
1214
1215 std::string toolchange_retract_str = gcodegen.retract(tcr.is_tool_change && !is_nozzle_change, false, auto_lift_type, true);
1217
1218
1219 std::string object_end_label_temp;
1220 gcodegen.m_writer.add_object_end_labels(object_end_label_temp);
1221
1222
1223
1225
1226 bool is_used_travel_avoid_perimeter = gcodegen.m_config.prime_tower_skip_points.value;
1227 if (is_nozzle_change && !tcr.nozzle_change_result.is_extruder_change) is_used_travel_avoid_perimeter = false;
1228
1229
1230 std::string nozzle_change_gcode_trans;
1231 if (is_nozzle_change) {
1232
1233
1234
1235
1236 const bool compact_intower_nc_travel = compacted_below_object
1237 && (tcr.print_z - gcodegen.writer().get_position().z()) >
EPSILON;
1238 std::string start_pos_str;
1240 "Move to nozzle change start pos", compact_intower_nc_travel ? z : DBL_MAX);
1242 nozzle_change_gcode_trans += start_pos_str;
1243
1244
1245 if (!compact_intower_nc_travel && compacted_below_object) {
1246 std::string nc_z_descend = gcodegen.writer().travel_to_z(z, "Descend to compacted wipe tower z (no sparse layers)");
1248 nozzle_change_gcode_trans += nc_z_descend;
1249 }
1250 nozzle_change_gcode_trans += gcodegen.unretract();
1251 nozzle_change_gcode_trans +=
transform_gcode(tcr.nozzle_change_result.gcode, tcr.nozzle_change_result.start_pos, wipe_tower_offset, wipe_tower_rotation);
1253 gcodegen.m_wipe.reset_path();
1254 for (
const Vec2f& wipe_pt : tcr.nozzle_change_result.wipe_path)
1256 nozzle_change_gcode_trans += gcodegen.retract(tcr.is_tool_change, false, auto_lift_type, true);
1257 end_filament_gcode_str = nozzle_change_gcode_trans + end_filament_gcode_str;
1258 }
1259
1260 end_filament_gcode_str = toolchange_retract_str + object_end_label_temp + end_filament_gcode_str;
1261
1262 std::string wipe_next_start_point_str;
1263 bool need_travel_after_change_filament_gcode = false;
1265 DynamicConfig config;
1266 int old_filament_id = gcodegen.writer().filament() ? (int)gcodegen.writer().filament()->id() : -1;
1267 int old_extruder_id = gcodegen.writer().filament() ? (int)gcodegen.writer().filament()->extruder_id() : -1;
1268
1271
1272 config.set_key_value("previous_extruder", new ConfigOptionInt(old_filament_id));
1273 config.set_key_value("next_extruder", new ConfigOptionInt(new_filament_id));
1274 const bool is_bbl_printer = gcodegen.m_print->is_BBL_printer();
1275 config.set_key_value("current_hotend", new ConfigOptionInt(
1277 config.set_key_value("next_hotend", new ConfigOptionInt(
1279 config.set_key_value("current_nozzle_id", new ConfigOptionInt(old_nozzle_id));
1280 config.set_key_value("next_nozzle_id", new ConfigOptionInt(next_nozzle_id));
1281 config.set_key_value("current_filament_id", new ConfigOptionInt(old_filament_id));
1282 config.set_key_value("next_filament_id", new ConfigOptionInt(new_filament_id));
1283
1284
1285 {
1286 const auto &extruder_variants =
m_print_config->printer_extruder_variant.values;
1288 (old_extruder_id >= 0 && old_extruder_id < (int) extruder_variants.size()) ? extruder_variants[old_extruder_id] : std::string()));
1290 (new_extruder_id >= 0 && new_extruder_id < (int) extruder_variants.size()) ? extruder_variants[new_extruder_id] : std::string()));
1291 }
1294 config.set_key_value("layer_num", new ConfigOptionInt(gcodegen.m_layer_index));
1297
1298
1299 {
1300 GCodeWriter& gcode_writer = gcodegen.m_writer;
1301 FullPrintConfig& full_config = gcodegen.m_config;
1302
1303
1304
1305
1306
1307 size_t old_fi = (old_filament_id != -1) ? gcodegen.get_filament_config_index(old_filament_id) : 0;
1308 size_t new_fi = gcodegen.get_filament_config_index(new_filament_id);
1309
1310
1311 float outer_wall_volumetric_speed =
get_outer_wall_volumetric_speed(full_config, *gcodegen.m_print, new_filament_id, (
int)new_fi, gcodegen.get_extruder_id(new_filament_id));
1312 config.set_key_value(
"outer_wall_volumetric_speed",
new ConfigOptionFloat(outer_wall_volumetric_speed));
1313
1314 float old_retract_length = (old_filament_id != -1) ? full_config.retraction_length.get_at(old_fi) : 0;
1315 float new_retract_length = full_config.retraction_length.get_at(new_fi);
1316 float old_retract_length_toolchange = (old_filament_id != -1) ? full_config.retract_length_toolchange.get_at(old_fi) : 0;
1317 float new_retract_length_toolchange = full_config.retract_length_toolchange.get_at(new_fi);
1318 int old_filament_temp = (old_filament_id != -1) ? (gcodegen.on_first_layer()? full_config.nozzle_temperature_initial_layer.get_at(old_fi) : full_config.nozzle_temperature.get_at(old_fi)) : 210;
1319 int new_filament_temp = gcodegen.on_first_layer() ? full_config.nozzle_temperature_initial_layer.get_at(new_fi) : full_config.nozzle_temperature.get_at(new_fi);
1320 Vec3d nozzle_pos = gcode_writer.get_position();
1321
1323 float filament_area = float((
M_PI / 4.f) * pow(full_config.filament_diameter.get_at(new_filament_id), 2));
1324 float purge_length = purge_volume / filament_area;
1325
1326 int old_filament_e_feedrate = (old_filament_id != -1) ? (int)(60.0 * full_config.filament_max_volumetric_speed.get_at(old_fi) / filament_area) : 200;
1327 old_filament_e_feedrate = old_filament_e_feedrate == 0 ? 100 : old_filament_e_feedrate;
1328 int new_filament_e_feedrate = (int)(60.0 * full_config.filament_max_volumetric_speed.get_at(new_fi) / filament_area);
1329 new_filament_e_feedrate = new_filament_e_feedrate == 0 ? 100 : new_filament_e_feedrate;
1330 float wipe_avoid_pos_x = 0.f;
1331 {
1332
1336 }
1337
1338
1339
1340
1341 Vec2f stop_pos = tool_change_start_pos;
1342 {
1345 stop_pos.x() += (stop_pos.x() < bbx.center().x()) ? -2.f : 2.f;
1346 auto printer_bbx =
unscaled(
get_extents(gcodegen.m_print->get_extruder_shared_printable_polygon()));
1347 if (stop_pos.x() < printer_bbx.min[0]) stop_pos.x() = float(printer_bbx.min[0]);
1348 if (stop_pos.x() > printer_bbx.max[0]) stop_pos.x() = float(printer_bbx.max[0]);
1349 }
1350 config.set_key_value(
"wipe_tower_wait_pos_x",
new ConfigOptionFloat(stop_pos.x()));
1351 config.set_key_value(
"wipe_tower_wait_pos_y",
new ConfigOptionFloat(stop_pos.y()));
1352 config.set_key_value("wipe_tower_wait_pos_valid", new ConfigOptionBool(true));
1353
1354 config.set_key_value(
"wipe_tower_center_pos_x",
new ConfigOptionFloat(stop_pos.x()));
1355 config.set_key_value(
"wipe_tower_center_pos_y",
new ConfigOptionFloat(stop_pos.y()));
1356 config.set_key_value("wipe_tower_center_pos_valid", new ConfigOptionBool(true));
1357
1358 config.set_key_value(
"max_layer_z",
new ConfigOptionFloat(gcodegen.m_max_layer_z));
1359 config.set_key_value("relative_e_axis", new ConfigOptionBool(full_config.use_relative_e_distances));
1360 config.set_key_value("toolchange_count", new ConfigOptionInt((int) gcodegen.m_toolchange_count + 1));
1361
1362
1363 config.set_key_value("fan_speed", new ConfigOptionInt((int) 0));
1364 config.set_key_value(
"old_retract_length",
new ConfigOptionFloat(old_retract_length));
1365 config.set_key_value(
"new_retract_length",
new ConfigOptionFloat(new_retract_length));
1366
1368 (old_filament_id != -1) ? (float) full_config.filament_retract_length_nc.get_at(old_fi) : 0.f));
1369 config.set_key_value(
"old_retract_length_toolchange",
new ConfigOptionFloat(old_retract_length_toolchange));
1370 config.set_key_value(
"new_retract_length_toolchange",
new ConfigOptionFloat(new_retract_length_toolchange));
1371
1372 config.set_key_value("new_extruder_retracted_length",
1373 new ConfigOptionFloat(gcode_writer.get_extruder_retracted_length((
int) new_filament_id)));
1374 config.set_key_value("old_filament_temp", new ConfigOptionInt(old_filament_temp));
1375 int interface_temp = full_config.filament_tower_interface_print_temp.get_at(new_filament_id);
1376 if (interface_temp == -1)
1377 interface_temp = full_config.nozzle_temperature_range_high.get_at(new_fi);
1378 if (full_config.enable_tower_interface_features && tcr.is_contact)
1379 new_filament_temp = interface_temp;
1380 config.set_key_value("new_filament_temp", new ConfigOptionInt(new_filament_temp));
1381 if (full_config.enable_tower_interface_features && tcr.is_contact) {
1382
1383
1384 size_t num_filaments = full_config.filament_type.values.size();
1385 std::vector<int> temps(num_filaments);
1386 std::vector<int> first_layer_temps(num_filaments);
1387 for (size_t i = 0; i < num_filaments; ++i) {
1388 size_t fi_i = gcodegen.get_filament_config_index((int)i);
1389 temps[i] = full_config.nozzle_temperature.get_at(fi_i);
1390 first_layer_temps[i] = full_config.nozzle_temperature_initial_layer.get_at(fi_i);
1391 }
1392 if (new_filament_id >= 0 && new_filament_id < (int)temps.size())
1393 temps[new_filament_id] = interface_temp;
1395 if (new_filament_id >= 0 && new_filament_id < (int)first_layer_temps.size())
1396 first_layer_temps[new_filament_id] = interface_temp;
1397 config.set_key_value(
"first_layer_temperature",
new ConfigOptionInts(first_layer_temps));
1398 }
1399 config.set_key_value(
"x_after_toolchange",
new ConfigOptionFloat(tool_change_start_pos(0)));
1400 config.set_key_value(
"y_after_toolchange",
new ConfigOptionFloat(tool_change_start_pos(1)));
1401 config.set_key_value(
"z_after_toolchange",
new ConfigOptionFloat(nozzle_pos(2)));
1402 config.set_key_value(
"first_flush_volume",
new ConfigOptionFloat(purge_length / 2.f));
1403 config.set_key_value(
"second_flush_volume",
new ConfigOptionFloat(purge_length / 2.f));
1404 config.set_key_value("old_filament_e_feedrate", new ConfigOptionInt(old_filament_e_feedrate));
1405 config.set_key_value("new_filament_e_feedrate", new ConfigOptionInt(new_filament_e_feedrate));
1412
1413 {
1414 size_t num_filaments =
m_print_config->filament_type.values.size();
1415
1417 std::vector<double> flush_v_speed(num_filaments);
1418 std::vector<int> flush_temps(num_filaments);
1419 std::vector<double> filament_cooling_before_tower(num_filaments);
1420 for (size_t idx = 0; idx < num_filaments; ++idx) {
1421 size_t fi = gcodegen.get_filament_config_index(idx);
1422 flush_v_speed[idx] =
m_print_config->filament_flush_volumetric_speed.get_at(fi);
1423 if (flush_v_speed[idx] == 0)
1424 flush_v_speed[idx] =
m_print_config->filament_max_volumetric_speed.get_at(fi);
1425 flush_temps[idx] = use_fast_flush ?
m_print_config->filament_flush_temp_fast.get_at(fi)
1427 if (flush_temps[idx] == 0)
1428 flush_temps[idx] =
m_print_config->nozzle_temperature_range_high.get_at(fi);
1429 filament_cooling_before_tower[idx] =
m_print_config->filament_cooling_before_tower.get_at(fi);
1430 }
1431 if (tcr.is_contact || gcodegen.m_layer_index == 0)
1432 std::fill(filament_cooling_before_tower.begin(), filament_cooling_before_tower.end(), 0);
1433 config.set_key_value(
"flush_volumetric_speeds",
new ConfigOptionFloats(flush_v_speed));
1434 config.set_key_value(
"flush_temperatures",
new ConfigOptionInts(flush_temps));
1435 config.set_key_value(
"filament_cooling_before_tower",
new ConfigOptionFloats(filament_cooling_before_tower));
1436 }
1438 config.set_key_value("wipe_avoid_perimeter", new ConfigOptionBool(is_used_travel_avoid_perimeter));
1439 config.set_key_value(
"wipe_avoid_pos_x",
new ConfigOptionFloat(wipe_avoid_pos_x));
1440 config.set_key_value("is_prime_tower_interface", new ConfigOptionBool(tcr.is_contact));
1441 config.set_key_value(
"filament_tower_interface_purge_volume",
new ConfigOptionFloat(full_config.filament_tower_interface_purge_volume.get_at(new_filament_id)));
1442 config.set_key_value("filament_tower_interface_print_temp", new ConfigOptionInt(interface_temp));
1443
1445 float flush_unit = purge_length / flush_count;
1446 int flush_idx = 0;
1447 for (; flush_idx < flush_count; flush_idx++) {
1448 char key_value[64] = {0};
1449 snprintf(key_value, sizeof(key_value), "flush_length_%d", flush_idx + 1);
1451 }
1452
1454 char key_value[64] = {0};
1455 snprintf(key_value, sizeof(key_value), "flush_length_%d", flush_idx + 1);
1457 }
1458 }
1459 toolchange_gcode_str = gcodegen.placeholder_parser_process(
"change_filament_gcode",
change_filament_gcode, new_filament_id, &config);
1460
1462
1463
1465
1466
1467 {
1468
1470 toolchange_gcode_str += ";_FORCE_RESUME_FAN_SPEED\n";
1471 gcodegen.writer().set_current_position_clear(false);
1472
1473 double temp_z_after_tool_change;
1475 Vec3d pos = gcodegen.writer().get_position();
1476 pos(2) = temp_z_after_tool_change;
1477 gcodegen.writer().set_position(pos);
1478 }
1479 }
1480 need_travel_after_change_filament_gcode = true;
1481 }
1482
1483 std::string toolchange_command;
1484 if (tcr.priming || (new_filament_id >= 0 && gcodegen.writer().need_toolchange(new_filament_id)))
1485
1486
1487 toolchange_command = gcodegen.writer().toolchange(new_filament_id,
1490 toolchange_gcode_str += toolchange_command;
1491 else {
1492
1493 }
1494
1495
1496
1497
1498
1499 if (position_before_toolchange)
1500 gcodegen.synchronize_toolchange_position(*position_before_toolchange, toolchange_gcode_str);
1501
1502 if (need_travel_after_change_filament_gcode) {
1503
1504 if (!is_used_travel_avoid_perimeter) {
1507 wipe_next_start_point_str = start_pos_str;
1508 } else {
1509
1510 Vec3f gcode_last_pos;
1512 Vec2f gcode_last_pos2d{gcode_last_pos[0], gcode_last_pos[1]};
1513 Point gcode_last_pos2d_object = gcodegen.gcode_to_point(gcode_last_pos2d.cast<
double>() + plate_origin_2d.cast<
double>());
1515 BoundingBox avoid_bbx;
1516 {
1517
1519 Polygon avoid_points = avoid_bbx.polygon();
1520 for (auto &p : avoid_points.points) {
1523 }
1524 avoid_bbx = BoundingBox(avoid_points.points);
1525 }
1526 std::string travel_to_wipe_tower_gcode;
1528
1529 for (size_t i = 0; i < travel_polyline.points.size(); ++i) {
1530 const auto &p = travel_polyline.points[i];
1531 if (i == travel_polyline.points.size() - 1) {
1532 wipe_next_start_point_str = gcodegen.travel_to(p,
erMixed,
"Move to start pos");
1534 break;
1535 }
1536 travel_to_wipe_tower_gcode += gcodegen.travel_to(p,
erMixed,
"Move to start pos");
1538 }
1539 toolchange_gcode_str += travel_to_wipe_tower_gcode;
1540 gcodegen.set_last_pos(start_wipe_pos);
1541 }
1542 }
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552 const ConfigOptionBool* has_filament_switcher_opt = gcodegen.m_print->full_print_config().option<ConfigOptionBool>("has_filament_switcher");
1553 bool is_contact_pre_extrusion = tcr.is_contact && gcodegen.m_config.enable_tower_interface_features;
1554 bool is_petg_pre_extrusion = !is_contact_pre_extrusion
1555 && gcodegen.config().filament_type.get_at(tcr.new_tool) == "PETG"
1556 && has_filament_switcher_opt && has_filament_switcher_opt->value;
1557 float extra_unretract = 0.f;
1558 if (is_contact_pre_extrusion)
1559 extra_unretract = gcodegen.m_config.filament_tower_interface_pre_extrusion_length.get_at(tcr.new_tool);
1560 else if (is_petg_pre_extrusion)
1561 extra_unretract = 2.f;
1562 std::string toolchange_unretract_str = (extra_unretract > 0.f) ? gcodegen.unretract(extra_unretract) : gcodegen.unretract();
1564
1565 gcodegen.placeholder_parser().set("current_extruder", new_filament_id);
1566 gcodegen.placeholder_parser().set("current_filament_id", new_filament_id);
1567 gcodegen.placeholder_parser().set("current_extruder_id", new_extruder_id);
1568 gcodegen.placeholder_parser().set("current_nozzle_id",
1570 gcodegen.placeholder_parser().set("current_hotend",
1572 {
1573 size_t fi = gcodegen.get_filament_config_index(new_filament_id);
1574 gcodegen.placeholder_parser().set("retraction_distance_when_cut", gcodegen.m_config.retraction_distances_when_cut.get_at(fi));
1575 gcodegen.placeholder_parser().set("long_retraction_when_cut", gcodegen.m_config.long_retractions_when_cut.get_at(fi));
1576 gcodegen.placeholder_parser().set("retraction_distance_when_ec", gcodegen.m_config.retraction_distances_when_ec.get_at(fi));
1577 gcodegen.placeholder_parser().set("long_retraction_when_ec", gcodegen.m_config.long_retractions_when_ec.get_at(fi));
1578 }
1579
1580
1581 std::string start_filament_gcode_str;
1582 const std::string &filament_start_gcode = gcodegen.config().filament_start_gcode.get_at(new_filament_id);
1583 if (!filament_start_gcode.empty()) {
1584
1585 DynamicConfig config;
1586 config.set_key_value("filament_extruder_id", new ConfigOptionInt(new_filament_id));
1587 config.set_key_value("current_filament_id", new ConfigOptionInt(new_filament_id));
1591 config.set_key_value("layer_num", new ConfigOptionInt(gcodegen.m_layer_index));
1593 config.set_key_value(
"max_layer_z",
new ConfigOptionFloat(gcodegen.m_max_layer_z));
1594 start_filament_gcode_str = gcodegen.placeholder_parser_process("filament_start_gcode", filament_start_gcode, new_filament_id, &config);
1595 if (add_change_filament_624) {
1596 start_filament_gcode_str += "M625\n";
1597 add_change_filament_624 = false;
1598 }
1600 }
1601
1602 start_filament_gcode_str = start_filament_gcode_str + wipe_next_start_point_str + toolchange_unretract_str;
1603
1604
1605
1606
1607 if (compacted_below_object) {
1608 std::string z_descend = gcodegen.writer().travel_to_z(z, "Descend to compacted wipe tower z (no sparse layers)");
1610 start_filament_gcode_str += z_descend;
1611 }
1612
1613
1614 DynamicConfig config;
1615 config.set_key_value(
"filament_end_gcode",
new ConfigOptionString(end_filament_gcode_str));
1616 config.set_key_value(
"change_filament_gcode",
new ConfigOptionString(toolchange_gcode_str));
1617 config.set_key_value(
"filament_start_gcode",
new ConfigOptionString(start_filament_gcode_str));
1618 std::string tcr_gcode, tcr_escaped_gcode = gcodegen.placeholder_parser_process("tcr_rotated_gcode", tcr_rotated_gcode, new_filament_id, &config);
1622
1623
1625 gcodegen.m_toolchange_count++;
1627
1628
1629 gcode += gcodegen.set_filament_pressure_advance(new_filament_id);
1630
1631
1632 gcodegen.writer().travel_to_xy((end_pos + plate_origin_2d).
cast<double>());
1635 gcode += gcodegen.writer().retract();
1636 gcode += gcodegen.writer().travel_to_z(current_z,
"Travel back up to the topmost object layer.");
1637 gcode += gcodegen.writer().unretract();
1638 }
1639
1640 else {
1641
1642 gcodegen.m_wipe.reset_path();
1643 for (
const Vec2f &wipe_pt : tcr.wipe_path)
1645 gcode += gcodegen.retract(
false,
false, auto_lift_type,
true);
1646 }
1647
1648
1649 gcodegen.m_avoid_crossing_perimeters.use_external_mp_once();
1650 if (position_before_toolchange)
1651 gcodegen.synchronize_toolchange_position(*position_before_toolchange, gcode);
1653 }
#define EPSILON
Definition ColorUtils.cpp:64
#define M_PI
Definition ExtrusionSimulator.cpp:31
static bool get_last_position_from_gcode(const std::string &gcode_str, Vec3f &pos)
Definition GCodeProcessor.cpp:4310
static bool get_last_z_from_gcode(const std::string &gcode_str, double &z)
Definition GCodeProcessor.cpp:4256
Vec2f m_rib_offset
Definition GCode.hpp:196
Polygons shared_printable_area(GCode &gcodegen) const
Definition GCode.cpp:1012
std::string post_process_wipe_tower_moves(const WipeTower::ToolChangeResult &tcr, const Vec2f &translation, float angle) const
Definition GCode.cpp:1957
std::string tower_height_tag(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, const std::string &tcr_gcode) const
Definition GCode.cpp:1079
Polyline generate_path_to_wipe_tower(const Point &start_pos, const Point &end_pos, const BoundingBox &avoid_polygon, const Polygons &bed_polygons) const
Definition GCode.cpp:887
BoundingBoxf m_wipe_tower_bbx
Definition GCode.hpp:195
@ gcode
Definition Time.hpp:14
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:16
zaa_minimize_perimeter_height ConfigOptionFloat
Definition PrintConfig.hpp:1954
static int nozzle_id_for_gcode_placeholder(const std::shared_ptr< MultiNozzleUtils::LayeredNozzleGroupResult > &group_result, int filament_id, int extruder_id, int layer_id=-1)
Definition GCode.cpp:241
zaa_minimize_perimeter_height nozzle_diameter((ConfigOptionBool, reduce_infill_retraction))((ConfigOptionBool
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:284
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
ZHopType
Definition PrintConfig.hpp:582
@ zhtSlope
Definition PrintConfig.hpp:585
@ zhtAuto
Definition PrintConfig.hpp:583
@ zhtSpiral
Definition PrintConfig.hpp:586
size_t get_extruder_index(const GCodeConfig &config, unsigned int filament_id)
Definition PrintConfig.cpp:140
static const float g_min_purge_volume
Definition GCode.cpp:208
static std::vector< double > get_nozzle_diameters_by_nozzle_id(const MultiNozzleUtils::NozzleGroupResultBase *group_result)
Definition GCode.cpp:280
BoundingBox get_extents(const ExPolygonsWithIds &e)
Definition Emboss.cpp:1374
std::string transform_gcode(const std::string &gcode, Vec2f pos, const Vec2f &translation, float angle)
Definition GCode.cpp:605
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65
LiftType
Definition PrintConfig.hpp:429
@ SpiralLift
Definition PrintConfig.hpp:431
@ NormalLift
Definition PrintConfig.hpp:430
@ erMixed
Definition ExtrusionEntity.hpp:47
static Point wipe_tower_point_to_object_point(GCode &gcodegen, const Vec2f &wipe_tower_pt)
Definition GCode.cpp:752
@ pvmFast
Definition PrintConfig.hpp:659
float get_wipe_avoid_pos_x(const Vec2f &wt_min, const Vec2f &wt_max, float offset)
Definition GCode.cpp:655
static int hotend_id_for_gcode_placeholder(const std::shared_ptr< MultiNozzleUtils::LayeredNozzleGroupResult > &group_result, bool is_bbl_printer, int filament_id, int extruder_id, int layer_id=-1)
Definition GCode.cpp:229
ConfigOptionIntsTempl< false > ConfigOptionInts
Definition Config.hpp:1154
constexpr bool is_approx(Number value, Number test_value, Number precision=EPSILON)
Definition libslic3r.h:320
constexpr Eigen::Matrix< Tout, 2, EigenArgs... > unscaled(const Slic3r::Point &v) noexcept
Definition Arrange.cpp:81
static const float g_purge_volume_one_time
Definition GCode.cpp:209
static std::vector< std::string > get_nozzle_volume_types_by_nozzle_id(const MultiNozzleUtils::NozzleGroupResultBase *group_result)
Definition GCode.cpp:296
zaa_minimize_perimeter_height change_filament_gcode((ConfigOptionString, change_extrusion_role_gcode))((ConfigOptionString
static const int g_max_flush_count
Definition GCode.cpp:210
zaa_minimize_perimeter_height ConfigOptionString
Definition PrintConfig.hpp:1702
T unscale(Q v)
Definition libslic3r.h:138
Vec2d travel_point_2
Definition GCode.cpp:322
static std::string wrap_custom_gcode_for_fan_mover(const FullPrintConfig &config, const std::string &gcode)
Definition GCode.cpp:1095
Vec2d travel_point_1
Definition GCode.cpp:321
Vec2d travel_point_3
Definition GCode.cpp:323
static float get_outer_wall_volumetric_speed(const FullPrintConfig &config, const Print &print, int filament_id, int filament_variant_idx, int extruder_id)
Definition GCode.cpp:760
Eigen::Matrix< float, 2, 1, Eigen::DontAlign > Vec2f
Definition Point.hpp:64
bool unescape_string_cstyle(const std::string &str, std::string &str_out)
Definition Config.cpp:150
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299
static void check_add_eol(std::string &gcode)
Definition GCode.cpp:447
ConfigOptionFloatsTempl< false > ConfigOptionFloats
Definition Config.hpp:1015
static bool custom_gcode_changes_tool(const std::string &custom_gcode, const std::string &tch_prefix, unsigned next_extruder)
Definition GCode.cpp:455
Slic3r::Polygon Polygon
Definition Emboss.cpp:101