main.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /****************************************************************************
  2. *
  3. * MODULE: r3.gradient
  4. * AUTHOR(S): Anna Petrasova kratochanna <at> gmail <dot> com
  5. * PURPOSE: Computes gradient of a 3D raster map
  6. * COPYRIGHT: (C) 2014 by the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public
  9. * License (>=v2). Read the file COPYING that comes with GRASS
  10. * for details.
  11. *
  12. *****************************************************************************/
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <math.h>
  16. #include <grass/raster3d.h>
  17. #include <grass/gis.h>
  18. #include <grass/glocale.h>
  19. #include "r3gradient_structs.h"
  20. int main(int argc, char *argv[])
  21. {
  22. struct Option *input_opt, *output_opt, *block_opt;
  23. struct GModule *module;
  24. RASTER3D_Region region;
  25. RASTER3D_Map *input;
  26. RASTER3D_Map *output[3];
  27. struct Gradient_block *blocks;
  28. int block_x, block_y, block_z;
  29. int index_x, index_y, index_z;
  30. int n_x, n_y, n_z;
  31. int start_x, start_y, start_z;
  32. int i, max_i, k, j, N;
  33. double step[3];
  34. int *bl_indices;
  35. int *bl_overlap;
  36. int r, c, d;
  37. DCELL value;
  38. module = G_define_module();
  39. G_add_keyword(_("raster3d"));
  40. G_add_keyword(_("gradient"));
  41. G_add_keyword(_("voxel"));
  42. module->description =
  43. _("Computes gradient of a 3D raster map "
  44. "and outputs gradient components as three 3D raster maps.");
  45. input_opt = G_define_standard_option(G_OPT_R3_INPUT);
  46. /* TODO: define G_OPT_R3_OUTPUTS or use separate options for each map? */
  47. output_opt = G_define_standard_option(G_OPT_R3_OUTPUT);
  48. output_opt->multiple = YES;
  49. output_opt->key_desc = "grad_x,grad_y,grad_z";
  50. output_opt->description = _("Name for output 3D raster map(s)");
  51. block_opt = G_define_option();
  52. block_opt->key = "blocksize";
  53. block_opt->multiple = TRUE;
  54. block_opt->answer = "30,30,20"; /* based on testing */
  55. block_opt->key_desc = "size_x,size_y,size_z";
  56. block_opt->description = _("Size of blocks");
  57. /* disabled - was there for openMP
  58. process_opt = G_define_option();
  59. process_opt->key = "nprocs";
  60. process_opt->type = TYPE_INTEGER;
  61. process_opt->required = NO;
  62. process_opt->description = _("Number of parallel processes");
  63. process_opt->options = "1-100";
  64. process_opt->answer = "1";
  65. */
  66. G_gisinit(argv[0]);
  67. if (G_parser(argc, argv))
  68. exit(EXIT_FAILURE);
  69. N = 1;
  70. /* disabled - was there for openMP
  71. N = atoi(process_opt->answer);
  72. #if defined(_OPENMP)
  73. omp_set_num_threads(N);
  74. #endif
  75. */
  76. Rast3d_init_defaults();
  77. Rast3d_get_window(&region);
  78. block_x = atoi(block_opt->answers[0]);
  79. block_y = atoi(block_opt->answers[1]);
  80. block_z = atoi(block_opt->answers[2]);
  81. if (block_x < 3 || block_y < 3 || block_z < 3)
  82. G_warning("block size too small, set to 3");
  83. block_x = block_x < 3 ? 3 : block_x;
  84. block_y = block_y < 3 ? 3 : block_y;
  85. block_z = block_z < 3 ? 3 : block_z;
  86. block_x = block_x > region.cols ? region.cols : block_x;
  87. block_y = block_y > region.rows ? region.rows : block_y;
  88. block_z = block_y > region.depths ? region.depths : block_z;
  89. step[0] = region.ew_res;
  90. step[1] = region.ns_res;
  91. step[2] = region.tb_res;
  92. input = Rast3d_open_cell_old(input_opt->answer,
  93. G_find_raster3d(input_opt->answer, ""),
  94. &region, RASTER3D_TILE_SAME_AS_FILE,
  95. RASTER3D_USE_CACHE_DEFAULT);
  96. if (!input)
  97. Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"),
  98. input_opt->answer);
  99. for (i = 0; i < 3; i++) {
  100. output[i] =
  101. Rast3d_open_new_opt_tile_size(output_opt->answers[i],
  102. RASTER3D_USE_CACHE_DEFAULT,
  103. &region, DCELL_TYPE, 32);
  104. if (!output[i]) {
  105. Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"),
  106. output_opt->answers[i]);
  107. }
  108. }
  109. blocks = G_calloc(N, sizeof(struct Gradient_block));
  110. if (!blocks)
  111. G_fatal_error(_("Failed to allocate memory for blocks"));
  112. for (i = 0; i < N; i++) {
  113. blocks[i].input.array = G_malloc(((block_x + 2) * (block_y + 2)
  114. * (block_z + 2)) * sizeof(DCELL));
  115. blocks[i].dx.array = G_malloc(((block_x + 2) * (block_y + 2)
  116. * (block_z + 2)) * sizeof(DCELL));
  117. blocks[i].dy.array = G_malloc(((block_x + 2) * (block_y + 2)
  118. * (block_z + 2)) * sizeof(DCELL));
  119. blocks[i].dz.array = G_malloc(((block_x + 2) * (block_y + 2)
  120. * (block_z + 2)) * sizeof(DCELL));
  121. }
  122. bl_indices = G_calloc(N * 3, sizeof(int));
  123. bl_overlap = G_calloc(N * 6, sizeof(int));
  124. max_i = (int)ceil(region.cols / (float)block_x) *
  125. (int)ceil(region.rows / (float)block_y) *
  126. (int)ceil(region.depths / (float)block_z);
  127. i = j = 0;
  128. index_z = 0;
  129. /* loop through the blocks */
  130. while (index_z < region.depths) {
  131. index_y = 0;
  132. while (index_y < region.rows) {
  133. index_x = 0;
  134. while (index_x < region.cols) {
  135. G_percent(i, max_i, 1);
  136. /* generally overlap is 1 on both sides */
  137. bl_overlap[j * 6 + 0] = bl_overlap[j * 6 + 2] =
  138. bl_overlap[j * 6 + 4] = 1;
  139. bl_overlap[j * 6 + 1] = bl_overlap[j * 6 + 3] =
  140. bl_overlap[j * 6 + 5] = 1;
  141. /* compute the starting index of the block and its size */
  142. start_x = fmax(index_x - 1, 0);
  143. n_x = fmin(index_x + block_x, region.cols - 1) - start_x + 1;
  144. start_y = fmax(index_y - 1, 0);
  145. n_y = fmin(index_y + block_y, region.rows - 1) - start_y + 1;
  146. start_z = fmax(index_z - 1, 0);
  147. n_z =
  148. fmin(index_z + block_z, region.depths - 1) - start_z + 1;
  149. /* adjust offset on edges */
  150. /* start offset */
  151. if (index_x == 0)
  152. bl_overlap[j * 6 + 0] = 0;
  153. if (index_y == 0)
  154. bl_overlap[j * 6 + 2] = 0;
  155. if (index_z == 0)
  156. bl_overlap[j * 6 + 4] = 0;
  157. /* end offset */
  158. if (index_x + block_x >= region.cols)
  159. bl_overlap[j * 6 + 1] = 0;
  160. if (index_y + block_y >= region.rows)
  161. bl_overlap[j * 6 + 3] = 0;
  162. if (index_z + block_z >= region.depths)
  163. bl_overlap[j * 6 + 5] = 0;
  164. /* adjust offset when the end block would be too small */
  165. if (n_x <= 2) {
  166. start_x -= 1;
  167. n_x += 1;
  168. bl_overlap[j * 6 + 0] = 2;
  169. }
  170. if (n_y <= 2) {
  171. start_y -= 1;
  172. n_y += 1;
  173. bl_overlap[j * 6 + 2] = 2;
  174. }
  175. if (n_z <= 2) {
  176. start_z -= 1;
  177. n_z += 1;
  178. bl_overlap[j * 6 + 4] = 2;
  179. }
  180. /* store indices for later writing */
  181. bl_indices[j * 3 + 0] = index_x;
  182. bl_indices[j * 3 + 1] = index_y;
  183. bl_indices[j * 3 + 2] = index_z;
  184. blocks[j].input.sx = n_x;
  185. blocks[j].input.sy = n_y;
  186. blocks[j].input.sz = n_z;
  187. blocks[j].dx.sx = blocks[j].dy.sx = blocks[j].dz.sx = n_x;
  188. blocks[j].dx.sy = blocks[j].dy.sy = blocks[j].dz.sy = n_y;
  189. blocks[j].dx.sz = blocks[j].dy.sz = blocks[j].dz.sz = n_z;
  190. /* read */
  191. Rast3d_get_block(input, start_x, start_y, start_z,
  192. n_x, n_y, n_z, blocks[j].input.array,
  193. DCELL_TYPE);
  194. if ((j + 1) == N || i == max_i - 1) {
  195. /* compute gradient */
  196. /* disabled openMP #pragma omp parallel for schedule (static) private (k) */
  197. for (k = 0; k <= j; k++) {
  198. Rast3d_gradient_double(&(blocks[k].input), step,
  199. &(blocks[k].dx), &(blocks[k].dy),
  200. &(blocks[k].dz));
  201. }
  202. /* write */
  203. for (k = 0; k <= j; k++) {
  204. for (c = 0;c < blocks[k].input.sx - bl_overlap[k * 6 + 0] -
  205. bl_overlap[k * 6 + 1]; c++) {
  206. for (r = 0; r < blocks[k].input.sy - bl_overlap[k * 6 + 2] -
  207. bl_overlap[k * 6 + 3]; r++) {
  208. for (d = 0; d < blocks[k].input.sz - bl_overlap[k * 6 + 4] -
  209. bl_overlap[k * 6 + 5]; d++) {
  210. value = RASTER3D_ARRAY_ACCESS(&(blocks[k].dx),
  211. c + bl_overlap[k * 6 + 0],
  212. r + bl_overlap[k * 6 + 2],
  213. d + bl_overlap[k * 6 + 4]);
  214. Rast3d_put_value(output[0],
  215. c + bl_indices[k * 3 + 0],
  216. r + bl_indices[k * 3 + 1],
  217. d + bl_indices[k * 3 + 2],
  218. &value, DCELL_TYPE);
  219. value = RASTER3D_ARRAY_ACCESS(&(blocks[k].dy),
  220. c + bl_overlap[k * 6 + 0],
  221. r + bl_overlap[k * 6 + 2],
  222. d + bl_overlap[k * 6 + 4]);
  223. Rast3d_put_value(output[1],
  224. c + bl_indices[k * 3 + 0],
  225. r + bl_indices[k * 3 + 1],
  226. d + bl_indices[k * 3 + 2],
  227. &value, DCELL_TYPE);
  228. value = RASTER3D_ARRAY_ACCESS(&(blocks[k].dz),
  229. c + bl_overlap[k * 6 + 0],
  230. r + bl_overlap[k * 6 + 2],
  231. d + bl_overlap[k * 6 + 4]);
  232. Rast3d_put_value(output[2],
  233. c + bl_indices[k * 3 + 0],
  234. r + bl_indices[k * 3 + 1],
  235. d + bl_indices[k * 3 + 2],
  236. &value, DCELL_TYPE);
  237. }
  238. }
  239. }
  240. }
  241. j = -1;
  242. }
  243. i++;
  244. j++;
  245. index_x += block_x;
  246. }
  247. index_y += block_y;
  248. }
  249. index_z += block_z;
  250. }
  251. G_percent(1, 1, 1);
  252. for (i = 0; i < N; i++) {
  253. G_free(blocks[i].input.array);
  254. G_free(blocks[i].dx.array);
  255. G_free(blocks[i].dy.array);
  256. G_free(blocks[i].dz.array);
  257. }
  258. G_free(blocks);
  259. G_free(bl_indices);
  260. G_free(bl_overlap);
  261. G_message(_("Writing gradient 3D raster maps..."));
  262. G_percent(0, 3, 1);
  263. Rast3d_close(output[0]);
  264. G_percent(1, 3, 1);
  265. Rast3d_close(output[1]);
  266. G_percent(2, 3, 1);
  267. Rast3d_close(output[2]);
  268. G_percent(1, 1, 1);
  269. exit(EXIT_SUCCESS);
  270. }