mirror of
https://git.mirrors.martin98.com/https://github.com/bambulab/BambuStudio.git
synced 2025-09-29 06:13:16 +08:00
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:
parent
1f4d2cf714
commit
55772c5912
@ -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"));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user