mirror of
https://git.mirrors.martin98.com/https://github.com/bambulab/BambuStudio.git
synced 2025-09-29 06:13:16 +08:00
ENH: Add gaps in the outer wall of the wipe_tower
and modify the path of travel to the wipe_tower after flushing jira:none Change-Id: Id4b0571fd12372c59cf522c13e256c7cc4ac3565
This commit is contained in:
parent
7d4e48aa83
commit
17771d0fbf
@ -99,5 +99,5 @@
|
||||
"machine_end_gcode": ";===== date: 2024/12/19 =====================\n;===== H2D =====================\nG392 S0 ;turn off nozzle clog detect\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\n{if timelapse_type == 2}\nM991 S0 P-1 ;end timelapse immediately\n{endif}\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\n\nG90\nG150.3\n\n{if timelapse_type == 1}\nM991 S0 P-1 ;end timelapse at safe pos\n{endif}\n\nM141 S0 ; turn off chamber heating\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\n; pull back filament to AMS\nM620 S65535\nT65535\nG150.2\nM621 S65535\n\nM620 S65279\nT65279\nG150.2\nM621 S65279\n\nG150.3\n\nM104 S0 T0; turn off hotend\nM104 S0 T1; turn off hotend\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 320}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z320 F600\n G1 Z320\n{endif}\nM400 P100\nM17 R ; restore z current\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM1015.4 S0 K0 ;disable air printing detect\n;=====printer finish sound=========\nM17\nM400 S1\nM1006 S1\nM1006 A53 B10 L99 C53 D10 M99 E53 F10 N99 \nM1006 A57 B10 L99 C57 D10 M99 E57 F10 N99 \nM1006 A0 B15 L0 C0 D15 M0 E0 F15 N0 \nM1006 A53 B10 L99 C53 D10 M99 E53 F10 N99 \nM1006 A57 B10 L99 C57 D10 M99 E57 F10 N99 \nM1006 A0 B15 L0 C0 D15 M0 E0 F15 N0 \nM1006 A48 B10 L99 C48 D10 M99 E48 F10 N99 \nM1006 A0 B15 L0 C0 D15 M0 E0 F15 N0 \nM1006 A60 B10 L99 C60 D10 M99 E60 F10 N99 \nM1006 W\n;=====printer finish sound=========\nM400\nM18\n\n",
|
||||
"layer_change_gcode": ";======== H2D 20250101========\n; layer num/total_layer_count: {layer_num+1}/[total_layer_count]\n; update layer progress\nM73 L{layer_num+1}\nM991 S0 P{layer_num} ;notify layer change",
|
||||
"time_lapse_gcode": ";======== H2D 20250101========\nM622.1 S1 ; for prev firware, default turned on\n\nM1002 judge_flag timelapse_record_flag\nM622 J1\nM9712 E{most_used_physical_extruder_id} M{timelapse_type}\nM83\nG1 E-[retraction_length] F1800\nG17\nG2 Z{layer_z + 0.4} I0.86 J0.86 P1 F20000 ; spiral lift a little\nG1 Z{max_layer_z + 0.4} F1200\nM400\nM9713\n\nM9711 M{timelapse_type} E{most_used_physical_extruder_id} Z{layer_z} S11 C10 O0 T3000\n\nM9712 E{most_used_physical_extruder_id}\nG90\n;G1 Z{max_layer_z + 3.0} F1200\n;G1 Y295 F30000\n;G1 Y265 F18000\nG1 Y320 F30000\nM83\nG1 E[retraction_length] F300\nM9713\nM623",
|
||||
"change_filament_gcode": ";======== H2D ========\n;===== 2024/12/23 =====\nM993 A2 B2 C2 ; nozzle cam detection allow status save.\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\n{if (filament_type[next_extruder] == \"PLA\") || (filament_type[next_extruder] == \"PETG\")\n || (filament_type[next_extruder] == \"PLA-CF\") || (filament_type[next_extruder] == \"PETG-CF\")\n || (filament_type[next_extruder] == \"PA-CF\") || (filament_type[next_extruder] == \"PET-CF\")}\nM1015.4 S1 K0 ;disable E air printing detect\n{else}\nM1015.4 S0 ; disable E air printing detect\n{endif}\n\nM620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\n\n;nozzle_change_gcode\n\nG1 Z{max_layer_z + 3.0} F1200\n\nM400\nM106 P1 S0\nM106 P2 S0\n\n{if toolchange_count == 2}\n; get travel path for change filament\n;M620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\n;M620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\n;M620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\n\nM620.10 A0 F{filament_max_volumetric_speed[current_extruder]/2.4053*60} L[flush_length] H{nozzle_diameter[current_extruder]} T{nozzle_temperature_range_high[current_extruder]} P{nozzle_temperature[current_extruder]}\nM620.10 A1 F{filament_max_volumetric_speed[next_extruder]/2.4053*60} L[flush_length] H{nozzle_diameter[next_extruder]} T{nozzle_temperature_range_high[next_extruder]} P{nozzle_temperature[next_extruder]}\n\n{if filament_type[current_extruder] == \"TPU\"}\nM620.11 S0 L0 I[current_extruder] E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{else}\nM620.11 S1 L0 I[current_extruder] E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{endif}\n\n{if filament_type[current_extruder] == \"TPU\" || filament_type[next_extruder] == \"TPU\"}\nM620.11 H2 C331\n{else}\nM620.11 H0\n{endif}\n\nT[next_extruder]\n\n; VFLUSH_START\n{if flush_length>41.5}\n;VG1 E41.5 F{min(old_filament_e_feedrate,new_filament_e_feedrate)}\n;VG1 E{flush_length-41.5} F{new_filament_e_feedrate}\n{else}\n;VG1 E{flush_length} F{min(old_filament_e_feedrate,new_filament_e_feedrate)}\n{endif}\n; VFLUSH_END\n\nM400\nM83\n{if next_extruder < 255}\n\nM628 S0\n\nM629\nM400\n\nM983.3 F{filament_max_volumetric_speed[next_extruder]/2.4} A0.4\n\nM400\nG1 Y295 F30000\nG1 Y265 F18000\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n\nM993 A3 B3 C3 ; nozzle cam detection allow status restore.\n\n{if (filament_type[next_extruder] == \"PLA\") || (filament_type[next_extruder] == \"PETG\")\n || (filament_type[next_extruder] == \"PLA-CF\") || (filament_type[next_extruder] == \"PETG-CF\")\n || (filament_type[next_extruder] == \"PA-CF\") || (filament_type[next_extruder] == \"PET-CF\")}\nM1015.4 S1 K1 H[nozzle_diameter] ;enable E air printing detect\n{else}\nM1015.4 S0 ; disable E air printing detect\n{endif}\n\nM620.6 I[next_extruder] W1 ;enable ams air printing detect\n\n"
|
||||
"change_filament_gcode": ";======== H2D ========\n;===== 2024/12/23 =====\nM993 A2 B2 C2 ; nozzle cam detection allow status save.\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\n{if (filament_type[next_extruder] == \"PLA\") || (filament_type[next_extruder] == \"PETG\")\n || (filament_type[next_extruder] == \"PLA-CF\") || (filament_type[next_extruder] == \"PETG-CF\")\n || (filament_type[next_extruder] == \"PA-CF\") || (filament_type[next_extruder] == \"PET-CF\")}\nM1015.4 S1 K0 ;disable E air printing detect\n{else}\nM1015.4 S0 ; disable E air printing detect\n{endif}\n\nM620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\n\n;nozzle_change_gcode\n\nG1 Z{max_layer_z + 3.0} F1200\n\nM400\nM106 P1 S0\nM106 P2 S0\n\n{if toolchange_count == 2}\n; get travel path for change filament\n;M620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\n;M620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\n;M620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\n\nM620.10 A0 F{filament_max_volumetric_speed[current_extruder]/2.4053*60} L[flush_length] H{nozzle_diameter[current_extruder]} T{nozzle_temperature_range_high[current_extruder]} P{nozzle_temperature[current_extruder]}\nM620.10 A1 F{filament_max_volumetric_speed[next_extruder]/2.4053*60} L[flush_length] H{nozzle_diameter[next_extruder]} T{nozzle_temperature_range_high[next_extruder]} P{nozzle_temperature[next_extruder]}\n\n{if filament_type[current_extruder] == \"TPU\"}\nM620.11 S0 L0 I[current_extruder] E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{else}\nM620.11 S1 L0 I[current_extruder] E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{endif}\n\n{if filament_type[current_extruder] == \"TPU\" || filament_type[next_extruder] == \"TPU\"}\nM620.11 H2 C331\n{else}\nM620.11 H0\n{endif}\n\nT[next_extruder]\n\n; VFLUSH_START\n{if flush_length>41.5}\n;VG1 E41.5 F{min(old_filament_e_feedrate,new_filament_e_feedrate)}\n;VG1 E{flush_length-41.5} F{new_filament_e_feedrate}\n{else}\n;VG1 E{flush_length} F{min(old_filament_e_feedrate,new_filament_e_feedrate)}\n{endif}\n; VFLUSH_END\n\nM400\nM83\n{if next_extruder < 255}\n\nM628 S0\n\nM629\nM400\n\nM983.3 F{filament_max_volumetric_speed[next_extruder]/2.4} A0.4\n\nM400\n{if wipe_avoid_perimeter}\nG1 Y320\nG1 X{wipe_avoid_pos_x} F30000\n{endif}\nG1 Y295 F30000\nG1 Y265 F18000\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n\nM993 A3 B3 C3 ; nozzle cam detection allow status restore.\n\n{if (filament_type[next_extruder] == \"PLA\") || (filament_type[next_extruder] == \"PETG\")\n || (filament_type[next_extruder] == \"PLA-CF\") || (filament_type[next_extruder] == \"PETG-CF\")\n || (filament_type[next_extruder] == \"PA-CF\") || (filament_type[next_extruder] == \"PET-CF\")}\nM1015.4 S1 K1 H[nozzle_diameter] ;enable E air printing detect\n{else}\nM1015.4 S0 ; disable E air printing detect\n{endif}\n\nM620.6 I[next_extruder] W1 ;enable ams air printing detect\n\n"
|
||||
}
|
@ -92,7 +92,7 @@ static const std::string lift_gcode_after_printing_object = "{if toolchange_coun
|
||||
Vec2d travel_point_1;
|
||||
Vec2d travel_point_2;
|
||||
Vec2d travel_point_3;
|
||||
|
||||
static bool is_used_travel_avoid_perimeter = true;
|
||||
static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
{
|
||||
// give safe value in case there is no start_end_points in config
|
||||
@ -345,6 +345,18 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
return gcode_out;
|
||||
}
|
||||
|
||||
float get_wipe_avoid_pos_x(const Vec2f &wt_ori, float wt_width, float offset, bool is_default)
|
||||
{
|
||||
float left = 100, right = 250;
|
||||
float default_value = 110.f;
|
||||
float a = 0.f, b = 0.f;
|
||||
if (is_default) return default_value;
|
||||
a = wt_ori.x() + wt_width + offset;
|
||||
b = wt_ori.x() - offset;
|
||||
if (a > left && a < right) return a;
|
||||
if (b > left && b < right) return b;
|
||||
return default_value;
|
||||
}
|
||||
|
||||
std::string Wipe::wipe(GCode& gcodegen, bool toolchange, bool is_last)
|
||||
{
|
||||
@ -445,6 +457,138 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
return outer_wall_volumetric_speed;
|
||||
}
|
||||
|
||||
// BBS
|
||||
// start_pos refers to the last position before the wipe_tower.
|
||||
// end_pos refers to the wipe tower's start_pos.
|
||||
// using the print coordinate system
|
||||
std::string WipeTowerIntegration::generate_path_to_wipe_tower(
|
||||
GCode &gcodegen, const Point &wipe_tower_left_front, const Point &start_pos, const Point &end_pos, int width, int depth, int brim_width) const
|
||||
{
|
||||
std::string gcode;
|
||||
int alpha = scaled(2.f); // offset distance
|
||||
BoundingBox wipe_tower_offset_bbx(wipe_tower_left_front, wipe_tower_left_front + Point(width, depth));
|
||||
wipe_tower_offset_bbx.offset(brim_width);
|
||||
wipe_tower_offset_bbx.offset(alpha);
|
||||
Polygon wipe_tower_offset_polygon = wipe_tower_offset_bbx.polygon();
|
||||
Polygon bed_polygon;
|
||||
for (size_t i = 0; i < gcodegen.m_config.printable_area.values.size(); i++) {
|
||||
bed_polygon.points.push_back(
|
||||
wipe_tower_point_to_object_point(gcodegen, gcodegen.m_config.printable_area.values[i].cast<float>() + Vec2f{m_plate_origin[0], m_plate_origin[1]}));
|
||||
} // gcode coordinate system to printing coordinate system
|
||||
Vec2f v(1, 0); // the first print direction of end_pos.
|
||||
if (abs(end_pos[0] - wipe_tower_left_front[0]) < width / 2) v = -v; // judge whether the wipe tower's infill goes to the left or right.
|
||||
// Judge whether the wipe_tower_bbx_offset is outside the bed_boundary.
|
||||
// If so, do nothing and just go directly to the end_pos.
|
||||
bool is_bbx_in_bed = true;
|
||||
for (auto &wipe_tower_bbx_p : wipe_tower_offset_polygon.points) {
|
||||
if (ClipperLib::PointInPolygon(wipe_tower_bbx_p, bed_polygon.points) != 1) {
|
||||
is_bbx_in_bed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_bbx_in_bed) {
|
||||
gcode += gcodegen.travel_to(end_pos, erMixed, "Move to start pos");
|
||||
check_add_eol(gcode);
|
||||
return gcode;
|
||||
}
|
||||
// Ray-Line Segment Intersection
|
||||
auto ray_intersetion_line = [](const Vec2d &a, const Vec2d &v1, const Vec2d &b, const Vec2d &c) -> std::pair<bool, Point> {
|
||||
const Vec2d v2 = c - b;
|
||||
double denom = cross2(v1, v2);
|
||||
if (fabs(denom) < EPSILON) return {false, Point(0, 0)};
|
||||
const Vec2d v12 = (a - b);
|
||||
double nume_a = cross2(v2, v12);
|
||||
double nume_b = cross2(v1, v12);
|
||||
double t1 = nume_a / denom;
|
||||
double t2 = nume_b / denom;
|
||||
if (t1 >= 0 && t2 >= 0 && t2 <= 1.) {
|
||||
// Get the intersection point.
|
||||
Vec2d res = a + t1 * v1;
|
||||
return std::pair<bool, Point>(true, scaled(res));
|
||||
}
|
||||
return std::pair<bool, Point>(false, {0, 0});
|
||||
};
|
||||
struct Inter_info
|
||||
{
|
||||
int inter_idx0 = -1;
|
||||
Point inter_p;
|
||||
};
|
||||
auto calc_path_len = [](Points &points, Inter_info &beg_info, Inter_info &end_info, bool is_add) -> std::pair<std::vector<Point>, double> {
|
||||
int beg = is_add ? (beg_info.inter_idx0 + 1) % points.size() : beg_info.inter_idx0;
|
||||
int end = is_add ? end_info.inter_idx0 : (end_info.inter_idx0 + 1) % points.size();
|
||||
int i = beg;
|
||||
double len = 0;
|
||||
std::vector<Point> path;
|
||||
path.push_back(beg_info.inter_p);
|
||||
len += (unscale(beg_info.inter_p) - unscale(points[beg])).squaredNorm();
|
||||
while (i != end) {
|
||||
int ni = is_add ? (i + 1) % points.size() : (i - 1 + points.size()) % points.size();
|
||||
auto a = unscale(points[i]);
|
||||
auto b = unscale(points[ni]);
|
||||
len += (a - b).squaredNorm();
|
||||
path.push_back(points[i]);
|
||||
i = ni;
|
||||
}
|
||||
path.push_back(points[end]);
|
||||
path.push_back(end_info.inter_p);
|
||||
len += (unscale(end_info.inter_p) - unscale(points[end])).squaredNorm();
|
||||
return {path, len};
|
||||
};
|
||||
// calculate the intersection point of end_pos along vector v with the wipe_tower_offset_polygon.
|
||||
// store in inter_info.
|
||||
// represent this intersection by 'p'.
|
||||
Inter_info inter_info;
|
||||
for (size_t i = 0; i < wipe_tower_offset_polygon.points.size(); i++) {
|
||||
auto &a = wipe_tower_offset_polygon[i];
|
||||
auto &b = wipe_tower_offset_polygon[(i + 1) % wipe_tower_offset_polygon.points.size()];
|
||||
auto [is_inter, inter_p] = ray_intersetion_line(unscale(end_pos), v.cast<double>(), unscale(a), unscale(b));
|
||||
if (is_inter) {
|
||||
inter_info.inter_idx0 = i;
|
||||
inter_info.inter_p = inter_p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (inter_info.inter_idx0 == -1) {
|
||||
gcode += gcodegen.travel_to(end_pos, erMixed, "Move to start pos");
|
||||
check_add_eol(gcode);
|
||||
return gcode;
|
||||
}
|
||||
// calculate the other intersection of start_to_p with the wipe_tower_offset_polygon.
|
||||
// represent this intersection by 'p_'.
|
||||
Inter_info inter_info2;
|
||||
Linef start_to_p(unscale(start_pos), unscale(inter_info.inter_p));
|
||||
for (size_t i = 0; i < wipe_tower_offset_polygon.points.size(); i++) {
|
||||
if (i == inter_info.inter_idx0) continue;
|
||||
Vec2d a = unscale(wipe_tower_offset_polygon.points[i]);
|
||||
Vec2d b = unscale(wipe_tower_offset_polygon.points[(i + 1) % wipe_tower_offset_polygon.points.size()]);
|
||||
Linef tower_edge(a, b);
|
||||
Vec2d inter;
|
||||
if (line_alg::intersection(start_to_p, tower_edge, &inter)) {
|
||||
inter_info2.inter_p = scaled(inter);
|
||||
inter_info2.inter_idx0 = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if p_ does not exist, go directly to p.
|
||||
// else p travels along the shorter path on the wipe_tower_offset_polygon to p_
|
||||
if (inter_info2.inter_idx0 == -1) {
|
||||
gcode += gcodegen.travel_to(inter_info.inter_p, erMixed, "Move to start pos");
|
||||
check_add_eol(gcode);
|
||||
} else {
|
||||
std::vector<Point> path;
|
||||
auto [path1, len1] = calc_path_len(wipe_tower_offset_polygon.points, inter_info2, inter_info, true);
|
||||
auto [path2, len2] = calc_path_len(wipe_tower_offset_polygon.points, inter_info2, inter_info, false);
|
||||
path = len1 < len2 ? path1 : path2;
|
||||
for (size_t i = 0; i < path.size(); i++) {
|
||||
gcode += gcodegen.travel_to(path[i], erMixed, "Move to start pos");
|
||||
check_add_eol(gcode);
|
||||
}
|
||||
}
|
||||
gcode += gcodegen.travel_to(end_pos, erMixed, "Move to start pos");
|
||||
check_add_eol(gcode);
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string WipeTowerIntegration::append_tcr(GCode& gcodegen, const WipeTower::ToolChangeResult& tcr, int new_filament_id, double z) const
|
||||
{
|
||||
if (new_filament_id != -1 && new_filament_id != tcr.new_tool)
|
||||
@ -587,6 +731,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
old_filament_e_feedrate = old_filament_e_feedrate == 0 ? 100 : old_filament_e_feedrate;
|
||||
int new_filament_e_feedrate = (int)(60.0 * full_config.filament_max_volumetric_speed.get_at(new_filament_id) / filament_area);
|
||||
new_filament_e_feedrate = new_filament_e_feedrate == 0 ? 100 : new_filament_e_feedrate;
|
||||
float wipe_avoid_pos_x = get_wipe_avoid_pos_x(m_wipe_tower_pos, gcodegen.m_config.prime_tower_width.value, 3.f + gcodegen.m_config.prime_tower_brim_width.value,false);
|
||||
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(gcodegen.m_max_layer_z));
|
||||
config.set_key_value("relative_e_axis", new ConfigOptionBool(full_config.use_relative_e_distances));
|
||||
@ -615,6 +760,8 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
config.set_key_value("travel_point_3_y", new ConfigOptionFloat(float(travel_point_3.y())));
|
||||
|
||||
config.set_key_value("flush_length", new ConfigOptionFloat(purge_length));
|
||||
config.set_key_value("wipe_avoid_perimeter", new ConfigOptionBool(is_used_travel_avoid_perimeter));
|
||||
config.set_key_value("wipe_avoid_pos_x", new ConfigOptionFloat(wipe_avoid_pos_x));
|
||||
|
||||
int flush_count = std::min(g_max_flush_count, (int)std::round(purge_volume / g_purge_volume_one_time));
|
||||
// handle cases for very small purge
|
||||
@ -654,9 +801,23 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
}
|
||||
|
||||
// move to start_pos for wiping after toolchange
|
||||
if (!is_used_travel_avoid_perimeter) {
|
||||
std::string start_pos_str = gcodegen.travel_to(wipe_tower_point_to_object_point(gcodegen, start_pos + plate_origin_2d), erMixed, "Move to start pos");
|
||||
check_add_eol(start_pos_str);
|
||||
toolchange_gcode_str += start_pos_str;
|
||||
} else {
|
||||
// BBS:change travel_path
|
||||
Vec3f gcode_last_pos;
|
||||
GCodeProcessor::get_last_position_from_gcode(toolchange_gcode_str, gcode_last_pos);
|
||||
Vec2f gcode_last_pos2d{gcode_last_pos[0], gcode_last_pos[1]};
|
||||
Point gcode_last_pos2d_object = gcodegen.gcode_to_point(gcode_last_pos2d.cast<double>() + plate_origin_2d.cast<double>());
|
||||
Point start_wipe_pos = wipe_tower_point_to_object_point(gcodegen, start_pos + plate_origin_2d);
|
||||
std::string travel_to_wipe_tower_gcode = generate_path_to_wipe_tower(gcodegen, wipe_tower_point_to_object_point(gcodegen, m_wipe_tower_pos + plate_origin_2d),
|
||||
gcode_last_pos2d_object, start_wipe_pos, scaled(gcodegen.m_config.prime_tower_width.value),
|
||||
scaled(m_wipe_tower_depth), scaled(gcodegen.m_config.prime_tower_brim_width.value));
|
||||
toolchange_gcode_str += travel_to_wipe_tower_gcode;
|
||||
gcodegen.set_last_pos(start_wipe_pos);
|
||||
}
|
||||
}
|
||||
|
||||
std::string toolchange_command;
|
||||
@ -2309,6 +2470,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
if (has_wipe_tower && !layers_to_print.empty()) {
|
||||
m_wipe_tower.reset(new WipeTowerIntegration(print.config(), print.get_plate_index(), print.get_plate_origin(), *print.wipe_tower_data().priming.get(),
|
||||
print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()));
|
||||
m_wipe_tower->set_wipe_tower_depth(print.get_wipe_tower_depth());
|
||||
// BBS
|
||||
// file.write(m_writer.travel_to_z(initial_layer_print_height + m_config.z_offset.value, "Move to the first layer height"));
|
||||
file.write(m_writer.travel_to_z(initial_layer_print_height, "Move to the first layer height"));
|
||||
@ -5805,7 +5967,7 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
|
||||
// set volumetric speed of outer wall ,ignore per obejct,just use default setting
|
||||
float outer_wall_volumetric_speed = get_outer_wall_volumetric_speed(m_config, *m_print, new_filament_id, get_extruder_id(new_filament_id));
|
||||
|
||||
float wipe_avoid_pos_x = get_wipe_avoid_pos_x(Vec2f{0, 0}, 0, 0, true);
|
||||
DynamicConfig dyn_config;
|
||||
dyn_config.set_key_value("outer_wall_volumetric_speed", new ConfigOptionFloat(outer_wall_volumetric_speed));
|
||||
dyn_config.set_key_value("previous_extruder", new ConfigOptionInt(old_filament_id));
|
||||
@ -5837,6 +5999,8 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
dyn_config.set_key_value("travel_point_2_y", new ConfigOptionFloat(float(travel_point_2.y())));
|
||||
dyn_config.set_key_value("travel_point_3_x", new ConfigOptionFloat(float(travel_point_3.x())));
|
||||
dyn_config.set_key_value("travel_point_3_y", new ConfigOptionFloat(float(travel_point_3.y())));
|
||||
dyn_config.set_key_value("wipe_avoid_perimeter", new ConfigOptionBool(is_used_travel_avoid_perimeter));
|
||||
dyn_config.set_key_value("wipe_avoid_pos_x", new ConfigOptionFloat(wipe_avoid_pos_x));
|
||||
|
||||
dyn_config.set_key_value("flush_length", new ConfigOptionFloat(wipe_length));
|
||||
|
||||
|
@ -106,10 +106,12 @@ public:
|
||||
void set_is_first_print(bool is) { m_is_first_print = is; }
|
||||
|
||||
bool enable_timelapse_print() const { return m_enable_timelapse_print; }
|
||||
void set_wipe_tower_depth(float depth) { m_wipe_tower_depth = depth; }
|
||||
|
||||
private:
|
||||
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
|
||||
std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z = -1.) const;
|
||||
std::string generate_path_to_wipe_tower(GCode &gcodegen, const Point &wipe_tower_left_front, const Point &start_pos, const Point &end_pos, int width, int depth, int brim_width) const;
|
||||
|
||||
// Postprocesses gcode: rotates and moves G1 extrusions and returns result
|
||||
std::string post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const;
|
||||
@ -136,6 +138,7 @@ private:
|
||||
bool m_enable_timelapse_print;
|
||||
bool m_is_first_print;
|
||||
const PrintConfig * m_print_config;
|
||||
float m_wipe_tower_depth;
|
||||
};
|
||||
|
||||
class ColorPrintColors
|
||||
|
@ -2732,6 +2732,98 @@ bool GCodeProcessor::get_last_z_from_gcode(const std::string& gcode_str, double&
|
||||
return is_z_changed;
|
||||
}
|
||||
|
||||
bool GCodeProcessor::get_last_position_from_gcode(const std::string &gcode_str, Vec3f &pos)
|
||||
{
|
||||
int str_size = gcode_str.size();
|
||||
int start_index = 0;
|
||||
int end_index = 0;
|
||||
bool is_z_changed = false;
|
||||
while (end_index < str_size) {
|
||||
// find a full line
|
||||
if (gcode_str[end_index] != '\n') {
|
||||
end_index++;
|
||||
continue;
|
||||
}
|
||||
// parse the line
|
||||
if (end_index > start_index) {
|
||||
std::string line_str = gcode_str.substr(start_index, end_index - start_index);
|
||||
line_str.erase(0, line_str.find_first_not_of(" "));
|
||||
line_str.erase(line_str.find_last_not_of(";") + 1);
|
||||
line_str.erase(line_str.find_last_not_of(" ") + 1);
|
||||
|
||||
// command which may have z movement
|
||||
if (line_str.size() > 5 && (line_str.find("G0 ") == 0 || line_str.find("G1 ") == 0 || line_str.find("G2 ") == 0 || line_str.find("G3 ") == 0)) {
|
||||
{
|
||||
float &x = pos.x();
|
||||
auto z_pos = line_str.find(" X");
|
||||
float temp_z = 0;
|
||||
if (z_pos != line_str.npos && z_pos + 2 < line_str.size()) {
|
||||
// Try to parse the numeric value.
|
||||
std::string z_sub = line_str.substr(z_pos + 2);
|
||||
char *c = &z_sub[0];
|
||||
char *end = c + sizeof(z_sub.c_str());
|
||||
|
||||
auto is_end_of_word = [](char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0 || c == ';'; };
|
||||
|
||||
auto [pend, ec] = fast_float::from_chars(c, end, temp_z);
|
||||
if (pend != c && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
x = temp_z;
|
||||
is_z_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
float &y = pos.y();
|
||||
auto z_pos = line_str.find(" Y");
|
||||
float temp_z = 0;
|
||||
if (z_pos != line_str.npos && z_pos + 2 < line_str.size()) {
|
||||
// Try to parse the numeric value.
|
||||
std::string z_sub = line_str.substr(z_pos + 2);
|
||||
char *c = &z_sub[0];
|
||||
char *end = c + sizeof(z_sub.c_str());
|
||||
|
||||
auto is_end_of_word = [](char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0 || c == ';'; };
|
||||
|
||||
auto [pend, ec] = fast_float::from_chars(c, end, temp_z);
|
||||
if (pend != c && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
y = temp_z;
|
||||
is_z_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
float &z = pos.z();
|
||||
auto z_pos = line_str.find(" Z");
|
||||
float temp_z = 0;
|
||||
if (z_pos != line_str.npos && z_pos + 2 < line_str.size()) {
|
||||
// Try to parse the numeric value.
|
||||
std::string z_sub = line_str.substr(z_pos + 2);
|
||||
char *c = &z_sub[0];
|
||||
char *end = c + sizeof(z_sub.c_str());
|
||||
|
||||
auto is_end_of_word = [](char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0 || c == ';'; };
|
||||
|
||||
auto [pend, ec] = fast_float::from_chars(c, end, temp_z);
|
||||
if (pend != c && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
z = temp_z;
|
||||
is_z_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// loop to handle next line
|
||||
start_index = end_index + 1;
|
||||
end_index = start_index;
|
||||
}
|
||||
return is_z_changed;
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_tags(const std::string_view comment, bool producers_enabled)
|
||||
{
|
||||
static ExtrusionRole prev_role;
|
||||
|
@ -403,6 +403,7 @@ namespace Slic3r {
|
||||
|
||||
static int get_gcode_last_filament(const std::string &gcode_str);
|
||||
static bool get_last_z_from_gcode(const std::string& gcode_str, double& z);
|
||||
static bool get_last_position_from_gcode(const std::string &gcode_str, Vec3f &pos);
|
||||
|
||||
static const float Wipe_Width;
|
||||
static const float Wipe_Height;
|
||||
|
@ -15,7 +15,8 @@
|
||||
namespace Slic3r
|
||||
{
|
||||
static const double wipe_tower_wall_infill_overlap = 0.0;
|
||||
|
||||
static const double wipe_tower_wall_infill_overlap_new = -0.2;
|
||||
static bool is_used_gap_wall = true;
|
||||
inline float align_round(float value, float base)
|
||||
{
|
||||
return std::round(value / base) * base;
|
||||
@ -60,6 +61,39 @@ static bool is_valid_gcode(const std::string &gcode)
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
struct Segment
|
||||
{
|
||||
Vec2f start;
|
||||
Vec2f end;
|
||||
|
||||
Segment(const Vec2f &s, const Vec2f &e) : start(s), end(e) {}
|
||||
bool is_valid() const { return start.y() < end.y(); }
|
||||
};
|
||||
|
||||
std::vector<Segment> remove_points_from_segment(const Segment &segment, const std::vector<Vec2f> &skip_points, double range)
|
||||
{
|
||||
std::vector<Segment> result;
|
||||
result.push_back(segment);
|
||||
float x = segment.start.x();
|
||||
|
||||
for (const Vec2f &point : skip_points) {
|
||||
std::vector<Segment> newResult;
|
||||
for (const auto &seg : result) {
|
||||
if (point.y() + range <= seg.start.y() || point.y() - range >= seg.end.y()) {
|
||||
newResult.push_back(seg);
|
||||
} else {
|
||||
if (point.y() - range > seg.start.y()) { newResult.push_back(Segment(Vec2f(x, seg.start.y()), Vec2f(x, point.y() - range))); }
|
||||
if (point.y() + range < seg.end.y()) { newResult.push_back(Segment(Vec2f(x, point.y() + range), Vec2f(x, seg.end.y()))); }
|
||||
}
|
||||
}
|
||||
|
||||
result = newResult;
|
||||
}
|
||||
|
||||
result.erase(std::remove_if(result.begin(), result.end(), [](const Segment &seg) { return !seg.is_valid(); }), result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
class WipeTowerWriter
|
||||
{
|
||||
public:
|
||||
@ -766,18 +800,19 @@ Vec2f WipeTower::get_next_pos(const WipeTower::box_coordinates &cleaning_box, fl
|
||||
|
||||
Vec2f res;
|
||||
int index = m_cur_layer_id % 4;
|
||||
Vec2f offset = is_used_gap_wall ? Vec2f(5 * m_perimeter_width, 0) : Vec2f{0, 0};
|
||||
switch (index % 4) {
|
||||
case 0:
|
||||
res = cleaning_box.ld + pos_offset;
|
||||
res = offset +cleaning_box.ld + pos_offset;
|
||||
break;
|
||||
case 1:
|
||||
res = cleaning_box.rd + pos_offset + Vec2f(0, y_offset);
|
||||
res = -offset +cleaning_box.rd + pos_offset + Vec2f(0, y_offset);
|
||||
break;
|
||||
case 2:
|
||||
res = cleaning_box.rd + pos_offset;
|
||||
res = -offset+ cleaning_box.rd + pos_offset;
|
||||
break;
|
||||
case 3:
|
||||
res = cleaning_box.ld + pos_offset + Vec2f(0, y_offset);
|
||||
res = offset+cleaning_box.ld + pos_offset + Vec2f(0, y_offset);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@ -1821,7 +1856,7 @@ static WipeTower::ToolChangeResult merge_tcr(WipeTower::ToolChangeResult& first,
|
||||
{
|
||||
assert(first.new_tool == second.initial_tool);
|
||||
WipeTower::ToolChangeResult out = first;
|
||||
if (first.end_pos != second.start_pos)
|
||||
if ((first.end_pos - second.start_pos).norm()> (float)EPSILON)
|
||||
out.gcode += "G1 X" + Slic3r::float_to_string_decimal_point(second.start_pos.x(), 3)
|
||||
+ " Y" + Slic3r::float_to_string_decimal_point(second.start_pos.y(), 3)
|
||||
+ "\n";
|
||||
@ -1842,6 +1877,50 @@ static WipeTower::ToolChangeResult merge_tcr(WipeTower::ToolChangeResult& first,
|
||||
return out;
|
||||
}
|
||||
|
||||
void WipeTower::get_wall_skip_points(const WipeTowerInfo &layer)
|
||||
{
|
||||
m_wall_skip_points.clear();
|
||||
std::unordered_map<int, float> cur_block_depth;
|
||||
for (int i = 0; i < int(layer.tool_changes.size()); ++i) {
|
||||
const WipeTowerInfo::ToolChange &tool_change = layer.tool_changes[i];
|
||||
size_t old_filament = tool_change.old_tool;
|
||||
size_t new_filament = tool_change.new_tool;
|
||||
float spacing = m_layer_info->extra_spacing;
|
||||
if (has_tpu_filament() && m_layer_info->extra_spacing < m_tpu_fixed_spacing) spacing = 1;
|
||||
float nozzle_change_depth = tool_change.nozzle_change_depth * spacing;
|
||||
//float nozzle_change_depth = tool_change.nozzle_change_depth * (has_tpu_filament() ? m_tpu_fixed_spacing : layer.extra_spacing);
|
||||
auto &block = get_block_by_category(m_filpar[new_filament].category);
|
||||
float wipe_depth = tool_change.required_depth - nozzle_change_depth;
|
||||
float process_depth = 0.f;
|
||||
if (!cur_block_depth.count(m_filpar[new_filament].category))
|
||||
cur_block_depth[m_filpar[new_filament].category] = block.start_depth;
|
||||
process_depth = cur_block_depth[m_filpar[new_filament].category];
|
||||
if (!m_filament_map.empty() && new_filament < m_filament_map.size() && m_filament_map[old_filament] != m_filament_map[new_filament]) {
|
||||
if (m_filament_categories[new_filament] == m_filament_categories[old_filament])
|
||||
process_depth += nozzle_change_depth;
|
||||
else {
|
||||
if (!cur_block_depth.count(m_filpar[old_filament].category))
|
||||
cur_block_depth[m_filpar[old_filament].category]=m_perimeter_width; //Here, it is assumed that the bottom-most lines of the blocks are adjacent to the previous line.
|
||||
cur_block_depth[m_filpar[old_filament].category] += nozzle_change_depth;
|
||||
}
|
||||
}
|
||||
{
|
||||
Vec2f res;
|
||||
int index = m_cur_layer_id % 4;
|
||||
switch (index % 4) {
|
||||
case 0: res = Vec2f(0, process_depth); break;
|
||||
case 1: res = Vec2f(m_wipe_tower_width, process_depth + wipe_depth - layer.extra_spacing*m_perimeter_width); break;
|
||||
case 2: res = Vec2f(m_wipe_tower_width, process_depth); break;
|
||||
case 3: res = Vec2f(0, process_depth + wipe_depth - layer.extra_spacing * m_perimeter_width); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_wall_skip_points.emplace_back(res);
|
||||
}
|
||||
cur_block_depth[m_filpar[new_filament].category] = process_depth + wipe_depth ;
|
||||
}
|
||||
}
|
||||
|
||||
WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool)
|
||||
{
|
||||
m_nozzle_change_result.gcode.clear();
|
||||
@ -1930,7 +2009,6 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool)
|
||||
Vec2f initial_position = get_next_pos(cleaning_box, wipe_length);
|
||||
//Vec2f initial_position = cleaning_box.ld;
|
||||
writer.set_initial_position(initial_position + Vec2f(m_perimeter_width, m_perimeter_width), m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
|
||||
|
||||
writer.travel(initial_position);
|
||||
|
||||
toolchange_wipe_new(writer, cleaning_box, wipe_length);
|
||||
@ -2171,6 +2249,9 @@ WipeTower::ToolChangeResult WipeTower::finish_layer_new(bool extrude_perimeter,
|
||||
box_coordinates wt_box(Vec2f(0.f, 0.f), m_wipe_tower_width, wipe_tower_depth);
|
||||
wt_box = align_perimeter(wt_box);
|
||||
if (extrude_perimeter) {
|
||||
if (is_used_gap_wall)
|
||||
generate_support_wall(writer, wt_box, feedrate, first_layer);
|
||||
else
|
||||
writer.rectangle(wt_box, feedrate);
|
||||
}
|
||||
|
||||
@ -2443,10 +2524,33 @@ void WipeTower::toolchange_wipe_new(WipeTowerWriter &writer, const box_coordinat
|
||||
need_change_flow = true;
|
||||
}
|
||||
|
||||
float ironing_length = 3.;
|
||||
if (i == 0 && is_used_gap_wall) { // BBS: add ironing after extruding start
|
||||
if (m_left_to_right) {
|
||||
float dx = xr + wipe_tower_wall_infill_overlap_new * m_perimeter_width - writer.pos().x();
|
||||
if (abs(dx) < ironing_length) ironing_length = abs(dx);
|
||||
writer.extrude(writer.x() + ironing_length, writer.y(), wipe_speed);
|
||||
writer.retract(0.8, 1800.);
|
||||
writer.travel(writer.x() - 1.5 * ironing_length, writer.y(), 600.);
|
||||
writer.travel(writer.x() + 1.5 * ironing_length, writer.y(), 240.);
|
||||
writer.retract(-0.8, 1800.);
|
||||
writer.extrude(xr + wipe_tower_wall_infill_overlap_new * m_perimeter_width, writer.y(), wipe_speed);
|
||||
} else {
|
||||
float dx = xl - wipe_tower_wall_infill_overlap_new * m_perimeter_width - writer.pos().x();
|
||||
if (abs(dx) < ironing_length) ironing_length = abs(dx);
|
||||
writer.extrude(writer.x() - ironing_length, writer.y(), wipe_speed);
|
||||
writer.retract(0.8, 1800.);
|
||||
writer.travel(writer.x() + 1.5 * ironing_length, writer.y(), 600.);
|
||||
writer.travel(writer.x() - 1.5 * ironing_length, writer.y(), 240.);
|
||||
writer.retract(-0.8, 1800.);
|
||||
writer.extrude(xl - wipe_tower_wall_infill_overlap_new * m_perimeter_width, writer.y(), wipe_speed);
|
||||
}
|
||||
} else {
|
||||
if (m_left_to_right)
|
||||
writer.extrude(xr + wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), wipe_speed);
|
||||
else
|
||||
writer.extrude(xl - wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), wipe_speed);
|
||||
}
|
||||
|
||||
// BBS: recover the flow in non-bridging area
|
||||
if (need_change_flow) {
|
||||
@ -2789,7 +2893,6 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
{
|
||||
if (m_plan.empty())
|
||||
return;
|
||||
|
||||
m_extra_spacing = 1.f;
|
||||
|
||||
plan_tower_new();
|
||||
@ -2827,6 +2930,8 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
}
|
||||
}
|
||||
|
||||
get_wall_skip_points(layer);
|
||||
|
||||
ToolChangeResult finish_layer_tcr;
|
||||
ToolChangeResult timelapse_wall;
|
||||
|
||||
@ -2964,7 +3069,6 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
if (m_enable_timelapse_print) {
|
||||
layer_result.insert(layer_result.begin(), std::move(timelapse_wall));
|
||||
}
|
||||
|
||||
result.emplace_back(std::move(layer_result));
|
||||
}
|
||||
}
|
||||
@ -3110,6 +3214,9 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall(bool is_new_mode)
|
||||
wipe_tower_depth = m_wipe_tower_width;
|
||||
box_coordinates wt_box(Vec2f(0.f, (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f)), m_wipe_tower_width, wipe_tower_depth);
|
||||
wt_box = align_perimeter(wt_box);
|
||||
if (is_used_gap_wall)
|
||||
generate_support_wall(writer, wt_box, feedrate, first_layer);
|
||||
else
|
||||
writer.rectangle(wt_box, feedrate);
|
||||
|
||||
// Now prepare future wipe. box contains rectangle that was extruded last (ccw).
|
||||
@ -3126,6 +3233,109 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall(bool is_new_mode)
|
||||
return construct_tcr(writer, false, old_tool, true, 0.f);
|
||||
}
|
||||
|
||||
Polygon WipeTower::generate_support_wall(WipeTowerWriter &writer, const box_coordinates &wt_box, double feedrate, bool first_layer)
|
||||
{
|
||||
bool is_left = false;
|
||||
bool is_right = false;
|
||||
for (auto pt : m_wall_skip_points) {
|
||||
if (abs(pt.x()) < EPSILON) {
|
||||
is_left = true;
|
||||
} else if (abs(pt.x() - m_wipe_tower_width) < EPSILON) {
|
||||
is_right = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_left && is_right) {
|
||||
Vec2f *p = nullptr;
|
||||
p->x();
|
||||
}
|
||||
|
||||
if (!is_left && !is_right) {
|
||||
Vec2f *p = nullptr;
|
||||
p->x();
|
||||
}
|
||||
|
||||
// 3 ------------- 2
|
||||
// | |
|
||||
// | |
|
||||
// 0 ------------- 1
|
||||
|
||||
int index = 0;
|
||||
Vec2f cur_pos = writer.pos();
|
||||
if (abs(cur_pos.x() - wt_box.ld.x()) > abs(cur_pos.x() - wt_box.rd.x())) {
|
||||
if (abs(cur_pos.y() - wt_box.ld.y()) > abs(cur_pos.y() - wt_box.lu.y())) {
|
||||
index = 2;
|
||||
} else {
|
||||
index = 1;
|
||||
}
|
||||
} else {
|
||||
if (abs(cur_pos.y() - wt_box.ld.y()) > abs(cur_pos.y() - wt_box.lu.y())) {
|
||||
index = 3;
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Vec2f> points;
|
||||
points.emplace_back(wt_box.ld);
|
||||
points.emplace_back(wt_box.rd);
|
||||
points.emplace_back(wt_box.ru);
|
||||
points.emplace_back(wt_box.lu);
|
||||
|
||||
writer.travel(points[index]);
|
||||
int extruded_nums = 0;
|
||||
while (extruded_nums < 4) {
|
||||
index = (index + 1) % 4;
|
||||
if (index == 2) {
|
||||
if (is_right) {
|
||||
std::vector<Segment> break_segments = remove_points_from_segment(Segment(wt_box.rd, wt_box.ru), m_wall_skip_points, 2.5 * m_perimeter_width);
|
||||
for (auto iter = break_segments.begin(); iter != break_segments.end(); ++iter) {
|
||||
float dx = iter->start.x() - writer.pos().x();
|
||||
float dy = iter->start.y() - writer.pos().y();
|
||||
float len = std::sqrt(dx * dx + dy * dy);
|
||||
if (len > 0) {
|
||||
writer.retract(0.8, 1800.);
|
||||
writer.travel(iter->start, 600.);
|
||||
writer.retract(-0.8, 1800.);
|
||||
} else
|
||||
writer.travel(iter->start, 600.);
|
||||
|
||||
writer.extrude(iter->end, feedrate);
|
||||
}
|
||||
writer.travel(wt_box.ru, feedrate);
|
||||
} else {
|
||||
writer.extrude(wt_box.ru, feedrate);
|
||||
}
|
||||
} else if (index == 0) {
|
||||
if (is_left) {
|
||||
std::vector<Segment> break_segments = remove_points_from_segment(Segment(wt_box.ld, wt_box.lu), m_wall_skip_points, 2.5 * m_perimeter_width);
|
||||
for (auto iter = break_segments.rbegin(); iter != break_segments.rend(); ++iter) {
|
||||
float dx = iter->end.x() - writer.pos().x();
|
||||
float dy = iter->end.y() - writer.pos().y();
|
||||
float len = std::sqrt(dx * dx + dy * dy);
|
||||
if (len > 0) {
|
||||
writer.retract(0.8, 1800.);
|
||||
writer.travel(iter->end, 600.);
|
||||
writer.retract(-0.8, 1800.);
|
||||
} else
|
||||
writer.travel(iter->end, 600.);
|
||||
|
||||
writer.extrude(iter->start, feedrate);
|
||||
}
|
||||
writer.travel(wt_box.ld, feedrate);
|
||||
} else {
|
||||
writer.extrude(wt_box.ld, feedrate);
|
||||
}
|
||||
} else {
|
||||
writer.extrude(points[index], feedrate);
|
||||
}
|
||||
extruded_nums++;
|
||||
}
|
||||
|
||||
return Polygon();
|
||||
}
|
||||
|
||||
|
||||
bool WipeTower::get_floating_area(float &start_pos_y, float &end_pos_y) const {
|
||||
if (m_layer_info == m_plan.begin() || (m_layer_info - 1) == m_plan.begin())
|
||||
return false;
|
||||
|
@ -174,6 +174,7 @@ public:
|
||||
void generate(std::vector<std::vector<ToolChangeResult>> &result);
|
||||
|
||||
WipeTower::ToolChangeResult only_generate_out_wall(bool is_new_mode = false);
|
||||
Polygon generate_support_wall(WipeTowerWriter &writer, const box_coordinates &wt_box, double feedrate, bool first_layer);
|
||||
|
||||
float get_depth() const { return m_wipe_tower_depth; }
|
||||
float get_brim_width() const { return m_wipe_tower_brim_width_real; }
|
||||
@ -436,6 +437,7 @@ private:
|
||||
float m_extra_spacing = 1.f;
|
||||
float m_tpu_fixed_spacing = 2;
|
||||
|
||||
std::vector<Vec2f> m_wall_skip_points;
|
||||
bool is_first_layer() const { return size_t(m_layer_info - m_plan.begin()) == m_first_layer_idx; }
|
||||
|
||||
// Calculates length of extrusion line to extrude given volume
|
||||
@ -520,6 +522,7 @@ private:
|
||||
WipeTowerWriter &writer,
|
||||
const box_coordinates &cleaning_box,
|
||||
float wipe_volume);
|
||||
void get_wall_skip_points(const WipeTowerInfo &layer);
|
||||
};
|
||||
|
||||
|
||||
|
@ -903,7 +903,7 @@ public:
|
||||
void set_calib_params(const Calib_Params ¶ms);
|
||||
const Calib_Params& calib_params() const { return m_calib_params; }
|
||||
Vec2d translate_to_print_space(const Vec2d& point) const;
|
||||
|
||||
float get_wipe_tower_depth() const { return m_wipe_tower_data.depth; }
|
||||
|
||||
// scaled point
|
||||
Vec2d translate_to_print_space(const Point& point) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user