From 289c1c1534ce535f53245c5bf7e378ace00cebcc Mon Sep 17 00:00:00 2001 From: SoftFever Date: Tue, 16 Jan 2024 09:33:44 +0800 Subject: [PATCH] ENH: QoL: improve PA Line method Signed-off-by: SoftFever Jira: XXXX Change-Id: I9b3a9f85f76ecb183a4f997b046128d88fecc488 --- src/libslic3r/Calib.cpp | 499 ++++++++++++++++++++-------------------- src/libslic3r/Calib.hpp | 73 +++--- 2 files changed, 283 insertions(+), 289 deletions(-) diff --git a/src/libslic3r/Calib.cpp b/src/libslic3r/Calib.cpp index d52a2ca67..933f646a9 100644 --- a/src/libslic3r/Calib.cpp +++ b/src/libslic3r/Calib.cpp @@ -202,12 +202,216 @@ std::string CalibPressureAdvance::draw_number( return gcode.str(); } -CalibPressureAdvanceLine::CalibPressureAdvanceLine(GCode *gcodegen) - : mp_gcodegen(gcodegen) - , m_nozzle_diameter(gcodegen->config().nozzle_diameter.get_at(0)) +double CalibPressureAdvance::get_distance(Vec2d from, Vec2d to) const { return std::hypot((to.x() - from.x()), (to.y() - from.y())); } + +std::string CalibPressureAdvance::draw_line(GCodeWriter &writer, Vec2d to_pt, double line_width, double layer_height, double speed, const std::string &comment) { + const double e_per_mm = CalibPressureAdvance::e_per_mm(line_width, layer_height, m_config.option("nozzle_diameter")->get_at(0), + m_config.option("filament_diameter")->get_at(0), + m_config.option("filament_flow_ratio")->get_at(0)); + + const double length = get_distance(Vec2d(m_last_pos.x(), m_last_pos.y()), to_pt); + auto dE = e_per_mm * length; + + std::stringstream gcode; + + gcode << writer.set_speed(speed); + gcode << writer.extrude_to_xy(to_pt, dE, comment); + + m_last_pos = Vec3d(to_pt.x(), to_pt.y(), 0); + + return gcode.str(); } +std::string CalibPressureAdvance::draw_box(GCodeWriter &writer, double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args) +{ + std::stringstream gcode; + + double x = min_x; + double y = min_y; + const double max_x = min_x + size_x; + const double max_y = min_y + size_y; + + const double spacing = opt_args.line_width - opt_args.height * (1 - M_PI / 4); + + // if number of perims exceeds size of box, reduce it to max + const int max_perimeters = std::min( + // this is the equivalent of number of perims for concentric fill + std::floor(size_x * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))), + std::floor(size_y * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45)))); + + opt_args.num_perimeters = std::min(opt_args.num_perimeters, max_perimeters); + + gcode << move_to(Vec2d(min_x, min_y), writer, "Move to box start"); + + // DrawLineOptArgs line_opt_args(*this); + auto line_arg_height = opt_args.height; + auto line_arg_line_width = opt_args.line_width; + auto line_arg_speed = opt_args.speed; + std::string comment = ""; + + for (int i = 0; i < opt_args.num_perimeters; ++i) { + if (i != 0) { // after first perimeter, step inwards to start next perimeter + x += spacing; + y += spacing; + gcode << move_to(Vec2d(x, y), writer, "Step inwards to print next perimeter"); + } + + y += size_y - i * spacing * 2; + comment = "Draw perimeter (up)"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + + x += size_x - i * spacing * 2; + comment = "Draw perimeter (right)"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + + y -= size_y - i * spacing * 2; + comment = "Draw perimeter (down)"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + + x -= size_x - i * spacing * 2; + comment = "Draw perimeter (left)"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + } + + if (!opt_args.is_filled) { return gcode.str(); } + + // create box infill + const double spacing_45 = spacing / std::sin(to_radians(45)); + + const double bound_modifier = (spacing * (opt_args.num_perimeters - 1)) + (opt_args.line_width * (1 - m_encroachment)); + const double x_min_bound = min_x + bound_modifier; + const double x_max_bound = max_x - bound_modifier; + const double y_min_bound = min_y + bound_modifier; + const double y_max_bound = max_y - bound_modifier; + const int x_count = std::floor((x_max_bound - x_min_bound) / spacing_45); + const int y_count = std::floor((y_max_bound - y_min_bound) / spacing_45); + + double x_remainder = std::fmod((x_max_bound - x_min_bound), spacing_45); + double y_remainder = std::fmod((y_max_bound - y_min_bound), spacing_45); + + x = x_min_bound; + y = y_min_bound; + + gcode << move_to(Vec2d(x, y), writer, "Move to fill start"); + + for (int i = 0; i < x_count + y_count + (x_remainder + y_remainder >= spacing_45 ? 1 : 0); + ++i) { // this isn't the most robust way, but less expensive than finding line intersections + if (i < std::min(x_count, y_count)) { + if (i % 2 == 0) { + x += spacing_45; + y = y_min_bound; + gcode << move_to(Vec2d(x, y), writer, "Fill: Step right"); + + y += x - x_min_bound; + x = x_min_bound; + comment = "Fill: Print up/left"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + } else { + y += spacing_45; + x = x_min_bound; + gcode << move_to(Vec2d(x, y), writer, "Fill: Step up"); + + x += y - y_min_bound; + y = y_min_bound; + comment = "Fill: Print down/right"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + } + } else if (i < std::max(x_count, y_count)) { + if (x_count > y_count) { + // box is wider than tall + if (i % 2 == 0) { + x += spacing_45; + y = y_min_bound; + gcode << move_to(Vec2d(x, y), writer, "Fill: Step right"); + + x -= y_max_bound - y_min_bound; + y = y_max_bound; + comment = "Fill: Print up/left"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + } else { + if (i == y_count) { + x += spacing_45 - y_remainder; + y_remainder = 0; + } else { + x += spacing_45; + } + y = y_max_bound; + gcode << move_to(Vec2d(x, y), writer, "Fill: Step right"); + + x += y_max_bound - y_min_bound; + y = y_min_bound; + comment = "Fill: Print down/right"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + } + } else { + // box is taller than wide + if (i % 2 == 0) { + x = x_max_bound; + if (i == x_count) { + y += spacing_45 - x_remainder; + x_remainder = 0; + } else { + y += spacing_45; + } + gcode << move_to(Vec2d(x, y), writer, "Fill: Step up"); + + x = x_min_bound; + y += x_max_bound - x_min_bound; + comment = "Fill: Print up/left"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + } else { + x = x_min_bound; + y += spacing_45; + gcode << move_to(Vec2d(x, y), writer, "Fill: Step up"); + + x = x_max_bound; + y -= x_max_bound - x_min_bound; + comment = "Fill: Print down/right"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + } + } + } else { + if (i % 2 == 0) { + x = x_max_bound; + if (i == x_count) { + y += spacing_45 - x_remainder; + } else { + y += spacing_45; + } + gcode << move_to(Vec2d(x, y), writer, "Fill: Step up"); + + x -= y_max_bound - y; + y = y_max_bound; + comment = "Fill: Print up/left"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + } else { + if (i == y_count) { + x += spacing_45 - y_remainder; + } else { + x += spacing_45; + } + y = y_max_bound; + gcode << move_to(Vec2d(x, y), writer, "Fill: Step right"); + + y -= x_max_bound - x; + x = x_max_bound; + comment = "Fill: Print down/right"; + gcode << draw_line(writer, Vec2d(x, y), line_arg_line_width, line_arg_height, line_arg_speed, comment); + } + } + } + + return gcode.str(); +} +CalibPressureAdvanceLine::CalibPressureAdvanceLine(GCode *gcodegen) + : CalibPressureAdvance(gcodegen->config()), mp_gcodegen(gcodegen), m_nozzle_diameter(gcodegen->config().nozzle_diameter.get_at(0)) +{ + m_line_width = m_nozzle_diameter < 0.51 ? m_nozzle_diameter * 1.5 : m_nozzle_diameter * 1.05; + m_height_layer = gcodegen->config().initial_layer_print_height; + m_number_line_width = m_thin_line_width = m_nozzle_diameter; +}; + std::string CalibPressureAdvanceLine::generate_test(double start_pa /*= 0*/, double step_pa /*= 0.002*/, int count /*= 10*/) { BoundingBoxf bed_ext = get_extents(mp_gcodegen->config().printable_area.values); @@ -220,9 +424,8 @@ std::string CalibPressureAdvanceLine::generate_test(double start_pa /*= 0*/, dou m_length_long = 40 + std::min(w - 120.0, 0.0); - auto startx = (w - m_length_short * 2 - m_length_long - 20) / 2; - auto starty = (h - count * m_space_y) / 2; - if (is_delta()) { CalibPressureAdvanceLine::delta_modify_start(startx, starty, count); } + auto startx = bed_ext.min.x() + (w - m_length_short * 2 - m_length_long - 20) / 2; + auto starty = bed_ext.min.y() + (h - count * m_space_y) / 2; return print_pa_lines(startx, starty, start_pa, step_pa, count); } @@ -248,10 +451,10 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star double y_pos = start_y; // prime line - auto prime_x = start_x - 2; - gcode << move_to(Vec2d(prime_x, y_pos + (num - 4) * m_space_y), writer); + auto prime_x = start_x; + gcode << move_to(Vec2d(prime_x, y_pos + (num) *m_space_y), writer); gcode << writer.set_speed(slow); - gcode << writer.extrude_to_xy(Vec2d(prime_x, y_pos + 3 * m_space_y), e_per_mm * m_space_y * num * 1.1); + gcode << writer.extrude_to_xy(Vec2d(prime_x, y_pos), e_per_mm * m_space_y * num * 1.2); for (int i = 0; i < num; ++i) { gcode << writer.set_pressure_advance(start_pa + i * step_pa); @@ -266,16 +469,21 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star gcode << writer.set_pressure_advance(0.0); if (m_draw_numbers) { - // draw indicator lines - gcode << writer.set_speed(fast); - gcode << move_to(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 2), writer); - gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 7), thin_e_per_mm * 7); - gcode << move_to(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 7), writer); - gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 2), thin_e_per_mm * 7); + // Orca: skip drawing indicator lines + // gcode << writer.set_speed(fast); + // gcode << move_to(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 2), writer); + // gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 7), thin_e_per_mm * 7); + // gcode << move_to(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 7), writer); + // gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 2), thin_e_per_mm * 7); + const auto box_start_x = start_x + m_length_short + m_length_long + m_length_short; + DrawBoxOptArgs default_box_opt_args(2, m_height_layer, m_line_width, fast); + default_box_opt_args.is_filled = true; + gcode << draw_box(writer, box_start_x, start_y - m_space_y, number_spacing() * 8, (num + 1) * m_space_y, default_box_opt_args); + gcode << writer.travel_to_z(m_height_layer * 2); for (int i = 0; i < num; i += 2) { - gcode << draw_number(start_x + m_length_short + m_length_long + m_length_short + 3, y_pos + i * m_space_y + m_space_y / 2, start_pa + i * step_pa, m_draw_digit_mode, - m_number_line_width, number_e_per_mm, 3600, writer); + gcode << draw_number(box_start_x + 3 + m_line_width, y_pos + i * m_space_y + m_space_y / 2, start_pa + i * step_pa, m_draw_digit_mode, m_number_line_width, + number_e_per_mm, 3600, writer); } } return gcode.str(); @@ -288,7 +496,7 @@ void CalibPressureAdvanceLine::delta_modify_start(double &startx, double &starty } CalibPressureAdvancePattern::CalibPressureAdvancePattern(const Calib_Params ¶ms, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin) - : m_params(params) + : m_params(params), CalibPressureAdvance(config) { this->m_draw_digit_mode = DrawDigitMode::Bottom_To_Top; @@ -306,24 +514,26 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi gcode << m_writer.travel_to_z(height_first_layer(), "Move to start Z position"); gcode << m_writer.set_pressure_advance(m_params.start); - const DrawBoxOptArgs default_box_opt_args(*this); + const DrawBoxOptArgs default_box_opt_args(wall_count(), height_first_layer(), line_width_first_layer(), speed_adjust(speed_first_layer())); // create anchoring frame - gcode << draw_box(m_starting_point.x(), m_starting_point.y(), print_size_x(), frame_size_y(), default_box_opt_args); + gcode << draw_box(m_writer, m_starting_point.x(), m_starting_point.y(), print_size_x(), frame_size_y(), default_box_opt_args); // create tab for numbers DrawBoxOptArgs draw_box_opt_args = default_box_opt_args; draw_box_opt_args.is_filled = true; draw_box_opt_args.num_perimeters = wall_count(); - gcode << draw_box(m_starting_point.x(), m_starting_point.y() + frame_size_y() + line_spacing_first_layer(), glyph_tab_max_x() - m_starting_point.x(), + gcode << draw_box(m_writer, m_starting_point.x(), m_starting_point.y() + frame_size_y() + line_spacing_first_layer(), glyph_tab_max_x() - m_starting_point.x(), max_numbering_height() + line_spacing_first_layer() + m_glyph_padding_vertical * 2, draw_box_opt_args); std::vector gcode_items; - const DrawLineOptArgs default_line_opt_args(*this); const int num_patterns = get_num_patterns(); // "cache" for use in loops // draw pressure advance pattern for (int i = 0; i < m_num_layers; ++i) { + const double layer_height = height_first_layer() + (i * height_layer()); + const double zhop_height = layer_height + height_layer(); + if (i > 0) { gcode << "; end pressure advance pattern for layer\n"; CustomGCode::Item item; @@ -335,8 +545,8 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi gcode = std::stringstream(); // reset for next layer contents gcode << "; start pressure advance pattern for layer\n"; - const double layer_height = height_first_layer() + (i * height_layer()); gcode << m_writer.travel_to_z(layer_height, "Move to layer height"); + gcode << m_writer.reset_e(); } // line numbering @@ -354,8 +564,6 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi } } - DrawLineOptArgs draw_line_opt_args = default_line_opt_args; - double to_x = m_starting_point.x() + pattern_shift(); double to_y = m_starting_point.y(); double side_length = m_wall_side_length; @@ -371,7 +579,9 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi double initial_x = to_x; double initial_y = to_y; + gcode << m_writer.travel_to_z(zhop_height, "z-hop before move"); gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to pattern start"); + gcode << m_writer.travel_to_z(layer_height, "undo z-hop"); for (int j = 0; j < num_patterns; ++j) { // increment pressure advance @@ -381,31 +591,37 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi to_x += std::cos(to_radians(m_corner_angle) / 2) * side_length; to_y += std::sin(to_radians(m_corner_angle) / 2) * side_length; - draw_line_opt_args = default_line_opt_args; - draw_line_opt_args.height = i == 0 ? height_first_layer() : height_layer(); - draw_line_opt_args.line_width = line_width(); // don't use line_width_first_layer so results are consistent across all layers - draw_line_opt_args.speed = i == 0 ? speed_adjust(speed_first_layer()) : speed_adjust(speed_perimeter()); - draw_line_opt_args.comment = "Print pattern wall"; - gcode << draw_line(Vec2d(to_x, to_y), draw_line_opt_args); + auto draw_line_arg_height = i == 0 ? height_first_layer() : height_layer(); + auto draw_line_arg_line_width = line_width(); // don't use line_width_first_layer so results are consistent across all layers + auto draw_line_arg_speed = i == 0 ? speed_adjust(speed_first_layer()) : speed_adjust(speed_perimeter()); + auto draw_line_arg_comment = "Print pattern wall"; + gcode << draw_line(m_writer, Vec2d(to_x, to_y), draw_line_arg_line_width, draw_line_arg_height, draw_line_arg_speed, draw_line_arg_comment); to_x -= std::cos(to_radians(m_corner_angle) / 2) * side_length; to_y += std::sin(to_radians(m_corner_angle) / 2) * side_length; - gcode << draw_line(Vec2d(to_x, to_y), draw_line_opt_args); + gcode << draw_line(m_writer, Vec2d(to_x, to_y), draw_line_arg_line_width, draw_line_arg_height, draw_line_arg_speed, draw_line_arg_comment); to_y = initial_y; if (k != wall_count() - 1) { // perimeters not done yet. move to next perimeter to_x += line_spacing_angle(); + gcode << m_writer.travel_to_z(zhop_height, "z-hop before move"); gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to start next pattern wall"); + gcode << m_writer.travel_to_z(layer_height, "undo z-hop"); } else if (j != num_patterns - 1) { // patterns not done yet. move to next pattern to_x += m_pattern_spacing + line_width(); + gcode << m_writer.travel_to_z(zhop_height, "z-hop before move"); gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to next pattern"); + gcode << m_writer.travel_to_z(layer_height, "undo z-hop"); } else if (i != m_num_layers - 1) { // layers not done yet. move back to start to_x = initial_x; + gcode << m_writer.travel_to_z(zhop_height, "z-hop before move"); gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move back to start position"); + gcode << m_writer.travel_to_z(layer_height, "undo z-hop"); + gcode << m_writer.reset_e(); // reset extruder before printing placeholder cube to avoid } else { // everything done } @@ -431,14 +647,11 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi void CalibPressureAdvancePattern::set_start_offset(const Vec3d &offset) { - m_starting_point = offset; + m_starting_point = offset; m_is_start_point_fixed = true; } -Vec3d CalibPressureAdvancePattern::get_start_offset() -{ - return m_starting_point; -} +Vec3d CalibPressureAdvancePattern::get_start_offset() { return m_starting_point; } void CalibPressureAdvancePattern::refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin) { @@ -446,27 +659,19 @@ void CalibPressureAdvancePattern::refresh_setup(const DynamicPrintConfig &config m_config.apply(model.objects.front()->config.get(), true); m_config.apply(model.objects.front()->volumes.front()->config.get(), true); - m_is_delta = (m_config.option("printable_area")->values.size() > 4); - _refresh_starting_point(model); _refresh_writer(is_bbl_machine, model, origin); } void CalibPressureAdvancePattern::_refresh_starting_point(const Model &model) { - if (m_is_start_point_fixed) - return; + if (m_is_start_point_fixed) return; ModelObject * obj = model.objects.front(); BoundingBoxf3 bbox = obj->instance_bounding_box(*obj->instances.front(), false); m_starting_point = Vec3d(bbox.min.x(), bbox.max.y(), 0); m_starting_point.y() += m_handle_spacing; - - if (m_is_delta) { - m_starting_point.x() *= -1; - m_starting_point.y() -= (frame_size_y() / 2); - } } void CalibPressureAdvancePattern::_refresh_writer(bool is_bbl_machine, const Model &model, const Vec3d &origin) @@ -483,208 +688,6 @@ void CalibPressureAdvancePattern::_refresh_writer(bool is_bbl_machine, const Mod m_writer.set_extruder(extruder_id); } -std::string CalibPressureAdvancePattern::draw_line(Vec2d to_pt, DrawLineOptArgs opt_args) -{ - const double e_per_mm = CalibPressureAdvance::e_per_mm(opt_args.line_width, opt_args.height, m_config.option("nozzle_diameter")->get_at(0), - m_config.option("filament_diameter")->get_at(0), - m_config.option("filament_flow_ratio")->get_at(0)); - - const double length = get_distance(Vec2d(m_last_pos.x(), m_last_pos.y()), to_pt); - auto dE = e_per_mm * length; - - std::stringstream gcode; - - gcode << m_writer.set_speed(opt_args.speed); - gcode << m_writer.extrude_to_xy(to_pt, dE, opt_args.comment); - - m_last_pos = Vec3d(to_pt.x(), to_pt.y(), 0); - - return gcode.str(); -} - -std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args) -{ - std::stringstream gcode; - - double x = min_x; - double y = min_y; - const double max_x = min_x + size_x; - const double max_y = min_y + size_y; - - const double spacing = opt_args.line_width - opt_args.height * (1 - M_PI / 4); - - // if number of perims exceeds size of box, reduce it to max - const int max_perimeters = std::min( - // this is the equivalent of number of perims for concentric fill - std::floor(size_x * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))), - std::floor(size_y * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45)))); - - opt_args.num_perimeters = std::min(opt_args.num_perimeters, max_perimeters); - - gcode << move_to(Vec2d(min_x, min_y), m_writer, "Move to box start"); - - DrawLineOptArgs line_opt_args(*this); - line_opt_args.height = opt_args.height; - line_opt_args.line_width = opt_args.line_width; - line_opt_args.speed = opt_args.speed; - - for (int i = 0; i < opt_args.num_perimeters; ++i) { - if (i != 0) { // after first perimeter, step inwards to start next perimeter - x += spacing; - y += spacing; - gcode << move_to(Vec2d(x, y), m_writer, "Step inwards to print next perimeter"); - } - - y += size_y - i * spacing * 2; - line_opt_args.comment = "Draw perimeter (up)"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - - x += size_x - i * spacing * 2; - line_opt_args.comment = "Draw perimeter (right)"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - - y -= size_y - i * spacing * 2; - line_opt_args.comment = "Draw perimeter (down)"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - - x -= size_x - i * spacing * 2; - line_opt_args.comment = "Draw perimeter (left)"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - } - - if (!opt_args.is_filled) { return gcode.str(); } - - // create box infill - const double spacing_45 = spacing / std::sin(to_radians(45)); - - const double bound_modifier = (spacing * (opt_args.num_perimeters - 1)) + (opt_args.line_width * (1 - m_encroachment)); - const double x_min_bound = min_x + bound_modifier; - const double x_max_bound = max_x - bound_modifier; - const double y_min_bound = min_y + bound_modifier; - const double y_max_bound = max_y - bound_modifier; - const int x_count = std::floor((x_max_bound - x_min_bound) / spacing_45); - const int y_count = std::floor((y_max_bound - y_min_bound) / spacing_45); - - double x_remainder = std::fmod((x_max_bound - x_min_bound), spacing_45); - double y_remainder = std::fmod((y_max_bound - y_min_bound), spacing_45); - - x = x_min_bound; - y = y_min_bound; - - gcode << move_to(Vec2d(x, y), m_writer, "Move to fill start"); - - for (int i = 0; i < x_count + y_count + (x_remainder + y_remainder >= spacing_45 ? 1 : 0); - ++i) { // this isn't the most robust way, but less expensive than finding line intersections - if (i < std::min(x_count, y_count)) { - if (i % 2 == 0) { - x += spacing_45; - y = y_min_bound; - gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right"); - - y += x - x_min_bound; - x = x_min_bound; - line_opt_args.comment = "Fill: Print up/left"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - } else { - y += spacing_45; - x = x_min_bound; - gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up"); - - x += y - y_min_bound; - y = y_min_bound; - line_opt_args.comment = "Fill: Print down/right"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - } - } else if (i < std::max(x_count, y_count)) { - if (x_count > y_count) { - // box is wider than tall - if (i % 2 == 0) { - x += spacing_45; - y = y_min_bound; - gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right"); - - x -= y_max_bound - y_min_bound; - y = y_max_bound; - line_opt_args.comment = "Fill: Print up/left"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - } else { - if (i == y_count) { - x += spacing_45 - y_remainder; - y_remainder = 0; - } else { - x += spacing_45; - } - y = y_max_bound; - gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right"); - - x += y_max_bound - y_min_bound; - y = y_min_bound; - line_opt_args.comment = "Fill: Print down/right"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - } - } else { - // box is taller than wide - if (i % 2 == 0) { - x = x_max_bound; - if (i == x_count) { - y += spacing_45 - x_remainder; - x_remainder = 0; - } else { - y += spacing_45; - } - gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up"); - - x = x_min_bound; - y += x_max_bound - x_min_bound; - line_opt_args.comment = "Fill: Print up/left"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - } else { - x = x_min_bound; - y += spacing_45; - gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up"); - - x = x_max_bound; - y -= x_max_bound - x_min_bound; - line_opt_args.comment = "Fill: Print down/right"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - } - } - } else { - if (i % 2 == 0) { - x = x_max_bound; - if (i == x_count) { - y += spacing_45 - x_remainder; - } else { - y += spacing_45; - } - gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up"); - - x -= y_max_bound - y; - y = y_max_bound; - line_opt_args.comment = "Fill: Print up/left"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - } else { - if (i == y_count) { - x += spacing_45 - y_remainder; - } else { - x += spacing_45; - } - y = y_max_bound; - gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right"); - - y -= x_max_bound - x; - x = x_max_bound; - line_opt_args.comment = "Fill: Print down/right"; - gcode << draw_line(Vec2d(x, y), line_opt_args); - } - } - } - - return gcode.str(); -} - -double CalibPressureAdvancePattern::get_distance(Vec2d from, Vec2d to) const { return std::hypot((to.x() - from.x()), (to.y() - from.y())); } - double CalibPressureAdvancePattern::object_size_x() const { return get_num_patterns() * ((wall_count() - 1) * line_spacing_angle()) + (get_num_patterns() - 1) * (m_pattern_spacing + line_width()) + diff --git a/src/libslic3r/Calib.hpp b/src/libslic3r/Calib.hpp index 0d7f421f4..6419c73c3 100644 --- a/src/libslic3r/Calib.hpp +++ b/src/libslic3r/Calib.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include "GCodeWriter.hpp" #include "PrintConfig.hpp" #include "BoundingBox.hpp" @@ -129,13 +130,26 @@ public: int confidence; // 0: success 1: uncertain 2: failed }; +struct DrawBoxOptArgs +{ + DrawBoxOptArgs(int num_perimeters, double height, double line_width, double speed) : num_perimeters{num_perimeters}, height{height}, line_width{line_width}, speed{speed} {}; + DrawBoxOptArgs() = default; + + bool is_filled{false}; + int num_perimeters; + double height; + double line_width; + double speed; +}; class CalibPressureAdvance { public: static float find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx = 0); protected: - CalibPressureAdvance() = default; + CalibPressureAdvance() = default; + CalibPressureAdvance(const DynamicPrintConfig &config) : m_config(config){}; + CalibPressureAdvance(const FullPrintConfig &config) { m_config.apply(config); }; ~CalibPressureAdvance() = default; enum class DrawDigitMode { Left_To_Right, Bottom_To_Top }; @@ -152,8 +166,16 @@ protected: std::string draw_number( double startx, double starty, double value, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, double speed, GCodeWriter &writer); - Vec3d m_last_pos; + std::string draw_line(GCodeWriter &writer, Vec2d to_pt, double line_width, double layer_height, double speed, const std::string &comment = std::string()); + std::string draw_box(GCodeWriter &writer, double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args); + double to_radians(double degrees) const { return degrees * M_PI / 180; }; + double get_distance(Vec2d from, Vec2d to) const; + + Vec3d m_last_pos; + DynamicPrintConfig m_config; + + const double m_encroachment{1. / 3.}; DrawDigitMode m_draw_digit_mode{DrawDigitMode::Left_To_Right}; const double m_digit_segment_len{2}; const double m_digit_gap_len{1}; @@ -175,6 +197,7 @@ public: } const double &line_width() { return m_line_width; }; + const double &height_layer() { return m_height_layer; }; bool is_delta() const; bool & draw_numbers() { return m_draw_numbers; } @@ -188,10 +211,10 @@ private: double m_nozzle_diameter; double m_slow_speed, m_fast_speed; - const double m_height_layer{0.2}; - const double m_line_width{0.6}; - const double m_thin_line_width{0.44}; - const double m_number_line_width{0.48}; + double m_height_layer{0.2}; + double m_line_width{0.6}; + double m_thin_line_width{0.44}; + double m_number_line_width{0.48}; const double m_space_y{3.5}; double m_length_short{20.0}, m_length_long{40.0}; @@ -211,7 +234,6 @@ struct SuggestedConfigCalibPAPattern class CalibPressureAdvancePattern : public CalibPressureAdvance { - friend struct DrawLineOptArgs; friend struct DrawBoxOptArgs; public: @@ -236,28 +258,6 @@ protected: int wall_count() const { return m_config.option("wall_loops")->value; }; private: - struct DrawLineOptArgs - { - DrawLineOptArgs(const CalibPressureAdvancePattern &p) : height{p.height_layer()}, line_width{p.line_width()}, speed{p.speed_adjust(p.speed_perimeter())} {}; - - double height; - double line_width; - double speed; - std::string comment{"Print line"}; - }; - - struct DrawBoxOptArgs - { - DrawBoxOptArgs(const CalibPressureAdvancePattern &p) - : num_perimeters{p.wall_count()}, height{p.height_first_layer()}, line_width{p.line_width_first_layer()}, speed{p.speed_adjust(p.speed_first_layer())} {}; - - bool is_filled{false}; - int num_perimeters; - double height; - double line_width; - double speed; - }; - void refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin); void _refresh_starting_point(const Model &model); void _refresh_writer(bool is_bbl_machine, const Model &model, const Vec3d &origin); @@ -266,12 +266,6 @@ private: double height_layer() const { return m_config.option("layer_height")->value; }; const int get_num_patterns() const { return std::ceil((m_params.end - m_params.start) / m_params.step + 1); } - std::string draw_line(Vec2d to_pt, DrawLineOptArgs opt_args); - std::string draw_box(double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args); - - double to_radians(double degrees) const { return degrees * M_PI / 180; }; - double get_distance(Vec2d from, Vec2d to) const; - /* from slic3r documentation: spacing = extrusion_width - layer_height * (1 - PI/4) "spacing" = center-to-center distance of adjacent extrusions, which partially overlap @@ -295,11 +289,9 @@ private: const Calib_Params &m_params; - DynamicPrintConfig m_config; - GCodeWriter m_writer; - bool m_is_delta; - Vec3d m_starting_point; - bool m_is_start_point_fixed = false; + GCodeWriter m_writer; + Vec3d m_starting_point; + bool m_is_start_point_fixed = false; const double m_handle_xy_size{5}; const double m_handle_spacing{2}; @@ -308,7 +300,6 @@ private: const double m_wall_side_length{30.0}; const int m_corner_angle{90}; const int m_pattern_spacing{2}; - const double m_encroachment{1. / 3.}; const double m_glyph_padding_horizontal{1}; const double m_glyph_padding_vertical{1};