main.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /****************************************************************************
  2. *
  3. * MODULE: r3.out.ascii
  4. *
  5. * AUTHOR(S): Original author
  6. * Mark Astley, Bill Brown, Soeren Gebbert
  7. * USA CERL started 4/4/96
  8. *
  9. * PURPOSE: Converts a 3D raster map layer into an ASCII text file
  10. *
  11. * COPYRIGHT: (C) 2005 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. *****************************************************************************/
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <grass/gis.h>
  22. #include <grass/raster3d.h>
  23. #include <grass/glocale.h>
  24. #define MAX(a,b) (a > b ? a : b)
  25. /* structs */
  26. typedef struct {
  27. struct Option *input, *output, *decimals, *null_val;
  28. struct Flag *header;
  29. struct Flag *row;
  30. struct Flag *depth;
  31. struct Flag *grass6;
  32. struct Flag *mask;
  33. } paramType;
  34. /* protos */
  35. static void fatalError(char *errorMsg);
  36. static void setParams();
  37. static void getParams(char **input, char **output, int *decim);
  38. static void writeHeaderString(FILE * fp, char *valueString, double value);
  39. static void writeHeaderString2(FILE * fp, char *valueString, int value);
  40. static void writeHeaderString3(FILE * fp, char *valueString, const char* value);
  41. static FILE *openAscii(char *asciiFile, RASTER3D_Region region);
  42. static void G3dToascii(FILE * fp, RASTER3D_Region region, int decim);
  43. /* globals */
  44. void *map = NULL;
  45. paramType param;
  46. /*---------------------------------------------------------------------------*/
  47. /* Simple error handling routine, will eventually replace this with
  48. * RASTER3D_fatalError.
  49. */
  50. void fatalError(char *errorMsg)
  51. {
  52. if (map != NULL) {
  53. /* should unopen map here! */
  54. if (!Rast3d_close_cell(map))
  55. fatalError(_("Error closing 3d raster map"));
  56. }
  57. Rast3d_fatal_error(errorMsg);
  58. }
  59. /*---------------------------------------------------------------------------*/
  60. /* Convenient way to set up the arguments we are expecting
  61. */
  62. void setParams()
  63. {
  64. param.input = G_define_option();
  65. param.input->key = "input";
  66. param.input->type = TYPE_STRING;
  67. param.input->required = YES;
  68. param.input->gisprompt = "old,grid3,3d-raster";
  69. param.input->multiple = NO;
  70. param.input->description = _("3d raster map to be converted to ASCII");
  71. param.output = G_define_option();
  72. param.output->key = "output";
  73. param.output->type = TYPE_STRING;
  74. param.output->gisprompt = "new_file,file,output";
  75. param.output->required = NO;
  76. param.output->description = _("Name for ASCII output file");
  77. param.decimals = G_define_option();
  78. param.decimals->key = "dp";
  79. param.decimals->type = TYPE_INTEGER;
  80. param.decimals->required = NO;
  81. param.decimals->multiple = NO;
  82. param.decimals->answer = "8";
  83. param.decimals->options = "0-20";
  84. param.decimals->description = _("Number of decimal places for floats");
  85. param.null_val = G_define_option();
  86. param.null_val->key = "null";
  87. param.null_val->type = TYPE_STRING;
  88. param.null_val->required = NO;
  89. param.null_val->description = _("Char string to represent no data cell");
  90. param.null_val->answer = "*";
  91. param.header = G_define_flag();
  92. param.header->key = 'h';
  93. param.header->description = _("Suppress printing of header information");
  94. param.row = G_define_flag();
  95. param.row->key = 'r';
  96. param.row->description = _("Switch the row order in output from north->south to south->north");
  97. param.depth = G_define_flag();
  98. param.depth->key = 'd';
  99. param.depth->description = _("Switch the depth order in output from bottom->top to top->bottom");
  100. param.grass6 = G_define_flag();
  101. param.grass6->key = 'c';
  102. param.grass6->description = _("Print grass6 compatible format. Flags -d and -r are ignored.");
  103. param.mask = G_define_flag();
  104. param.mask->key = 'm';
  105. param.mask->description = _("Use RASTER3D mask (if exists) with input map");
  106. }
  107. /*---------------------------------------------------------------------------*/
  108. /* Set up the input and output file names from the user's responses
  109. */
  110. void getParams(char **input, char **output, int *decim)
  111. {
  112. *input = param.input->answer;
  113. *output = param.output->answer;
  114. sscanf(param.decimals->answer, "%d", decim);
  115. }
  116. /*---------------------------------------------------------------------------*/
  117. /* This function is used to write parts of the header for the output
  118. * ASCII file.
  119. */
  120. void writeHeaderString(FILE * fp, char *valueString, double value)
  121. {
  122. static char format[100];
  123. G_snprintf(format, 100, "%s %%lf\n", valueString);
  124. if (fprintf(fp, format, value) < 0)
  125. fatalError("writeHeaderString: header value invalid");
  126. }
  127. /*---------------------------------------------------------------------------*/
  128. void writeHeaderString2(FILE * fp, char *valueString, int value)
  129. {
  130. static char format[100];
  131. G_snprintf(format, 100, "%s %%d\n", valueString);
  132. if (fprintf(fp, format, value) < 0)
  133. fatalError("writeHeaderString: header value invalid");
  134. }
  135. /*---------------------------------------------------------------------------*/
  136. void writeHeaderString3(FILE * fp, char *valueString, const char* value)
  137. {
  138. static char format[100];
  139. G_snprintf(format, 100, "%s %%s\n", valueString);
  140. if (fprintf(fp, format, value) < 0)
  141. fatalError("writeHeaderString: header value invalid");
  142. }
  143. /*---------------------------------------------------------------------------*/
  144. /* Opens the output acsii file and writes the header.
  145. * Returns the file handle for the output file.
  146. */
  147. FILE *openAscii(char *asciiFile, RASTER3D_Region region)
  148. {
  149. FILE *fp;
  150. if (asciiFile) {
  151. fp = fopen(asciiFile, "w");
  152. if (fp == NULL) {
  153. perror(asciiFile);
  154. G_usage();
  155. exit(EXIT_FAILURE);
  156. }
  157. } else
  158. fp = stdout;
  159. if (!param.header->answer) {
  160. /* Do not print the new header in grass compatibility mode */
  161. if (!param.grass6->answer) {
  162. /* Write the version information */
  163. writeHeaderString3(fp, "version:", "grass7");
  164. /* Write the row and depth order information */
  165. if (!param.depth->answer && !param.row->answer)
  166. writeHeaderString3(fp, "order:", "nsbt");
  167. else if (param.depth->answer && !param.row->answer)
  168. writeHeaderString3(fp, "order:", "nstb");
  169. else if (!param.depth->answer && param.row->answer)
  170. writeHeaderString3(fp, "order:", "snbt");
  171. else if (param.depth->answer && param.row->answer)
  172. writeHeaderString3(fp, "order:", "sntb");
  173. }
  174. writeHeaderString(fp, "north:", region.north);
  175. writeHeaderString(fp, "south:", region.south);
  176. writeHeaderString(fp, "east:", region.east);
  177. writeHeaderString(fp, "west:", region.west);
  178. writeHeaderString(fp, "top:", region.top);
  179. writeHeaderString(fp, "bottom:", region.bottom);
  180. writeHeaderString2(fp, "rows:", region.rows);
  181. writeHeaderString2(fp, "cols:", region.cols);
  182. writeHeaderString2(fp, "levels:", region.depths);
  183. }
  184. return fp;
  185. }
  186. /*---------------------------------------------------------------------------*/
  187. /* This function does all the work. Basically, we just output the
  188. * source G3d file one layer at a time.
  189. *//* * */
  190. void G3dToascii(FILE * fp, RASTER3D_Region region, int decim)
  191. {
  192. DCELL dvalue;
  193. FCELL fvalue;
  194. int x, y, z;
  195. int rows, cols, depths, typeIntern;
  196. int col, row, depth;
  197. rows = region.rows;
  198. cols = region.cols;
  199. depths = region.depths;
  200. typeIntern = Rast3d_tile_type_map(map);
  201. for (z = 0; z < depths; z++) {
  202. G_percent(z, depths, 1);
  203. for (y = 0; y < rows; y++) { /* g3d rows count from south to north */
  204. for (x = 0; x < cols; x++) {
  205. /* From west to east */
  206. col = x;
  207. /* The default is to write rows from north to south
  208. to be r.in.ascii compatible
  209. */
  210. row = y;
  211. /* From bottom to the top */
  212. depth = z;
  213. /* Write rows from south to north */
  214. if (param.row->answer)
  215. row = rows - y - 1;
  216. /* write XY layer from top to bottom */
  217. if (param.depth->answer)
  218. depth = depths - z - 1;
  219. /* Get the data and resample if nessessary */
  220. if (typeIntern == FCELL_TYPE) {
  221. Rast3d_get_value(map, col, row, depth, &fvalue, FCELL_TYPE);
  222. if (Rast3d_is_null_value_num(&fvalue, FCELL_TYPE))
  223. fprintf(fp, "%s ", param.null_val->answer);
  224. else
  225. fprintf(fp, "%.*f ", decim, fvalue);
  226. } else {
  227. Rast3d_get_value(map, col, row, depth, &dvalue, DCELL_TYPE);
  228. if (Rast3d_is_null_value_num(&dvalue, DCELL_TYPE))
  229. fprintf(fp, "%s ", param.null_val->answer);
  230. else
  231. fprintf(fp, "%.*lf ", decim, dvalue);
  232. }
  233. }
  234. fprintf(fp, "\n");
  235. }
  236. }
  237. G_percent(1, 1, 1);
  238. G_percent_reset();
  239. }
  240. /*---------------------------------------------------------------------------*/
  241. /* Main function: open the input and output files, then call
  242. * G3dtoascii.
  243. */
  244. int main(int argc, char *argv[])
  245. {
  246. char *input, *output;
  247. int decim;
  248. RASTER3D_Region region;
  249. FILE *fp;
  250. int changemask = 0;
  251. struct GModule *module;
  252. /* Initialize GRASS */
  253. G_gisinit(argv[0]);
  254. module = G_define_module();
  255. G_add_keyword(_("raster3d"));
  256. G_add_keyword(_("voxel"));
  257. G_add_keyword(_("export"));
  258. module->description =
  259. _("Converts a 3D raster map layer into a ASCII text file.");
  260. /* Get parameters from user */
  261. setParams();
  262. /* Have GRASS get inputs */
  263. if (G_parser(argc, argv))
  264. exit(EXIT_FAILURE);
  265. /* Parse input parameters */
  266. getParams(&input, &output, &decim);
  267. if (param.grass6->answer) {
  268. param.depth->answer = 0;
  269. param.row->answer = 0;
  270. }
  271. if (NULL == G_find_grid3(input, ""))
  272. Rast3d_fatal_error(_("Requested 3d raster map not found"));
  273. /* Initiate the default settings */
  274. Rast3d_init_defaults();
  275. /* Figure out the current region settings */
  276. Rast3d_get_window(&region);
  277. /* Open the map and use XY cache mode */
  278. map = Rast3d_open_cell_old(input, G_find_grid3(input, ""), &region,
  279. RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT);
  280. if (map == NULL)
  281. Rast3d_fatal_error(_("Error opening 3d raster map"));
  282. /* Open the output ascii file */
  283. fp = openAscii(output, region);
  284. /*if requested set the Mask on */
  285. if (param.mask->answer) {
  286. if (Rast3d_mask_file_exists()) {
  287. changemask = 0;
  288. if (Rast3d_mask_is_off(map)) {
  289. Rast3d_mask_on(map);
  290. changemask = 1;
  291. }
  292. }
  293. }
  294. /* Now barf out the contents of the map in ascii form */
  295. G3dToascii(fp, region, decim);
  296. /*We set the Mask off, if it was off bevor */
  297. if (param.mask->answer) {
  298. if (Rast3d_mask_file_exists())
  299. if (Rast3d_mask_is_on(map) && changemask)
  300. Rast3d_mask_off(map);
  301. }
  302. /* Close files and exit */
  303. if (!Rast3d_close_cell(map))
  304. fatalError(_("Error closing 3d raster map"));
  305. if (output)
  306. if (fclose(fp))
  307. fatalError(_("Error closing new ASCII file"));
  308. return 0;
  309. }
  310. /*---------------------------------------------------------------------------*/