volume.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/types.h>
  4. #include <unistd.h>
  5. #include <grass/raster.h>
  6. #include <grass/raster3d.h>
  7. /*---------------------------------------------------------------------------*/
  8. static int verifyVolumeVertices(void *map, double v[2][2][2][3])
  9. {
  10. if (!(Rast3d_is_valid_location(map, v[0][0][0][0], v[0][0][0][1],
  11. v[0][0][0][2]) &&
  12. Rast3d_is_valid_location(map, v[0][0][1][0], v[0][0][1][1],
  13. v[0][0][1][2]) &&
  14. Rast3d_is_valid_location(map, v[0][1][0][0], v[0][1][0][1],
  15. v[0][1][0][2]) &&
  16. Rast3d_is_valid_location(map, v[0][1][1][0], v[0][1][1][1],
  17. v[0][1][1][2]) &&
  18. Rast3d_is_valid_location(map, v[1][0][0][0], v[1][0][0][1],
  19. v[1][0][0][2]) &&
  20. Rast3d_is_valid_location(map, v[1][0][1][0], v[1][0][1][1],
  21. v[1][0][1][2]) &&
  22. Rast3d_is_valid_location(map, v[1][1][0][0], v[1][1][0][1],
  23. v[1][1][0][2]) &&
  24. Rast3d_is_valid_location(map, v[1][1][1][0], v[1][1][1][1],
  25. v[1][1][1][2])))
  26. Rast3d_fatal_error("verifyCubeVertices: volume vertex out of range");
  27. return 0;
  28. }
  29. /*---------------------------------------------------------------------------*/
  30. static int verifyVolumeEdges(int nx, int ny, int nz)
  31. {
  32. if ((nx <= 0) || (ny <= 0) || (nz <= 0))
  33. Rast3d_fatal_error("verifyCubeEdges: Volume edge out of range");
  34. return 0;
  35. }
  36. /*---------------------------------------------------------------------------*/
  37. void
  38. Rast3d_get_volume_a(void *map, double u[2][2][2][3], int nx, int ny, int nz,
  39. void *volumeBuf, int type)
  40. {
  41. typedef double doubleArray[3];
  42. doubleArray *u000, *u001, *u010, *u011;
  43. doubleArray *u100, *u101, *u110, *u111;
  44. double v00[3], v01[3], v10[3], v11[3];
  45. double v0[3], v1[3];
  46. double v[3];
  47. double r, rp, s, sp, t, tp;
  48. double dx, dy, dz;
  49. int x, y, z, nxp, nyp, nzp;
  50. double *doubleBuf;
  51. float *floatBuf;
  52. doubleBuf = (double *)volumeBuf;
  53. floatBuf = (float *)volumeBuf;
  54. verifyVolumeVertices(map, u);
  55. verifyVolumeEdges(nx, ny, nz);
  56. nxp = nx * 2 + 1;
  57. nyp = ny * 2 + 1;
  58. nzp = nz * 2 + 1;
  59. u000 = (doubleArray *) u[0][0][0];
  60. u001 = (doubleArray *) u[0][0][1];
  61. u010 = (doubleArray *) u[0][1][0];
  62. u011 = (doubleArray *) u[0][1][1];
  63. u100 = (doubleArray *) u[1][0][0];
  64. u101 = (doubleArray *) u[1][0][1];
  65. u110 = (doubleArray *) u[1][1][0];
  66. u111 = (doubleArray *) u[1][1][1];
  67. for (dz = 1; dz < nzp; dz += 2) {
  68. r = 1. - (rp = dz / nz / 2.);
  69. v00[0] = r * (*u000)[0] + rp * (*u100)[0];
  70. v00[1] = r * (*u000)[1] + rp * (*u100)[1];
  71. v00[2] = r * (*u000)[2] + rp * (*u100)[2];
  72. v01[0] = r * (*u001)[0] + rp * (*u101)[0];
  73. v01[1] = r * (*u001)[1] + rp * (*u101)[1];
  74. v01[2] = r * (*u001)[2] + rp * (*u101)[2];
  75. v10[0] = r * (*u010)[0] + rp * (*u110)[0];
  76. v10[1] = r * (*u010)[1] + rp * (*u110)[1];
  77. v10[2] = r * (*u010)[2] + rp * (*u110)[2];
  78. v11[0] = r * (*u011)[0] + rp * (*u111)[0];
  79. v11[1] = r * (*u011)[1] + rp * (*u111)[1];
  80. v11[2] = r * (*u011)[2] + rp * (*u111)[2];
  81. for (dy = 1; dy < nyp; dy += 2) {
  82. s = 1. - (sp = dy / ny / 2.);
  83. v0[0] = s * v00[0] + sp * v10[0];
  84. v0[1] = s * v00[1] + sp * v10[1];
  85. v0[2] = s * v00[2] + sp * v10[2];
  86. v1[0] = s * v01[0] + sp * v11[0];
  87. v1[1] = s * v01[1] + sp * v11[1];
  88. v1[2] = s * v01[2] + sp * v11[2];
  89. for (dx = 1; dx < nxp; dx += 2) {
  90. t = 1. - (tp = dx / nx / 2.);
  91. v[0] = t * v0[0] + tp * v1[0];
  92. v[1] = t * v0[1] + tp * v1[1];
  93. v[2] = t * v0[2] + tp * v1[2];
  94. Rast3d_location2coord2(map, v[0], v[1], v[2], &x, &y, &z);
  95. /* DEBUG
  96. printf ("(%d %d %d) (%lf %lf %lf) (%d %d %d) %lf\n",
  97. (int) dx / 2, (int) dy / 2, (int) dz / 2,
  98. v[0], v[1], v[2],
  99. x, y, z,
  100. Rast3d_get_double_region (map, x, y, z));
  101. */
  102. if (type == DCELL_TYPE)
  103. *(doubleBuf + ((int)dz / 2) * nx * ny +
  104. ((int)dy / 2) * nx + (int)dx / 2) =
  105. Rast3d_get_double_region(map, x, y, z);
  106. else
  107. *(floatBuf + ((int)dz / 2) * nx * ny +
  108. ((int)dy / 2) * nx + (int)dx / 2) =
  109. Rast3d_get_float_region(map, x, y, z);
  110. }
  111. }
  112. }
  113. }
  114. /*---------------------------------------------------------------------------*/
  115. void
  116. Rast3d_get_volume(void *map,
  117. double originNorth, double originWest, double originBottom,
  118. double vxNorth, double vxWest, double vxBottom,
  119. double vyNorth, double vyWest, double vyBottom,
  120. double vzNorth, double vzWest, double vzBottom,
  121. int nx, int ny, int nz, void *volumeBuf, int type)
  122. {
  123. double u[2][2][2][3];
  124. u[0][0][0][0] = originNorth;
  125. u[0][0][0][1] = originWest;
  126. u[0][0][0][2] = originBottom;
  127. u[0][0][1][0] = vxNorth;
  128. u[0][0][1][1] = vxWest;
  129. u[0][0][1][2] = vxBottom;
  130. u[1][0][0][0] = vzNorth;
  131. u[1][0][0][1] = vzWest;
  132. u[1][0][0][2] = vzBottom;
  133. u[1][0][1][0] = (u[0][0][1][0] - u[0][0][0][0]) + u[1][0][0][0];
  134. u[1][0][1][1] = (u[0][0][1][1] - u[0][0][0][1]) + u[1][0][0][1];
  135. u[1][0][1][2] = (u[0][0][1][2] - u[0][0][0][2]) + u[1][0][0][2];
  136. u[0][1][0][0] = vyNorth;
  137. u[0][1][0][1] = vyWest;
  138. u[0][1][0][2] = vyBottom;
  139. u[0][1][1][0] = (u[0][0][1][0] - u[0][0][0][0]) + u[0][1][0][0];
  140. u[0][1][1][1] = (u[0][0][1][1] - u[0][0][0][1]) + u[0][1][0][1];
  141. u[0][1][1][2] = (u[0][0][1][2] - u[0][0][0][2]) + u[0][1][0][2];
  142. u[1][1][0][0] = (u[1][0][0][0] - u[0][0][0][0]) + u[0][1][0][0];
  143. u[1][1][0][1] = (u[1][0][0][1] - u[0][0][0][1]) + u[0][1][0][1];
  144. u[1][1][0][2] = (u[1][0][0][2] - u[0][0][0][2]) + u[0][1][0][2];
  145. u[1][1][1][0] = (u[1][0][0][0] - u[0][0][0][0]) + u[0][1][1][0];
  146. u[1][1][1][1] = (u[1][0][0][1] - u[0][0][0][1]) + u[0][1][1][1];
  147. u[1][1][1][2] = (u[1][0][0][2] - u[0][0][0][2]) + u[0][1][1][2];
  148. Rast3d_get_volume_a(map, u, nx, ny, nz, volumeBuf, type);
  149. }
  150. /*---------------------------------------------------------------------------*/
  151. void
  152. Rast3d_get_aligned_volume(void *map,
  153. double originNorth, double originWest,
  154. double originBottom, double lengthNorth,
  155. double lengthWest, double lengthBottom, int nx, int ny,
  156. int nz, void *volumeBuf, int type)
  157. {
  158. Rast3d_get_volume(map,
  159. originNorth, originWest, originBottom,
  160. originNorth + lengthNorth, originWest, originBottom,
  161. originNorth, originWest + lengthWest, originBottom,
  162. originNorth, originWest, originBottom + lengthBottom,
  163. nx, ny, nz, volumeBuf, type);
  164. }
  165. /*---------------------------------------------------------------------------*/
  166. void
  167. Rast3d_make_aligned_volume_file(void *map, const char *fileName,
  168. double originNorth, double originWest,
  169. double originBottom, double lengthNorth,
  170. double lengthWest, double lengthBottom, int nx,
  171. int ny, int nz)
  172. {
  173. void *volumeBuf;
  174. void *mapVolume;
  175. int x, y, z, eltLength;
  176. RASTER3D_Region region;
  177. volumeBuf = Rast3d_malloc(nx * ny * nz * sizeof(Rast3d_get_file_type()));
  178. if (volumeBuf == NULL)
  179. Rast3d_fatal_error("Rast3d_make_aligned_volume_file: error in Rast3d_malloc");
  180. Rast3d_get_aligned_volume(map,
  181. originNorth, originWest, originBottom,
  182. lengthNorth, lengthWest, lengthBottom,
  183. nx, ny, nz, volumeBuf, Rast3d_get_file_type());
  184. region.north = originNorth;
  185. region.south = originNorth + lengthNorth;
  186. region.east = originWest;
  187. region.west = originWest + lengthWest;
  188. region.top = originBottom;
  189. region.bottom = originBottom + lengthBottom;
  190. region.rows = ny;
  191. region.cols = nx;
  192. region.depths = nz;
  193. mapVolume = Rast3d_open_cell_new(fileName, Rast3d_get_file_type(),
  194. RASTER3D_USE_CACHE_DEFAULT, &region);
  195. if (mapVolume == NULL)
  196. Rast3d_fatal_error("Rast3d_make_aligned_volume_file: error in Rast3d_open_cell_new");
  197. eltLength = Rast3d_length(Rast3d_get_file_type());
  198. for (z = 0; z < nz; z++) {
  199. for (y = 0; y < ny; y++) {
  200. for (x = 0; x < nx; x++) {
  201. /* Rast3d_putValueRegion? */
  202. if (!Rast3d_put_value(mapVolume, x, y, z,
  203. G_incr_void_ptr(volumeBuf,
  204. (z * ny * nx + y * nx +
  205. x) * eltLength),
  206. Rast3d_file_type_map(mapVolume)))
  207. Rast3d_fatal_error
  208. ("Rast3d_make_aligned_volume_file: error in Rast3d_put_value");
  209. }
  210. }
  211. }
  212. if (!Rast3d_close(mapVolume))
  213. Rast3d_fatal_error("Rast3d_make_aligned_volume_file: error in Rast3d_close");
  214. Rast3d_free(volumeBuf);
  215. }