main.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /****************************************************************************
  2. *
  3. * MODULE: r3.to.rast
  4. *
  5. * AUTHOR(S): Original author
  6. * Soeren Gebbert soerengebbert@gmx.de
  7. * 08 01 2005 Berlin
  8. * PURPOSE: Converts 3D raster maps to 2D raster maps
  9. *
  10. * COPYRIGHT: (C) 2005 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General Public
  13. * License (>=v2). Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. *****************************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <grass/gis.h>
  21. #include <grass/raster.h>
  22. #include <grass/raster3d.h>
  23. #include <grass/glocale.h>
  24. /*- Parameters and global variables -----------------------------------------*/
  25. typedef struct {
  26. struct Option *input, *output;
  27. struct Option *type;
  28. struct Option *coeff_a;
  29. struct Option *coeff_b;
  30. struct Flag *mask;
  31. struct Flag *res; /*If set, use the same resolution as the input map */
  32. } paramType;
  33. paramType param; /*Parameters */
  34. /*- prototypes --------------------------------------------------------------*/
  35. void fatal_error(void *map, int *fd, int depths, char *errorMsg); /*Simple Error message */
  36. void set_params(); /*Fill the paramType structure */
  37. void g3d_to_raster(void *map, RASTER3D_Region region, int *fd,
  38. int output_type, int use_coeffs, double coeff_a,
  39. double coeff_b); /*Write the raster */
  40. int open_output_map(const char *name, int res_type); /*opens the outputmap */
  41. void close_output_map(int fd); /*close the map */
  42. /* get the output type */
  43. static int raster_type_option_string_enum(const char *type)
  44. {
  45. /* this function could go to the library but the exact behavior needs
  46. * to be figured out */
  47. if (strcmp("CELL", type) == 0)
  48. return CELL_TYPE;
  49. else if (strcmp("DCELL", type) == 0)
  50. return DCELL_TYPE;
  51. else
  52. return FCELL_TYPE;
  53. }
  54. /* ************************************************************************* */
  55. /* Error handling ********************************************************** */
  56. /* ************************************************************************* */
  57. /* TODO: use G_add_error_handler (or future Rast3d_add_error_handler) instead */
  58. /* this one would require implementation of varargs here or though
  59. * non-existent va_list version of the library function */
  60. void fatal_error(void *map, int *fd, int depths, char *errorMsg)
  61. {
  62. int i;
  63. /* Close files and exit */
  64. if (map != NULL) {
  65. if (!Rast3d_close(map))
  66. Rast3d_fatal_error(_("Unable to close 3D raster map"));
  67. }
  68. if (fd != NULL) {
  69. for (i = 0; i < depths; i++)
  70. Rast_unopen(fd[i]);
  71. }
  72. Rast3d_fatal_error("%s", errorMsg);
  73. exit(EXIT_FAILURE);
  74. }
  75. /* ************************************************************************* */
  76. /* Set up the arguments we are expecting ********************************** */
  77. /* ************************************************************************* */
  78. void set_params()
  79. {
  80. param.input = G_define_option();
  81. param.input->key = "input";
  82. param.input->type = TYPE_STRING;
  83. param.input->required = YES;
  84. param.input->gisprompt = "old,grid3,3d-raster";
  85. param.input->description =
  86. _("3D raster map(s) to be converted to 2D raster slices");
  87. param.output = G_define_option();
  88. param.output->key = "output";
  89. param.output->type = TYPE_STRING;
  90. param.output->required = YES;
  91. param.output->description = _("Basename for resultant raster slice maps");
  92. param.output->gisprompt = "new,cell,raster";
  93. param.type = G_define_standard_option(G_OPT_R_TYPE);
  94. param.type->required = NO;
  95. param.coeff_a = G_define_option();
  96. param.coeff_a->key = "multiply";
  97. param.coeff_a->type = TYPE_DOUBLE;
  98. param.coeff_a->required = NO;
  99. param.coeff_a->label = _("Value to multiply the raster values with");
  100. param.coeff_a->description = _("Coefficient a in the equation y = ax + b");
  101. param.coeff_b = G_define_option();
  102. param.coeff_b->key = "add";
  103. param.coeff_b->type = TYPE_DOUBLE;
  104. param.coeff_b->required = NO;
  105. param.coeff_b->label = _("Value to add to the raster values");
  106. param.coeff_b->description = _("Coefficient b in the equation y = ax + b");
  107. param.mask = G_define_flag();
  108. param.mask->key = 'm';
  109. param.mask->description = _("Use 3D raster mask (if exists) with input map");
  110. param.res = G_define_flag();
  111. param.res->key = 'r';
  112. param.res->description =
  113. _("Use the same resolution as the input 3D raster map for the 2D output "
  114. "maps, independent of the current region settings");
  115. }
  116. /* ************************************************************************* */
  117. /* Write the slices to separate raster maps ******************************** */
  118. /* ************************************************************************* */
  119. /* coefficients are used only when needed, otherwise the original values
  120. * is preserved as well as possible */
  121. void g3d_to_raster(void *map, RASTER3D_Region region, int *fd,
  122. int output_type, int use_coeffs, double coeff_a,
  123. double coeff_b)
  124. {
  125. FCELL f1 = 0;
  126. DCELL d1 = 0;
  127. int x, y, z;
  128. int rows, cols, depths, typeIntern, pos = 0;
  129. void *cell = NULL; /* point to row buffer */
  130. void *ptr = NULL; /* pointer to single cell */
  131. size_t cell_size = 0;
  132. rows = region.rows;
  133. cols = region.cols;
  134. depths = region.depths;
  135. G_debug(2, "g3d_to_raster: Writing %i raster maps with %i rows %i cols.",
  136. depths, rows, cols);
  137. typeIntern = Rast3d_tile_type_map(map);
  138. /* we test it here undefined just to be sure and then we use else for CELL */
  139. if (output_type == CELL_TYPE)
  140. cell = Rast_allocate_c_buf();
  141. else if (output_type == FCELL_TYPE)
  142. cell = Rast_allocate_f_buf();
  143. else if (output_type == DCELL_TYPE)
  144. cell = Rast_allocate_d_buf();
  145. else
  146. Rast3d_fatal_error(_("Unknown raster type <%d>"), output_type);
  147. cell_size = Rast_cell_size(output_type);
  148. pos = 0;
  149. /*Every Rastermap */
  150. for (z = 0; z < depths; z++) { /*From the bottom to the top */
  151. G_debug(2, "Writing raster map %d of %d", z + 1, depths);
  152. G_percent(z, depths - 1, 2);
  153. for (y = 0; y < rows; y++) {
  154. ptr = cell; /* reset at the beginning of a row */
  155. for (x = 0; x < cols; x++) {
  156. if (typeIntern == FCELL_TYPE) {
  157. Rast3d_get_value(map, x, y, z, &f1, typeIntern);
  158. if (Rast3d_is_null_value_num(&f1, FCELL_TYPE)) {
  159. Rast_set_null_value(ptr, 1, output_type);
  160. }
  161. else {
  162. if (use_coeffs)
  163. f1 = coeff_a * f1 + coeff_b;
  164. Rast_set_f_value(ptr, f1, output_type);
  165. }
  166. } else {
  167. Rast3d_get_value(map, x, y, z, &d1, typeIntern);
  168. if (Rast3d_is_null_value_num(&d1, DCELL_TYPE)) {
  169. Rast_set_null_value(ptr, 1, output_type);
  170. }
  171. else {
  172. if (use_coeffs)
  173. d1 = coeff_a * d1 + coeff_b;
  174. Rast_set_d_value(ptr, d1, output_type);
  175. }
  176. }
  177. ptr = G_incr_void_ptr(ptr, cell_size);
  178. }
  179. Rast_put_row(fd[pos], cell, output_type);
  180. }
  181. G_debug(2, "Finished writing map %d.", z + 1);
  182. pos++;
  183. }
  184. G_percent(1, 1, 1);
  185. G_free(cell);
  186. }
  187. /* ************************************************************************* */
  188. /* Open the raster output map ********************************************** */
  189. /* ************************************************************************* */
  190. int open_output_map(const char *name, int res_type)
  191. {
  192. return Rast_open_new(name, res_type);
  193. }
  194. /* ************************************************************************* */
  195. /* Close the raster output map ********************************************* */
  196. /* ************************************************************************* */
  197. void close_output_map(int fd)
  198. {
  199. Rast_close(fd);
  200. }
  201. /* ************************************************************************* */
  202. /* Main function, open the RASTER3D map and create the raster maps ************** */
  203. /* ************************************************************************* */
  204. int main(int argc, char *argv[])
  205. {
  206. RASTER3D_Region region, inputmap_bounds;
  207. struct Cell_head region2d;
  208. struct GModule *module;
  209. struct History history;
  210. void *map = NULL; /*The 3D Rastermap */
  211. int i = 0, changemask = 0;
  212. int *fd = NULL, output_type, cols, rows;
  213. char *RasterFileName;
  214. int overwrite = 0;
  215. int use_coeffs = 0; /* bool */
  216. double coeff_a = 1;
  217. double coeff_b = 0;
  218. /* Initialize GRASS */
  219. G_gisinit(argv[0]);
  220. module = G_define_module();
  221. G_add_keyword(_("raster3d"));
  222. G_add_keyword(_("conversion"));
  223. G_add_keyword(_("raster"));
  224. G_add_keyword(_("voxel"));
  225. module->description = _("Converts 3D raster maps to 2D raster maps");
  226. /* Get parameters from user */
  227. set_params();
  228. /* Have GRASS get inputs */
  229. if (G_parser(argc, argv))
  230. exit(EXIT_FAILURE);
  231. G_debug(3, "Open 3D raster map <%s>", param.input->answer);
  232. if (NULL == G_find_raster3d(param.input->answer, ""))
  233. Rast3d_fatal_error(_("3D raster map <%s> not found"),
  234. param.input->answer);
  235. /* coefficients to modify the map */
  236. if (param.coeff_a->answer || param.coeff_b->answer)
  237. use_coeffs = 1;
  238. if (param.coeff_a->answer)
  239. coeff_a = atof(param.coeff_a->answer);
  240. if (param.coeff_b->answer)
  241. coeff_b = atof(param.coeff_b->answer);
  242. /*Set the defaults */
  243. Rast3d_init_defaults();
  244. /*Set the resolution of the output maps */
  245. if (param.res->answer) {
  246. /*Open the map with current region */
  247. map = Rast3d_open_cell_old(param.input->answer,
  248. G_find_raster3d(param.input->answer, ""),
  249. RASTER3D_DEFAULT_WINDOW, RASTER3D_TILE_SAME_AS_FILE,
  250. RASTER3D_USE_CACHE_DEFAULT);
  251. if (map == NULL)
  252. Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"),
  253. param.input->answer);
  254. /*Get the region of the map */
  255. Rast3d_get_region_struct_map(map, &region);
  256. /*set this region as current 3D window for map */
  257. Rast3d_set_window_map(map, &region);
  258. /*Set the 2d region appropriate */
  259. Rast3d_extract2d_region(&region, &region2d);
  260. /*Make the new 2d region the default */
  261. Rast_set_window(&region2d);
  262. } else {
  263. /* Figure out the region from the map */
  264. Rast3d_get_window(&region);
  265. /*Open the 3d raster map */
  266. map = Rast3d_open_cell_old(param.input->answer,
  267. G_find_raster3d(param.input->answer, ""),
  268. &region, RASTER3D_TILE_SAME_AS_FILE,
  269. RASTER3D_USE_CACHE_DEFAULT);
  270. if (map == NULL)
  271. Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"),
  272. param.input->answer);
  273. }
  274. /*Check if the g3d-region is equal to the 2D rows and cols */
  275. rows = Rast_window_rows();
  276. cols = Rast_window_cols();
  277. /*If not equal, set the 3D window correct */
  278. if (rows != region.rows || cols != region.cols) {
  279. G_message(_("The 2D and 3D region settings are different. "
  280. "Using the 2D window settings to adjust the 2D part of the 3D region."));
  281. G_get_set_window(&region2d);
  282. region.ns_res = region2d.ns_res;
  283. region.ew_res = region2d.ew_res;
  284. region.rows = region2d.rows;
  285. region.cols = region2d.cols;
  286. Rast3d_adjust_region(&region);
  287. Rast3d_set_window_map(map, &region);
  288. }
  289. /* save the input map region for later use (history meta-data) */
  290. Rast3d_get_region_struct_map(map, &inputmap_bounds);
  291. /*Get the output type */
  292. if (param.type->answer) {
  293. output_type = raster_type_option_string_enum(param.type->answer);
  294. }
  295. else {
  296. output_type = Rast3d_file_type_map(map);
  297. }
  298. /*prepare the filehandler */
  299. fd = (int *) G_malloc(region.depths * sizeof (int));
  300. if (fd == NULL)
  301. fatal_error(map, NULL, 0, _("Out of memory"));
  302. G_message(_("Creating %i raster maps"), region.depths);
  303. /*Loop over all output maps! open */
  304. for (i = 0; i < region.depths; i++) {
  305. /*Create the outputmaps */
  306. G_asprintf(&RasterFileName, "%s_%05d", param.output->answer, i + 1);
  307. G_message(_("Raster map %i Filename: %s"), i + 1, RasterFileName);
  308. overwrite = G_check_overwrite(argc, argv);
  309. if (G_find_raster2(RasterFileName, "") && !overwrite)
  310. G_fatal_error(_("Raster map %d Filename: %s already exists. Use the flag --o to overwrite."),
  311. i + 1, RasterFileName);
  312. fd[i] = open_output_map(RasterFileName, output_type);
  313. }
  314. /*if requested set the Mask on */
  315. if (param.mask->answer) {
  316. if (Rast3d_mask_file_exists()) {
  317. changemask = 0;
  318. if (Rast3d_mask_is_off(map)) {
  319. Rast3d_mask_on(map);
  320. changemask = 1;
  321. }
  322. }
  323. }
  324. /*Create the Rastermaps */
  325. g3d_to_raster(map, region, fd, output_type, use_coeffs, coeff_a, coeff_b);
  326. /*Loop over all output maps! close */
  327. for (i = 0; i < region.depths; i++) {
  328. close_output_map(fd[i]);
  329. /* write history */
  330. G_asprintf(&RasterFileName, "%s_%i", param.output->answer, i + 1);
  331. G_debug(4, "Raster map %d Filename: %s", i + 1, RasterFileName);
  332. Rast_short_history(RasterFileName, "raster", &history);
  333. Rast_set_history(&history, HIST_DATSRC_1, "3D Raster map:");
  334. Rast_set_history(&history, HIST_DATSRC_2, param.input->answer);
  335. Rast_append_format_history(&history, "Level %d of %d", i + 1, region.depths);
  336. Rast_append_format_history(&history, "Level z-range: %f to %f",
  337. region.bottom + (i * region.tb_res),
  338. region.bottom + (i + 1 * region.tb_res));
  339. Rast_append_format_history(&history, "Input map full z-range: %f to %f",
  340. inputmap_bounds.bottom, inputmap_bounds.top);
  341. Rast_append_format_history(&history, "Input map z-resolution: %f",
  342. inputmap_bounds.tb_res);
  343. if (!param.res->answer) {
  344. Rast_append_format_history(&history, "GIS region full z-range: %f to %f",
  345. region.bottom, region.top);
  346. Rast_append_format_history(&history, "GIS region z-resolution: %f",
  347. region.tb_res);
  348. }
  349. Rast_command_history(&history);
  350. Rast_write_history(RasterFileName, &history);
  351. }
  352. /*We set the Mask off, if it was off before */
  353. if (param.mask->answer) {
  354. if (Rast3d_mask_file_exists())
  355. if (Rast3d_mask_is_on(map) && changemask)
  356. Rast3d_mask_off(map);
  357. }
  358. /*Cleaning */
  359. if (RasterFileName)
  360. G_free(RasterFileName);
  361. if (fd)
  362. G_free(fd);
  363. /* Close files and exit */
  364. if (!Rast3d_close(map))
  365. fatal_error(map, NULL, 0, _("Unable to close 3D raster map"));
  366. map = NULL;
  367. return (EXIT_SUCCESS);
  368. }