/**************************************************************************** * * MODULE: r3.out.ascii * * AUTHOR(S): Original author * Mark Astley, Bill Brown * USA CERL started 4/4/96 * * PURPOSE: Converts a 3D raster map layer into an ASCII text file * * COPYRIGHT: (C) 2005 by the GRASS Development Team * * This program is free software under the GNU General Public * License (>=v2). Read the file COPYING that comes with GRASS * for details. * *****************************************************************************/ #include #include #include #include #include #include #define MAX(a,b) (a > b ? a : b) /* structs */ typedef struct { struct Option *input, *output, *decimals, *null_val; struct Flag *header; struct Flag *mask; } paramType; /* protos */ void fatalError (char *errorMsg); void setParams (); void getParams (char **input, char **output, int *decim); void writeHeaderString (FILE * fp, char *valueString, double value); void writeHeaderString2 (FILE * fp, char *valueString, int value); FILE *openAscii (char *asciiFile, G3D_Region region); void G3dToascii (FILE * fp, G3D_Region region, int decim); /* globals */ void *map = NULL; paramType param; /*---------------------------------------------------------------------------*/ /* Simple error handling routine, will eventually replace this with * G3D_fatalError. */ void fatalError (char *errorMsg) { if (map != NULL) { /* should unopen map here! */ if (!G3d_closeCell (map)) fatalError ("Error closing g3d file"); } G3d_fatalError (errorMsg); } /*---------------------------------------------------------------------------*/ /* Convenient way to set up the arguments we are expecting */ void setParams () { param.input = G_define_option (); param.input->key = "input"; param.input->type = TYPE_STRING; param.input->required = YES; param.input->gisprompt = "old,grid3,3d-raster"; param.input->multiple = NO; param.input->description = _("3dcell map to be converted to ASCII"); param.output = G_define_option (); param.output->key = "output"; param.output->type = TYPE_STRING; param.output->gisprompt = "new_file,file,output"; param.output->required = NO; param.output->description = _("Name for ASCII output file"); param.decimals = G_define_option (); param.decimals->key = "dp"; param.decimals->type = TYPE_INTEGER; param.decimals->required = NO; param.decimals->multiple = NO; param.decimals->answer = "8"; param.decimals->options = "0-20"; param.decimals->description = _("Number of decimal places for floats"); param.null_val = G_define_option (); param.null_val->key = "null"; param.null_val->type = TYPE_STRING; param.null_val->required = NO; param.null_val->description = _("Char string to represent no data cell"); param.null_val->answer = "*"; param.header = G_define_flag (); param.header->key = 'h'; param.header->description = _("Suppress printing of header information"); param.mask = G_define_flag (); param.mask->key = 'm'; param.mask->description = _("Use G3D mask (if exists) with input map"); } /*---------------------------------------------------------------------------*/ /* Set up the input and output file names from the user's responses */ void getParams (char **input, char **output, int *decim) { *input = param.input->answer; *output = param.output->answer; sscanf (param.decimals->answer, "%d", decim); } /*---------------------------------------------------------------------------*/ /* This function is used to write parts of the header for the output * ASCII file. */ void writeHeaderString (FILE * fp, char *valueString, double value) { static char format[100]; sprintf (format, "%s %%lf\n", valueString); if (fprintf (fp, format, value) < 0) fatalError ("writeHeaderString: header value invalid"); } /*---------------------------------------------------------------------------*/ void writeHeaderString2 (FILE * fp, char *valueString, int value) { static char format[100]; sprintf (format, "%s %%d\n", valueString); if (fprintf (fp, format, value) < 0) fatalError ("writeHeaderString: header value invalid"); } /*---------------------------------------------------------------------------*/ /* Opens the output acsii file and writes the header. * Returns the file handle for the output file. */ FILE * openAscii (char *asciiFile, G3D_Region region) { FILE *fp; if (asciiFile) { fp = fopen (asciiFile, "w"); if (fp == NULL) { perror (asciiFile); G_usage (); exit (-1); } } else fp = stdout; if (!param.header->answer) { writeHeaderString (fp, "north:", region.north); writeHeaderString (fp, "south:", region.south); writeHeaderString (fp, "east:", region.east); writeHeaderString (fp, "west:", region.west); writeHeaderString (fp, "top:", region.top); writeHeaderString (fp, "bottom:", region.bottom); writeHeaderString2 (fp, "rows:", region.rows); writeHeaderString2 (fp, "cols:", region.cols); writeHeaderString2 (fp, "levels:", region.depths); } return fp; } /*---------------------------------------------------------------------------*/ /* This function does all the work. Basically, we just output the * source G3d file one layer at a time. *//* * */ void G3dToascii (FILE * fp, G3D_Region region, int decim) { double d1 = 0; double *d1p; float *f1p; int x, y, z; int rows, cols, depths, typeIntern; /*AV*/ /* BEGIN OF ORIGINAL CODE */ /* G3d_getCoordsMap (map, &rows, &cols, &depths); */ /* END OF ORIGINAL CODE */ /*AV*/ /* BEGIN OF MY CODE */ rows = region.rows; cols = region.cols; depths = region.depths; /* END OF MY CODE */ typeIntern = G3d_tileTypeMap (map); d1p = &d1; f1p = (float *) &d1; for (z = 0; z < depths; z++) for (y = rows - 1; y >= 0; y--) { /* north to south */ for (x = 0; x < cols; x++) { G3d_getValue (map, x, y, z, d1p, typeIntern); if (typeIntern == G3D_FLOAT) { if (G3d_isNullValueNum (f1p, G3D_FLOAT)) fprintf (fp, "%s ", param.null_val->answer); else fprintf (fp, "%.*f ", decim, *f1p); } else { if (G3d_isNullValueNum (&d1, G3D_DOUBLE)) fprintf (fp, "%s ", param.null_val->answer); else fprintf (fp, "%.*lf ", decim, d1); } } fprintf (fp, "\n"); } } /*---------------------------------------------------------------------------*/ /* Main function: open the input and output files, then call * G3dtoascii. */ int main (int argc, char *argv[]) { char *input, *output; int decim; G3D_Region region; FILE *fp; int changemask = 0; struct GModule *module; /* Initialize GRASS */ G_gisinit (argv[0]); module = G_define_module (); module->keywords = _("raster3d, voxel"); module->description = _("Converts a 3D raster map layer into an ASCII text file"); /* Get parameters from user */ setParams (); /* Have GRASS get inputs */ if (G_parser (argc, argv)) exit (-1); /* Parse input parameters */ getParams (&input, &output, &decim); if (NULL == G_find_grid3 (input, "")) G3d_fatalError (_("Requested g3d file not found")); /* map = G3d_openCellOld(input, G_find_grid3(input, ""), G3D_DEFAULT_WINDOW, G3D_TILE_SAME_AS_FILE, G3D_NO_CACHE);*/ /* using cache mode due to bug */ map = G3d_openCellOld (input, G_find_grid3 (input, ""), G3D_DEFAULT_WINDOW, G3D_TILE_SAME_AS_FILE, G3D_USE_CACHE_DEFAULT); if (map == NULL) G3d_fatalError (_("Error opening g3d file")); /* Figure out the region from the map */ /* G3d_getRegionStructMap(map, ®ion);*/ G3d_getWindow (®ion); /* Open the output ascii file */ fp = openAscii (output, region); /*if requested set the Mask on */ if (param.mask->answer) { if (G3d_maskFileExists ()) { changemask = 0; if (G3d_maskIsOff (map)) { G3d_maskOn (map); changemask = 1; } } } /* Now barf out the contents of the map in ascii form */ G3dToascii (fp, region, decim); /*We set the Mask off, if it was off bevor */ if (param.mask->answer) { if (G3d_maskFileExists ()) if (G3d_maskIsOn (map) && changemask) G3d_maskOff (map); } /* Close files and exit */ if (!G3d_closeCell (map)) fatalError ("Error closing g3d file"); map = NULL; if (output) if (fclose (fp)) fatalError ("Error closing new ASCII file"); return 0; } /*---------------------------------------------------------------------------*/