My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

hilbert_curve.cpp 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*********************
  2. * hilbert_curve.cpp *
  3. *********************/
  4. /****************************************************************************
  5. * Written By Marcio Teixeira 2021 - SynDaver Labs, Inc. *
  6. * *
  7. * This program is free software: you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation, either version 3 of the License, or *
  10. * (at your option) any later version. *
  11. * *
  12. * This program is distributed in the hope that it will be useful, *
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15. * GNU General Public License for more details. *
  16. * *
  17. * To view a copy of the GNU General Public License, go to the following *
  18. * location: <https://www.gnu.org/licenses/>. *
  19. ****************************************************************************/
  20. #include "../../inc/MarlinConfig.h"
  21. #if ENABLED(UBL_HILBERT_CURVE)
  22. #include "bedlevel.h"
  23. #include "hilbert_curve.h"
  24. constexpr int8_t to_fix(int8_t v) { return v * 2; }
  25. constexpr int8_t to_int(int8_t v) { return v / 2; }
  26. constexpr uint8_t log2(uint8_t n) { return (n > 1) ? 1 + log2(n >> 1) : 0; }
  27. constexpr uint8_t order(uint8_t n) { return uint8_t(log2(n - 1)) + 1; }
  28. constexpr uint8_t ord = order(_MAX(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y));
  29. constexpr uint8_t dim = _BV(ord);
  30. static inline bool eval_candidate(int8_t x, int8_t y, hilbert_curve::callback_ptr func, void *data) {
  31. // The print bed likely has fewer points than the full Hilbert
  32. // curve, so cull unnecessary points
  33. return x < (GRID_MAX_POINTS_X) && y < (GRID_MAX_POINTS_Y) ? func(x, y, data) : false;
  34. }
  35. bool hilbert_curve::hilbert(int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n, hilbert_curve::callback_ptr func, void *data) {
  36. /**
  37. * Hilbert space-filling curve implementation
  38. *
  39. * x and y : coordinates of the bottom left corner
  40. * xi and xj : i and j components of the unit x vector of the frame
  41. * yi and yj : i and j components of the unit y vector of the frame
  42. *
  43. * From: http://www.fundza.com/algorithmic/space_filling/hilbert/basics/index.html
  44. */
  45. if (n)
  46. return hilbert(x, y, yi/2, yj/2, xi/2, xj/2, n-1, func, data) ||
  47. hilbert(x+xi/2, y+xj/2, xi/2, xj/2, yi/2, yj/2, n-1, func, data) ||
  48. hilbert(x+xi/2+yi/2, y+xj/2+yj/2, xi/2, xj/2, yi/2, yj/2, n-1, func, data) ||
  49. hilbert(x+xi/2+yi, y+xj/2+yj, -yi/2, -yj/2, -xi/2, -xj/2, n-1, func, data);
  50. else
  51. return eval_candidate(to_int(x+(xi+yi)/2), to_int(y+(xj+yj)/2), func, data);
  52. }
  53. /**
  54. * Calls func(x, y, data) for all points in the Hilbert curve.
  55. * If that function returns true, the search is terminated.
  56. */
  57. bool hilbert_curve::search(hilbert_curve::callback_ptr func, void *data) {
  58. return hilbert(to_fix(0), to_fix(0),to_fix(dim), to_fix(0), to_fix(0), to_fix(dim), ord, func, data);
  59. }
  60. /* Helper function for starting the search at a particular point */
  61. typedef struct {
  62. uint8_t x, y;
  63. bool found_1st;
  64. hilbert_curve::callback_ptr func;
  65. void *data;
  66. } search_from_t;
  67. static bool search_from_helper(uint8_t x, uint8_t y, void *data) {
  68. search_from_t *d = (search_from_t *) data;
  69. if (d->x == x && d->y == y)
  70. d->found_1st = true;
  71. return d->found_1st ? d->func(x, y, d->data) : false;
  72. }
  73. /**
  74. * Same as search, except start at a specific grid intersection point.
  75. */
  76. bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_ptr func, void *data) {
  77. search_from_t d;
  78. d.x = x;
  79. d.y = y;
  80. d.found_1st = false;
  81. d.func = func;
  82. d.data = data;
  83. // Call twice to allow search to wrap back to the beginning and picked up points prior to the start.
  84. return search(search_from_helper, &d) || search(search_from_helper, &d);
  85. }
  86. /**
  87. * Like search_from, but takes a bed position and starts from the nearest
  88. * point on the Hilbert curve.
  89. */
  90. bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) {
  91. // Find closest grid intersection
  92. const uint8_t grid_x = LROUND(constrain(float(pos.x - (MESH_MIN_X)) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1));
  93. const uint8_t grid_y = LROUND(constrain(float(pos.y - (MESH_MIN_Y)) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1));
  94. return search_from(grid_x, grid_y, func, data);
  95. }
  96. #endif // UBL_HILBERT_CURVE