|
49 | 49 | #include "../../../lcd/extui/ui_api.h" |
50 | 50 | #endif |
51 | 51 |
|
| 52 | +#if ENABLED(UBL_HILBERT_CURVE) |
| 53 | + #include "../hilbert_curve.h" |
| 54 | +#endif |
| 55 | + |
52 | 56 | #include <math.h> |
53 | 57 |
|
54 | 58 | #define UBL_G29_P31 |
@@ -747,11 +751,9 @@ void unified_bed_leveling::shift_mesh_height() { |
747 | 751 | } |
748 | 752 | #endif |
749 | 753 |
|
750 | | - best = do_furthest ? find_furthest_invalid_mesh_point() |
751 | | - : TERN(UBL_HILBERT_CURVE, |
752 | | - find_next_mesh_point(), |
753 | | - find_closest_mesh_point_of_type(INVALID, nearby, true) |
754 | | - ); |
| 754 | + best = do_furthest |
| 755 | + ? find_furthest_invalid_mesh_point() |
| 756 | + : find_closest_mesh_point_of_type(INVALID, nearby, true); |
755 | 757 |
|
756 | 758 | if (best.pos.x >= 0) { // mesh point found and is reachable by probe |
757 | 759 | TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::PROBE_START)); |
@@ -1269,97 +1271,93 @@ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() { |
1269 | 1271 | return farthest; |
1270 | 1272 | } |
1271 | 1273 |
|
1272 | | -mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const MeshPointType type, const xy_pos_t &pos, const bool probe_relative/*=false*/, MeshFlags *done_flags/*=nullptr*/) { |
1273 | | - mesh_index_pair closest; |
1274 | | - closest.invalidate(); |
1275 | | - closest.distance = -99999.9f; |
1276 | | - |
1277 | | - // Get the reference position, either nozzle or probe |
1278 | | - const xy_pos_t ref = probe_relative ? pos + probe.offset_xy : pos; |
1279 | | - |
1280 | | - float best_so_far = 99999.99f; |
| 1274 | +#if ENABLED(UBL_HILBERT_CURVE) |
1281 | 1275 |
|
1282 | | - GRID_LOOP(i, j) { |
1283 | | - if ( (type == (isnan(z_values[i][j]) ? INVALID : REAL)) |
1284 | | - || (type == SET_IN_BITMAP && !done_flags->marked(i, j)) |
| 1276 | + typedef struct { |
| 1277 | + MeshPointType type; |
| 1278 | + MeshFlags *done_flags; |
| 1279 | + bool probe_relative; |
| 1280 | + mesh_index_pair closest; |
| 1281 | + } find_closest_t; |
| 1282 | + |
| 1283 | + static bool test_func(uint8_t i, uint8_t j, void *data) { |
| 1284 | + find_closest_t *d = (find_closest_t*)data; |
| 1285 | + if ( (d->type == (isnan(ubl.z_values[i][j]) ? INVALID : REAL)) |
| 1286 | + || (d->type == SET_IN_BITMAP && !d->done_flags->marked(i, j)) |
1285 | 1287 | ) { |
1286 | 1288 | // Found a Mesh Point of the specified type! |
1287 | | - const xy_pos_t mpos = { mesh_index_to_xpos(i), mesh_index_to_ypos(j) }; |
| 1289 | + const xy_pos_t mpos = { ubl.mesh_index_to_xpos(i), ubl.mesh_index_to_ypos(j) }; |
1288 | 1290 |
|
1289 | 1291 | // If using the probe as the reference there are some unreachable locations. |
1290 | 1292 | // Also for round beds, there are grid points outside the bed the nozzle can't reach. |
1291 | 1293 | // Prune them from the list and ignore them till the next Phase (manual nozzle probing). |
1292 | 1294 |
|
1293 | | - if (!(probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos))) |
1294 | | - continue; |
| 1295 | + if (!(d->probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos))) |
| 1296 | + return false; |
| 1297 | + d->closest.pos.set(i, j); |
| 1298 | + return true; |
| 1299 | + } |
| 1300 | + return false; |
| 1301 | + } |
1295 | 1302 |
|
1296 | | - // Reachable. Check if it's the best_so_far location to the nozzle. |
| 1303 | +#endif |
1297 | 1304 |
|
1298 | | - const xy_pos_t diff = current_position - mpos; |
1299 | | - const float distance = (ref - mpos).magnitude() + diff.magnitude() * 0.1f; |
| 1305 | +mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const MeshPointType type, const xy_pos_t &pos, const bool probe_relative/*=false*/, MeshFlags *done_flags/*=nullptr*/) { |
1300 | 1306 |
|
1301 | | - // factor in the distance from the current location for the normal case |
1302 | | - // so the nozzle isn't running all over the bed. |
1303 | | - if (distance < best_so_far) { |
1304 | | - best_so_far = distance; // Found a closer location with the desired value type. |
1305 | | - closest.pos.set(i, j); |
1306 | | - closest.distance = best_so_far; |
1307 | | - } |
1308 | | - } |
1309 | | - } // GRID_LOOP |
| 1307 | + #if ENABLED(UBL_HILBERT_CURVE) |
1310 | 1308 |
|
1311 | | - return closest; |
1312 | | -} |
| 1309 | + find_closest_t d; |
| 1310 | + d.type = type; |
| 1311 | + d.done_flags = done_flags; |
| 1312 | + d.probe_relative = probe_relative; |
| 1313 | + d.closest.invalidate(); |
| 1314 | + hilbert_curve::search_from_closest(pos, test_func, &d); |
| 1315 | + return d.closest; |
1313 | 1316 |
|
1314 | | -#if ENABLED(UBL_HILBERT_CURVE) |
| 1317 | + #else |
1315 | 1318 |
|
1316 | | - constexpr int8_t to_fix(int8_t v) { return v << 1; } |
1317 | | - constexpr int8_t to_int(int8_t v) { return v >> 1; } |
1318 | | - constexpr uint8_t log2(uint8_t n) { return (n > 1) ? 1 + log2(n >> 1) : 0; } |
1319 | | - constexpr uint8_t order(uint8_t n) { return uint8_t(log2(n - 1)) + 1; } |
1320 | | - |
1321 | | - void unified_bed_leveling::hilbert(mesh_index_pair &pt, int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n) { |
1322 | | - /* Hilbert space filling curve implementation |
1323 | | - * |
1324 | | - * x and y are the coordinates of the bottom left corner |
1325 | | - * xi & xj are the i & j components of the unit x vector of the frame |
1326 | | - * similarly yi and yj |
1327 | | - * |
1328 | | - * From: http://www.fundza.com/algorithmic/space_filling/hilbert/basics/index.html |
1329 | | - */ |
1330 | | - if (n <= 0) |
1331 | | - check_if_missing(pt, to_int(x+(xi+yi)/2),to_int(y+(xj+yj)/2)); |
1332 | | - else { |
1333 | | - hilbert(pt, x, y, yi/2, yj/2, xi/2, xj/2, n-1); |
1334 | | - hilbert(pt, x+xi/2, y+xj/2, xi/2, xj/2, yi/2, yj/2, n-1); |
1335 | | - hilbert(pt, x+xi/2+yi/2, y+xj/2+yj/2, xi/2, xj/2, yi/2, yj/2, n-1); |
1336 | | - hilbert(pt, x+xi/2+yi, y+xj/2+yj, -yi/2, -yj/2, -xi/2, -xj/2, n-1); |
1337 | | - } |
1338 | | - } |
| 1319 | + mesh_index_pair closest; |
| 1320 | + closest.invalidate(); |
| 1321 | + closest.distance = -99999.9f; |
| 1322 | + |
| 1323 | + // Get the reference position, either nozzle or probe |
| 1324 | + const xy_pos_t ref = probe_relative ? pos + probe.offset_xy : pos; |
1339 | 1325 |
|
1340 | | - void unified_bed_leveling::check_if_missing(mesh_index_pair &pt, int x, int y) { |
1341 | | - if ( pt.distance < 0 |
1342 | | - && x < GRID_MAX_POINTS_X |
1343 | | - && y < GRID_MAX_POINTS_Y |
1344 | | - && isnan(z_values[x][y]) |
1345 | | - && probe.can_reach(mesh_index_to_xpos(x), mesh_index_to_ypos(y)) |
| 1326 | + float best_so_far = 99999.99f; |
| 1327 | + |
| 1328 | + GRID_LOOP(i, j) { |
| 1329 | + if ( (type == (isnan(z_values[i][j]) ? INVALID : REAL)) |
| 1330 | + || (type == SET_IN_BITMAP && !done_flags->marked(i, j)) |
1346 | 1331 | ) { |
1347 | | - pt.pos.set(x, y); |
1348 | | - pt.distance = 1; |
| 1332 | + // Found a Mesh Point of the specified type! |
| 1333 | + const xy_pos_t mpos = { mesh_index_to_xpos(i), mesh_index_to_ypos(j) }; |
| 1334 | + |
| 1335 | + // If using the probe as the reference there are some unreachable locations. |
| 1336 | + // Also for round beds, there are grid points outside the bed the nozzle can't reach. |
| 1337 | + // Prune them from the list and ignore them till the next Phase (manual nozzle probing). |
| 1338 | + |
| 1339 | + if (!(probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos))) |
| 1340 | + continue; |
| 1341 | + |
| 1342 | + // Reachable. Check if it's the best_so_far location to the nozzle. |
| 1343 | + |
| 1344 | + const xy_pos_t diff = current_position - mpos; |
| 1345 | + const float distance = (ref - mpos).magnitude() + diff.magnitude() * 0.1f; |
| 1346 | + |
| 1347 | + // factor in the distance from the current location for the normal case |
| 1348 | + // so the nozzle isn't running all over the bed. |
| 1349 | + if (distance < best_so_far) { |
| 1350 | + best_so_far = distance; // Found a closer location with the desired value type. |
| 1351 | + closest.pos.set(i, j); |
| 1352 | + closest.distance = best_so_far; |
| 1353 | + } |
1349 | 1354 | } |
1350 | | - } |
1351 | | - |
1352 | | - mesh_index_pair unified_bed_leveling::find_next_mesh_point() { |
1353 | | - mesh_index_pair pt; |
1354 | | - pt.invalidate(); |
1355 | | - pt.distance = -99999.9f; |
1356 | | - constexpr uint8_t ord = order(_MAX(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y)); |
1357 | | - constexpr uint8_t dim = _BV(ord); |
1358 | | - hilbert(pt, to_fix(0), to_fix(0), to_fix(dim), to_fix(0), to_fix(0), to_fix(dim), ord); |
1359 | | - return pt; |
1360 | | - } |
1361 | | - |
1362 | | -#endif // UBL_HILBERT_CURVE |
| 1355 | + } // GRID_LOOP |
| 1356 | + |
| 1357 | + return closest; |
| 1358 | + |
| 1359 | + #endif |
| 1360 | +} |
1363 | 1361 |
|
1364 | 1362 | /** |
1365 | 1363 | * 'Smart Fill': Scan from the outward edges of the mesh towards the center. |
|
0 commit comments