G2 & G3 gcode-viewer support

supermerill/SuperSlicer#1456
also better handling of variable un-commented height change
default bed grid can scale up to big printers.
This commit is contained in:
supermerill 2021-08-22 15:41:54 +02:00
parent a2a2f38d41
commit da8cb11408
4 changed files with 138 additions and 5 deletions

View File

@ -940,7 +940,6 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
m_result.moves[i].layer_duration = 0;
}
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
std::cout << "\n";
m_mm3_per_mm_compare.output();
m_height_compare.output();
m_width_compare.output();
@ -1050,7 +1049,6 @@ void GCodeProcessor::process_klipper_ACTIVATE_EXTRUDER(const GCodeReader::GCodeL
void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
{
/* std::cout << line.raw() << std::endl; */
// update start position
m_start_position = m_end_position;
@ -1078,6 +1076,8 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
{
case 0: { process_G0(line); break; } // Move
case 1: { process_G1(line); break; } // Move
case 2: { process_G2_G3(line, false); break; } // Move
case 3: { process_G2_G3(line, true); break; } // Move
case 10: { process_G10(line); break; } // Retract
case 11: { process_G11(line); break; } // Unretract
case 20: { process_G20(line); break; } // Set Units to Inches
@ -1876,6 +1876,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
if (type == EMoveType::Extrude && m_end_position[Z] == 0.0f)
type = EMoveType::Travel;
float height_saved = -1;
if (type == EMoveType::Extrude) {
double delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
#if !ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
@ -1935,9 +1936,10 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// cross section: rectangle + 2 semicircles
m_width = float(delta_pos[E] * (M_PI * sqr(filament_radius)) / (delta_xyz * m_height) + (1.0 - 0.25 * M_PI) * m_height);
// if teh value seems wrong, fall back to circular extrusion from flow
// if the value seems wrong, fall back to circular extrusion from flow
if (m_width > m_height * 10 || m_width < m_height) {
m_width = 2 * std::sqrt(m_mm3_per_mm / float(PI));
height_saved = m_height;
m_height = m_width;
}
}
@ -2114,6 +2116,123 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// store move
store_move_vertex(type);
//restore
if(height_saved > 0)
m_height = height_saved;
}
void GCodeProcessor::emit_G1_from_G2(Vec2d dest, float e, float f) {
GCodeReader::FakeGCodeLine line_fake;
line_fake.set_x(dest.x());
line_fake.set_y(dest.y());
//line_fake.set_z(dest.z());
line_fake.set_e(e);
if( f > 0)
line_fake.set_f(f);
process_G1(line_fake);
}
void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool direct)
{
//check it has everything
float i = 0, j = 0;
bool has_i = line.has_value('I', i);
bool has_j = line.has_value('J', j);
if(!((line.has_x() || line.has_y()) && (has_i || has_j)))
return;
//compute points
// compute mult factor
float lengthsScaleFactor = (m_units == EUnits::Inches) ? INCHES_TO_MM : 1.0f;
Vec2d p_start = { m_end_position[Axis::X], m_end_position[Axis::Y] };
Vec2d p_end = { line.x() * lengthsScaleFactor, line.y() * lengthsScaleFactor };
Vec2d p_center = { i * lengthsScaleFactor, j * lengthsScaleFactor };
p_center += p_start;
// if relative positioning
if ((m_global_positioning_type == EPositioningType::Relative)) {
Vec2d p_to_add = { m_start_position[Axis::X], m_start_position[Axis::Y] };
p_end += p_to_add;
p_center += p_to_add;
}
// get missing values
if (!line.has_x())
p_end.x() = p_start.x();
if (!line.has_y())
p_end.y() = p_start.y();
if (!has_i)
p_center.x() = p_start.x();
if (!has_j)
p_center.y() = p_start.y();
//compute angles
double min_dist = m_width == 0 ? 1 : m_width * 4;
const double pi2 = 2 * PI;
const double radius = (p_start - p_center).norm();
const double radius2 = (p_end - p_center).norm();
if (std::abs(radius - radius2) > min_dist*0.1) {
BOOST_LOG_TRIVIAL(error) << "error, radius from start & end are too different in command '" << line.raw() << "'.";
return;
}
Vec2d p_start_rel = p_start - p_center;
Vec2d p_end_rel = p_end - p_center;
const double a1 = atan2(p_start_rel.y(), p_start_rel.x());
const double a2 = atan2(p_end_rel.y(), p_end_rel.x());
double adiff = a2 - a1;
//if (a1 < 0)
// a1 += pi2;
//if (a2 < 0)
// a2 += pi2;
if (adiff > pi2)
adiff -= pi2;
if (adiff < -pi2)
adiff += pi2;
//check order
if (direct) {
if (adiff < 0)
adiff += pi2;
} else {
if (adiff > 0)
adiff -= pi2;
}
double distance = std::abs(adiff * radius);
//get E
float dE = 0;
float start_e = m_start_position[E];
bool e_relative = true;
if (line.has_e()) {
e_relative = (m_e_local_positioning_type == EPositioningType::Relative);
double ret = line.e() * lengthsScaleFactor;
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
if (m_use_volumetric_e) {
float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_filament_diameters.size()) ? m_filament_diameters[m_extruder_id] : m_filament_diameters.back();
float filament_radius = 0.5f * filament_diameter;
double area_filament_cross_section = M_PI * sqr(filament_radius);
ret /= area_filament_cross_section;
}
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
dE = e_relative ? ret : m_origin[E] + ret - start_e;
}
//compute how much sections we need (~1 per 4 * width/nozzle)
int nb_sections = std::min(30, 1 + int(distance / min_dist));
Vec2d p_current = p_start;
float angle_incr = adiff / nb_sections;
float dE_incr = dE / nb_sections;
float current_angle = a1;
//create smaller sections
for (int i = 1; i < nb_sections;i++) {
current_angle += angle_incr;
p_current = { std::cos(current_angle) * radius, std::sin(current_angle) * radius };
p_current += p_center;
emit_G1_from_G2(p_current, e_relative ? dE_incr : start_e + i * dE_incr, line.has_f() ? line.f() : -1);
// update start position for next fake G1
m_start_position[X] = p_current.x();
m_start_position[Y] = p_current.y();
m_start_position[E] += dE_incr;
}
//emit last
emit_G1_from_G2(p_end, e_relative ? dE_incr : start_e + dE, line.has_f() ? line.f() : -1);
}
void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line)

View File

@ -507,6 +507,8 @@ namespace Slic3r {
// Move
void process_G0(const GCodeReader::GCodeLine& line);
void process_G1(const GCodeReader::GCodeLine& line);
void process_G2_G3(const GCodeReader::GCodeLine& line, bool direct);
void emit_G1_from_G2(Vec2d dest, float de, float f);
// Retract
void process_G10(const GCodeReader::GCodeLine& line);

View File

@ -72,6 +72,14 @@ public:
uint32_t m_mask;
friend class GCodeReader;
};
class FakeGCodeLine : public GCodeLine {
public:
void set_x(float x) { m_axis[X] = x; m_mask = (m_mask | (1 << int(X))); }
void set_y(float y) { m_axis[Y] = y; m_mask = (m_mask | (1 << int(Y))); }
void set_z(float z) { m_axis[Z] = z; m_mask = (m_mask | (1 << int(Z))); }
void set_e(float e) { m_axis[E] = e; m_mask = (m_mask | (1 << int(E))); }
void set_f(float f) { m_axis[F] = f; m_mask = (m_mask | (1 << int(F))); }
};
typedef std::function<void(GCodeReader&, const GCodeLine&)> callback_t;

View File

@ -337,7 +337,11 @@ void Bed3D::calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox)
Polylines axes_lines;
Polylines axes_lines_big;
Polylines axes_lines_small;
for (coord_t x = bed_bbox.min(0), idx= 0; x <= bed_bbox.max(0); x += scale_(5.0), idx++) {
coord_t square = scale_(5);
while (bed_bbox.radius() > square * 100) {
square *= 10;
}
for (coord_t x = bed_bbox.min(0), idx= 0; x <= bed_bbox.max(0); x += square, idx++) {
Polyline line;
line.append(Point(x, bed_bbox.min(1)));
line.append(Point(x, bed_bbox.max(1)));
@ -348,7 +352,7 @@ void Bed3D::calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox)
else
axes_lines.push_back(line);
}
for (coord_t y = bed_bbox.min(1), idx = 0; y <= bed_bbox.max(1); y += scale_(5.0), idx++) {
for (coord_t y = bed_bbox.min(1), idx = 0; y <= bed_bbox.max(1); y += square, idx++) {
Polyline line;
line.append(Point(bed_bbox.min(0), y));
line.append(Point(bed_bbox.max(0), y));