EMH: enhance for rib wall wiper tower

1. fix the slice error status
2. add rendering for wiper tower
3. modify the wipe tower start pos for rib wall wipe tower
jira: none

Change-Id: If554ca0fb30f6c7ce9641014c0ed4a7f23afd6f4
(cherry picked from commit 3ae08b458dea1d04cad33b2787d98407111b038c)
This commit is contained in:
zhimin.zeng 2025-01-19 10:34:51 +08:00 committed by lane.wei
parent 1f4d2cf714
commit 55772c5912
9 changed files with 139 additions and 45 deletions

View File

@ -590,7 +590,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
auto transform_wt_pt = [&alpha, this](const Vec2f& pt) -> Vec2f {
Vec2f out = Eigen::Rotation2Df(alpha) * pt;
out += m_wipe_tower_pos;
out += m_wipe_tower_pos + m_rib_offset;
return out;
};
@ -605,7 +605,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
tool_change_start_pos = transform_wt_pt(tool_change_start_pos);
}
Vec2f wipe_tower_offset = tcr.priming ? Vec2f::Zero() : m_wipe_tower_pos;
Vec2f wipe_tower_offset = (tcr.priming ? Vec2f::Zero() : m_wipe_tower_pos) + m_rib_offset;
float wipe_tower_rotation = tcr.priming ? 0.f : alpha;
std::string tcr_rotated_gcode = post_process_wipe_tower_moves(tcr, wipe_tower_offset, wipe_tower_rotation);
@ -2514,6 +2514,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
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());
m_wipe_tower->set_wipe_tower_bbx(print.get_wipe_tower_bbx());
m_wipe_tower->set_rib_offset(print.get_rib_offset());
// 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"));

View File

@ -108,6 +108,7 @@ public:
bool enable_timelapse_print() const { return m_enable_timelapse_print; }
void set_wipe_tower_depth(float depth) { m_wipe_tower_depth = depth; }
void set_wipe_tower_bbx(const BoundingBoxf & bbx) { m_wipe_tower_bbx = bbx; }
void set_rib_offset(const Vec2f &rib_offset) { m_rib_offset = rib_offset; }
private:
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
@ -141,7 +142,7 @@ private:
const PrintConfig * m_print_config;
float m_wipe_tower_depth;
BoundingBoxf m_wipe_tower_bbx;
Vec2f m_rib_offset{Vec2f(0, 0)};
};
class ColorPrintColors

View File

@ -719,6 +719,7 @@ public:
width += m_layer_height * float(1. - M_PI / 4.);
if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos) m_extrusions.emplace_back(WipeTower::Extrusion(rotated_current_pos, 0, m_current_tool));
{
float sample_angle = 5.f / 180.f * PI;
int n = std::ceil(abs(arc.angle_radians) / sample_angle);
for (int j = 0; j < n; j++) {
@ -887,6 +888,7 @@ public:
segments.back().arcsegment = pl.fitting_result[i].arc_data;
}
}
int index_of_closest = get_closet_idx(segments);
int i = index_of_closest;
travel(segments[i].start); // travel to the closest points
@ -1119,6 +1121,7 @@ public:
segments.back().is_arc = true;
segments.back().arcsegment = pl.fitting_result[i].arc_data;
}
}
}
int index_of_closest = get_closet_idx(segments);
@ -1268,6 +1271,42 @@ const std::map<float, float> WipeTower::min_depth_per_height = {
{10.f, 10.f}, {100.f, 20.f}, {180.f, 40.f}, {250.f, 50.f}, {350.f, 60.f}
};
float WipeTower::get_limit_depth_by_height(float max_height)
{
float min_wipe_tower_depth = 0.f;
auto iter = WipeTower::min_depth_per_height.begin();
while (iter != WipeTower::min_depth_per_height.end()) {
auto curr_height_to_depth = *iter;
// This is the case that wipe tower height is lower than the first min_depth_to_height member.
if (curr_height_to_depth.first >= max_height) {
min_wipe_tower_depth = curr_height_to_depth.second;
break;
}
iter++;
// If curr_height_to_depth is the last member, use its min_depth.
if (iter == WipeTower::min_depth_per_height.end()) {
min_wipe_tower_depth = curr_height_to_depth.second;
break;
}
// If wipe tower height is between the current and next member, set the min_depth as linear interpolation between them
auto next_height_to_depth = *iter;
if (next_height_to_depth.first > max_height) {
float height_base = curr_height_to_depth.first;
float height_diff = next_height_to_depth.first - curr_height_to_depth.first;
float min_depth_base = curr_height_to_depth.second;
float depth_diff = next_height_to_depth.second - curr_height_to_depth.second;
min_wipe_tower_depth = min_depth_base + (max_height - curr_height_to_depth.first) / height_diff * depth_diff;
break;
}
}
return min_wipe_tower_depth;
}
WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origin, const float prime_volume, size_t initial_tool, const float wipe_tower_height) :
m_semm(config.single_extruder_multi_material.value),
m_wipe_tower_pos(config.wipe_tower_x.get_at(plate_idx), config.wipe_tower_y.get_at(plate_idx)),
@ -2322,37 +2361,7 @@ void WipeTower::plan_tower()
for (auto& info : m_plan)
max_depth = std::max(max_depth, info.toolchanges_depth());
float min_wipe_tower_depth = 0.f;
auto iter = WipeTower::min_depth_per_height.begin();
while (iter != WipeTower::min_depth_per_height.end()) {
auto curr_height_to_depth = *iter;
// This is the case that wipe tower height is lower than the first min_depth_to_height member.
if (curr_height_to_depth.first >= m_wipe_tower_height) {
min_wipe_tower_depth = curr_height_to_depth.second;
break;
}
iter++;
// If curr_height_to_depth is the last member, use its min_depth.
if (iter == WipeTower::min_depth_per_height.end()) {
min_wipe_tower_depth = curr_height_to_depth.second;
break;
}
// If wipe tower height is between the current and next member, set the min_depth as linear interpolation between them
auto next_height_to_depth = *iter;
if (next_height_to_depth.first > m_wipe_tower_height) {
float height_base = curr_height_to_depth.first;
float height_diff = next_height_to_depth.first - curr_height_to_depth.first;
float min_depth_base = curr_height_to_depth.second;
float depth_diff = next_height_to_depth.second - curr_height_to_depth.second;
min_wipe_tower_depth = min_depth_base + (m_wipe_tower_height - curr_height_to_depth.first) / height_diff * depth_diff;
break;
}
}
float min_wipe_tower_depth = WipeTower::get_limit_depth_by_height(m_wipe_tower_height);
{
if (m_enable_timelapse_print && max_depth < EPSILON)
@ -2930,6 +2939,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer_new(bool extrude_perimeter,
outer_wall = offset(outer_wall, scaled(spacing)).front();
writer.polygon(outer_wall, feedrate);
}
/*for (size_t i = 0; i < loops_num; ++i) {
box.expand(spacing);
writer.rectangle(box, feedrate);
@ -3455,7 +3465,7 @@ void WipeTower::plan_tower_new()
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 = extrusion_flow(m_plan[idx].height);
double length = m_nozzle_change_length / e_flow;
double length = m_filaments_change_length[toolchange.old_tool] / e_flow;
int nozzle_change_line_count = length / (m_wipe_tower_width - 2*m_perimeter_width) + 1;
if (has_tpu_filament())
nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_perimeter_width;
@ -3558,6 +3568,7 @@ void WipeTower::plan_tower_new()
update_all_layer_depth(max_depth);
m_rib_length = std::max({m_rib_length, sqrt(m_wipe_tower_depth * m_wipe_tower_depth + m_wipe_tower_width * m_wipe_tower_width)});
m_rib_length += m_extra_rib_length;
}
int WipeTower::get_wall_filament_for_all_layer()
@ -3934,8 +3945,10 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall(bool is_new_mode)
// writer.rectangle(wt_box, feedrate);
outer_wall = generate_support_wall_new(writer, wt_box, feedrate, first_layer, m_use_rib_wall, true, m_use_gap_wall);
// Now prepare future wipe. box contains rectangle that was extruded last (ccw).
// Vec2f target = (writer.pos() == wt_box.ld ? wt_box.rd : (writer.pos() == wt_box.rd ? wt_box.ru : (writer.pos() == wt_box.ru ? wt_box.lu : wt_box.ld)));
//writer.add_wipe_point(writer.pos()).add_wipe_point(target);
writer.add_wipe_path(outer_wall, m_filpar[m_current_tool].wipe_dist);
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_End) + "\n");
@ -4022,6 +4035,11 @@ Polygon WipeTower::generate_support_wall_new(WipeTowerWriter &writer, const box_
insert_skip_polygon = wall_polygon;
}
writer.generate_path(result_wall, feedrate, retract_length, retract_speed,m_used_fillet);
if (m_cur_layer_id == 0) {
BoundingBox bbox = get_extents(result_wall);
m_rib_offset = Vec2f(-unscaled<float>(bbox.min.x()), -unscaled<float>(bbox.min.y()));
}
return insert_skip_polygon;
}

View File

@ -25,6 +25,7 @@ public:
// WipeTower height to minimum depth map
static const std::map<float, float> min_depth_per_height;
static float get_limit_depth_by_height(float max_height);
struct Extrusion
{
@ -358,6 +359,7 @@ public:
ToolChangeResult finish_block(const WipeTowerBlock &block, int filament_id, bool extrude_fill = true);
ToolChangeResult finish_block_solid(const WipeTowerBlock &block, int filament_id, bool extrude_fill = true);
void toolchange_wipe_new(WipeTowerWriter &writer, const box_coordinates &cleaning_box, float wipe_length);
Vec2f get_rib_offset() const { return m_rib_offset; }
private:
enum wipe_shape // A fill-in direction
@ -406,6 +408,7 @@ private:
float m_rib_width=0.f;
float m_extra_rib_length=0.f;
bool m_used_fillet{false};
Vec2f m_rib_offset{Vec2f(0.f, 0.f)};
// G-code generator parameters.
// BBS: remove useless config

View File

@ -932,6 +932,9 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
float depth = print.wipe_tower_data(filaments_count).depth;
//float brim_width = print.wipe_tower_data(filaments_count).brim_width;
if (config.prime_tower_rib_wall.value)
width = depth;
Polygons convex_hulls_temp;
if (print.has_wipe_tower()) {
Polygon wipe_tower_convex_hull;
@ -2528,6 +2531,29 @@ const WipeTowerData& Print::wipe_tower_data(size_t filaments_cnt) const
{
// If the wipe tower wasn't created yet, make sure the depth and brim_width members are set to default.
if (! is_step_done(psWipeTower) && filaments_cnt !=0) {
if (m_config.prime_tower_rib_wall.value) {
double layer_height = 0.08f; // hard code layer height
double wipe_volume = m_config.prime_volume;
double max_height = 0;
for (size_t obj_idx = 0; obj_idx < m_objects.size(); obj_idx++) {
double object_z = (double) m_objects[obj_idx]->size().z();
max_height = std::max(unscale_(object_z), max_height);
}
if (max_height < EPSILON)
return m_wipe_tower_data;
layer_height = m_objects.front()->config().layer_height.value;
int filament_depth_count = m_config.nozzle_diameter.values.size() == 2 ? filaments_cnt : filaments_cnt - 1;
if (filaments_cnt == 1 && enable_timelapse_print())
filament_depth_count = 1;
double depth = std::sqrt(wipe_volume * filament_depth_count / layer_height);
float min_wipe_tower_depth = WipeTower::get_limit_depth_by_height(max_height);
depth = std::max((double) min_wipe_tower_depth, depth);
const_cast<Print *>(this)->m_wipe_tower_data.depth = depth;
const_cast<Print *>(this)->m_wipe_tower_data.brim_width = m_config.prime_tower_brim_width;
}
else {
// BBS
double width = m_config.prime_tower_width;
double layer_height = 0.2; // hard code layer height
@ -2537,7 +2563,8 @@ const WipeTowerData& Print::wipe_tower_data(size_t filaments_cnt) const
} else {
const_cast<Print *>(this)->m_wipe_tower_data.depth = wipe_volume * (filaments_cnt - 1) / (layer_height * width);
}
const_cast<Print*>(this)->m_wipe_tower_data.brim_width = m_config.prime_tower_brim_width;
const_cast<Print *>(this)->m_wipe_tower_data.brim_width = m_config.prime_tower_brim_width;
}
}
return m_wipe_tower_data;
@ -2699,6 +2726,7 @@ void Print::_make_wipe_tower()
m_wipe_tower_data.depth = wipe_tower.get_depth();
m_wipe_tower_data.brim_width = wipe_tower.get_brim_width();
m_wipe_tower_data.bbx = wipe_tower.get_bbx();
m_wipe_tower_data.rib_offset = wipe_tower.get_rib_offset();
// Unload the current filament over the purge tower.
coordf_t layer_height = m_objects.front()->config().layer_height.value;
@ -2725,7 +2753,6 @@ void Print::_make_wipe_tower()
m_fake_wipe_tower.set_fake_extrusion_data(wipe_tower.position(), wipe_tower.width(), wipe_tower.get_height(), wipe_tower.get_layer_height(), m_wipe_tower_data.depth,
m_wipe_tower_data.brim_width, {scale_(origin.x()), scale_(origin.y())});
m_fake_wipe_tower.real_bbx = wipe_tower.get_bbx();
m_config.prime_tower_width.set(new ConfigOptionFloat( wipe_tower.width()));
}
// Generate a recommended G-code output file name based on the format template, default extension, and template parameters

View File

@ -679,6 +679,7 @@ struct WipeTowerData
float depth;
float brim_width;
BoundingBoxf bbx;
Vec2f rib_offset;
void clear() {
priming.reset(nullptr);
@ -949,6 +950,7 @@ public:
Vec2d translate_to_print_space(const Vec2d& point) const;
float get_wipe_tower_depth() const { return m_wipe_tower_data.depth; }
BoundingBoxf get_wipe_tower_bbx() const { return m_wipe_tower_data.bbx; }
Vec2f get_rib_offset() const { return m_wipe_tower_data.rib_offset; }
// scaled point
Vec2d translate_to_print_space(const Point& point) const;

View File

@ -2918,6 +2918,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
float brim_width = print->wipe_tower_data(filaments_count).brim_width;
const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
Vec3d wipe_tower_size = ppl.get_plate(plate_id)->estimate_wipe_tower_size(print_cfg, w, v);
if (dynamic_cast<const ConfigOptionBool *>(m_config->option("prime_tower_rib_wall"))->value)
wipe_tower_size = ppl.get_plate(plate_id)->calculate_wipe_tower_size(print_cfg, w, v);
{ // update for wipe tower position
part_plate->get_extruder_areas();

View File

@ -1385,6 +1385,45 @@ bool PartPlate::check_mixture_of_pla_and_petg(const DynamicPrintConfig &config)
return true;
}
Vec3d PartPlate::calculate_wipe_tower_size(const DynamicPrintConfig &config, const double w, const double wipe_volume, int plate_extruder_size, bool use_global_objects) const
{
Vec3d wipe_tower_size;
double layer_height = 0.08f; // hard code layer height
double max_height = 0.f;
wipe_tower_size.setZero();
const ConfigOption *layer_height_opt = config.option("layer_height");
if (layer_height_opt)
layer_height = layer_height_opt->getFloat();
std::vector<int> plate_extruders = get_extruders(true);
plate_extruder_size = plate_extruders.size();
if (plate_extruder_size == 0)
return wipe_tower_size;
for (int obj_idx = 0; obj_idx < m_model->objects.size(); obj_idx++) {
if (!use_global_objects && !contain_instance_totally(obj_idx, 0))
continue;
BoundingBoxf3 bbox = m_model->objects[obj_idx]->bounding_box();
max_height = std::max(bbox.size().z(), max_height);
}
wipe_tower_size(2) = max_height;
auto timelapse_type = config.option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
bool timelapse_enabled = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
int nozzle_nums = wxGetApp().preset_bundle->get_printer_extruder_count();
double depth = std::sqrt(wipe_volume * (nozzle_nums == 2 ? plate_extruder_size : (plate_extruder_size - 1)) / layer_height);
if (timelapse_enabled || plate_extruder_size > 1) {
float min_wipe_tower_depth = WipeTower::get_limit_depth_by_height(max_height);
depth = std::max((double) min_wipe_tower_depth, depth);
wipe_tower_size(0) = wipe_tower_size(1) = depth;
}
return wipe_tower_size;
}
Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int plate_extruder_size, bool use_global_objects) const
{
Vec3d wipe_tower_size;

View File

@ -304,6 +304,7 @@ public:
BoundingBoxf3 get_objects_bounding_box();
Vec3d get_origin() { return m_origin; }
Vec3d calculate_wipe_tower_size(const DynamicPrintConfig &config, const double w, const double wipe_volume, int plate_extruder_size = 0, bool use_global_objects = false) const;
Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int plate_extruder_size = 0, bool use_global_objects = false) const;
arrangement::ArrangePolygon estimate_wipe_tower_polygon(const DynamicPrintConfig & config, int plate_index, int plate_extruder_size = 0, bool use_global_objects = false) const;
bool check_objects_empty_and_gcode3mf(std::vector<int> &result) const;