ENH: wipe_tower infill alignment

jira: none
Change-Id: I76144e423cf0d2f96263eb2be7431ba0f755b637
This commit is contained in:
jiangkai.zhao 2025-03-28 11:42:38 +08:00 committed by lane.wei
parent 6e09e68046
commit 82664c05ba
3 changed files with 173 additions and 73 deletions

View File

@ -1766,7 +1766,7 @@ Vec2f WipeTower::get_next_pos(const WipeTower::box_coordinates &cleaning_box, fl
const float &xr = cleaning_box.rd.x(); const float &xr = cleaning_box.rd.x();
int line_count = wipe_length / (xr - xl); int line_count = wipe_length / (xr - xl);
float dy = m_layer_info->extra_spacing * m_perimeter_width; float dy = m_layer_info->extra_spacing * get_block_gap_width(m_current_tool,false);
float y_offset = float(line_count) * dy; float y_offset = float(line_count) * dy;
const Vec2f pos_offset = Vec2f(0.f, m_depth_traversed); const Vec2f pos_offset = Vec2f(0.f, m_depth_traversed);
@ -2606,6 +2606,33 @@ WipeTower::ToolChangeResult WipeTower::finish_layer(bool extrude_perimeter, bool
return construct_tcr(writer, false, old_tool, true, false, 0.f); return construct_tcr(writer, false, old_tool, true, false, 0.f);
} }
WipeTower::WipeTowerInfo::ToolChange WipeTower::set_toolchange(int old_tool, int new_tool, float layer_height, float wipe_volume, float purge_volume)
{
float depth = 0.f;
float width = m_wipe_tower_width - 2 * m_perimeter_width;
float nozzle_change_width = m_wipe_tower_width - (m_nozzle_change_perimeter_width + m_perimeter_width);
float length_to_extrude = volume_to_length(wipe_volume, m_perimeter_width, layer_height);
float toolchange_gap_width = get_block_gap_width(new_tool,false);
float nozzlechange_gap_width = get_block_gap_width(old_tool,true);
depth += std::ceil(length_to_extrude / width) * toolchange_gap_width;
// depth *= m_extra_spacing;
float nozzle_change_depth = 0;
float nozzle_change_length = 0;
if (!m_filament_map.empty() && m_filament_map[old_tool] != m_filament_map[new_tool]) {
double e_flow = nozzle_change_extrusion_flow(layer_height);
double length = m_filaments_change_length[old_tool] / e_flow;
int nozzle_change_line_count = std::ceil(length / nozzle_change_width);
nozzle_change_depth = nozzle_change_line_count * nozzlechange_gap_width;
depth += nozzle_change_depth;
nozzle_change_length = length;
}
WipeTowerInfo::ToolChange tool_change = WipeTowerInfo::ToolChange(old_tool, new_tool, depth, 0.f, 0.f, wipe_volume, length_to_extrude, purge_volume);
tool_change.nozzle_change_depth = nozzle_change_depth;
tool_change.nozzle_change_length = nozzle_change_length;
return tool_change;
}
// Appends a toolchange into m_plan and calculates neccessary depth of the corresponding box // Appends a toolchange into m_plan and calculates neccessary depth of the corresponding box
void WipeTower::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, void WipeTower::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool,
unsigned int new_tool, float wipe_volume, float purge_volume) unsigned int new_tool, float wipe_volume, float purge_volume)
@ -2652,18 +2679,18 @@ void WipeTower::plan_toolchange(float z_par, float layer_height_par, unsigned in
//depth *= m_extra_spacing; //depth *= m_extra_spacing;
float nozzle_change_depth = 0; float nozzle_change_depth = 0;
float nozzle_change_length = 0;
if (!m_filament_map.empty() && m_filament_map[old_tool] != m_filament_map[new_tool]) { if (!m_filament_map.empty() && m_filament_map[old_tool] != m_filament_map[new_tool]) {
double e_flow = nozzle_change_extrusion_flow(layer_height_par); double e_flow = nozzle_change_extrusion_flow(layer_height_par);
double length = m_filaments_change_length[old_tool] / e_flow; double length = m_filaments_change_length[old_tool] / e_flow;
int nozzle_change_line_count = std::ceil(length / (m_wipe_tower_width - 2*m_nozzle_change_perimeter_width)); int nozzle_change_line_count = std::ceil(length / (m_wipe_tower_width - 2*m_nozzle_change_perimeter_width));
if (m_need_reverse_travel) nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width;
nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_nozzle_change_perimeter_width;
else
nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width;
depth += nozzle_change_depth; depth += nozzle_change_depth;
nozzle_change_length = length;
} }
WipeTowerInfo::ToolChange tool_change = WipeTowerInfo::ToolChange(old_tool, new_tool, depth, 0.f, 0.f, wipe_volume, length_to_extrude, purge_volume); WipeTowerInfo::ToolChange tool_change = WipeTowerInfo::ToolChange(old_tool, new_tool, depth, 0.f, 0.f, wipe_volume, length_to_extrude, purge_volume);
tool_change.nozzle_change_depth = nozzle_change_depth; tool_change.nozzle_change_depth = nozzle_change_depth;
tool_change.nozzle_change_length = nozzle_change_length;
m_plan.back().tool_changes.push_back(tool_change); m_plan.back().tool_changes.push_back(tool_change);
#endif #endif
} }
@ -2794,7 +2821,7 @@ bool WipeTower::is_tpu_filament(int filament_id) const
bool WipeTower::is_need_reverse_travel(int filament_id) const bool WipeTower::is_need_reverse_travel(int filament_id) const
{ {
return m_filpar[filament_id].ramming_travel_time > EPSILON; return m_filpar[filament_id].ramming_travel_time > EPSILON && m_filaments_change_length[filament_id]>EPSILON;
} }
// BBS: consider both soluable and support properties // BBS: consider both soluable and support properties
@ -2864,16 +2891,12 @@ void WipeTower::get_wall_skip_points(const WipeTowerInfo &layer)
const WipeTowerInfo::ToolChange &tool_change = layer.tool_changes[i]; const WipeTowerInfo::ToolChange &tool_change = layer.tool_changes[i];
size_t old_filament = tool_change.old_tool; size_t old_filament = tool_change.old_tool;
size_t new_filament = tool_change.new_tool; size_t new_filament = tool_change.new_tool;
float spacing = m_layer_info->extra_spacing; float nozzle_change_depth = tool_change.nozzle_change_depth;
if (m_need_reverse_travel && m_layer_info->extra_spacing < m_tpu_fixed_spacing) spacing = 1; float wipe_depth = tool_change.required_depth - nozzle_change_depth;
else if (m_need_reverse_travel) spacing = spacing / m_tpu_fixed_spacing; if (!is_valid_last_layer(old_filament)) nozzle_change_depth = 0.f;
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, false); auto* block = get_block_by_category(m_filpar[new_filament].category, false);
if (!block) if (!block)
continue; continue;
//float wipe_depth = tool_change.required_depth - nozzle_change_depth;
float wipe_depth = ceil(tool_change.wipe_length / (m_wipe_tower_width - 2 * m_perimeter_width)) * m_perimeter_width*layer.extra_spacing;
float process_depth = 0.f; float process_depth = 0.f;
if (!cur_block_depth.count(m_filpar[new_filament].category)) if (!cur_block_depth.count(m_filpar[new_filament].category))
cur_block_depth[m_filpar[new_filament].category] = block->start_depth; cur_block_depth[m_filpar[new_filament].category] = block->start_depth;
@ -2891,20 +2914,21 @@ void WipeTower::get_wall_skip_points(const WipeTowerInfo &layer)
cur_block_depth[m_filpar[old_filament].category] += nozzle_change_depth; cur_block_depth[m_filpar[old_filament].category] += nozzle_change_depth;
} }
} }
{ {
float infill_gap_width = get_block_gap_width(new_filament,false);
Vec2f res; Vec2f res;
int index = m_cur_layer_id % 4; int index = m_cur_layer_id % 4;
switch (index % 4) { switch (index % 4) {
case 0: res = Vec2f(0, process_depth); break; 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 1: res = Vec2f(m_wipe_tower_width, process_depth + wipe_depth - m_layer_info->extra_spacing * infill_gap_width); break;
case 2: res = Vec2f(m_wipe_tower_width, process_depth); 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; case 3: res = Vec2f(0, process_depth + wipe_depth - m_layer_info->extra_spacing * infill_gap_width); break;
default: break; default: break;
} }
m_wall_skip_points.emplace_back(res); m_wall_skip_points.emplace_back(res);
} }
cur_block_depth[m_filpar[new_filament].category] = process_depth + tool_change.required_depth - tool_change.nozzle_change_depth * layer.extra_spacing; cur_block_depth[m_filpar[new_filament].category] = process_depth + wipe_depth;
} }
} }
@ -2931,21 +2955,17 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool, bool sol
wipe_depth = b.required_depth; wipe_depth = b.required_depth;
purge_volume = b.purge_volume; purge_volume = b.purge_volume;
nozzle_change_depth = b.nozzle_change_depth; nozzle_change_depth = b.nozzle_change_depth;
if (m_need_reverse_travel)
nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width) / 2;
else
nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width;
break; break;
} }
} }
m_current_tool = new_tool;
WipeTowerBlock* block = get_block_by_category(m_filpar[new_tool].category, false); WipeTowerBlock* block = get_block_by_category(m_filpar[new_tool].category, false);
if (!block) { if (!block) {
assert(block != nullptr); assert(block != nullptr);
return WipeTower::ToolChangeResult(); return WipeTower::ToolChangeResult();
} }
m_cur_block = block; m_cur_block = block;
box_coordinates cleaning_box(Vec2f(m_perimeter_width, block->cur_depth), m_wipe_tower_width - 2 * m_perimeter_width, wipe_depth-m_layer_info->extra_spacing*nozzle_change_depth); box_coordinates cleaning_box(Vec2f(m_perimeter_width, block->cur_depth), m_wipe_tower_width - 2 * m_perimeter_width, wipe_depth-nozzle_change_depth);
WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar); WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
writer.set_extrusion_flow(m_extrusion_flow) writer.set_extrusion_flow(m_extrusion_flow)
@ -3015,7 +3035,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool, bool sol
} else } else
toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, m_filpar[m_current_tool].nozzle_temperature); toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, m_filpar[m_current_tool].nozzle_temperature);
block->cur_depth += (wipe_depth - nozzle_change_depth * m_layer_info->extra_spacing); block->cur_depth += (wipe_depth - nozzle_change_depth);
block->last_filament_change_id = new_tool; block->last_filament_change_id = new_tool;
// BBS // BBS
@ -3037,13 +3057,14 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool, bool sol
WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id, int new_filament_id, bool solid_infill) WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id, int new_filament_id, bool solid_infill)
{ {
int nozzle_change_line_count = 0; int nozzle_change_line_count = 0;
float x_offset = m_perimeter_width + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2;
float nozzle_change_box_width = m_wipe_tower_width - 2 * x_offset;
float nozzle_change_depth = 0.f;
if (new_filament_id != (unsigned int) (-1)) { if (new_filament_id != (unsigned int) (-1)) {
for (const auto &b : m_layer_info->tool_changes) for (const auto &b : m_layer_info->tool_changes)
if (b.new_tool == new_filament_id) { if (b.new_tool == new_filament_id) {
if (m_need_reverse_travel) nozzle_change_line_count = std::ceil(b.nozzle_change_length / nozzle_change_box_width);
nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width) / 2; nozzle_change_depth = b.nozzle_change_depth;
else
nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width;
break; break;
} }
} }
@ -3076,14 +3097,10 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
return WipeTower::NozzleChangeResult(); return WipeTower::NozzleChangeResult();
} }
m_cur_block = block; m_cur_block = block;
float dy = m_layer_info->extra_spacing * m_nozzle_change_perimeter_width; float dy = is_first_layer() ? m_nozzle_change_perimeter_width : m_layer_info->extra_spacing * get_block_gap_width(m_current_tool,true);
if (m_need_reverse_travel && m_extra_spacing < m_tpu_fixed_spacing)
dy = m_tpu_fixed_spacing * m_nozzle_change_perimeter_width;
float x_offset = m_perimeter_width + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2;
box_coordinates cleaning_box(Vec2f(x_offset,block->cur_depth + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2), box_coordinates cleaning_box(Vec2f(x_offset,block->cur_depth + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2),
m_wipe_tower_width - 2 * x_offset, nozzle_change_box_width,
nozzle_change_line_count * dy - (m_nozzle_change_perimeter_width - m_perimeter_width) / 2);//top can not print nozzle_change_depth); // top can not print
Vec2f initial_position = cleaning_box.ld; Vec2f initial_position = cleaning_box.ld;
writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
@ -3131,7 +3148,7 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
} }
writer.set_extrusion_flow(nz_extrusion_flow); // Reset the extrusion flow. writer.set_extrusion_flow(nz_extrusion_flow); // Reset the extrusion flow.
block->cur_depth += nozzle_change_line_count * dy; block->cur_depth += nozzle_change_depth;
block->last_nozzle_change_id = old_filament_id; block->last_nozzle_change_id = old_filament_id;
NozzleChangeResult result; NozzleChangeResult result;
@ -3164,7 +3181,7 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
} }
} else { } else {
result.wipe_path.push_back(writer.pos_rotated()); result.wipe_path.push_back(writer.pos_rotated());
if (m_left_to_right) { if (m_left_to_right) {
result.wipe_path.push_back(Vec2f(0, writer.pos_rotated().y())); result.wipe_path.push_back(Vec2f(0, writer.pos_rotated().y()));
} else { } else {
result.wipe_path.push_back(Vec2f(m_wipe_tower_width, writer.pos_rotated().y())); result.wipe_path.push_back(Vec2f(m_wipe_tower_width, writer.pos_rotated().y()));
@ -3558,7 +3575,9 @@ void WipeTower::toolchange_wipe_new(WipeTowerWriter &writer, const box_coordinat
const float &xr = cleaning_box.rd.x(); const float &xr = cleaning_box.rd.x();
float x_to_wipe = wipe_length; float x_to_wipe = wipe_length;
float dy = solid_tool_toolchange ? m_perimeter_width :m_layer_info->extra_spacing * m_perimeter_width; float dy = is_first_layer() ? m_perimeter_width : m_layer_info->extra_spacing * get_block_gap_width(m_current_tool,false);
if (solid_tool_toolchange)
dy = m_perimeter_width;
x_to_wipe = solid_tool_toolchange ? std::numeric_limits<float>::max(): x_to_wipe; x_to_wipe = solid_tool_toolchange ? std::numeric_limits<float>::max(): x_to_wipe;
float target_speed = is_first_layer() ? std::min(m_first_layer_speed * 60.f, m_max_speed) : m_max_speed; float target_speed = is_first_layer() ? std::min(m_first_layer_speed * 60.f, m_max_speed) : m_max_speed;
target_speed = solid_tool_toolchange ? 20.f * 60.f : target_speed; target_speed = solid_tool_toolchange ? 20.f * 60.f : target_speed;
@ -3864,35 +3883,100 @@ void WipeTower::generate_wipe_tower_blocks()
} }
} }
} }
void WipeTower::calc_block_infill_gap()
{
//1.calc block infill gap width
struct BlockInfo
{
bool has_ramming = false;
bool has_reverse_travel = false;
float depth = 0.f;
};
std::unordered_map<int, BlockInfo> block_info;
std::unordered_map<int, BlockInfo> high_block_info;
for (int i= (int)m_plan.size()-1;i>=0;i--)
{
for (auto &toolchange : m_plan[i].tool_changes) {
int new_tool =toolchange.new_tool;
int old_tool =toolchange.old_tool;
if (!m_filament_map.empty() && m_filament_map[old_tool] != m_filament_map[new_tool]) {
block_info[m_filpar[old_tool].category].has_ramming=true;
if (is_need_reverse_travel(old_tool)) block_info[m_filpar[old_tool].category].has_reverse_travel = true;
block_info[m_filpar[old_tool].category].depth += toolchange.nozzle_change_depth;
}
if (!block_info.count(m_filpar[new_tool].category)) block_info.insert({m_filpar[new_tool].category,BlockInfo{}});
block_info[m_filpar[new_tool].category].depth += toolchange.required_depth - toolchange.nozzle_change_depth;
}
for (auto &block : block_info) {
if (high_block_info.count(block.first) && high_block_info[block.first].depth > block.second.depth)
block.second.depth = high_block_info[block.first].depth;
}
high_block_info = block_info;
for (auto &block : block_info) { block.second.depth = 0.f;}
if (i == 0) block_info = high_block_info;
}
float max_depth = std::accumulate(block_info.begin(), block_info.end(), 0.f, [](float value, const std::pair<int,BlockInfo> &block) { return value + block.second.depth; });
float height_to_depth = get_limit_depth_by_height(m_wipe_tower_height);
float height_to_spacing = max_depth > height_to_depth ? 1.f : height_to_depth / max_depth;
float spacing_ratio = m_extra_spacing - 1.f;
float extra_width = spacing_ratio * m_perimeter_width;
float line_gap_tol = 2.f * m_nozzle_change_perimeter_width; //If the block's line_gap is greater than it, the block should be aligned.
for (auto &info : block_info) {
//case1: no ramming, it can always align
if (!info.second.has_ramming) {
m_block_infill_gap_width[info.first].first = m_block_infill_gap_width[info.first].second = extra_width + m_perimeter_width;
}
// case2: has ramming, but no reverse travel
//
else if (!info.second.has_reverse_travel) {
float line_gap = m_nozzle_change_perimeter_width + extra_width;
if (!m_use_rib_wall) line_gap *= height_to_spacing;
if (line_gap < line_gap_tol) {
m_block_infill_gap_width[info.first].first = m_perimeter_width + extra_width;
m_block_infill_gap_width[info.first].second = m_nozzle_change_perimeter_width + extra_width;
} else {
m_block_infill_gap_width[info.first].first = m_block_infill_gap_width[info.first].second = m_nozzle_change_perimeter_width + extra_width;
}
}
// case 3: has ramming and reverse travel
else {
float extra_tpu_fix_spacing = m_tpu_fixed_spacing - 1.f;
float line_gap = m_nozzle_change_perimeter_width + std::max(extra_tpu_fix_spacing * m_perimeter_width, extra_width);
if (!m_use_rib_wall) line_gap = height_to_spacing * line_gap;
if (line_gap < line_gap_tol) {
m_block_infill_gap_width[info.first].first = m_perimeter_width + extra_width;
m_block_infill_gap_width[info.first].second = m_nozzle_change_perimeter_width + std::max(extra_tpu_fix_spacing * m_perimeter_width, extra_width);
} else {
m_block_infill_gap_width[info.first].first = m_block_infill_gap_width[info.first].second = m_nozzle_change_perimeter_width +
std::max(extra_tpu_fix_spacing * m_perimeter_width, extra_width);
}
}
}
//2. recalculate toolchange depth
for (int idx = 0; idx < m_plan.size(); idx++) {
for (auto &toolchange : m_plan[idx].tool_changes) {
toolchange = set_toolchange(toolchange.old_tool, toolchange.new_tool, m_plan[idx].height, toolchange.wipe_volume, toolchange.purge_volume);
}
}
m_extra_spacing = 1.f;
}
void WipeTower::plan_tower_new() void WipeTower::plan_tower_new()
{ {
if (m_wipe_tower_brim_width < 0) m_wipe_tower_brim_width = get_auto_brim_by_height(m_wipe_tower_height); if (m_wipe_tower_brim_width < 0) m_wipe_tower_brim_width = get_auto_brim_by_height(m_wipe_tower_height);
calc_block_infill_gap();
if (m_use_rib_wall) { if (m_use_rib_wall) {
// recalculate wipe_tower_with and layer's depth // recalculate wipe_tower_with and layer's depth
generate_wipe_tower_blocks(); generate_wipe_tower_blocks();
float max_depth = std::accumulate(m_wipe_tower_blocks.begin(), m_wipe_tower_blocks.end(), 0.f, [](float a, const auto &t) { return a + t.depth; }) + m_perimeter_width; float max_depth = std::accumulate(m_wipe_tower_blocks.begin(), m_wipe_tower_blocks.end(), 0.f, [](float a, const auto &t) { return a + t.depth; }) + m_perimeter_width;
float square_width = align_ceil(std::sqrt(max_depth * m_wipe_tower_width * m_extra_spacing), m_perimeter_width); float square_width = align_ceil(std::sqrt(max_depth * m_wipe_tower_width * m_extra_spacing), m_perimeter_width);
//std::cout << " before m_wipe_tower_width = " << m_wipe_tower_width << " max_depth = " << max_depth << std::endl;
m_wipe_tower_width = square_width; m_wipe_tower_width = square_width;
float width = m_wipe_tower_width - 2 * m_perimeter_width;
for (int idx = 0; idx < m_plan.size(); idx++) { for (int idx = 0; idx < m_plan.size(); idx++) {
for (auto &toolchange : m_plan[idx].tool_changes) { for (auto &toolchange : m_plan[idx].tool_changes) {
float length_to_extrude = toolchange.wipe_length; toolchange = set_toolchange(toolchange.old_tool, toolchange.new_tool, m_plan[idx].height, toolchange.wipe_volume, toolchange.purge_volume);
float depth = std::ceil(length_to_extrude / width) * m_perimeter_width;
float nozzle_change_depth = 0;
if (!m_filament_map.empty() && m_filament_map[toolchange.old_tool] != m_filament_map[toolchange.new_tool]) {
double e_flow = nozzle_change_extrusion_flow(m_plan[idx].height);
double length = m_filaments_change_length[toolchange.old_tool] / e_flow;
int nozzle_change_line_count = std::ceil(length / (m_wipe_tower_width - 2*m_nozzle_change_perimeter_width));
if (m_need_reverse_travel)
nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_nozzle_change_perimeter_width;
else
nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width;
depth += nozzle_change_depth;
}
toolchange.nozzle_change_depth = nozzle_change_depth;
toolchange.required_depth = depth;
} }
} }
} }
@ -3924,28 +4008,29 @@ void WipeTower::plan_tower_new()
for (int idx = 0; idx < m_plan.size(); idx++) { for (int idx = 0; idx < m_plan.size(); idx++) {
auto &info = m_plan[idx]; auto &info = m_plan[idx];
if (idx == 0 && m_extra_spacing > 1.f + EPSILON) { if (idx == 0 /*&& m_extra_spacing > 1.f + EPSILON*/) {
// apply solid fill for the first layer // apply solid fill for the first layer
info.extra_spacing = 1.f; info.extra_spacing = 1.f;
for (auto &toolchange : info.tool_changes) { for (auto &toolchange : info.tool_changes) {
float x_to_wipe = volume_to_length(toolchange.wipe_volume, m_perimeter_width, info.height); //float x_to_wipe = volume_to_length(toolchange.wipe_volume, m_perimeter_width, info.height);
float line_len = m_wipe_tower_width - 2 * m_perimeter_width; float line_len = m_wipe_tower_width - 2 * m_perimeter_width;
float x_to_wipe_new = x_to_wipe * m_extra_spacing; float wipe_depth = (toolchange.required_depth - toolchange.nozzle_change_depth) * m_extra_spacing;
x_to_wipe_new = std::floor(x_to_wipe_new / line_len) * line_len; float wipe_line_count = wipe_depth / m_perimeter_width;
x_to_wipe_new = std::max(x_to_wipe_new, x_to_wipe); float nozzle_change_depth = toolchange.nozzle_change_depth * m_extra_spacing;
int line_count = std::ceil((x_to_wipe_new - WT_EPSILON) / line_len); int nozzle_change_line_count = (toolchange.nozzle_change_depth * m_extra_spacing + WT_EPSILON) / m_nozzle_change_perimeter_width;
// nozzle change length
int nozzle_change_line_count = (toolchange.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width;
toolchange.required_depth = line_count * m_perimeter_width + nozzle_change_line_count * m_nozzle_change_perimeter_width; toolchange.required_depth = wipe_depth + nozzle_change_depth;
toolchange.wipe_volume = x_to_wipe_new / x_to_wipe * toolchange.wipe_volume; toolchange.wipe_length = wipe_line_count * line_len;
toolchange.wipe_length = x_to_wipe_new; toolchange.wipe_volume = length_to_volume(toolchange.wipe_length, m_perimeter_width, info.height);
toolchange.nozzle_change_length = nozzle_change_line_count * (m_wipe_tower_width - (m_nozzle_change_perimeter_width + m_perimeter_width));
toolchange.nozzle_change_depth = nozzle_change_depth;
} }
} else { } else {
info.extra_spacing = m_extra_spacing; info.extra_spacing = m_extra_spacing;
for (auto &toolchange : info.tool_changes) { for (auto &toolchange : info.tool_changes) {
toolchange.required_depth *= m_extra_spacing; toolchange.required_depth *= m_extra_spacing;
toolchange.nozzle_change_depth *= m_extra_spacing;
toolchange.wipe_length = volume_to_length(toolchange.wipe_volume, m_perimeter_width, info.height); toolchange.wipe_length = volume_to_length(toolchange.wipe_volume, m_perimeter_width, info.height);
} }
} }
@ -4628,5 +4713,14 @@ bool WipeTower::is_valid_last_layer(int tool) const
if (m_last_layer_id[nozzle_id] == m_cur_layer_id && m_z_pos > m_printable_height[nozzle_id]) return false; if (m_last_layer_id[nozzle_id] == m_cur_layer_id && m_z_pos > m_printable_height[nozzle_id]) return false;
return true; return true;
} }
float WipeTower::get_block_gap_width(int tool,bool is_nozzlechangle)
{
assert(m_block_infill_gap_width.count(m_filpar[tool].category));
if (!m_block_infill_gap_width.count(m_filpar[tool].category)) {
return m_perimeter_width;
}
return is_nozzlechangle ? m_block_infill_gap_width[m_filpar[tool].category].second : m_block_infill_gap_width[m_filpar[tool].category].first;
}
} // namespace Slic3r } // namespace Slic3r

View File

@ -184,6 +184,7 @@ public:
// to be used before building begins. The entries must be added ordered in z. // to be used before building begins. The entries must be added ordered in z.
void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, float wipe_volume = 0.f, float prime_volume = 0.f); void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, float wipe_volume = 0.f, float prime_volume = 0.f);
// Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result" // Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result"
void generate(std::vector<std::vector<ToolChangeResult>> &result); void generate(std::vector<std::vector<ToolChangeResult>> &result);
@ -307,14 +308,13 @@ public:
void set_need_reverse_travel(const std::vector<unsigned int> & used_extruders) void set_need_reverse_travel(const std::vector<unsigned int> & used_extruders)
{ {
for (unsigned int filament_id : used_extruders) { for (unsigned int filament_id : used_extruders) {
if (m_filpar[filament_id].ramming_travel_time > EPSILON) { if (m_filpar[filament_id].ramming_travel_time > EPSILON && m_filaments_change_length[filament_id]>EPSILON) {
m_need_reverse_travel = true; m_need_reverse_travel = true;
return; return;
} }
} }
} }
bool has_tpu_filament() const { return m_has_tpu_filament; } bool has_tpu_filament() const { return m_has_tpu_filament; }
struct FilamentParameters { struct FilamentParameters {
std::string material = "PLA"; std::string material = "PLA";
int category; int category;
@ -393,7 +393,7 @@ public:
void generate_wipe_tower_blocks(); void generate_wipe_tower_blocks();
void update_all_layer_depth(float wipe_tower_depth); void update_all_layer_depth(float wipe_tower_depth);
void set_nozzle_last_layer_id(); void set_nozzle_last_layer_id();
void calc_block_infill_gap();
ToolChangeResult tool_change_new(size_t new_tool, bool solid_change = false, bool solid_nozzlechange=false); ToolChangeResult tool_change_new(size_t new_tool, bool solid_change = false, bool solid_nozzlechange=false);
NozzleChangeResult nozzle_change_new(int old_filament_id, int new_filament_id, bool solid_change = false); NozzleChangeResult nozzle_change_new(int old_filament_id, int new_filament_id, bool solid_change = false);
ToolChangeResult finish_layer_new(bool extrude_perimeter = true, bool extrude_fill = true, bool extrude_fill_wall = true); ToolChangeResult finish_layer_new(bool extrude_perimeter = true, bool extrude_fill = true, bool extrude_fill_wall = true);
@ -484,7 +484,7 @@ private:
float m_perimeter_width = 0.4f * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. float m_perimeter_width = 0.4f * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill.
float m_nozzle_change_perimeter_width = 0.4f * Width_To_Nozzle_Ratio; float m_nozzle_change_perimeter_width = 0.4f * Width_To_Nozzle_Ratio;
float m_extrusion_flow = 0.038f; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. float m_extrusion_flow = 0.038f; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter.
std::unordered_map<int, std::pair<float,float>> m_block_infill_gap_width; // categories to infill_gap: toolchange gap, nozzlechange gap
// Extruder specific parameters. // Extruder specific parameters.
std::vector<FilamentParameters> m_filpar; std::vector<FilamentParameters> m_filpar;
@ -516,7 +516,11 @@ private:
float volume_to_length(float volume, float line_width, float layer_height) const { float volume_to_length(float volume, float line_width, float layer_height) const {
return std::max(0.f, volume / (layer_height * (line_width - layer_height * (1.f - float(M_PI) / 4.f)))); return std::max(0.f, volume / (layer_height * (line_width - layer_height * (1.f - float(M_PI) / 4.f))));
} }
// Calculates volume of extrusion line
float length_to_volume(float length,float line_width, float layer_height) const
{
return std::max(0.f, length * (layer_height * (line_width - layer_height * (1.f - float(M_PI) / 4.f))));
}
// Calculates depth for all layers and propagates them downwards // Calculates depth for all layers and propagates them downwards
void plan_tower(); void plan_tower();
@ -546,6 +550,7 @@ private:
float wipe_volume; float wipe_volume;
float wipe_length; float wipe_length;
float nozzle_change_depth{0}; float nozzle_change_depth{0};
float nozzle_change_length{0};
// BBS // BBS
float purge_volume; float purge_volume;
ToolChange(size_t old, size_t newtool, float depth=0.f, float ramming_depth=0.f, float fwl=0.f, float wv=0.f, float wl = 0, float pv = 0) ToolChange(size_t old, size_t newtool, float depth=0.f, float ramming_depth=0.f, float fwl=0.f, float wv=0.f, float wl = 0, float pv = 0)
@ -575,7 +580,7 @@ private:
// ot -1 if there is no such toolchange. // ot -1 if there is no such toolchange.
int first_toolchange_to_nonsoluble_nonsupport( int first_toolchange_to_nonsoluble_nonsupport(
const std::vector<WipeTowerInfo::ToolChange>& tool_changes) const; const std::vector<WipeTowerInfo::ToolChange>& tool_changes) const;
WipeTowerInfo::ToolChange set_toolchange(int old_tool, int new_tool, float layer_height, float wipe_volume, float purge_volume);
void toolchange_Unload( void toolchange_Unload(
WipeTowerWriter &writer, WipeTowerWriter &writer,
const box_coordinates &cleaning_box, const box_coordinates &cleaning_box,
@ -597,6 +602,7 @@ private:
float wipe_volume); float wipe_volume);
void get_wall_skip_points(const WipeTowerInfo &layer); void get_wall_skip_points(const WipeTowerInfo &layer);
ToolChangeResult merge_tcr(ToolChangeResult &first, ToolChangeResult &second); ToolChangeResult merge_tcr(ToolChangeResult &first, ToolChangeResult &second);
float get_block_gap_width(int tool, bool is_nozzlechangle = false);
}; };

View File

@ -36,7 +36,7 @@ class SupportLayer;
// BBS // BBS
class TreeSupportData; class TreeSupportData;
class TreeSupport; class TreeSupport;
struct ExtrusionLayers; class ExtrusionLayers;
#define MARGIN_HEIGHT 1.5 #define MARGIN_HEIGHT 1.5
#define MAX_OUTER_NOZZLE_RADIUS 4 #define MAX_OUTER_NOZZLE_RADIUS 4