diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index a4506b791c..1701382e3d 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3246,7 +3246,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato BoundingBoxf bbox; auto pts = std::make_unique(); - if (print.calib_mode() == CalibMode::Calib_PA_Line || print.calib_mode() == CalibMode::Calib_PA_Pattern) { + if (print.calib_mode() == CalibMode::Calib_PA_Pattern) { + //PA_Pattern can have any size or arrangement - not dependent on 3mf model size bbox = bbox_bed; bbox.offset(-25.0); // add 4 corner points of bbox into pts @@ -3256,6 +3257,22 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato pts->values.emplace_back(bbox.max.x(), bbox.max.y()); pts->values.emplace_back(bbox.min.x(), bbox.max.y()); + } else if (print.calib_mode() == CalibMode::Calib_PA_Line) { + // Derive X bounds from the actual calibration geometry. + CalibPressureAdvanceLine temp_pa_line_forsize(this); + BoundingBoxf pattern_extents = temp_pa_line_forsize.print_extents(bbox_bed); + + bbox = bbox_bed; + bbox.offset(-25.0); + bbox.min.x() = std::max(pattern_extents.min.x(), bbox.min.x()); + bbox.max.x() = std::min(pattern_extents.max.x(), bbox.max.x()); + + pts->values.reserve(4); + pts->values.emplace_back(bbox.min.x(), bbox.min.y()); + pts->values.emplace_back(bbox.max.x(), bbox.min.y()); + pts->values.emplace_back(bbox.max.x(), bbox.max.y()); + pts->values.emplace_back(bbox.min.x(), bbox.max.y()); + } else { // Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line. // It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower. @@ -7532,7 +7549,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, // If adaptive PA is enabled, by default evaluate PA on all extrusion moves bool is_pa_calib = m_curr_print->calib_mode() == CalibMode::Calib_PA_Line || m_curr_print->calib_mode() == CalibMode::Calib_PA_Pattern || - m_curr_print->calib_mode() == CalibMode::Calib_PA_Tower; + m_curr_print->calib_mode() == CalibMode::Calib_PA_Tower; bool evaluate_adaptive_pa = false; bool role_change = (m_last_extrusion_role != path.role()); if (!is_pa_calib && FILAMENT_CONFIG(adaptive_pressure_advance) && FILAMENT_CONFIG(enable_pressure_advance)) { @@ -9087,7 +9104,7 @@ std::string GCode::set_object_info(Print *print) { std::ostringstream gcode; size_t object_id = 0; // Orca: check if we are in pa calib mode - if (print->calib_mode() == CalibMode::Calib_PA_Line || print->calib_mode() == CalibMode::Calib_PA_Pattern) { + if (print->calib_mode() == CalibMode::Calib_PA_Pattern) { BoundingBoxf bbox_bed(print->config().printable_area.values); bbox_bed.offset(-25.0); Polygon polygon_bed; @@ -9098,6 +9115,8 @@ std::string GCode::set_object_info(Print *print) { gcode << "EXCLUDE_OBJECT_DEFINE NAME=" << "Orca-PA-Calibration-Test" << " CENTER=" << 0 << "," << 0 << " POLYGON=" << polygon_to_string(polygon_bed, print, true) << "\n"; + } else if (print->calib_mode() == CalibMode::Calib_PA_Line) { + // PA_Line has only one object, no EXCLUDE_OBJECT_DEFINE needed } else { size_t unique_id = 0; for (PrintObject* object : print->objects()) { diff --git a/src/libslic3r/calib.cpp b/src/libslic3r/calib.cpp index 9f33b4459a..f5490138ed 100644 --- a/src/libslic3r/calib.cpp +++ b/src/libslic3r/calib.cpp @@ -469,6 +469,31 @@ std::string CalibPressureAdvanceLine::generate_test(double start_pa /*= 0*/, dou return print_pa_lines(startx, starty, start_pa, step_pa, count); } +BoundingBoxf CalibPressureAdvanceLine::print_extents(const BoundingBoxf &bed_ext) const +{ + BoundingBoxf adjusted_bed = bed_ext; + if (is_delta()) { + CalibPressureAdvanceLine::delta_scale_bed_ext(adjusted_bed); + } + + double bed_width = adjusted_bed.size().x(); + // m_length_long adjusts for narrow beds – exactly as in generate_test() + double line_long = 40.0 + std::min(bed_width - 120.0, 0.0); + double total_line_len = m_length_short * 2 + line_long; + double start_x = adjusted_bed.min.x() + (bed_width - 2 * m_length_short - line_long - 20.0) / 2.0; + double box_width = m_draw_numbers ? (number_spacing() * 8) : 0.0; // 3.0 * 8 = 24 mm + + BoundingBoxf extent; + extent.min.x() = start_x; + extent.max.x() = start_x + total_line_len + m_line_width + box_width; + + // Y bounds are the full bed (the caller will inset them by -25) + extent.min.y() = adjusted_bed.min.y(); + extent.max.y() = adjusted_bed.max.y(); + + return extent; +} + bool CalibPressureAdvanceLine::is_delta() const { return mp_gcodegen->config().printable_area.values.size() > 4; } std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num) @@ -491,9 +516,10 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star const double slow = CalibPressureAdvance::speed_adjust(m_slow_speed); std::stringstream gcode; gcode << mp_gcodegen->writer().travel_to_z(m_height_layer + z_offset); + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) << (m_height_layer + z_offset) << "\n"; double y_pos = start_y; - - // prime line + // Purge/first perimeter - acts as an anchor to the rest of the model + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Custom\n"; gcode << writer.set_pressure_advance(0.0); auto prime_x = start_x; gcode << move_to(Vec2d(prime_x, y_pos + (num) * m_space_y), writer); @@ -503,10 +529,13 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star for (int i = 0; i < num; ++i) { gcode << writer.set_pressure_advance(start_pa + i * step_pa); gcode << move_to(Vec2d(start_x, y_pos + i * m_space_y), writer); + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Custom\n"; gcode << writer.set_speed(slow); gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + i * m_space_y), e_per_mm * m_length_short); + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Outer wall\n"; gcode << writer.set_speed(fast); gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + i * m_space_y), e_per_mm * m_length_long); + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Custom\n"; gcode << writer.set_speed(slow); gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long + m_length_short, y_pos + i * m_space_y), e_per_mm * m_length_short); @@ -530,9 +559,15 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star const auto box_start_x = start_x + m_length_short + m_length_long + m_length_short + m_line_width; DrawBoxOptArgs default_box_opt_args(2, m_height_layer, m_line_width, fast); + //Draw box default_box_opt_args.is_filled = true; + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Bottom surface\n"; gcode << draw_box(writer, box_start_x, start_y - m_space_y, number_spacing() * 8, (num + 1) * m_space_y, default_box_opt_args); + //Ensure numbers are shown on the next layer in gcode processor, as in reality + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Layer_Change) << "\n"; + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) << (m_height_layer*2 + z_offset) << "\n"; + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Top surface\n"; gcode << writer.travel_to_z(m_height_layer*2 + z_offset); for (int i = 0; i < num; i += 2) { 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, @@ -595,12 +630,16 @@ CustomGCode::Info CalibPressureAdvancePattern::generate_custom_gcodes(const Dyna speed_adjust(speed_first_layer())); // create anchoring frame + //pattern uses outer wall speed/width + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Outer wall\n"; 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(); + //draw box as bottom surface, so numbers are clearly visible on top + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Bottom surface\n"; gcode << draw_box(m_writer, m_starting_point.x(), m_starting_point.y() + frame_size_y() + line_spacing_first_layer(), print_size_x(), max_numbering_height() + line_spacing_first_layer() + m_glyph_padding_vertical * 2, draw_box_opt_args); @@ -611,7 +650,9 @@ CustomGCode::Info CalibPressureAdvancePattern::generate_custom_gcodes(const Dyna const double zhop_config_value = m_config.option("z_hop")->get_at(0); const auto accel = accel_perimeter(); - // draw pressure advance pattern + // Draw pressure advance pattern + // pattern uses outer wall speed, label it as such + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Outer wall\n"; for (int i = 0; i < m_num_layers; ++i) { const double layer_height = height_first_layer() + height_z_offset() + (i * height_layer()); const double zhop_height = layer_height + zhop_config_value; @@ -643,6 +684,7 @@ CustomGCode::Info CalibPressureAdvancePattern::generate_custom_gcodes(const Dyna m_config.option("filament_flow_ratio")->get_at(0)); // glyph on every other line + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Outer wall\n"; for (int j = 0; j < num_patterns; j += 2) { gcode << draw_number(glyph_start_x(j), m_starting_point.y() + frame_size_y() + m_glyph_padding_vertical + line_width(), m_params.start + (j * m_params.step), m_draw_digit_mode, line_width(), number_e_per_mm, @@ -692,7 +734,7 @@ CustomGCode::Info CalibPressureAdvancePattern::generate_custom_gcodes(const Dyna for (int j = 0; j < num_patterns; ++j) { // increment pressure advance gcode << m_writer.set_pressure_advance(m_params.start + (j * m_params.step)); - + gcode << ";" << GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role) << "Outer wall\n"; for (int k = 0; k < wall_count(); ++k) { to_x += std::cos(to_radians(m_corner_angle) / 2) * side_length; to_y += std::sin(to_radians(m_corner_angle) / 2) * side_length; diff --git a/src/libslic3r/calib.hpp b/src/libslic3r/calib.hpp index fc8e0cddc0..db147fdeb4 100644 --- a/src/libslic3r/calib.hpp +++ b/src/libslic3r/calib.hpp @@ -254,6 +254,8 @@ class CalibPressureAdvanceLine : public CalibPressureAdvance public: CalibPressureAdvanceLine(GCode* gcodegen); ~CalibPressureAdvanceLine(){}; + // Return the X‑bounds of the pattern on the given bed. + BoundingBoxf print_extents(const BoundingBoxf &bed_ext) const; std::string generate_test(double start_pa = 0, double step_pa = 0.002, int count = 50); @@ -379,4 +381,4 @@ private: const double m_glyph_padding_vertical{1}; }; -} // namespace Slic3r \ No newline at end of file +} // namespace Slic3r