diff --git a/src/libslic3r/Calib.cpp b/src/libslic3r/Calib.cpp index 0718f68287..b210d36721 100644 --- a/src/libslic3r/Calib.cpp +++ b/src/libslic3r/Calib.cpp @@ -1,221 +1,748 @@ #include "Calib.hpp" -#include "Point.hpp" -#include "PrintConfig.hpp" -#include "GCodeWriter.hpp" +#include "Config.hpp" +#include "Model.hpp" #include "GCode.hpp" -#include +#include namespace Slic3r { +float CalibPressureAdvance::find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx) +{ + const double general_suggested_min_speed = 100.0; + double filament_max_volumetric_speed = config.option("filament_max_volumetric_speed")->get_at(0); + Flow pattern_line = Flow(line_width, layer_height, config.option("nozzle_diameter")->get_at(0)); + auto pa_speed = std::min(std::max(general_suggested_min_speed, config.option("outer_wall_speed")->value), + filament_max_volumetric_speed / pattern_line.mm3_per_mm()); - calib_pressure_advance::calib_pressure_advance(GCode* gcodegen) :mp_gcodegen(gcodegen), m_length_short(20.0), m_length_long(40.0), m_space_y(3.5), m_line_width(0.6), m_draw_numbers(true) {} + return std::floor(pa_speed); +} - std::string calib_pressure_advance::generate_test(double start_pa, double step_pa, int count ) { - BoundingBoxf bed_ext = get_extents(mp_gcodegen->config().printable_area.values); - bool is_delta = false; - if (mp_gcodegen->config().printable_area.values.size() > 4) { - is_delta = true; - bed_ext.scale(1.0f / 1.41421f); - } +std::string CalibPressureAdvance::move_to(Vec2d pt, GCodeWriter &writer, std::string comment) +{ + std::stringstream gcode; - auto bed_sizes = mp_gcodegen->config().printable_area.values; - const auto &w = bed_ext.size().x(); - const auto &h = bed_ext.size().y(); - count = std::min(count, int((h - 10) / m_space_y)); + gcode << writer.retract(); + gcode << writer.travel_to_xy(pt, comment); + gcode << writer.unretract(); - m_length_long = 40 + std::min(w - 120.0, 0.0); + m_last_pos = Vec3d(pt.x(), pt.y(), 0); - auto startx = (w - m_length_short * 2 - m_length_long - 20) / 2; - auto starty = (h - count * m_space_y) / 2; - if (is_delta) { - startx = -startx; - starty = -(count * m_space_y) / 2; - } + return gcode.str(); +} - return print_pa_lines(startx, starty, start_pa, step_pa, count); - } +double CalibPressureAdvance::e_per_mm(double line_width, double layer_height, float nozzle_diameter, float filament_diameter, float print_flow_ratio) const +{ + const Flow line_flow = Flow(line_width, layer_height, nozzle_diameter); + const double filament_area = M_PI * std::pow(filament_diameter / 2, 2); - std::string calib_pressure_advance::move_to(Vec2d pt) { - std::stringstream gcode; - gcode << mp_gcodegen->retract(); - gcode << mp_gcodegen->writer().travel_to_xyz(Vec3d(pt.x(), pt.y(), 0.2)); - gcode << mp_gcodegen->unretract(); - return gcode.str(); - } + return line_flow.mm3_per_mm() / filament_area * print_flow_ratio; +} - std::string calib_pressure_advance::print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num) { +std::string CalibPressureAdvance::convert_number_to_string(double num) const +{ + auto sNumber = std::to_string(num); + sNumber.erase(sNumber.find_last_not_of('0') + 1, std::string::npos); + sNumber.erase(sNumber.find_last_not_of('.') + 1, std::string::npos); - auto& writer = mp_gcodegen->writer(); - Flow line_flow = Flow(m_line_width, 0.2, mp_gcodegen->config().nozzle_diameter.get_at(0)); - Flow thin_line_flow = Flow(0.44, 0.2, mp_gcodegen->config().nozzle_diameter.get_at(0)); - const double e_calib = line_flow.mm3_per_mm() / 2.40528; // filament_mm/extrusion_mm - const double e = thin_line_flow.mm3_per_mm() / 2.40528; // filament_mm/extrusion_mm + return sNumber; +} +std::string CalibPressureAdvance::draw_digit( + double startx, double starty, char c, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, GCodeWriter &writer) +{ + const double len = m_digit_segment_len; + const double gap = line_width / 2.0; - const double fast = m_fast_speed * 60.0; - const double slow = m_slow_speed * 60.0; - std::stringstream gcode; - gcode << mp_gcodegen->writer().travel_to_z(0.2); - double y_pos = start_y; + const auto dE = e_per_mm * len; + const auto two_dE = dE * 2; - // prime line - auto prime_x = start_x - 2; - gcode << move_to(Vec2d(prime_x, y_pos + (num - 4) * m_space_y)); - gcode << writer.set_speed(slow); - gcode << writer.extrude_to_xy(Vec2d(prime_x, y_pos + 3 * m_space_y), e_calib * m_space_y * num * 1.1); + Vec2d p0, p1, p2, p3, p4, p5; + Vec2d p0_5, p4_5; + Vec2d gap_p0_toward_p3, gap_p2_toward_p3; + Vec2d dot_direction; - for (int i = 0; i < num; ++i) { + if (mode == CalibPressureAdvance::DrawDigitMode::Bottom_To_Top) { + // 1-------2-------5 + // | | | + // | | | + // 0-------3-------4 + p0 = Vec2d(startx, starty); + p0_5 = Vec2d(startx, starty + len / 2); + p1 = Vec2d(startx, starty + len); + p2 = Vec2d(startx + len, starty + len); + p3 = Vec2d(startx + len, starty); + p4 = Vec2d(startx + len * 2, starty); + p4_5 = Vec2d(startx + len * 2, starty + len / 2); + p5 = Vec2d(startx + len * 2, starty + len); - gcode << writer.set_pressure_advance(start_pa + i * step_pa); - gcode << move_to(Vec2d(start_x, y_pos + i * m_space_y)); - gcode << writer.set_speed(slow); - gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + i * m_space_y), e_calib * m_length_short); - 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_calib * m_length_long); - 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_calib * m_length_short); + gap_p0_toward_p3 = p0 + Vec2d(gap, 0); + gap_p2_toward_p3 = p2 + Vec2d(0, gap); - } - 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)); - gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 7), e * 7); - gcode << move_to(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 7)); - gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 2), e * 7); - - 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); - } - } - return gcode.str(); - } - - - std::string calib_pressure_advance::draw_digit(double startx, double starty, char c) { - auto& writer = mp_gcodegen->writer(); - std::stringstream gcode; - const double lw = 0.48; - Flow line_flow = Flow(lw, 0.2, mp_gcodegen->config().nozzle_diameter.get_at(0)); - const double len = 2; - const double gap = lw / 2.0; - const double e = line_flow.mm3_per_mm() / 2.40528; // filament_mm/extrusion_mm - - // 0-------1 + dot_direction = Vec2d(-len / 2, 0); + } else { + // 0-------1 // | | // 3-------2 // | | // 4-------5 - const Vec2d p0(startx, starty); - const Vec2d p1(startx + len, starty); - const Vec2d p2(startx + len, starty - len); - const Vec2d p3(startx, starty - len); - const Vec2d p4(startx, starty - len * 2); - const Vec2d p5(startx + len, starty - len * 2); + p0 = Vec2d(startx, starty); + p0_5 = Vec2d(startx + len / 2, starty); + p1 = Vec2d(startx + len, starty); + p2 = Vec2d(startx + len, starty - len); + p3 = Vec2d(startx, starty - len); + p4 = Vec2d(startx, starty - len * 2); + p4_5 = Vec2d(startx + len / 2, starty - len * 2); + p5 = Vec2d(startx + len, starty - len * 2); - switch (c) - { - case '0': - gcode << move_to(p0); - gcode << writer.extrude_to_xy(p1, e * len); - gcode << writer.extrude_to_xy(p5, e * len * 2); - gcode << writer.extrude_to_xy(p4, e * len); - gcode << writer.extrude_to_xy(p0 - Vec2d(0, gap), e * len * 2); - break; - case '1': - gcode << move_to(p0 + Vec2d(len / 2, 0)); - gcode << writer.extrude_to_xy(p4 + Vec2d(len / 2, 0), e * len * 2); - break; - case '2': - gcode << move_to(p0); - gcode << writer.extrude_to_xy(p1, e * len); - gcode << writer.extrude_to_xy(p2, e * len); - gcode << writer.extrude_to_xy(p3, e * len); - gcode << writer.extrude_to_xy(p4, e * len); - gcode << writer.extrude_to_xy(p5, e * len); - break; - case '3': - gcode << move_to(p0); - gcode << writer.extrude_to_xy(p1, e * len); - gcode << writer.extrude_to_xy(p5, e * len * 2); - gcode << writer.extrude_to_xy(p4, e * len); - gcode << move_to(p2 - Vec2d(gap, 0)); - gcode << writer.extrude_to_xy(p3, e * len); - break; - case '4': - gcode << move_to(p0); - gcode << writer.extrude_to_xy(p3, e * len); - gcode << writer.extrude_to_xy(p2, e * len); - gcode << move_to(p1); - gcode << writer.extrude_to_xy(p5, e * len * 2); - break; - case '5': - gcode << move_to(p1); - gcode << writer.extrude_to_xy(p0, e * len); - gcode << writer.extrude_to_xy(p3, e * len); - gcode << writer.extrude_to_xy(p2, e * len); - gcode << writer.extrude_to_xy(p5, e * len); - gcode << writer.extrude_to_xy(p4, e * len); - break; - case '6': - gcode << move_to(p1); - gcode << writer.extrude_to_xy(p0, e * len); - gcode << writer.extrude_to_xy(p4, e * len * 2); - gcode << writer.extrude_to_xy(p5, e * len); - gcode << writer.extrude_to_xy(p2, e * len); - gcode << writer.extrude_to_xy(p3, e * len); - break; - case '7': - gcode << move_to(p0); - gcode << writer.extrude_to_xy(p1, e * len); - gcode << writer.extrude_to_xy(p5, e * len * 2); - break; - case '8': - gcode << move_to(p2); - gcode << writer.extrude_to_xy(p3, e * len); - gcode << writer.extrude_to_xy(p4, e * len); - gcode << writer.extrude_to_xy(p5, e * len); - gcode << writer.extrude_to_xy(p1, e * len * 2); - gcode << writer.extrude_to_xy(p0, e * len); - gcode << writer.extrude_to_xy(p3, e * len); - break; - case '9': - gcode << move_to(p5); - gcode << writer.extrude_to_xy(p1, e * len * 2); - gcode << writer.extrude_to_xy(p0, e * len); - gcode << writer.extrude_to_xy(p3, e * len); - gcode << writer.extrude_to_xy(p2, e * len); - break; - case '.': - gcode << move_to(p4 + Vec2d(len / 2, 0)); - gcode << writer.extrude_to_xy(p4 + Vec2d(len / 2, len / 2), e * len); - break; - default: - break; + gap_p0_toward_p3 = p0 - Vec2d(0, gap); + gap_p2_toward_p3 = p2 - Vec2d(gap, 0); + + dot_direction = Vec2d(0, len / 2); + } + + std::stringstream gcode; + + switch (c) { + case '0': + gcode << move_to(p0, writer, "Glyph: 0"); + gcode << writer.extrude_to_xy(p1, dE); + gcode << writer.extrude_to_xy(p5, two_dE); + gcode << writer.extrude_to_xy(p4, dE); + gcode << writer.extrude_to_xy(gap_p0_toward_p3, two_dE); + break; + case '1': + gcode << move_to(p0_5, writer, "Glyph: 1"); + gcode << writer.extrude_to_xy(p4_5, two_dE); + break; + case '2': + gcode << move_to(p0, writer, "Glyph: 2"); + gcode << writer.extrude_to_xy(p1, dE); + gcode << writer.extrude_to_xy(p2, dE); + gcode << writer.extrude_to_xy(p3, dE); + gcode << writer.extrude_to_xy(p4, dE); + gcode << writer.extrude_to_xy(p5, dE); + break; + case '3': + gcode << move_to(p0, writer, "Glyph: 3"); + gcode << writer.extrude_to_xy(p1, dE); + gcode << writer.extrude_to_xy(p5, two_dE); + gcode << writer.extrude_to_xy(p4, dE); + gcode << move_to(gap_p2_toward_p3, writer); + gcode << writer.extrude_to_xy(p3, dE); + break; + case '4': + gcode << move_to(p0, writer, "Glyph: 4"); + gcode << writer.extrude_to_xy(p3, dE); + gcode << writer.extrude_to_xy(p2, dE); + gcode << move_to(p1, writer); + gcode << writer.extrude_to_xy(p5, two_dE); + break; + case '5': + gcode << move_to(p1, writer, "Glyph: 5"); + gcode << writer.extrude_to_xy(p0, dE); + gcode << writer.extrude_to_xy(p3, dE); + gcode << writer.extrude_to_xy(p2, dE); + gcode << writer.extrude_to_xy(p5, dE); + gcode << writer.extrude_to_xy(p4, dE); + break; + case '6': + gcode << move_to(p1, writer, "Glyph: 6"); + gcode << writer.extrude_to_xy(p0, dE); + gcode << writer.extrude_to_xy(p4, two_dE); + gcode << writer.extrude_to_xy(p5, dE); + gcode << writer.extrude_to_xy(p2, dE); + gcode << writer.extrude_to_xy(p3, dE); + break; + case '7': + gcode << move_to(p0, writer, "Glyph: 7"); + gcode << writer.extrude_to_xy(p1, dE); + gcode << writer.extrude_to_xy(p5, two_dE); + break; + case '8': + gcode << move_to(p2, writer, "Glyph: 8"); + gcode << writer.extrude_to_xy(p3, dE); + gcode << writer.extrude_to_xy(p4, dE); + gcode << writer.extrude_to_xy(p5, dE); + gcode << writer.extrude_to_xy(p1, two_dE); + gcode << writer.extrude_to_xy(p0, dE); + gcode << writer.extrude_to_xy(p3, dE); + break; + case '9': + gcode << move_to(p5, writer, "Glyph: 9"); + gcode << writer.extrude_to_xy(p1, two_dE); + gcode << writer.extrude_to_xy(p0, dE); + gcode << writer.extrude_to_xy(p3, dE); + gcode << writer.extrude_to_xy(p2, dE); + break; + case '.': + gcode << move_to(p4_5, writer, "Glyph: ."); + gcode << writer.extrude_to_xy(p4_5 + dot_direction, dE); + break; + default: break; + } + + return gcode.str(); +} + +std::string CalibPressureAdvance::draw_number( + double startx, double starty, double value, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, double speed, GCodeWriter &writer) +{ + auto sNumber = convert_number_to_string(value); + std::stringstream gcode; + gcode << writer.set_speed(speed); + + for (std::string::size_type i = 0; i < sNumber.length(); ++i) { + if (i > m_max_number_len) { break; } + switch (mode) { + case DrawDigitMode::Bottom_To_Top: gcode << draw_digit(startx, starty + i * number_spacing(), sNumber[i], mode, line_width, e_per_mm, writer); break; + default: gcode << draw_digit(startx + i * number_spacing(), starty, sNumber[i], mode, line_width, e_per_mm, writer); + } + } + + return gcode.str(); +} + +CalibPressureAdvanceLine::CalibPressureAdvanceLine(GCode *gcodegen) + : mp_gcodegen(gcodegen) + , m_nozzle_diameter(gcodegen->config().nozzle_diameter.get_at(0)) +{ +} + +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); + if (is_delta()) { CalibPressureAdvanceLine::delta_scale_bed_ext(bed_ext); } + + auto bed_sizes = mp_gcodegen->config().printable_area.values; + const auto &w = bed_ext.size().x(); + const auto &h = bed_ext.size().y(); + count = std::min(count, int((h - 10) / m_space_y)); + + 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); } + + return print_pa_lines(startx, starty, start_pa, step_pa, count); +} + +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) +{ + auto & writer = mp_gcodegen->writer(); + const auto &config = mp_gcodegen->config(); + + const auto filament_diameter = config.filament_diameter.get_at(0); + const auto print_flow_ratio = config.print_flow_ratio; + + const double e_per_mm = CalibPressureAdvance::e_per_mm(m_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio); + const double thin_e_per_mm = CalibPressureAdvance::e_per_mm(m_thin_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio); + const double number_e_per_mm = CalibPressureAdvance::e_per_mm(m_number_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio); + + const double fast = CalibPressureAdvance::speed_adjust(m_fast_speed); + const double slow = CalibPressureAdvance::speed_adjust(m_slow_speed); + std::stringstream gcode; + gcode << mp_gcodegen->writer().travel_to_z(m_height_layer); + 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); + 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); + + 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 << 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 << 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 << 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); + } + 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); + + 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); + } + } + return gcode.str(); +} + +void CalibPressureAdvanceLine::delta_modify_start(double &startx, double &starty, int count) +{ + startx = -startx; + starty = -(count * m_space_y) / 2; +} + +CalibPressureAdvancePattern::CalibPressureAdvancePattern(const Calib_Params ¶ms, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin) + : m_params(params) +{ + this->m_draw_digit_mode = DrawDigitMode::Bottom_To_Top; + + refresh_setup(config, is_bbl_machine, model, origin); +}; + +void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin) +{ + std::stringstream gcode; + gcode << "; start pressure advance pattern for layer\n"; + + refresh_setup(config, is_bbl_machine, model, origin); + + gcode << move_to(Vec2d(m_starting_point.x(), m_starting_point.y()), m_writer, "Move to start XY position"); + 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); + + // create anchoring frame + gcode << draw_box(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(), + 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) { + if (i > 0) { + gcode << "; end pressure advance pattern for layer\n"; + CustomGCode::Item item; + item.print_z = height_first_layer() + (i - 1) * height_layer(); + item.type = CustomGCode::Type::Custom; + item.extra = gcode.str(); + gcode_items.push_back(item); + + 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"); } - return gcode.str(); - } - // draw number - std::string calib_pressure_advance::draw_number(double startx, double starty, double value) { - double spacing = 3.0; - auto sNumber = std::to_string(value); - sNumber.erase(sNumber.find_last_not_of('0') + 1, std::string::npos); - sNumber.erase(sNumber.find_last_not_of('.') + 1, std::string::npos); - std::stringstream gcode; - gcode << mp_gcodegen->writer().set_speed(3600); + // line numbering + if (i == 1) { + gcode << m_writer.set_pressure_advance(m_params.start); + double number_e_per_mm = e_per_mm(line_width(), height_layer(), 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)); - for (int i = 0; i < sNumber.length(); ++i) { - if (i > 5) - break; - gcode << draw_digit(startx + i * spacing, starty, sNumber[i]); - + // glyph on every other line + 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, speed_first_layer(), m_writer); + } } - return gcode.str(); + 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; + + // shrink first layer to fit inside frame + if (i == 0) { + double shrink = (line_spacing_first_layer() * (wall_count() - 1) + (line_width_first_layer() * (1 - m_encroachment))) / std::sin(to_radians(m_corner_angle) / 2); + side_length = m_wall_side_length - shrink; + to_x += shrink * std::sin(to_radians(90) - to_radians(m_corner_angle) / 2); + to_y += line_spacing_first_layer() * (wall_count() - 1) + (line_width_first_layer() * (1 - m_encroachment)); + } + + double initial_x = to_x; + double initial_y = to_y; + + gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to pattern start"); + + for (int j = 0; j < num_patterns; ++j) { + // increment pressure advance + gcode << m_writer.set_pressure_advance(m_params.start + (j * m_params.step)); + + 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; + + 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); + + 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); + + to_y = initial_y; + if (k != wall_count() - 1) { + // perimeters not done yet. move to next perimeter + to_x += line_spacing_angle(); + gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to start next pattern wall"); + } else if (j != num_patterns - 1) { + // patterns not done yet. move to next pattern + to_x += m_pattern_spacing + line_width(); + gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to next pattern"); + } else if (i != m_num_layers - 1) { + // layers not done yet. move back to start + to_x = initial_x; + gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move back to start position"); + } else { + // everything done + } + } + } } + + gcode << m_writer.set_pressure_advance(m_params.start); + gcode << "; end pressure advance pattern for layer\n"; + + CustomGCode::Item item; + item.print_z = max_layer_z(); + item.type = CustomGCode::Type::Custom; + item.extra = gcode.str(); + gcode_items.push_back(item); + + CustomGCode::Info info; + info.mode = CustomGCode::Mode::SingleExtruder; + info.gcodes = gcode_items; + + model.plates_custom_gcodes[model.curr_plate_index] = info; +} + +void CalibPressureAdvancePattern::refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin) +{ + m_config = 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) +{ + 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) +{ + PrintConfig print_config; + print_config.apply(m_config, true); + + m_writer.apply_print_config(print_config); + m_writer.set_xy_offset(origin(0), origin(1)); + //m_writer.set_is_bbl_machine(is_bbl_machine); + + const unsigned int extruder_id = model.objects.front()->volumes.front()->extruder_id(); + m_writer.set_extruders({extruder_id}); + 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()) + + std::cos(to_radians(m_corner_angle) / 2) * m_wall_side_length + line_spacing_first_layer() * wall_count(); +} + +double CalibPressureAdvancePattern::object_size_y() const +{ + return 2 * (std::sin(to_radians(m_corner_angle) / 2) * m_wall_side_length) + max_numbering_height() + m_glyph_padding_vertical * 2 + line_width_first_layer(); +} + +double CalibPressureAdvancePattern::glyph_start_x(int pattern_i) const +{ + // note that pattern_i is zero-based! + // align glyph's start with first perimeter of specified pattern + double x = + // starting offset + m_starting_point.x() + pattern_shift() + + + // width of pattern extrusions + pattern_i * (wall_count() - 1) * line_spacing_angle() + // center to center distance of extrusions + pattern_i * line_width() + // endcaps. center to end on either side = 1 line width + + // space between each pattern + pattern_i * m_pattern_spacing; + + // align to middle of pattern walls + x += wall_count() * line_spacing_angle() / 2; + + // shift so glyph is centered on pattern + // m_digit_segment_len = half of X length of glyph + x -= (glyph_length_x() / 2); + + return x; +} + +double CalibPressureAdvancePattern::glyph_length_x() const +{ + // half of line_width sticks out on each side + return line_width() + (2 * m_digit_segment_len); +} + +double CalibPressureAdvancePattern::glyph_tab_max_x() const +{ + // only every other glyph is shown, starting with 1 + int num = get_num_patterns(); + int max_num = (num % 2 == 0) ? num - 1 : num; + + // padding at end should be same as padding at start + double padding = glyph_start_x(0) - m_starting_point.x(); + + return glyph_start_x(max_num - 1) + // glyph_start_x is zero-based + (glyph_length_x() - line_width() / 2) + padding; +} + +double CalibPressureAdvancePattern::max_numbering_height() const +{ + std::string::size_type most_characters = 0; + const int num_patterns = get_num_patterns(); + + // note: only every other number is printed + for (std::string::size_type i = 0; i < num_patterns; i += 2) { + std::string sNumber = convert_number_to_string(m_params.start + (i * m_params.step)); + + if (sNumber.length() > most_characters) { most_characters = sNumber.length(); } + } + + most_characters = std::min(most_characters, m_max_number_len); + + return (most_characters * m_digit_segment_len) + ((most_characters - 1) * m_digit_gap_len); +} + +double CalibPressureAdvancePattern::pattern_shift() const { return (wall_count() - 1) * line_spacing_first_layer() + line_width_first_layer() + m_glyph_padding_horizontal; } } // namespace Slic3r diff --git a/src/libslic3r/Calib.hpp b/src/libslic3r/Calib.hpp index b7a9981d89..9311f244a2 100644 --- a/src/libslic3r/Calib.hpp +++ b/src/libslic3r/Calib.hpp @@ -1,14 +1,18 @@ #pragma once -#include -#include "Point.hpp" +#include "GCodeWriter.hpp" +#include "PrintConfig.hpp" +#include "BoundingBox.hpp" + namespace Slic3r { class GCode; +class Model; enum class CalibMode : int { Calib_None = 0, Calib_PA_Line, + Calib_PA_Pattern, Calib_PA_Tower, Calib_Flow_Rate, Calib_Temp_Tower, @@ -119,34 +123,185 @@ public: int confidence; // 0: success 1: uncertain 2: failed }; -class calib_pressure_advance +class CalibPressureAdvance { public: - calib_pressure_advance(GCode *gcodegen); - ~calib_pressure_advance() {} + static float find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx = 0); + +protected: + CalibPressureAdvance() = default; + ~CalibPressureAdvance() = default; + + enum class DrawDigitMode { Left_To_Right, Bottom_To_Top }; + + void delta_scale_bed_ext(BoundingBoxf &bed_ext) const { bed_ext.scale(1.0f / 1.41421f); } + + std::string move_to(Vec2d pt, GCodeWriter &writer, std::string comment = std::string()); + double e_per_mm(double line_width, double layer_height, float nozzle_diameter, float filament_diameter, float print_flow_ratio) const; + double speed_adjust(int speed) const { return speed * 60; }; + + std::string convert_number_to_string(double num) const; + double number_spacing() const { return m_digit_segment_len + m_digit_gap_len; }; + std::string draw_digit(double startx, double starty, char c, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, GCodeWriter &writer); + 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; + + DrawDigitMode m_draw_digit_mode{DrawDigitMode::Left_To_Right}; + const double m_digit_segment_len{2}; + const double m_digit_gap_len{1}; + const std::string::size_type m_max_number_len{5}; +}; + +class CalibPressureAdvanceLine : public CalibPressureAdvance +{ +public: + CalibPressureAdvanceLine(GCode *gcodegen); + ~CalibPressureAdvanceLine(){}; std::string generate_test(double start_pa = 0, double step_pa = 0.002, int count = 50); - void set_speed(double fast = 100.0, double slow = 20.0) + + void set_speed(double fast = 100.0, double slow = 20.0) { m_slow_speed = slow; m_fast_speed = fast; } - double &line_width() { return m_line_width; }; - bool & draw_numbers() { return m_draw_numbers; } + + const double &line_width() { return m_line_width; }; + bool is_delta() const; + bool & draw_numbers() { return m_draw_numbers; } private: - std::string move_to(Vec2d pt); std::string print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num); - std::string draw_digit(double startx, double starty, char c); - std::string draw_number(double startx, double starty, double value); + + void delta_modify_start(double &startx, double &starty, int count); + + GCode *mp_gcodegen; + + 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}; + const double m_space_y{3.5}; + + double m_length_short{20.0}, m_length_long{40.0}; + bool m_draw_numbers{true}; +}; + +struct SuggestedConfigCalibPAPattern +{ + const std::vector> float_pairs{{"initial_layer_print_height", 0.25}, {"layer_height", 0.2}, {"initial_layer_speed", 30}}; + + const std::vector> nozzle_ratio_pairs{{"line_width", 112.5}, {"initial_layer_line_width", 140}}; + + const std::vector> int_pairs{{"skirt_loops", 0}, {"wall_loops", 3}}; + + const std::pair brim_pair{"brim_type", BrimType::btNoBrim}; +}; + +class CalibPressureAdvancePattern : public CalibPressureAdvance +{ + friend struct DrawLineOptArgs; + friend struct DrawBoxOptArgs; + +public: + CalibPressureAdvancePattern(const Calib_Params ¶ms, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin); + + double handle_xy_size() const { return m_handle_xy_size; }; + double handle_spacing() const { return m_handle_spacing; }; + double print_size_x() const { return object_size_x() + pattern_shift(); }; + double print_size_y() const { return object_size_y(); }; + double max_layer_z() const { return height_first_layer() + ((m_num_layers - 1) * height_layer()); }; + + void generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin); + +protected: + double speed_first_layer() const { return m_config.option("initial_layer_speed")->value; }; + double speed_perimeter() const { return m_config.option("outer_wall_speed")->value; }; + double line_width_first_layer() const { return m_config.get_abs_value("initial_layer_line_width"); }; + double line_width() const { return m_config.get_abs_value("line_width"); }; + int wall_count() const { return m_config.option("wall_loops")->value; }; private: - GCode *mp_gcodegen; - double m_length_short, m_length_long; - double m_space_y; - double m_slow_speed, m_fast_speed; - double m_line_width; - bool m_draw_numbers; + 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); + + double height_first_layer() const { return m_config.option("initial_layer_print_height")->value; }; + 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 + https://manual.slic3r.org/advanced/flow-math + https://ellis3dp.com/Print-Tuning-Guide/articles/misconceptions.html#two-04mm-perimeters--08mm + */ + double line_spacing() const { return line_width() - height_layer() * (1 - M_PI / 4); }; + double line_spacing_first_layer() const { return line_width_first_layer() - height_first_layer() * (1 - M_PI / 4); }; + double line_spacing_angle() const { return line_spacing() / std::sin(to_radians(m_corner_angle) / 2); }; + + double object_size_x() const; + double object_size_y() const; + double frame_size_y() const { return std::sin(to_radians(double(m_corner_angle) / 2)) * m_wall_side_length * 2; }; + + double glyph_start_x(int pattern_i = 0) const; + double glyph_length_x() const; + double glyph_tab_max_x() const; + double max_numbering_height() const; + + double pattern_shift() const; + + const Calib_Params &m_params; + + DynamicPrintConfig m_config; + GCodeWriter m_writer; + bool m_is_delta; + Vec3d m_starting_point; + + const double m_handle_xy_size{5}; + const double m_handle_spacing{2}; + const int m_num_layers{4}; + + 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}; }; } // namespace Slic3r diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 9d78f0fdf8..0c316aae04 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1916,7 +1916,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato gcode += m_writer.set_jerk_xy(jerk); } - calib_pressure_advance pa_test(this); + CalibPressureAdvanceLine pa_test(this); double filament_max_volumetric_speed = m_config.option("filament_max_volumetric_speed")->get_at(initial_extruder_id); Flow pattern_line = Flow(pa_test.line_width(), 0.2, m_config.nozzle_diameter.get_at(0)); auto fast_speed = std::min(print.default_region_config().outer_wall_speed.value, filament_max_volumetric_speed / pattern_line.mm3_per_mm()); diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 2e0514ca8e..d9d8a1be43 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -77,6 +77,10 @@ Model& Model::assign_copy(const Model &rhs) this->plates_custom_gcodes = rhs.plates_custom_gcodes; this->curr_plate_index = rhs.curr_plate_index; + if (rhs.calib_pa_pattern) { + this->calib_pa_pattern = std::make_unique(CalibPressureAdvancePattern(*rhs.calib_pa_pattern)); + } + // BBS: for design info this->design_info = rhs.design_info; this->model_info = rhs.model_info; @@ -105,6 +109,7 @@ Model& Model::assign_copy(Model &&rhs) // BBS this->plates_custom_gcodes = std::move(rhs.plates_custom_gcodes); this->curr_plate_index = rhs.curr_plate_index; + this->calib_pa_pattern = std::move(rhs.calib_pa_pattern); //BBS: add auxiliary path logic // BBS: backup, all in one temp dir @@ -910,6 +915,7 @@ void Model::load_from(Model& model) model.design_info.reset(); model.model_info.reset(); model.profile_info.reset(); + model.calib_pa_pattern.reset(); } // BBS: backup diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index d3efbaa197..ceb88148a6 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -21,6 +21,8 @@ //BBS: add stl #include "Format/STL.hpp" +#include "Calib.hpp" + #include #include #include @@ -1624,6 +1626,8 @@ public: // Checks if any of objects is painted using the multi-material painting gizmo. bool is_mm_painted() const; + std::unique_ptr calib_pa_pattern; + private: explicit Model(int) : ObjectBase(-1) { diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index bbea9d1980..d5daf3ee13 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -677,6 +677,25 @@ std::string Preset::get_current_printer_type(PresetBundle *preset_bundle) return ""; } +bool Preset::has_lidar(PresetBundle *preset_bundle) +{ + bool has_lidar = false; + if (preset_bundle) { + auto config = &preset_bundle->printers.get_edited_preset().config; + std::string vendor_name; + for (auto vendor_profile : preset_bundle->vendors) { + for (auto vendor_model : vendor_profile.second.models) + if (vendor_model.name == config->opt_string("printer_model")) { + vendor_name = vendor_profile.first; + break; + } + } + if (!vendor_name.empty()) + has_lidar = vendor_name.compare("BBL") == 0 ? true : false; + } + return has_lidar; +} + bool Preset::is_custom_defined() { if (custom_defined == "1") diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index 960aade378..b3a5d775bd 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -300,6 +300,8 @@ public: std::string get_filament_type(std::string &display_filament_type); std::string get_printer_type(PresetBundle *preset_bundle); // get edited preset type std::string get_current_printer_type(PresetBundle *preset_bundle); // get current preset type + + bool has_lidar(PresetBundle *preset_bundle); bool is_custom_defined(); bool is_bbl_vendor_preset(PresetBundle *preset_bundle); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 956d3e65fb..d92d99dd72 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -738,7 +738,7 @@ void Preview::load_print_as_fff(bool keep_z_range, bool only_gcode) unsigned int number_extruders = wxGetApp().is_editor() ? (unsigned int)print->extruders().size() : m_canvas->get_gcode_extruders_count(); - std::vector gcodes = wxGetApp().is_editor() ? + std::vector gcodes = wxGetApp().is_editor() ? //BBS wxGetApp().plater()->model().get_curr_plate_custom_gcodes().gcodes : m_canvas->get_custom_gcode_per_print_z(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index de4b9852c3..d490d20224 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -8351,55 +8351,140 @@ void Plater::calib_pa(const Calib_Params ¶ms) const auto calib_pa_name = wxString::Format(L"Pressure Advance Test"); new_project(false, false, calib_pa_name); wxGetApp().mainframe->select_tab(size_t(MainFrame::tp3DEditor)); - if (params.mode == CalibMode::Calib_PA_Line) { - add_model(false, Slic3r::resources_dir() + "/calib/pressure_advance/pressure_advance_test.stl"); - } else { - add_model(false, Slic3r::resources_dir() + "/calib/pressure_advance/tower_with_seam.stl"); - auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; - auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; - auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config; - filament_config->set_key_value("slow_down_layer_time", new ConfigOptionInts{1}); - // todo: for 3rd printer - //print_config->set_key_value("default_jerk", new ConfigOptionFloat(1.0f)); - //print_config->set_key_value("outer_wall_jerk", new ConfigOptionFloat(1.0f)); - //print_config->set_key_value("inner_wall_jerk", new ConfigOptionFloat(1.0f)); - if (print_config->option>("wall_generator")->value == PerimeterGeneratorType::Arachne) - print_config->set_key_value("wall_transition_angle", new ConfigOptionFloat(25)); - model().objects[0]->config.set_key_value("seam_position", new ConfigOptionEnum(spRear)); - - changed_objects({0}); - wxGetApp().get_tab(Preset::TYPE_PRINT)->update_dirty(); - wxGetApp().get_tab(Preset::TYPE_FILAMENT)->update_dirty(); - wxGetApp().get_tab(Preset::TYPE_PRINTER)->update_dirty(); - wxGetApp().get_tab(Preset::TYPE_PRINT)->reload_config(); - wxGetApp().get_tab(Preset::TYPE_FILAMENT)->reload_config(); - wxGetApp().get_tab(Preset::TYPE_PRINTER)->reload_config(); - - auto new_height = std::ceil((params.end - params.start) / params.step) + 1; - auto obj_bb = model().objects[0]->bounding_box(); - if (new_height < obj_bb.size().z()) { - std::array plane_pts = get_cut_plane(obj_bb, new_height); - cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower); - } - - // automatic selection of added objects - // update printable state for new volumes on canvas3D - wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects({0}); - - Selection &selection = p->view3D->get_canvas3d()->get_selection(); - selection.clear(); - selection.add_object(0, false); - - // BBS: update object list selection - p->sidebar->obj_list()->update_selections(); - selection.notify_instance_update(-1, -1); - if (p->view3D->get_canvas3d()->get_gizmos_manager().is_enabled()) - // this is required because the selected object changed and the flatten on face an sla support gizmos need to be updated accordingly - p->view3D->get_canvas3d()->update_gizmos_on_off_state(); + switch (params.mode) { + case CalibMode::Calib_PA_Line: + add_model(false, Slic3r::resources_dir() + "/calib/pressure_advance/pressure_advance_test.stl"); + break; + case CalibMode::Calib_PA_Pattern: + _calib_pa_pattern(params); + break; + case CalibMode::Calib_PA_Tower: + _calib_pa_tower(params); + break; + default: break; } + p->background_process.fff_print()->set_calib_params(params); } +void Plater::_calib_pa_pattern(const Calib_Params ¶ms) +{ + // add "handle" cube + sidebar().obj_list()->load_generic_subobject("Cube", ModelVolumeType::INVALID); + orient(); + changed_objects({0}); + _calib_pa_select_added_objects(); + + const DynamicPrintConfig &printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config; + DynamicPrintConfig & print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + float nozzle_diameter = printer_config.option("nozzle_diameter")->get_at(0); + + for (const auto opt : SuggestedConfigCalibPAPattern().float_pairs) { + print_config.set_key_value(opt.first, new ConfigOptionFloat(opt.second)); + } + print_config.set_key_value("outer_wall_speed", + new ConfigOptionFloat(CalibPressureAdvance::find_optimal_PA_speed( + wxGetApp().preset_bundle->full_config(), print_config.get_abs_value("line_width"), + print_config.get_abs_value("layer_height"), 0))); + + for (const auto opt : SuggestedConfigCalibPAPattern().nozzle_ratio_pairs) { + print_config.set_key_value(opt.first, new ConfigOptionFloat(nozzle_diameter * opt.second / 100)); + } + + for (const auto opt : SuggestedConfigCalibPAPattern().int_pairs) { + print_config.set_key_value(opt.first, new ConfigOptionInt(opt.second)); + } + + print_config.set_key_value(SuggestedConfigCalibPAPattern().brim_pair.first, + new ConfigOptionEnum(SuggestedConfigCalibPAPattern().brim_pair.second)); + + wxGetApp().get_tab(Preset::TYPE_PRINT)->update_dirty(); + wxGetApp().get_tab(Preset::TYPE_PRINT)->reload_config(); + + const DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config(); + PresetBundle * preset_bundle = wxGetApp().preset_bundle; + const bool is_bbl_machine = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle); + const Vec3d plate_origin = get_partplate_list().get_current_plate_origin(); + CalibPressureAdvancePattern pa_pattern(params, full_config, is_bbl_machine, model(), plate_origin); + + // scale cube to suit test + GizmoObjectManipulation &giz_obj_manip = p->view3D->get_canvas3d()->get_gizmos_manager().get_object_manipulation(); + giz_obj_manip.set_uniform_scaling(true); + giz_obj_manip.on_change("size", 0, pa_pattern.handle_xy_size()); + giz_obj_manip.set_uniform_scaling(false); + giz_obj_manip.on_change("size", 2, pa_pattern.max_layer_z()); + // start with pattern centered on plate + center_selection(); + const Vec3d plate_center = get_partplate_list().get_curr_plate()->get_center_origin(); + giz_obj_manip.on_change("position", 0, plate_center.x() - (pa_pattern.print_size_x() / 2)); + giz_obj_manip.on_change("position", 1, plate_center.y() - (pa_pattern.print_size_y() / 2) - pa_pattern.handle_spacing()); + + pa_pattern.generate_custom_gcodes(full_config, is_bbl_machine, model(), plate_origin); + model().calib_pa_pattern = std::make_unique(pa_pattern); + changed_objects({0}); +} + +void Plater::_calib_pa_tower(const Calib_Params ¶ms) +{ + add_model(false, Slic3r::resources_dir() + "/calib/pressure_advance/tower_with_seam.stl"); + + auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; + auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; + auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config; + + const float nozzle_diameter = printer_config->option("nozzle_diameter")->get_at(0); + + filament_config->set_key_value("slow_down_layer_time", new ConfigOptionInts{1}); + //print_config->set_key_value("default_jerk", new ConfigOptionFloat(1.0f)); + //print_config->set_key_value("outer_wall_jerk", new ConfigOptionFloat(1.0f)); + //print_config->set_key_value("inner_wall_jerk", new ConfigOptionFloat(1.0f)); + auto full_config = wxGetApp().preset_bundle->full_config(); + auto wall_speed = CalibPressureAdvance::find_optimal_PA_speed(full_config, full_config.get_abs_value("line_width"), + full_config.get_abs_value("layer_height"), 0); + print_config->set_key_value("outer_wall_speed", new ConfigOptionFloat(wall_speed)); + print_config->set_key_value("inner_wall_speed", new ConfigOptionFloat(wall_speed)); + // print_config->set_key_value("wall_generator", new ConfigOptionEnum(PerimeterGeneratorType::Classic)); + const auto _wall_generator = print_config->option>("wall_generator"); + if (_wall_generator->value == PerimeterGeneratorType::Arachne) print_config->set_key_value("wall_transition_angle", new ConfigOptionFloat(25)); + model().objects[0]->config.set_key_value("seam_position", new ConfigOptionEnum(spRear)); + + changed_objects({0}); + wxGetApp().get_tab(Preset::TYPE_PRINT)->update_dirty(); + wxGetApp().get_tab(Preset::TYPE_FILAMENT)->update_dirty(); + wxGetApp().get_tab(Preset::TYPE_PRINTER)->update_dirty(); + wxGetApp().get_tab(Preset::TYPE_PRINT)->reload_config(); + wxGetApp().get_tab(Preset::TYPE_FILAMENT)->reload_config(); + wxGetApp().get_tab(Preset::TYPE_PRINTER)->reload_config(); + + auto new_height = std::ceil((params.end - params.start) / params.step) + 1; + auto obj_bb = model().objects[0]->bounding_box(); + if (new_height < obj_bb.size().z()) { + std::array plane_pts = get_cut_plane(obj_bb, new_height); + cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower); + } + + _calib_pa_select_added_objects(); +} + +void Plater::_calib_pa_select_added_objects() +{ + // update printable state for new volumes on canvas3D + wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects({0}); + + Selection &selection = p->view3D->get_canvas3d()->get_selection(); + selection.clear(); + selection.add_object(0, false); + + // BBS: update object list selection + p->sidebar->obj_list()->update_selections(); + selection.notify_instance_update(-1, -1); + if (p->view3D->get_canvas3d()->get_gizmos_manager().is_enabled()) { + // this is required because the selected object changed and the flatten on face an sla support gizmos need to be updated accordingly + p->view3D->get_canvas3d()->update_gizmos_on_off_state(); + } +} + + void Plater::calib_flowrate(int pass) { if (pass != 1 && pass != 2) return; @@ -10568,6 +10653,19 @@ void Plater::reslice() // Stop arrange and (or) optimize rotation tasks. this->stop_jobs(); + // softfever: regenerate CalibPressureAdvancePattern custom G-code to apply changes + if (model().calib_pa_pattern) { + PresetBundle* preset_bundle = wxGetApp().preset_bundle; + + model().calib_pa_pattern->generate_custom_gcodes( + wxGetApp().preset_bundle->full_config(), + preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(preset_bundle), + model(), + get_partplate_list().get_current_plate_origin() + ); + } + + if (printer_technology() == ptSLA) { for (auto& object : model().objects) if (object->sla_points_status == sla::PointsStatus::NoPoints) diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 07ce3d5f2a..878cfc890f 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -736,6 +736,10 @@ private: // BBS: add project slice related functions int start_next_slice(); + void _calib_pa_pattern(const Calib_Params ¶ms); + void _calib_pa_tower(const Calib_Params ¶ms); + void _calib_pa_select_added_objects(); + friend class SuppressBackgroundProcessingUpdate; }; diff --git a/src/slic3r/GUI/calib_dlg.cpp b/src/slic3r/GUI/calib_dlg.cpp index 093dea0c39..22aa835542 100644 --- a/src/slic3r/GUI/calib_dlg.cpp +++ b/src/slic3r/GUI/calib_dlg.cpp @@ -51,7 +51,7 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* //choice_sizer->Add(m_rbExtruderType, 0, wxALL, 5); //choice_sizer->Add(FromDIP(5), 0, 0, wxEXPAND, 5); - wxString m_rbMethodChoices[] = { _L("PA Tower"), _L("PA Line") }; + wxString m_rbMethodChoices[] = { _L("PA Tower"), _L("PA Line"), _L("PA Pattern") }; int m_rbMethodNChoices = sizeof(m_rbMethodChoices) / sizeof(wxString); m_rbMethod = new wxRadioBox(this, wxID_ANY, _L("Method"), wxDefaultPosition, wxDefaultSize, m_rbMethodNChoices, m_rbMethodChoices, 2, wxRA_SPECIFY_COLS); m_rbMethod->SetSelection(0); @@ -75,7 +75,7 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* // start PA auto start_PA_sizer = new wxBoxSizer(wxHORIZONTAL); auto start_pa_text = new wxStaticText(this, wxID_ANY, start_pa_str, wxDefaultPosition, st_size, wxALIGN_LEFT); - m_tiStartPA = new TextInput(this, wxString::FromDouble(0.0), "", "", wxDefaultPosition, ti_size, wxTE_CENTRE | wxTE_PROCESS_ENTER); + m_tiStartPA = new TextInput(this, "", "", "", wxDefaultPosition, ti_size, wxTE_CENTRE | wxTE_PROCESS_ENTER); m_tiStartPA->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); start_PA_sizer->Add(start_pa_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2); @@ -85,7 +85,7 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* // end PA auto end_PA_sizer = new wxBoxSizer(wxHORIZONTAL); auto end_pa_text = new wxStaticText(this, wxID_ANY, end_pa_str, wxDefaultPosition, st_size, wxALIGN_LEFT); - m_tiEndPA = new TextInput(this, wxString::FromDouble(0.1), "", "", wxDefaultPosition, ti_size, wxTE_CENTRE | wxTE_PROCESS_ENTER); + m_tiEndPA = new TextInput(this, "", "", "", wxDefaultPosition, ti_size, wxTE_CENTRE | wxTE_PROCESS_ENTER); m_tiStartPA->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); end_PA_sizer->Add(end_pa_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2); end_PA_sizer->Add(m_tiEndPA, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2); @@ -94,7 +94,7 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* // PA step auto PA_step_sizer = new wxBoxSizer(wxHORIZONTAL); auto PA_step_text = new wxStaticText(this, wxID_ANY, PA_step_str, wxDefaultPosition, st_size, wxALIGN_LEFT); - m_tiPAStep = new TextInput(this, wxString::FromDouble(0.002), "", "", wxDefaultPosition, ti_size, wxTE_CENTRE | wxTE_PROCESS_ENTER); + m_tiPAStep = new TextInput(this, "", "", "", wxDefaultPosition, ti_size, wxTE_CENTRE | wxTE_PROCESS_ENTER); m_tiStartPA->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); PA_step_sizer->Add(PA_step_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2); PA_step_sizer->Add(m_tiPAStep, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2); @@ -120,6 +120,8 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* m_btnStart->Bind(wxEVT_BUTTON, &PA_Calibration_Dlg::on_start, this); v_sizer->Add(m_btnStart, 0, wxALL | wxALIGN_RIGHT, FromDIP(5)); + PA_Calibration_Dlg::reset_params(); + // Connect Events //m_rbExtruderType->Connect(wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(PA_Calibration_Dlg::on_extruder_type_changed), NULL, this); m_rbMethod->Connect(wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(PA_Calibration_Dlg::on_method_changed), NULL, this); @@ -149,6 +151,49 @@ PA_Calibration_Dlg::~PA_Calibration_Dlg() { m_btnStart->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PA_Calibration_Dlg::on_start), NULL, this); } +void PA_Calibration_Dlg::reset_params() { + Preset &printer_preset = wxGetApp().preset_bundle->printers.get_edited_preset(); + int extruder_type = printer_preset.config.opt_enum("extruder_type", 0); + bool isDDE =extruder_type == 0 ? true : false; + int method = m_rbMethod->GetSelection(); + + m_tiStartPA->GetTextCtrl()->SetValue(wxString::FromDouble(0.0)); + + switch (method) { + case 1: + m_params.mode = CalibMode::Calib_PA_Line; + m_tiEndPA->GetTextCtrl()->SetValue(wxString::FromDouble(0.1)); + m_tiPAStep->GetTextCtrl()->SetValue(wxString::FromDouble(0.002)); + m_cbPrintNum->SetValue(true); + m_cbPrintNum->Enable(true); + break; + case 2: + m_params.mode = CalibMode::Calib_PA_Pattern; + m_tiEndPA->GetTextCtrl()->SetValue(wxString::FromDouble(0.08)); + m_tiPAStep->GetTextCtrl()->SetValue(wxString::FromDouble(0.005)); + m_cbPrintNum->SetValue(true); + m_cbPrintNum->Enable(false); + break; + default: + m_params.mode = CalibMode::Calib_PA_Tower; + m_tiEndPA->GetTextCtrl()->SetValue(wxString::FromDouble(0.1)); + m_tiPAStep->GetTextCtrl()->SetValue(wxString::FromDouble(0.002)); + m_cbPrintNum->SetValue(false); + m_cbPrintNum->Enable(false); + break; + } + + if (!isDDE) { + m_tiEndPA->GetTextCtrl()->SetValue(wxString::FromDouble(1.0)); + + if (m_params.mode == CalibMode::Calib_PA_Pattern) { + m_tiPAStep->GetTextCtrl()->SetValue(wxString::FromDouble(0.05)); + } else { + m_tiPAStep->GetTextCtrl()->SetValue(wxString::FromDouble(0.02)); + } + } +} + void PA_Calibration_Dlg::on_start(wxCommandEvent& event) { bool read_double = false; read_double = m_tiStartPA->GetTextCtrl()->GetValue().ToDouble(&m_params.start); @@ -159,7 +204,18 @@ void PA_Calibration_Dlg::on_start(wxCommandEvent& event) { msg_dlg.ShowModal(); return; } - m_params.mode = m_rbMethod->GetSelection() == 0 ? CalibMode::Calib_PA_Tower : CalibMode::Calib_PA_Line; + + switch (m_rbMethod->GetSelection()) { + case 1: + m_params.mode = CalibMode::Calib_PA_Line; + break; + case 2: + m_params.mode = CalibMode::Calib_PA_Pattern; + break; + default: + m_params.mode = CalibMode::Calib_PA_Tower; + } + m_params.print_numbers = m_cbPrintNum->GetValue(); m_plater->calib_pa(m_params); @@ -167,41 +223,21 @@ void PA_Calibration_Dlg::on_start(wxCommandEvent& event) { } void PA_Calibration_Dlg::on_extruder_type_changed(wxCommandEvent& event) { - int selection = event.GetSelection(); - m_bDDE = selection == 0 ? true : false; - m_tiEndPA->GetTextCtrl()->SetValue(wxString::FromDouble(m_bDDE ? 0.1 : 1.0)); - m_tiStartPA->GetTextCtrl()->SetValue(wxString::FromDouble(0.0)); - m_tiPAStep->GetTextCtrl()->SetValue(wxString::FromDouble(m_bDDE ? 0.002 : 0.02)); + PA_Calibration_Dlg::reset_params(); event.Skip(); } void PA_Calibration_Dlg::on_method_changed(wxCommandEvent& event) { - int selection = event.GetSelection(); - m_params.mode = selection == 0 ? CalibMode::Calib_PA_Tower : CalibMode::Calib_PA_Line; - if (selection == 0) { - m_cbPrintNum->SetValue(false); - m_cbPrintNum->Enable(false); - } - else { - m_cbPrintNum->SetValue(true); - m_cbPrintNum->Enable(true); - } - + PA_Calibration_Dlg::reset_params(); event.Skip(); } - void PA_Calibration_Dlg::on_dpi_changed(const wxRect& suggested_rect) { this->Refresh(); Fit(); - } void PA_Calibration_Dlg::on_show(wxShowEvent& event) { - - if (m_rbMethod->GetSelection() == 0) - m_cbPrintNum->Enable(false); - else - m_cbPrintNum->Enable(true); + PA_Calibration_Dlg::reset_params(); } // Temp Calib dlg diff --git a/src/slic3r/GUI/calib_dlg.hpp b/src/slic3r/GUI/calib_dlg.hpp index a0b15e5d16..690fa87ec8 100644 --- a/src/slic3r/GUI/calib_dlg.hpp +++ b/src/slic3r/GUI/calib_dlg.hpp @@ -25,6 +25,7 @@ public: void on_dpi_changed(const wxRect& suggested_rect) override; void on_show(wxShowEvent& event); protected: + void reset_params(); virtual void on_start(wxCommandEvent& event); virtual void on_extruder_type_changed(wxCommandEvent& event); virtual void on_method_changed(wxCommandEvent& event);