voxel_traversal.c 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include <math.h>
  2. #include <grass/raster3d.h>
  3. #include "voxel_traversal.h"
  4. void traverse(RASTER3D_Region * region, double *start, double *end,
  5. int **coordinates, int *size, int *coor_count)
  6. {
  7. double dx, dy, dz;
  8. int step_x, step_y, step_z;
  9. int x, y, z;
  10. int x_end, y_end, z_end;
  11. double t_delta_x, t_delta_y, t_delta_z;
  12. double t_max_x, t_max_y, t_max_z;
  13. double xtmp, ytmp, ztmp;
  14. int count;
  15. /* initialize */
  16. dx = end[0] - start[0];
  17. dy = end[1] - start[1];
  18. dz = end[2] - start[2];
  19. step_x = start[0] < end[0] ? 1 : -1;
  20. step_y = start[1] < end[1] ? 1 : -1;
  21. step_z = start[2] < end[2] ? 1 : -1;
  22. x = (int)floor((start[0] - region->west) / region->ew_res);
  23. y = (int)floor((start[1] - region->south) / region->ns_res);
  24. z = (int)floor((start[2] - region->bottom) / region->tb_res);
  25. x_end = (int)floor((end[0] - region->west) / region->ew_res);
  26. y_end = (int)floor((end[1] - region->south) / region->ns_res);
  27. z_end = (int)floor((end[2] - region->bottom) / region->tb_res);
  28. t_delta_x = fabs(region->ew_res / (dx != 0 ? dx : 1e6));
  29. t_delta_y = fabs(region->ns_res / (dy != 0 ? dy : 1e6));
  30. t_delta_z = fabs(region->tb_res / (dz != 0 ? dz : 1e6));
  31. xtmp = (start[0] - region->west) / region->ew_res;
  32. ytmp = (start[1] - region->south) / region->ns_res;
  33. ztmp = (start[2] - region->bottom) / region->tb_res;
  34. if (step_x > 0)
  35. t_max_x = t_delta_x * (1.0 - (xtmp - floor(xtmp)));
  36. else
  37. t_max_x = t_delta_x * (xtmp - floor(xtmp));
  38. if (step_y > 0)
  39. t_max_y = t_delta_y * (1.0 - (ytmp - floor(ytmp)));
  40. else
  41. t_max_y = t_delta_y * (ytmp - floor(ytmp));
  42. if (step_z > 0)
  43. t_max_z = t_delta_z * (1.0 - (ztmp - floor(ztmp)));
  44. else
  45. t_max_z = t_delta_z * (ztmp - floor(ztmp));
  46. count = 0;
  47. while (TRUE) {
  48. if (t_max_x < t_max_y) {
  49. if (t_max_x < t_max_z) {
  50. t_max_x = t_max_x + t_delta_x;
  51. x = x + step_x;
  52. }
  53. else {
  54. t_max_z = t_max_z + t_delta_z;
  55. z = z + step_z;
  56. }
  57. }
  58. else {
  59. if (t_max_y < t_max_z) {
  60. t_max_y = t_max_y + t_delta_y;
  61. y = y + step_y;
  62. }
  63. else {
  64. t_max_z = t_max_z + t_delta_z;
  65. z = z + step_z;
  66. }
  67. }
  68. if ((x == x_end && y == y_end && z == z_end) ||
  69. /* just to make sure it breaks */
  70. (step_x * (x - x_end) > 0 || step_y * (y - y_end) > 0 ||
  71. step_z * (z - z_end) > 0))
  72. break;
  73. (*coordinates)[count * 3 + 0] = x;
  74. (*coordinates)[count * 3 + 1] = region->rows - y - 1;
  75. (*coordinates)[count * 3 + 2] = z;
  76. count++;
  77. /* reallocation for cases when the steps would be too big */
  78. if (*size <= count) {
  79. *size = 2 * (*size);
  80. *coordinates = G_realloc(*coordinates, (*size) * 3 * sizeof(int));
  81. }
  82. }
  83. *coor_count = count;
  84. }