g3dvolume.c 7.9 KB

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