mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-18 04:08:02 -06:00
NEW: Add Ellis' pattern method for pressure advance calibration
Add a new calibration pattern method for pressure advance calibration, which can better test the influence of k value on the corner. The changes of this patch are picked from OrcaSlicer by thewildmage, thanks to thewildmage for the great work! github issue: https://github.com/bambulab/BambuStudio/issues/2222 Change-Id: Icc8fd4d52b20c1668bfa08716b48549dfada515b (cherry picked from commit eb72d8b681bef270906406a2d10a36d4efbce900) (cherry picked from commit 2b07c1154f4a009612f951938e7865dc338b2d9b)
This commit is contained in:
parent
d3785577ef
commit
047015fa5e
12 changed files with 1131 additions and 279 deletions
|
@ -1,23 +1,218 @@
|
|||
#include "Calib.hpp"
|
||||
#include "Point.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
#include "GCodeWriter.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "GCode.hpp"
|
||||
#include <map>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
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<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(0);
|
||||
Flow pattern_line = Flow(line_width, layer_height, config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0));
|
||||
auto pa_speed = std::min(std::max(general_suggested_min_speed, config.option<ConfigOptionFloat>("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;
|
||||
|
||||
gcode << writer.retract();
|
||||
gcode << writer.travel_to_xy(pt, comment);
|
||||
gcode << writer.unretract();
|
||||
|
||||
m_last_pos = Vec3d(pt.x(), pt.y(), 0);
|
||||
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return line_flow.mm3_per_mm() / filament_area * print_flow_ratio;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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 auto dE = e_per_mm * len;
|
||||
const auto two_dE = dE * 2;
|
||||
|
||||
Vec2d p0, p1, p2, p3, p4, p5;
|
||||
Vec2d p0_5, p4_5;
|
||||
Vec2d gap_p0_toward_p3, gap_p2_toward_p3;
|
||||
Vec2d dot_direction;
|
||||
|
||||
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);
|
||||
|
||||
gap_p0_toward_p3 = p0 + Vec2d(gap, 0);
|
||||
gap_p2_toward_p3 = p2 + Vec2d(0, gap);
|
||||
|
||||
dot_direction = Vec2d(-len / 2, 0);
|
||||
} else {
|
||||
// 0-------1
|
||||
// | |
|
||||
// 3-------2
|
||||
// | |
|
||||
// 4-------5
|
||||
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);
|
||||
|
||||
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();
|
||||
|
@ -27,195 +222,527 @@ namespace Slic3r {
|
|||
|
||||
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;
|
||||
}
|
||||
if (is_delta()) { CalibPressureAdvanceLine::delta_modify_start(startx, starty, count); }
|
||||
|
||||
return print_pa_lines(startx, starty, start_pa, step_pa, count);
|
||||
}
|
||||
}
|
||||
|
||||
std::string calib_pressure_advance::move_to(Vec2d pt) {
|
||||
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->retract();
|
||||
gcode << mp_gcodegen->writer().travel_to_xyz(Vec3d(pt.x(), pt.y(), 0.2));
|
||||
gcode << mp_gcodegen->unretract();
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string calib_pressure_advance::print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num) {
|
||||
|
||||
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
|
||||
|
||||
|
||||
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);
|
||||
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));
|
||||
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_calib * m_space_y * num * 1.1);
|
||||
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));
|
||||
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_calib * m_length_short);
|
||||
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_calib * m_length_long);
|
||||
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_calib * m_length_short);
|
||||
|
||||
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));
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
std::string calib_pressure_advance::draw_digit(double startx, double starty, char c) {
|
||||
auto& writer = mp_gcodegen->writer();
|
||||
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;
|
||||
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
|
||||
gcode << "; start pressure advance pattern for layer\n";
|
||||
|
||||
// 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);
|
||||
refresh_setup(config, is_bbl_machine, model, origin);
|
||||
|
||||
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;
|
||||
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<CustomGCode::Item> 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();
|
||||
// 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<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
|
||||
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
|
||||
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0));
|
||||
|
||||
// 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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
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<ConfigOptionPoints>("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<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
|
||||
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
|
||||
m_config.option<ConfigOptionFloats>("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 << mp_gcodegen->writer().set_speed(3600);
|
||||
|
||||
gcode << m_writer.set_speed(opt_args.speed);
|
||||
gcode << m_writer.extrude_to_xy(to_pt, dE, opt_args.comment);
|
||||
|
||||
for (int i = 0; i < sNumber.length(); ++i) {
|
||||
if (i > 5)
|
||||
break;
|
||||
gcode << draw_digit(startx + i * spacing, starty, sNumber[i]);
|
||||
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
|
||||
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#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)
|
||||
{
|
||||
m_slow_speed = slow;
|
||||
m_fast_speed = fast;
|
||||
}
|
||||
double &line_width() { return m_line_width; };
|
||||
|
||||
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<std::pair<std::string, double>> float_pairs{{"initial_layer_print_height", 0.25}, {"layer_height", 0.2}, {"initial_layer_speed", 30}};
|
||||
|
||||
const std::vector<std::pair<std::string, double>> nozzle_ratio_pairs{{"line_width", 112.5}, {"initial_layer_line_width", 140}};
|
||||
|
||||
const std::vector<std::pair<std::string, int>> int_pairs{{"skirt_loops", 0}, {"wall_loops", 3}};
|
||||
|
||||
const std::pair<std::string, BrimType> 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<ConfigOptionFloat>("initial_layer_speed")->value; };
|
||||
double speed_perimeter() const { return m_config.option<ConfigOptionFloat>("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<ConfigOptionInt>("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<ConfigOptionFloat>("initial_layer_print_height")->value; };
|
||||
double height_layer() const { return m_config.option<ConfigOptionFloat>("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
|
||||
|
|
|
@ -1890,7 +1890,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<ConfigOptionFloats>("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());
|
||||
|
|
|
@ -72,6 +72,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>(CalibPressureAdvancePattern(*rhs.calib_pa_pattern));
|
||||
}
|
||||
|
||||
// BBS: for design info
|
||||
this->design_info = rhs.design_info;
|
||||
this->model_info = rhs.model_info;
|
||||
|
@ -100,6 +104,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
|
||||
|
@ -893,6 +898,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
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
//BBS: add stl
|
||||
#include "Format/STL.hpp"
|
||||
|
||||
#include "Calib.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
@ -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<CalibPressureAdvancePattern> calib_pa_pattern;
|
||||
|
||||
private:
|
||||
explicit Model(int) : ObjectBase(-1)
|
||||
{
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<Item> gcodes = wxGetApp().is_editor() ?
|
||||
std::vector<CustomGCode::Item> gcodes = wxGetApp().is_editor() ?
|
||||
//BBS
|
||||
wxGetApp().plater()->model().get_curr_plate_custom_gcodes().gcodes :
|
||||
m_canvas->get_custom_gcode_per_print_z();
|
||||
|
|
|
@ -8337,20 +8337,101 @@ 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) {
|
||||
switch (params.mode) {
|
||||
case CalibMode::Calib_PA_Line:
|
||||
add_model(false, Slic3r::resources_dir() + "/calib/pressure_advance/pressure_advance_test.stl");
|
||||
} else {
|
||||
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<ConfigOptionFloats>("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<BrimType>(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<CalibPressureAdvancePattern>(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<ConfigOptionFloats>("nozzle_diameter")->get_at(0);
|
||||
|
||||
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<ConfigOptionEnum<PerimeterGeneratorType>>("wall_generator")->value == PerimeterGeneratorType::Arachne)
|
||||
print_config->set_key_value("wall_transition_angle", new ConfigOptionFloat(25));
|
||||
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>(PerimeterGeneratorType::Classic));
|
||||
const auto _wall_generator = print_config->option<ConfigOptionEnum<PerimeterGeneratorType>>("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<SeamPosition>(spRear));
|
||||
|
||||
changed_objects({0});
|
||||
|
@ -8368,7 +8449,11 @@ void Plater::calib_pa(const Calib_Params ¶ms)
|
|||
cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower);
|
||||
}
|
||||
|
||||
// automatic selection of added objects
|
||||
_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});
|
||||
|
||||
|
@ -8379,13 +8464,13 @@ void Plater::calib_pa(const Calib_Params ¶ms)
|
|||
// 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())
|
||||
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();
|
||||
}
|
||||
p->background_process.fff_print()->set_calib_params(params);
|
||||
}
|
||||
|
||||
|
||||
void Plater::calib_flowrate(int pass)
|
||||
{
|
||||
if (pass != 1 && pass != 2) return;
|
||||
|
@ -10554,6 +10639,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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue