♻️ Common Bed Leveling object name, accessors (#24214)

This commit is contained in:
Scott Lahteine
2022-05-19 06:05:52 -05:00
committed by Scott Lahteine
parent 06c4a9acdb
commit b72f9277e9
47 changed files with 390 additions and 434 deletions

View File

@ -35,7 +35,7 @@
#include "../../../lcd/extui/ui_api.h"
#endif
LevelingBilinear bbl;
LevelingBilinear bedlevel;
xy_pos_t LevelingBilinear::grid_spacing,
LevelingBilinear::grid_start;
@ -258,8 +258,8 @@ void LevelingBilinear::print_leveling_grid(const bed_mesh_t* _z_values /*= NULL*
);
}
}
#endif // ABL_BILINEAR_SUBDIVISION
#endif // ABL_BILINEAR_SUBDIVISION
// Refresh after other values have been updated
void LevelingBilinear::refresh_bed_level() {

View File

@ -24,10 +24,12 @@
#include "../../../inc/MarlinConfigPre.h"
class LevelingBilinear {
private:
static xy_pos_t grid_spacing, grid_start;
static xy_float_t grid_factor;
public:
static bed_mesh_t z_values;
static xy_pos_t grid_spacing, grid_start;
private:
static xy_float_t grid_factor;
static xy_pos_t cached_rel;
static xy_int8_t cached_g;
@ -54,20 +56,15 @@ public:
static void print_leveling_grid(const bed_mesh_t* _z_values = NULL);
static void refresh_bed_level();
static bool has_mesh() { return !!grid_spacing.x; }
static bed_mesh_t& get_z_values() { return z_values; }
static const xy_pos_t& get_grid_spacing() { return grid_spacing; }
static const xy_pos_t& get_grid_start() { return grid_start; }
static float get_mesh_x(int16_t i) { return grid_start.x + i * grid_spacing.x; }
static float get_mesh_y(int16_t j) { return grid_start.y + j * grid_spacing.y; }
static bool mesh_is_valid() { return has_mesh(); }
static float get_mesh_x(const uint8_t i) { return grid_start.x + i * grid_spacing.x; }
static float get_mesh_y(const uint8_t j) { return grid_start.y + j * grid_spacing.y; }
static float get_z_correction(const xy_pos_t &raw);
static constexpr float get_z_offset() { return 0.0f; }
#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
static void line_to_destination(const_feedRate_t scaled_fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF);
#endif
};
extern LevelingBilinear bbl;
#define _GET_MESH_X(I) bbl.get_mesh_x(I)
#define _GET_MESH_Y(J) bbl.get_mesh_y(J)
#define Z_VALUES_ARR bbl.get_z_values()
extern LevelingBilinear bedlevel;

View File

@ -47,14 +47,11 @@
#endif
bool leveling_is_valid() {
return TERN1(MESH_BED_LEVELING, mbl.has_mesh())
&& TERN1(AUTO_BED_LEVELING_BILINEAR, bbl.has_mesh())
&& TERN1(AUTO_BED_LEVELING_UBL, ubl.mesh_is_valid());
return TERN1(HAS_MESH, bedlevel.mesh_is_valid());
}
/**
* Turn bed leveling on or off, fixing the current
* position as-needed.
* Turn bed leveling on or off, correcting the current position.
*
* Disable: Current position = physical position
* Enable: Current position = "unleveled" physical position
@ -65,24 +62,31 @@ void set_bed_leveling_enabled(const bool enable/*=true*/) {
if (can_change && enable != planner.leveling_active) {
auto _report_leveling = []{
if (DEBUGGING(LEVELING)) {
if (planner.leveling_active)
DEBUG_POS("Leveling ON", current_position);
else
DEBUG_POS("Leveling OFF", current_position);
}
};
_report_leveling();
planner.synchronize();
if (planner.leveling_active) { // leveling from on to off
if (DEBUGGING(LEVELING)) DEBUG_POS("Leveling ON", current_position);
// change unleveled current_position to physical current_position without moving steppers.
planner.apply_leveling(current_position);
planner.leveling_active = false; // disable only AFTER calling apply_leveling
if (DEBUGGING(LEVELING)) DEBUG_POS("...Now OFF", current_position);
}
else { // leveling from off to on
if (DEBUGGING(LEVELING)) DEBUG_POS("Leveling OFF", current_position);
planner.leveling_active = true; // enable BEFORE calling unapply_leveling, otherwise ignored
// change physical current_position to unleveled current_position without moving steppers.
planner.unapply_leveling(current_position);
if (DEBUGGING(LEVELING)) DEBUG_POS("...Now ON", current_position);
}
sync_plan_position();
_report_leveling();
}
}
@ -116,18 +120,9 @@ TemporaryBedLevelingState::TemporaryBedLevelingState(const bool enable) : saved(
*/
void reset_bed_level() {
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("reset_bed_level");
#if ENABLED(AUTO_BED_LEVELING_UBL)
ubl.reset();
#else
set_bed_leveling_enabled(false);
#if ENABLED(MESH_BED_LEVELING)
mbl.reset();
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
bbl.reset();
#elif ABL_PLANAR
planner.bed_level_matrix.set_to_identity();
#endif
#endif
IF_DISABLED(AUTO_BED_LEVELING_UBL, set_bed_leveling_enabled(false));
TERN_(HAS_MESH, bedlevel.reset());
TERN_(ABL_PLANAR, planner.bed_level_matrix.set_to_identity());
}
#if EITHER(AUTO_BED_LEVELING_BILINEAR, MESH_BED_LEVELING)

View File

@ -69,9 +69,6 @@ class TemporaryBedLevelingState {
#include "mbl/mesh_bed_leveling.h"
#endif
#define Z_VALUES(X,Y) Z_VALUES_ARR[X][Y]
#define _GET_MESH_POS(M) { _GET_MESH_X(M.a), _GET_MESH_Y(M.b) }
#if EITHER(AUTO_BED_LEVELING_BILINEAR, MESH_BED_LEVELING)
#include <stdint.h>
@ -92,7 +89,7 @@ class TemporaryBedLevelingState {
bool valid() const { return pos.x >= 0 && pos.y >= 0; }
#if ENABLED(AUTO_BED_LEVELING_UBL)
xy_pos_t meshpos() {
return { ubl.mesh_index_to_xpos(pos.x), ubl.mesh_index_to_ypos(pos.y) };
return { bedlevel.get_mesh_x(pos.x), bedlevel.get_mesh_y(pos.y) };
}
#endif
operator xy_int8_t&() { return pos; }

View File

@ -32,7 +32,7 @@
#include "../../../lcd/extui/ui_api.h"
#endif
mesh_bed_leveling mbl;
mesh_bed_leveling bedlevel;
float mesh_bed_leveling::z_offset,
mesh_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y],

View File

@ -34,9 +34,6 @@ enum MeshLevelingState : char {
#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
#define _GET_MESH_X(I) mbl.index_to_xpos[I]
#define _GET_MESH_Y(J) mbl.index_to_ypos[J]
#define Z_VALUES_ARR mbl.z_values
class mesh_bed_leveling {
public:
@ -56,6 +53,8 @@ public:
return false;
}
static bool mesh_is_valid() { return has_mesh(); }
static void set_z(const int8_t px, const int8_t py, const_float_t z) { z_values[px][py] = z; }
static void zigzag(const int8_t index, int8_t &px, int8_t &py) {
@ -70,6 +69,9 @@ public:
set_z(px, py, z);
}
static float get_mesh_x(const uint8_t i) { return index_to_xpos[i]; }
static float get_mesh_y(const uint8_t i) { return index_to_ypos[i]; }
static int8_t cell_index_x(const_float_t x) {
int8_t cx = (x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST);
return constrain(cx, 0, GRID_MAX_CELLS_X - 1);
@ -102,12 +104,9 @@ public:
return z1 + delta_a * delta_z;
}
static float get_z(const xy_pos_t &pos
OPTARG(ENABLE_LEVELING_FADE_HEIGHT, const_float_t factor=1.0f)
) {
#if DISABLED(ENABLE_LEVELING_FADE_HEIGHT)
constexpr float factor = 1.0f;
#endif
static float get_z_offset() { return z_offset; }
static float get_z_correction(const xy_pos_t &pos) {
const xy_int8_t ind = cell_indexes(pos);
const float x1 = index_to_xpos[ind.x], x2 = index_to_xpos[ind.x+1],
y1 = index_to_xpos[ind.y], y2 = index_to_xpos[ind.y+1],
@ -115,7 +114,7 @@ public:
z2 = calc_z0(pos.x, x1, z_values[ind.x][ind.y+1], x2, z_values[ind.x+1][ind.y+1]),
zf = calc_z0(pos.y, y1, z1, y2, z2);
return z_offset + zf * factor;
return zf;
}
#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
@ -123,4 +122,4 @@ public:
#endif
};
extern mesh_bed_leveling mbl;
extern mesh_bed_leveling bedlevel;

View File

@ -26,7 +26,7 @@
#include "../bedlevel.h"
unified_bed_leveling ubl;
unified_bed_leveling bedlevel;
#include "../../../MarlinCore.h"
#include "../../../gcode/gcode.h"

View File

@ -215,7 +215,7 @@ public:
return _UBL_OUTER_Z_RAISE;
}
const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * RECIPROCAL(MESH_X_DIST),
const float xratio = (rx0 - get_mesh_x(x1_i)) * RECIPROCAL(MESH_X_DIST),
z1 = z_values[x1_i][yi];
return z1 + xratio * (z_values[_MIN(x1_i, (GRID_MAX_POINTS_X) - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array
@ -238,7 +238,7 @@ public:
return _UBL_OUTER_Z_RAISE;
}
const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * RECIPROCAL(MESH_Y_DIST),
const float yratio = (ry0 - get_mesh_y(y1_i)) * RECIPROCAL(MESH_Y_DIST),
z1 = z_values[xi][y1_i];
return z1 + yratio * (z_values[xi][_MIN(y1_i, (GRID_MAX_POINTS_Y) - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array
@ -264,16 +264,17 @@ public:
return UBL_Z_RAISE_WHEN_OFF_MESH;
#endif
const uint8_t mx = _MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1, my = _MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1;
const float z1 = calc_z0(rx0, mesh_index_to_xpos(cx), z_values[cx][cy], mesh_index_to_xpos(cx + 1), z_values[mx][cy]);
const float z2 = calc_z0(rx0, mesh_index_to_xpos(cx), z_values[cx][my], mesh_index_to_xpos(cx + 1), z_values[mx][my]);
float z0 = calc_z0(ry0, mesh_index_to_ypos(cy), z1, mesh_index_to_ypos(cy + 1), z2);
const uint8_t mx = _MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1, my = _MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1,
x0 = get_mesh_x(cx), x1 = get_mesh_x(cx + 1);
const float z1 = calc_z0(rx0, x0, z_values[cx][cy], x1, z_values[mx][cy]),
z2 = calc_z0(rx0, x0, z_values[cx][my], x1, z_values[mx][my]);
float z0 = calc_z0(ry0, get_mesh_y(cy), z1, get_mesh_y(cy + 1), z2);
if (isnan(z0)) { // if part of the Mesh is undefined, it will show up as NAN
z0 = 0.0; // in ubl.z_values[][] and propagate through the
// calculations. If our correction is NAN, we throw it out
// because part of the Mesh is undefined and we don't have the
// information we need to complete the height correction.
if (isnan(z0)) { // If part of the Mesh is undefined, it will show up as NAN
z0 = 0.0; // in z_values[][] and propagate through the calculations.
// If our correction is NAN, we throw it out because part of
// the Mesh is undefined and we don't have the information
// needed to complete the height correction.
if (DEBUGGING(MESH_ADJUST)) DEBUG_ECHOLNPGM("??? Yikes! NAN in ");
}
@ -287,10 +288,12 @@ public:
}
static float get_z_correction(const xy_pos_t &pos) { return get_z_correction(pos.x, pos.y); }
static float mesh_index_to_xpos(const uint8_t i) {
static constexpr float get_z_offset() { return 0.0f; }
static float get_mesh_x(const uint8_t i) {
return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
}
static float mesh_index_to_ypos(const uint8_t i) {
static float get_mesh_y(const uint8_t i) {
return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
}
@ -307,11 +310,7 @@ public:
}; // class unified_bed_leveling
extern unified_bed_leveling ubl;
#define _GET_MESH_X(I) ubl.mesh_index_to_xpos(I)
#define _GET_MESH_Y(J) ubl.mesh_index_to_ypos(J)
#define Z_VALUES_ARR ubl.z_values
extern unified_bed_leveling bedlevel;
// Prevent debugging propagating to other files
#include "../../../core/debug_out.h"

View File

@ -905,11 +905,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
// It doesn't matter if the probe can't reach the NAN location. This is a manual probe.
if (!location.valid()) continue;
const xyz_pos_t ppos = {
mesh_index_to_xpos(lpos.x),
mesh_index_to_ypos(lpos.y),
z_clearance
};
const xyz_pos_t ppos = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), z_clearance };
if (!position_is_reachable(ppos)) break; // SHOULD NOT OCCUR (find_closest_mesh_point only returns reachable points)
@ -1004,11 +1000,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
done_flags.mark(lpos); // Mark this location as 'adjusted' so a new
// location is used on the next loop
const xyz_pos_t raw = {
mesh_index_to_xpos(lpos.x),
mesh_index_to_ypos(lpos.y),
Z_CLEARANCE_BETWEEN_PROBES
};
const xyz_pos_t raw = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), Z_CLEARANCE_BETWEEN_PROBES };
if (!position_is_reachable(raw)) break; // SHOULD NOT OCCUR (find_closest_mesh_point_of_type only returns reachable)
@ -1241,7 +1233,7 @@ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
if (!isnan(z_values[i][j])) continue; // Skip valid mesh points
// Skip unreachable points
if (!probe.can_reach(mesh_index_to_xpos(i), mesh_index_to_ypos(j)))
if (!probe.can_reach(get_mesh_x(i), get_mesh_y(j)))
continue;
found_a_NAN = true;
@ -1293,11 +1285,11 @@ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
static bool test_func(uint8_t i, uint8_t j, void *data) {
find_closest_t *d = (find_closest_t*)data;
if ( d->type == CLOSEST || d->type == (isnan(ubl.z_values[i][j]) ? INVALID : REAL)
if ( d->type == CLOSEST || d->type == (isnan(bedlevel.z_values[i][j]) ? INVALID : REAL)
|| (d->type == SET_IN_BITMAP && !d->done_flags->marked(i, j))
) {
// Found a Mesh Point of the specified type!
const xy_pos_t mpos = { ubl.mesh_index_to_xpos(i), ubl.mesh_index_to_ypos(j) };
const xy_pos_t mpos = { bedlevel.get_mesh_x(i), bedlevel.get_mesh_y(j) };
// If using the probe as the reference there are some unreachable locations.
// Also for round beds, there are grid points outside the bed the nozzle can't reach.
@ -1341,7 +1333,7 @@ mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const Mesh
|| (type == SET_IN_BITMAP && !done_flags->marked(i, j))
) {
// Found a Mesh Point of the specified type!
const xy_pos_t mpos = { mesh_index_to_xpos(i), mesh_index_to_ypos(j) };
const xy_pos_t mpos = { get_mesh_x(i), get_mesh_y(j) };
// If using the probe as the reference there are some unreachable locations.
// Also for round beds, there are grid points outside the bed the nozzle can't reach.
@ -1397,10 +1389,10 @@ typedef struct { uint8_t sx, ex, sy, ey; bool yfirst; } smart_fill_info;
void unified_bed_leveling::smart_fill_mesh() {
static const smart_fill_info
info0 PROGMEM = { 0, GRID_MAX_POINTS_X, 0, GRID_MAX_POINTS_Y - 2, false }, // Bottom of the mesh looking up
info1 PROGMEM = { 0, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y - 1, 0, false }, // Top of the mesh looking down
info2 PROGMEM = { 0, GRID_MAX_POINTS_X - 2, 0, GRID_MAX_POINTS_Y, true }, // Left side of the mesh looking right
info3 PROGMEM = { GRID_MAX_POINTS_X - 1, 0, 0, GRID_MAX_POINTS_Y, true }; // Right side of the mesh looking left
info0 PROGMEM = { 0, GRID_MAX_POINTS_X, 0, (GRID_MAX_POINTS_Y) - 2, false }, // Bottom of the mesh looking up
info1 PROGMEM = { 0, GRID_MAX_POINTS_X, (GRID_MAX_POINTS_Y) - 1, 0, false }, // Top of the mesh looking down
info2 PROGMEM = { 0, (GRID_MAX_POINTS_X) - 2, 0, GRID_MAX_POINTS_Y, true }, // Left side of the mesh looking right
info3 PROGMEM = { (GRID_MAX_POINTS_X) - 1, 0, 0, GRID_MAX_POINTS_Y, true }; // Right side of the mesh looking left
static const smart_fill_info * const info[] PROGMEM = { &info0, &info1, &info2, &info3 };
LOOP_L_N(i, COUNT(info)) {
@ -1589,9 +1581,7 @@ void unified_bed_leveling::smart_fill_mesh() {
matrix_3x3 rotation = matrix_3x3::create_look_at(vector_3(lsf_results.A, lsf_results.B, 1));
GRID_LOOP(i, j) {
float mx = mesh_index_to_xpos(i),
my = mesh_index_to_ypos(j),
mz = z_values[i][j];
float mx = get_mesh_x(i), my = get_mesh_y(j), mz = z_values[i][j];
if (DEBUGGING(LEVELING)) {
DEBUG_ECHOPAIR_F("before rotation = [", mx, 7);
@ -1688,18 +1678,18 @@ void unified_bed_leveling::smart_fill_mesh() {
xy_pos_t ppos;
LOOP_L_N(ix, GRID_MAX_POINTS_X) {
ppos.x = mesh_index_to_xpos(ix);
ppos.x = get_mesh_x(ix);
LOOP_L_N(iy, GRID_MAX_POINTS_Y) {
ppos.y = mesh_index_to_ypos(iy);
ppos.y = get_mesh_y(iy);
if (isnan(z_values[ix][iy])) {
// undefined mesh point at (ppos.x,ppos.y), compute weighted LSF from original valid mesh points.
incremental_LSF_reset(&lsf_results);
xy_pos_t rpos;
LOOP_L_N(jx, GRID_MAX_POINTS_X) {
rpos.x = mesh_index_to_xpos(jx);
rpos.x = get_mesh_x(jx);
LOOP_L_N(jy, GRID_MAX_POINTS_Y) {
if (TEST(bitmap[jx], jy)) {
rpos.y = mesh_index_to_ypos(jy);
rpos.y = get_mesh_y(jy);
const float rz = z_values[jx][jy],
w = 1.0f + weight_scaled / (rpos - ppos).magnitude();
incremental_WLSF(&lsf_results, rpos, rz, w);
@ -1758,7 +1748,7 @@ void unified_bed_leveling::smart_fill_mesh() {
SERIAL_ECHOPGM("X-Axis Mesh Points at: ");
LOOP_L_N(i, GRID_MAX_POINTS_X) {
SERIAL_ECHO_F(LOGICAL_X_POSITION(mesh_index_to_xpos(i)), 3);
SERIAL_ECHO_F(LOGICAL_X_POSITION(get_mesh_x(i)), 3);
SERIAL_ECHOPGM(" ");
serial_delay(25);
}
@ -1766,7 +1756,7 @@ void unified_bed_leveling::smart_fill_mesh() {
SERIAL_ECHOPGM("Y-Axis Mesh Points at: ");
LOOP_L_N(i, GRID_MAX_POINTS_Y) {
SERIAL_ECHO_F(LOGICAL_Y_POSITION(mesh_index_to_ypos(i)), 3);
SERIAL_ECHO_F(LOGICAL_Y_POSITION(get_mesh_y(i)), 3);
SERIAL_ECHOPGM(" ");
serial_delay(25);
}

View File

@ -76,8 +76,8 @@
#endif
// The distance is always MESH_X_DIST so multiply by the constant reciprocal.
const float xratio = (end.x - mesh_index_to_xpos(iend.x)) * RECIPROCAL(MESH_X_DIST),
yratio = (end.y - mesh_index_to_ypos(iend.y)) * RECIPROCAL(MESH_Y_DIST),
const float xratio = (end.x - get_mesh_x(iend.x)) * RECIPROCAL(MESH_X_DIST),
yratio = (end.y - get_mesh_y(iend.y)) * RECIPROCAL(MESH_Y_DIST),
z1 = z_values[iend.x][iend.y ] + xratio * (z_values[iend.x + 1][iend.y ] - z_values[iend.x][iend.y ]),
z2 = z_values[iend.x][iend.y + 1] + xratio * (z_values[iend.x + 1][iend.y + 1] - z_values[iend.x][iend.y + 1]);
@ -139,7 +139,7 @@
icell.y += ineg.y; // Line going down? Just go to the bottom.
while (icell.y != iend.y + ineg.y) {
icell.y += iadd.y;
const float next_mesh_line_y = mesh_index_to_ypos(icell.y);
const float next_mesh_line_y = get_mesh_y(icell.y);
/**
* Skip the calculations for an infinite slope.
@ -155,7 +155,7 @@
// Replace NAN corrections with 0.0 to prevent NAN propagation.
if (isnan(z0)) z0 = 0.0;
dest.y = mesh_index_to_ypos(icell.y);
dest.y = get_mesh_y(icell.y);
/**
* Without this check, it's possible to generate a zero length move, as in the case where
@ -196,7 +196,7 @@
while (icell.x != iend.x + ineg.x) {
icell.x += iadd.x;
dest.x = mesh_index_to_xpos(icell.x);
dest.x = get_mesh_x(icell.x);
dest.y = ratio * dest.x + c; // Calculate Y at the next X mesh line
float z0 = z_correction_for_y_on_vertical_mesh_line(dest.y, icell.x, icell.y)
@ -245,8 +245,8 @@
while (cnt) {
const float next_mesh_line_x = mesh_index_to_xpos(icell.x + iadd.x),
next_mesh_line_y = mesh_index_to_ypos(icell.y + iadd.y);
const float next_mesh_line_x = get_mesh_x(icell.x + iadd.x),
next_mesh_line_y = get_mesh_y(icell.y + iadd.y);
dest.y = ratio * next_mesh_line_x + c; // Calculate Y at the next X mesh line
dest.x = (next_mesh_line_y - c) / ratio; // Calculate X at the next Y mesh line
@ -423,7 +423,7 @@
if (isnan(z_x0y1)) z_x0y1 = 0; // in order to avoid isnan tests per cell,
if (isnan(z_x1y1)) z_x1y1 = 0; // thus guessing zero for undefined points
const xy_pos_t pos = { mesh_index_to_xpos(icell.x), mesh_index_to_ypos(icell.y) };
const xy_pos_t pos = { get_mesh_x(icell.x), get_mesh_y(icell.y) };
xy_pos_t cell = raw - pos;
const float z_xmy0 = (z_x1y0 - z_x0y0) * RECIPROCAL(MESH_X_DIST), // z slope per x along y0 (lower left to lower right)
@ -450,10 +450,7 @@
if (--segments == 0) raw = destination; // if this is last segment, use destination for exact
const float z_cxcy = (z_cxy0 + z_cxym * cell.y) // interpolated mesh z height along cell.x at cell.y
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
* fade_scaling_factor // apply fade factor to interpolated mesh height
#endif
;
TERN_(ENABLE_LEVELING_FADE_HEIGHT, * fade_scaling_factor); // apply fade factor to interpolated height
const float oldz = raw.z; raw.z += z_cxcy;
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm OPTARG(SCARA_FEEDRATE_SCALING, inv_duration) );