123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- /****************************************************************************
- *
- * MODULE: r3.to.rast
- *
- * AUTHOR(S): Original author
- * Soeren Gebbert soerengebbert@gmx.de
- * 08 01 2005 Berlin
- * PURPOSE: Converts 3D raster maps to 2D raster maps
- *
- * 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 <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/raster.h>
- #include <grass/raster3d.h>
- #include <grass/glocale.h>
- /*- Parameters and global variables -----------------------------------------*/
- typedef struct {
- struct Option *input, *output;
- struct Option *type;
- struct Option *coeff_a;
- struct Option *coeff_b;
- struct Flag *mask;
- struct Flag *res; /*If set, use the same resolution as the input map */
- } paramType;
- paramType param; /*Parameters */
- /*- prototypes --------------------------------------------------------------*/
- void fatal_error(void *map, int *fd, int depths, char *errorMsg); /*Simple Error message */
- void set_params(); /*Fill the paramType structure */
- void g3d_to_raster(void *map, RASTER3D_Region region, int *fd,
- int output_type, int use_coeffs, double coeff_a,
- double coeff_b); /*Write the raster */
- int open_output_map(const char *name, int res_type); /*opens the outputmap */
- void close_output_map(int fd); /*close the map */
- /* get the output type */
- static int raster_type_option_string_enum(const char *type)
- {
- /* this function could go to the library but the exact behavior needs
- * to be figured out */
- if (strcmp("CELL", type) == 0)
- return CELL_TYPE;
- else if (strcmp("DCELL", type) == 0)
- return DCELL_TYPE;
- else
- return FCELL_TYPE;
- }
- /* ************************************************************************* */
- /* Error handling ********************************************************** */
- /* ************************************************************************* */
- /* TODO: use G_add_error_handler (or future Rast3d_add_error_handler) instead */
- /* this one would require implementation of varargs here or though
- * non-existent va_list version of the library function */
- void fatal_error(void *map, int *fd, int depths, char *errorMsg)
- {
- int i;
- /* Close files and exit */
- if (map != NULL) {
- if (!Rast3d_close(map))
- Rast3d_fatal_error(_("Unable to close 3D raster map"));
- }
- if (fd != NULL) {
- for (i = 0; i < depths; i++)
- Rast_unopen(fd[i]);
- }
- Rast3d_fatal_error("%s", errorMsg);
- exit(EXIT_FAILURE);
- }
- /* ************************************************************************* */
- /* Set up the arguments we are expecting ********************************** */
- /* ************************************************************************* */
- void set_params()
- {
- 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->description =
- _("3D raster map(s) to be converted to 2D raster slices");
- param.output = G_define_option();
- param.output->key = "output";
- param.output->type = TYPE_STRING;
- param.output->required = YES;
- param.output->description = _("Basename for resultant raster slice maps");
- param.output->gisprompt = "new,cell,raster";
- param.type = G_define_standard_option(G_OPT_R_TYPE);
- param.type->required = NO;
- param.coeff_a = G_define_option();
- param.coeff_a->key = "multiply";
- param.coeff_a->type = TYPE_DOUBLE;
- param.coeff_a->required = NO;
- param.coeff_a->label = _("Value to multiply the raster values with");
- param.coeff_a->description = _("Coefficient a in the equation y = ax + b");
- param.coeff_b = G_define_option();
- param.coeff_b->key = "add";
- param.coeff_b->type = TYPE_DOUBLE;
- param.coeff_b->required = NO;
- param.coeff_b->label = _("Value to add to the raster values");
- param.coeff_b->description = _("Coefficient b in the equation y = ax + b");
- param.mask = G_define_flag();
- param.mask->key = 'm';
- param.mask->description = _("Use 3D raster mask (if exists) with input map");
- param.res = G_define_flag();
- param.res->key = 'r';
- param.res->description =
- _("Use the same resolution as the input 3D raster map for the 2D output "
- "maps, independent of the current region settings");
- }
- /* ************************************************************************* */
- /* Write the slices to separate raster maps ******************************** */
- /* ************************************************************************* */
- /* coefficients are used only when needed, otherwise the original values
- * is preserved as well as possible */
- void g3d_to_raster(void *map, RASTER3D_Region region, int *fd,
- int output_type, int use_coeffs, double coeff_a,
- double coeff_b)
- {
- FCELL f1 = 0;
- DCELL d1 = 0;
- int x, y, z;
- int rows, cols, depths, typeIntern, pos = 0;
- void *cell = NULL; /* point to row buffer */
- void *ptr = NULL; /* pointer to single cell */
- size_t cell_size = 0;
- rows = region.rows;
- cols = region.cols;
- depths = region.depths;
- G_debug(2, "g3d_to_raster: Writing %i raster maps with %i rows %i cols.",
- depths, rows, cols);
- typeIntern = Rast3d_tile_type_map(map);
- /* we test it here undefined just to be sure and then we use else for CELL */
- if (output_type == CELL_TYPE)
- cell = Rast_allocate_c_buf();
- else if (output_type == FCELL_TYPE)
- cell = Rast_allocate_f_buf();
- else if (output_type == DCELL_TYPE)
- cell = Rast_allocate_d_buf();
- else
- Rast3d_fatal_error(_("Unknown raster type <%d>"), output_type);
- cell_size = Rast_cell_size(output_type);
- pos = 0;
- /*Every Rastermap */
- for (z = 0; z < depths; z++) { /*From the bottom to the top */
- G_debug(2, "Writing raster map %d of %d", z + 1, depths);
- G_percent(z, depths - 1, 2);
- for (y = 0; y < rows; y++) {
- ptr = cell; /* reset at the beginning of a row */
- for (x = 0; x < cols; x++) {
- if (typeIntern == FCELL_TYPE) {
- Rast3d_get_value(map, x, y, z, &f1, typeIntern);
- if (Rast3d_is_null_value_num(&f1, FCELL_TYPE)) {
- Rast_set_null_value(ptr, 1, output_type);
- }
- else {
- if (use_coeffs)
- f1 = coeff_a * f1 + coeff_b;
- Rast_set_f_value(ptr, f1, output_type);
- }
- } else {
- Rast3d_get_value(map, x, y, z, &d1, typeIntern);
- if (Rast3d_is_null_value_num(&d1, DCELL_TYPE)) {
- Rast_set_null_value(ptr, 1, output_type);
- }
- else {
- if (use_coeffs)
- d1 = coeff_a * d1 + coeff_b;
- Rast_set_d_value(ptr, d1, output_type);
- }
- }
- ptr = G_incr_void_ptr(ptr, cell_size);
- }
- Rast_put_row(fd[pos], cell, output_type);
- }
- G_debug(2, "Finished writing map %d.", z + 1);
- pos++;
- }
- G_percent(1, 1, 1);
- G_free(cell);
- }
- /* ************************************************************************* */
- /* Open the raster output map ********************************************** */
- /* ************************************************************************* */
- int open_output_map(const char *name, int res_type)
- {
- return Rast_open_new(name, res_type);
- }
- /* ************************************************************************* */
- /* Close the raster output map ********************************************* */
- /* ************************************************************************* */
- void close_output_map(int fd)
- {
- Rast_close(fd);
- }
- /* ************************************************************************* */
- /* Main function, open the RASTER3D map and create the raster maps ************** */
- /* ************************************************************************* */
- int main(int argc, char *argv[])
- {
- RASTER3D_Region region, inputmap_bounds;
- struct Cell_head region2d;
- struct GModule *module;
- struct History history;
- void *map = NULL; /*The 3D Rastermap */
- int i = 0, changemask = 0;
- int *fd = NULL, output_type, cols, rows;
- char *RasterFileName;
- int overwrite = 0;
- int use_coeffs = 0; /* bool */
- double coeff_a = 1;
- double coeff_b = 0;
- /* Initialize GRASS */
- G_gisinit(argv[0]);
- module = G_define_module();
- G_add_keyword(_("raster3d"));
- G_add_keyword(_("conversion"));
- G_add_keyword(_("raster"));
- G_add_keyword(_("voxel"));
- module->description = _("Converts 3D raster maps to 2D raster maps");
- /* Get parameters from user */
- set_params();
- /* Have GRASS get inputs */
- if (G_parser(argc, argv))
- exit(EXIT_FAILURE);
- G_debug(3, "Open 3D raster map <%s>", param.input->answer);
- if (NULL == G_find_raster3d(param.input->answer, ""))
- Rast3d_fatal_error(_("3D raster map <%s> not found"),
- param.input->answer);
- /* coefficients to modify the map */
- if (param.coeff_a->answer || param.coeff_b->answer)
- use_coeffs = 1;
- if (param.coeff_a->answer)
- coeff_a = atof(param.coeff_a->answer);
- if (param.coeff_b->answer)
- coeff_b = atof(param.coeff_b->answer);
- /*Set the defaults */
- Rast3d_init_defaults();
- /*Set the resolution of the output maps */
- if (param.res->answer) {
- /*Open the map with current region */
- map = Rast3d_open_cell_old(param.input->answer,
- G_find_raster3d(param.input->answer, ""),
- RASTER3D_DEFAULT_WINDOW, RASTER3D_TILE_SAME_AS_FILE,
- RASTER3D_USE_CACHE_DEFAULT);
- if (map == NULL)
- Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"),
- param.input->answer);
- /*Get the region of the map */
- Rast3d_get_region_struct_map(map, ®ion);
- /*set this region as current 3D window for map */
- Rast3d_set_window_map(map, ®ion);
- /*Set the 2d region appropriate */
- Rast3d_extract2d_region(®ion, ®ion2d);
- /*Make the new 2d region the default */
- Rast_set_window(®ion2d);
- } else {
- /* Figure out the region from the map */
- Rast3d_get_window(®ion);
- /*Open the 3d raster map */
- map = Rast3d_open_cell_old(param.input->answer,
- G_find_raster3d(param.input->answer, ""),
- ®ion, RASTER3D_TILE_SAME_AS_FILE,
- RASTER3D_USE_CACHE_DEFAULT);
- if (map == NULL)
- Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"),
- param.input->answer);
- }
- /*Check if the g3d-region is equal to the 2D rows and cols */
- rows = Rast_window_rows();
- cols = Rast_window_cols();
- /*If not equal, set the 3D window correct */
- if (rows != region.rows || cols != region.cols) {
- G_message(_("The 2D and 3D region settings are different. "
- "Using the 2D window settings to adjust the 2D part of the 3D region."));
- G_get_set_window(®ion2d);
- region.ns_res = region2d.ns_res;
- region.ew_res = region2d.ew_res;
- region.rows = region2d.rows;
- region.cols = region2d.cols;
-
- Rast3d_adjust_region(®ion);
-
- Rast3d_set_window_map(map, ®ion);
- }
- /* save the input map region for later use (history meta-data) */
- Rast3d_get_region_struct_map(map, &inputmap_bounds);
- /*Get the output type */
- if (param.type->answer) {
- output_type = raster_type_option_string_enum(param.type->answer);
- }
- else {
- output_type = Rast3d_file_type_map(map);
- }
- /*prepare the filehandler */
- fd = (int *) G_malloc(region.depths * sizeof (int));
- if (fd == NULL)
- fatal_error(map, NULL, 0, _("Out of memory"));
- G_message(_("Creating %i raster maps"), region.depths);
- /*Loop over all output maps! open */
- for (i = 0; i < region.depths; i++) {
- /*Create the outputmaps */
- G_asprintf(&RasterFileName, "%s_%05d", param.output->answer, i + 1);
- G_message(_("Raster map %i Filename: %s"), i + 1, RasterFileName);
- overwrite = G_check_overwrite(argc, argv);
-
- if (G_find_raster2(RasterFileName, "") && !overwrite)
- G_fatal_error(_("Raster map %d Filename: %s already exists. Use the flag --o to overwrite."),
- i + 1, RasterFileName);
- fd[i] = open_output_map(RasterFileName, output_type);
- }
- /*if requested set the Mask on */
- if (param.mask->answer) {
- if (Rast3d_mask_file_exists()) {
- changemask = 0;
- if (Rast3d_mask_is_off(map)) {
- Rast3d_mask_on(map);
- changemask = 1;
- }
- }
- }
- /*Create the Rastermaps */
- g3d_to_raster(map, region, fd, output_type, use_coeffs, coeff_a, coeff_b);
- /*Loop over all output maps! close */
- for (i = 0; i < region.depths; i++) {
- close_output_map(fd[i]);
- /* write history */
- G_asprintf(&RasterFileName, "%s_%i", param.output->answer, i + 1);
- G_debug(4, "Raster map %d Filename: %s", i + 1, RasterFileName);
- Rast_short_history(RasterFileName, "raster", &history);
- Rast_set_history(&history, HIST_DATSRC_1, "3D Raster map:");
- Rast_set_history(&history, HIST_DATSRC_2, param.input->answer);
- Rast_append_format_history(&history, "Level %d of %d", i + 1, region.depths);
- Rast_append_format_history(&history, "Level z-range: %f to %f",
- region.bottom + (i * region.tb_res),
- region.bottom + (i + 1 * region.tb_res));
- Rast_append_format_history(&history, "Input map full z-range: %f to %f",
- inputmap_bounds.bottom, inputmap_bounds.top);
- Rast_append_format_history(&history, "Input map z-resolution: %f",
- inputmap_bounds.tb_res);
- if (!param.res->answer) {
- Rast_append_format_history(&history, "GIS region full z-range: %f to %f",
- region.bottom, region.top);
- Rast_append_format_history(&history, "GIS region z-resolution: %f",
- region.tb_res);
- }
- Rast_command_history(&history);
- Rast_write_history(RasterFileName, &history);
- }
- /*We set the Mask off, if it was off before */
- if (param.mask->answer) {
- if (Rast3d_mask_file_exists())
- if (Rast3d_mask_is_on(map) && changemask)
- Rast3d_mask_off(map);
- }
- /*Cleaning */
- if (RasterFileName)
- G_free(RasterFileName);
- if (fd)
- G_free(fd);
- /* Close files and exit */
- if (!Rast3d_close(map))
- fatal_error(map, NULL, 0, _("Unable to close 3D raster map"));
- map = NULL;
- return (EXIT_SUCCESS);
- }
|