int closefiles(char *h_name, char *i_name, char *s_name, int fd_output[3], CELL * rowbuf[3]) { int i; struct Colors colors; struct Range range; struct History history; CELL min, max; const char *mapset; for (i = 0; i < 3; i++) { Rast_close(fd_output[i]); G_free(rowbuf[i]); } mapset = G_mapset(); /* write colors */ /* set to 0,max_level instead of min,max ?? */ Rast_read_range(h_name, mapset, &range); Rast_get_range_min_max(&range, &min, &max); Rast_make_grey_scale_colors(&colors, min, max); Rast_write_colors(h_name, mapset, &colors); Rast_read_range(i_name, mapset, &range); Rast_get_range_min_max(&range, &min, &max); Rast_make_grey_scale_colors(&colors, min, max); Rast_write_colors(i_name, mapset, &colors); Rast_read_range(s_name, mapset, &range); Rast_get_range_min_max(&range, &min, &max); Rast_make_grey_scale_colors(&colors, min, max); Rast_write_colors(s_name, mapset, &colors); /* write metadata */ Rast_short_history(h_name, "raster", &history); Rast_command_history(&history); Rast_write_history(h_name, &history); Rast_put_cell_title(h_name, "Image hue"); Rast_short_history(i_name, "raster", &history); Rast_command_history(&history); Rast_write_history(i_name, &history); Rast_put_cell_title(i_name, "Image intensity"); Rast_short_history(s_name, "raster", &history); Rast_command_history(&history); Rast_write_history(s_name, &history); Rast_put_cell_title(s_name, "Image saturation"); return 0; }
/* record map history info */ static void write_hist(char *map_name, char *title, char *source_name, int mode, int sfd) { struct History history; Rast_put_cell_title(map_name, title); Rast_short_history(map_name, "raster", &history); Rast_set_history(&history, HIST_DATSRC_1, source_name); Rast_append_format_history( &history, "Processing mode: %s", sfd ? "SFD (D8)" : "MFD"); Rast_append_format_history( &history, "Memory mode: %s", mode ? "Segmented" : "All in RAM"); Rast_command_history(&history); Rast_write_history(map_name, &history); }
static void write_support_files(int xtile, int ytile, int overlap) { char name[GNAME_MAX]; struct Cell_head cellhd; char title[64]; struct History history; struct Colors colors; struct Categories cats; sprintf(name, "%s-%03d-%03d", parm.rastout->answer, ytile, xtile); Rast_get_cellhd(name, G_mapset(), &cellhd); cellhd.north = src_w.north - ytile * dst_w.rows * src_w.ns_res; cellhd.south = cellhd.north - (dst_w.rows + 2 * overlap) * src_w.ns_res; cellhd.west = src_w.west + xtile * dst_w.cols * src_w.ew_res; cellhd.east = cellhd.west + (dst_w.cols + 2 * overlap) * src_w.ew_res; Rast_put_cellhd(name, &cellhd); /* copy cats from source map */ if (Rast_read_cats(parm.rastin->answer, "", &cats) < 0) G_fatal_error(_("Unable to read cats for %s"), parm.rastin->answer); Rast_write_cats(name, &cats); /* record map metadata/history info */ G_debug(1, "Tile %d,%d of %s: writing %s", xtile, ytile, parm.rastin->answer, name); sprintf(title, "Tile %d,%d of %s", xtile, ytile, parm.rastin->answer); Rast_put_cell_title(name, title); Rast_short_history(name, "raster", &history); Rast_set_history(&history, HIST_DATSRC_1, parm.rastin->answer); Rast_command_history(&history); Rast_write_history(name, &history); /* copy color table from source map */ if (Rast_read_colors(parm.rastin->answer, "", &colors) < 0) G_fatal_error(_("Unable to read color table for %s"), parm.rastin->answer); if (map_type != CELL_TYPE) Rast_mark_colors_as_fp(&colors); Rast_write_colors(name, G_mapset(), &colors); }
int main(int argc, char **argv) { FILTER *filter; int nfilters; int repeat; char *in_name; char *filt_name; char *out_name; char title[1024]; char temp[300]; int i; struct GModule *module; struct Flag *flag2; struct Option *opt1; struct Option *opt2; struct Option *opt3; struct Option *opt4; struct Option *opt5; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("algebra")); G_add_keyword(_("statistics")); module->description = _("Performs raster map matrix filter."); /* Define the different options */ opt1 = G_define_standard_option(G_OPT_R_INPUT); opt2 = G_define_standard_option(G_OPT_R_OUTPUT); opt3 = G_define_standard_option(G_OPT_F_INPUT); opt3->key = "filter"; opt3->required = YES; opt3->description = _("Path to filter file"); opt4 = G_define_option(); opt4->key = "repeat"; opt4->type = TYPE_INTEGER; opt4->multiple = NO; opt4->required = NO; opt4->answer = "1"; opt4->description = _("Number of times to repeat the filter"); opt4->guisection = _("Filter"); opt5 = G_define_option(); opt5->key = "title"; opt5->type = TYPE_STRING; opt5->required = NO; opt5->description = _("Output raster map title"); /* Define the different flags */ /* this isn't implemented at all flag3 = G_define_flag() ; flag3->key = 'p' ; flag3->description = _("Preserved edge") ; */ flag2 = G_define_flag(); flag2->key = 'z'; flag2->description = _("Apply filter only to null data values"); flag2->guisection = _("Filter"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* preserve_edges = flag3->answer; */ null_only = flag2->answer; sscanf(opt4->answer, "%d", &repeat); out_name = opt2->answer; filt_name = opt3->answer; in_name = opt1->answer; nrows = Rast_window_rows(); ncols = Rast_window_cols(); buflen = ncols * sizeof(DCELL); /* get the filter */ filter = get_filter(filt_name, &nfilters, temp); /* make sure filter matrix won't extend outside the raster map */ for (i = 0; i < nfilters; i++) { if (filter[i].size > ncols || filter[i].size > nrows) G_fatal_error(_("Raster map too small for the size of the filter")); } /* make a title for result */ if (opt5->answer) strcpy(title, opt5->answer); else { if (*temp == 0) strcpy(temp, "unknown filter"); sprintf(title, "%s filtered using %s", in_name, temp); } perform_filter(in_name, out_name, filter, nfilters, repeat); Rast_put_cell_title(out_name, title); exit(EXIT_SUCCESS); }
/*--------------------------------------------------------------------*/ int main(int argc, char *argv[]) { /* Variable declarations */ int nsply, nsplx, nrows, ncols, nsplx_adj, nsply_adj; int nsubregion_col, nsubregion_row, subregion_row, subregion_col; int subregion = 0, nsubregions = 0; int last_row, last_column, grid, bilin, ext, flag_auxiliar, cross; /* booleans */ double stepN, stepE, lambda, mean; double N_extension, E_extension, edgeE, edgeN; const char *mapset, *drv, *db, *vector, *map; char table_name[GNAME_MAX], title[64]; char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; int dim_vect, nparameters, BW; int *lineVect; /* Vector restoring primitive's ID */ double *TN, *Q, *parVect; /* Interpolating and least-square vectors */ double **N, **obsVect; /* Interpolation and least-square matrix */ SEGMENT out_seg, mask_seg; const char *out_file, *mask_file; int out_fd, mask_fd; double seg_size; int seg_mb, segments_in_memory; int have_mask; /* Structs declarations */ int raster; struct Map_info In, In_ext, Out; struct History history; struct GModule *module; struct Option *in_opt, *in_ext_opt, *out_opt, *out_map_opt, *stepE_opt, *stepN_opt, *lambda_f_opt, *type_opt, *dfield_opt, *col_opt, *mask_opt, *memory_opt, *solver, *error, *iter; struct Flag *cross_corr_flag, *spline_step_flag; struct Reg_dimens dims; struct Cell_head elaboration_reg, original_reg; struct bound_box general_box, overlap_box, original_box; struct Point *observ; struct line_cats *Cats; dbCatValArray cvarr; int with_z; int nrec, ctype = 0; struct field_info *Fi; dbDriver *driver, *driver_cats; /*----------------------------------------------------------------*/ /* Options declarations */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("surface")); G_add_keyword(_("interpolation")); G_add_keyword(_("LIDAR")); module->description = _("Performs bicubic or bilinear spline interpolation with Tykhonov regularization."); cross_corr_flag = G_define_flag(); cross_corr_flag->key = 'c'; cross_corr_flag->description = _("Find the best Tykhonov regularizing parameter using a \"leave-one-out\" cross validation method"); spline_step_flag = G_define_flag(); spline_step_flag->key = 'e'; spline_step_flag->label = _("Estimate point density and distance"); spline_step_flag->description = _("Estimate point density and distance for the input vector points within the current region extends and quit"); in_opt = G_define_standard_option(G_OPT_V_INPUT); in_opt->label = _("Name of input vector point map"); dfield_opt = G_define_standard_option(G_OPT_V_FIELD); dfield_opt->guisection = _("Settings"); col_opt = G_define_standard_option(G_OPT_DB_COLUMN); col_opt->required = NO; col_opt->label = _("Name of the attribute column with values to be used for approximation"); col_opt->description = _("If not given and input is 3D vector map then z-coordinates are used."); col_opt->guisection = _("Settings"); in_ext_opt = G_define_standard_option(G_OPT_V_INPUT); in_ext_opt->key = "sparse_input"; in_ext_opt->required = NO; in_ext_opt->label = _("Name of input vector map with sparse points"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->required = NO; out_opt->guisection = _("Outputs"); out_map_opt = G_define_standard_option(G_OPT_R_OUTPUT); out_map_opt->key = "raster_output"; out_map_opt->required = NO; out_map_opt->guisection = _("Outputs"); mask_opt = G_define_standard_option(G_OPT_R_INPUT); mask_opt->key = "mask"; mask_opt->label = _("Raster map to use for masking (applies to raster output only)"); mask_opt->description = _("Only cells that are not NULL and not zero are interpolated"); mask_opt->required = NO; stepE_opt = G_define_option(); stepE_opt->key = "ew_step"; stepE_opt->type = TYPE_DOUBLE; stepE_opt->required = NO; stepE_opt->answer = "4"; stepE_opt->description = _("Length of each spline step in the east-west direction"); stepE_opt->guisection = _("Settings"); stepN_opt = G_define_option(); stepN_opt->key = "ns_step"; stepN_opt->type = TYPE_DOUBLE; stepN_opt->required = NO; stepN_opt->answer = "4"; stepN_opt->description = _("Length of each spline step in the north-south direction"); stepN_opt->guisection = _("Settings"); type_opt = G_define_option(); type_opt->key = "method"; type_opt->description = _("Spline interpolation algorithm"); type_opt->type = TYPE_STRING; type_opt->options = "bilinear,bicubic"; type_opt->answer = "bilinear"; type_opt->guisection = _("Settings"); G_asprintf((char **) &(type_opt->descriptions), "bilinear;%s;bicubic;%s", _("Bilinear interpolation"), _("Bicubic interpolation")); lambda_f_opt = G_define_option(); lambda_f_opt->key = "lambda_i"; lambda_f_opt->type = TYPE_DOUBLE; lambda_f_opt->required = NO; lambda_f_opt->description = _("Tykhonov regularization parameter (affects smoothing)"); lambda_f_opt->answer = "0.01"; lambda_f_opt->guisection = _("Settings"); solver = N_define_standard_option(N_OPT_SOLVER_SYMM); solver->options = "cholesky,cg"; solver->answer = "cholesky"; iter = N_define_standard_option(N_OPT_MAX_ITERATIONS); error = N_define_standard_option(N_OPT_ITERATION_ERROR); memory_opt = G_define_option(); memory_opt->key = "memory"; memory_opt->type = TYPE_INTEGER; memory_opt->required = NO; memory_opt->answer = "300"; memory_opt->label = _("Maximum memory to be used (in MB)"); memory_opt->description = _("Cache size for raster rows"); /*----------------------------------------------------------------*/ /* Parsing */ G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); vector = out_opt->answer; map = out_map_opt->answer; if (vector && map) G_fatal_error(_("Choose either vector or raster output, not both")); if (!vector && !map && !cross_corr_flag->answer) G_fatal_error(_("No raster or vector or cross-validation output")); if (!strcmp(type_opt->answer, "linear")) bilin = P_BILINEAR; else bilin = P_BICUBIC; stepN = atof(stepN_opt->answer); stepE = atof(stepE_opt->answer); lambda = atof(lambda_f_opt->answer); flag_auxiliar = FALSE; drv = db_get_default_driver_name(); if (!drv) { if (db_set_default_connection() != DB_OK) G_fatal_error(_("Unable to set default DB connection")); drv = db_get_default_driver_name(); } db = db_get_default_database_name(); if (!db) G_fatal_error(_("No default DB defined")); /* Set auxiliary table's name */ if (vector) { if (G_name_is_fully_qualified(out_opt->answer, xname, xmapset)) { sprintf(table_name, "%s_aux", xname); } else sprintf(table_name, "%s_aux", out_opt->answer); } /* Something went wrong in a previous v.surf.bspline execution */ if (db_table_exists(drv, db, table_name)) { /* Start driver and open db */ driver = db_start_driver_open_database(drv, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."), drv); db_set_error_handler_driver(driver); if (P_Drop_Aux_Table(driver, table_name) != DB_OK) G_fatal_error(_("Old auxiliary table could not be dropped")); db_close_database_shutdown_driver(driver); } /* Open input vector */ if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL) G_fatal_error(_("Vector map <%s> not found"), in_opt->answer); Vect_set_open_level(1); /* WITHOUT TOPOLOGY */ if (1 > Vect_open_old(&In, in_opt->answer, mapset)) G_fatal_error(_("Unable to open vector map <%s> at the topological level"), in_opt->answer); bspline_field = 0; /* assume 3D input */ bspline_column = col_opt->answer; with_z = !bspline_column && Vect_is_3d(&In); if (Vect_is_3d(&In)) { if (!with_z) G_verbose_message(_("Input is 3D: using attribute values instead of z-coordinates for approximation")); else G_verbose_message(_("Input is 3D: using z-coordinates for approximation")); } else { /* 2D */ if (!bspline_column) G_fatal_error(_("Input vector map is 2D. Parameter <%s> required."), col_opt->key); } if (!with_z) { bspline_field = Vect_get_field_number(&In, dfield_opt->answer); } /* Estimate point density and mean distance for current region */ if (spline_step_flag->answer) { double dens, dist; if (P_estimate_splinestep(&In, &dens, &dist) == 0) { fprintf(stdout, _("Estimated point density: %.4g"), dens); fprintf(stdout, _("Estimated mean distance between points: %.4g"), dist); } else { fprintf(stdout, _("No points in current region")); } Vect_close(&In); exit(EXIT_SUCCESS); } /*----------------------------------------------------------------*/ /* Cross-correlation begins */ if (cross_corr_flag->answer) { G_debug(1, "CrossCorrelation()"); cross = cross_correlation(&In, stepE, stepN); if (cross != TRUE) G_fatal_error(_("Cross validation didn't finish correctly")); else { G_debug(1, "Cross validation finished correctly"); Vect_close(&In); G_done_msg(_("Cross validation finished for ew_step = %f and ns_step = %f"), stepE, stepN); exit(EXIT_SUCCESS); } } /* Open input ext vector */ ext = FALSE; if (in_ext_opt->answer) { ext = TRUE; G_message(_("Vector map <%s> of sparse points will be interpolated"), in_ext_opt->answer); if ((mapset = G_find_vector2(in_ext_opt->answer, "")) == NULL) G_fatal_error(_("Vector map <%s> not found"), in_ext_opt->answer); Vect_set_open_level(1); /* WITHOUT TOPOLOGY */ if (1 > Vect_open_old(&In_ext, in_ext_opt->answer, mapset)) G_fatal_error(_("Unable to open vector map <%s> at the topological level"), in_opt->answer); } /* Open output map */ /* vector output */ if (vector && !map) { if (strcmp(drv, "dbf") == 0) G_fatal_error(_("Sorry, the <%s> driver is not compatible with " "the vector output of this module. " "Try with raster output or another driver."), drv); Vect_check_input_output_name(in_opt->answer, out_opt->answer, G_FATAL_EXIT); grid = FALSE; if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z)) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); /* Copy vector Head File */ if (ext == FALSE) { Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); } else { Vect_copy_head_data(&In_ext, &Out); Vect_hist_copy(&In_ext, &Out); } Vect_hist_command(&Out); G_verbose_message(_("Points in input vector map <%s> will be interpolated"), vector); } /* read z values from attribute table */ if (bspline_field > 0) { G_message(_("Reading values from attribute table...")); db_CatValArray_init(&cvarr); Fi = Vect_get_field(&In, bspline_field); if (Fi == NULL) G_fatal_error(_("Cannot read layer info")); driver_cats = db_start_driver_open_database(Fi->driver, Fi->database); /*G_debug (0, _("driver=%s db=%s"), Fi->driver, Fi->database); */ if (driver_cats == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_set_error_handler_driver(driver_cats); nrec = db_select_CatValArray(driver_cats, Fi->table, Fi->key, col_opt->answer, NULL, &cvarr); G_debug(3, "nrec = %d", nrec); ctype = cvarr.ctype; if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE) G_fatal_error(_("Column type not supported")); if (nrec < 0) G_fatal_error(_("Unable to select data from table")); G_verbose_message(_("%d records selected from table"), nrec); db_close_database_shutdown_driver(driver_cats); } /*----------------------------------------------------------------*/ /* Interpolation begins */ G_debug(1, "Interpolation()"); /* Open driver and database */ driver = db_start_driver_open_database(drv, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. " "Run db.connect."), drv); db_set_error_handler_driver(driver); /* Create auxiliary table */ if (vector) { if ((flag_auxiliar = P_Create_Aux4_Table(driver, table_name)) == FALSE) { P_Drop_Aux_Table(driver, table_name); G_fatal_error(_("Interpolation: Creating table: " "It was impossible to create table <%s>."), table_name); } /* db_create_index2(driver, table_name, "ID"); */ /* sqlite likes that ??? */ db_close_database_shutdown_driver(driver); driver = db_start_driver_open_database(drv, db); } /* raster output */ raster = -1; Rast_set_fp_type(DCELL_TYPE); if (!vector && map) { grid = TRUE; raster = Rast_open_fp_new(out_map_opt->answer); G_verbose_message(_("Cells for raster map <%s> will be interpolated"), map); } /* Setting regions and boxes */ G_debug(1, "Interpolation: Setting regions and boxes"); G_get_window(&original_reg); G_get_window(&elaboration_reg); Vect_region_box(&original_reg, &original_box); Vect_region_box(&elaboration_reg, &overlap_box); Vect_region_box(&elaboration_reg, &general_box); nrows = Rast_window_rows(); ncols = Rast_window_cols(); /* Alloc raster matrix */ have_mask = 0; out_file = mask_file = NULL; out_fd = mask_fd = -1; if (grid == TRUE) { int row; DCELL *drastbuf; seg_mb = atoi(memory_opt->answer); if (seg_mb < 3) G_fatal_error(_("Memory in MB must be >= 3")); if (mask_opt->answer) seg_size = sizeof(double) + sizeof(char); else seg_size = sizeof(double); seg_size = (seg_size * SEGSIZE * SEGSIZE) / (1 << 20); segments_in_memory = seg_mb / seg_size + 0.5; G_debug(1, "%d %dx%d segments held in memory", segments_in_memory, SEGSIZE, SEGSIZE); out_file = G_tempfile(); out_fd = creat(out_file, 0666); if (Segment_format(out_fd, nrows, ncols, SEGSIZE, SEGSIZE, sizeof(double)) != 1) G_fatal_error(_("Can not create temporary file")); close(out_fd); out_fd = open(out_file, 2); if (Segment_init(&out_seg, out_fd, segments_in_memory) != 1) G_fatal_error(_("Can not initialize temporary file")); /* initialize output */ G_message(_("Initializing output...")); drastbuf = Rast_allocate_buf(DCELL_TYPE); Rast_set_d_null_value(drastbuf, ncols); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); Segment_put_row(&out_seg, drastbuf, row); } G_percent(row, nrows, 2); if (mask_opt->answer) { int row, col, maskfd; DCELL dval, *drastbuf; char mask_val; G_message(_("Load masking map")); mask_file = G_tempfile(); mask_fd = creat(mask_file, 0666); if (Segment_format(mask_fd, nrows, ncols, SEGSIZE, SEGSIZE, sizeof(char)) != 1) G_fatal_error(_("Can not create temporary file")); close(mask_fd); mask_fd = open(mask_file, 2); if (Segment_init(&mask_seg, mask_fd, segments_in_memory) != 1) G_fatal_error(_("Can not initialize temporary file")); maskfd = Rast_open_old(mask_opt->answer, ""); drastbuf = Rast_allocate_buf(DCELL_TYPE); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); Rast_get_d_row(maskfd, drastbuf, row); for (col = 0; col < ncols; col++) { dval = drastbuf[col]; if (Rast_is_d_null_value(&dval) || dval == 0) mask_val = 0; else mask_val = 1; Segment_put(&mask_seg, &mask_val, row, col); } } G_percent(row, nrows, 2); G_free(drastbuf); Rast_close(maskfd); have_mask = 1; } } /*------------------------------------------------------------------ | Subdividing and working with tiles: | Each original region will be divided into several subregions. | Each one will be overlaped by its neighbouring subregions. | The overlapping is calculated as a fixed OVERLAP_SIZE times | the largest spline step plus 2 * edge ----------------------------------------------------------------*/ /* Fixing parameters of the elaboration region */ P_zero_dim(&dims); /* Set dim struct to zero */ nsplx_adj = NSPLX_MAX; nsply_adj = NSPLY_MAX; if (stepN > stepE) dims.overlap = OVERLAP_SIZE * stepN; else dims.overlap = OVERLAP_SIZE * stepE; P_get_edge(bilin, &dims, stepE, stepN); P_set_dim(&dims, stepE, stepN, &nsplx_adj, &nsply_adj); G_verbose_message(_("Adjusted EW splines %d"), nsplx_adj); G_verbose_message(_("Adjusted NS splines %d"), nsply_adj); /* calculate number of subregions */ edgeE = dims.ew_size - dims.overlap - 2 * dims.edge_v; edgeN = dims.sn_size - dims.overlap - 2 * dims.edge_h; N_extension = original_reg.north - original_reg.south; E_extension = original_reg.east - original_reg.west; nsubregion_col = ceil(E_extension / edgeE) + 0.5; nsubregion_row = ceil(N_extension / edgeN) + 0.5; if (nsubregion_col < 0) nsubregion_col = 0; if (nsubregion_row < 0) nsubregion_row = 0; nsubregions = nsubregion_row * nsubregion_col; /* Creating line and categories structs */ Cats = Vect_new_cats_struct(); Vect_cat_set(Cats, 1, 0); subregion_row = 0; elaboration_reg.south = original_reg.north; last_row = FALSE; while (last_row == FALSE) { /* For each subregion row */ subregion_row++; P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, GENERAL_ROW); if (elaboration_reg.north > original_reg.north) { /* First row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, FIRST_ROW); } if (elaboration_reg.south <= original_reg.south) { /* Last row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, LAST_ROW); last_row = TRUE; } nsply = ceil((elaboration_reg.north - elaboration_reg.south) / stepN) + 0.5; G_debug(1, "Interpolation: nsply = %d", nsply); /* if (nsply > NSPLY_MAX) nsply = NSPLY_MAX; */ elaboration_reg.east = original_reg.west; last_column = FALSE; subregion_col = 0; /* TODO: process each subregion using its own thread (via OpenMP or pthreads) */ /* I'm not sure about pthreads, but you can tell OpenMP to start all at the same time and it will keep num_workers supplied with the next job as free cpus become available */ while (last_column == FALSE) { /* For each subregion column */ int npoints = 0; /* needed for sparse points interpolation */ int npoints_ext, *lineVect_ext = NULL; double **obsVect_ext; /*, mean_ext = .0; */ struct Point *observ_ext; subregion_col++; subregion++; if (nsubregions > 1) G_message(_("Processing subregion %d of %d..."), subregion, nsubregions); P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, GENERAL_COLUMN); if (elaboration_reg.west < original_reg.west) { /* First column */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, FIRST_COLUMN); } if (elaboration_reg.east >= original_reg.east) { /* Last column */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, LAST_COLUMN); last_column = TRUE; } nsplx = ceil((elaboration_reg.east - elaboration_reg.west) / stepE) + 0.5; G_debug(1, "Interpolation: nsplx = %d", nsplx); /* if (nsplx > NSPLX_MAX) nsplx = NSPLX_MAX; */ G_debug(1, "Interpolation: (%d,%d): subregion bounds", subregion_row, subregion_col); G_debug(1, "Interpolation: \t\tNORTH:%.2f\t", elaboration_reg.north); G_debug(1, "Interpolation: WEST:%.2f\t\tEAST:%.2f", elaboration_reg.west, elaboration_reg.east); G_debug(1, "Interpolation: \t\tSOUTH:%.2f", elaboration_reg.south); #ifdef DEBUG_SUBREGIONS fprintf(stdout, "B 5\n"); fprintf(stdout, " %.11g %.11g\n", elaboration_reg.east, elaboration_reg.north); fprintf(stdout, " %.11g %.11g\n", elaboration_reg.west, elaboration_reg.north); fprintf(stdout, " %.11g %.11g\n", elaboration_reg.west, elaboration_reg.south); fprintf(stdout, " %.11g %.11g\n", elaboration_reg.east, elaboration_reg.south); fprintf(stdout, " %.11g %.11g\n", elaboration_reg.east, elaboration_reg.north); fprintf(stdout, "C 1 1\n"); fprintf(stdout, " %.11g %.11g\n", (elaboration_reg.west + elaboration_reg.east) / 2, (elaboration_reg.south + elaboration_reg.north) / 2); fprintf(stdout, " 1 %d\n", subregion); #endif /* reading points in interpolation region */ dim_vect = nsplx * nsply; observ_ext = NULL; if (grid == FALSE && ext == TRUE) { observ_ext = P_Read_Vector_Region_Map(&In_ext, &elaboration_reg, &npoints_ext, dim_vect, 1); } else npoints_ext = 1; if (grid == TRUE && have_mask) { /* any unmasked cells in general region ? */ mean = 0; observ_ext = P_Read_Raster_Region_masked(&mask_seg, &original_reg, original_box, general_box, &npoints_ext, dim_vect, mean); } observ = NULL; if (npoints_ext > 0) { observ = P_Read_Vector_Region_Map(&In, &elaboration_reg, &npoints, dim_vect, bspline_field); } else npoints = 1; G_debug(1, "Interpolation: (%d,%d): Number of points in <elaboration_box> is %d", subregion_row, subregion_col, npoints); if (npoints > 0) G_verbose_message(_("%d points found in this subregion"), npoints); /* only interpolate if there are any points in current subregion */ if (npoints > 0 && npoints_ext > 0) { int i; nparameters = nsplx * nsply; BW = P_get_BandWidth(bilin, nsply); /* Least Squares system */ N = G_alloc_matrix(nparameters, BW); /* Normal matrix */ TN = G_alloc_vector(nparameters); /* vector */ parVect = G_alloc_vector(nparameters); /* Parameters vector */ obsVect = G_alloc_matrix(npoints, 3); /* Observation vector */ Q = G_alloc_vector(npoints); /* "a priori" var-cov matrix */ lineVect = G_alloc_ivector(npoints); /* */ for (i = 0; i < npoints; i++) { /* Setting obsVect vector & Q matrix */ double dval; Q[i] = 1; /* Q=I */ lineVect[i] = observ[i].lineID; obsVect[i][0] = observ[i].coordX; obsVect[i][1] = observ[i].coordY; /* read z coordinates from attribute table */ if (bspline_field > 0) { int cat, ival, ret; cat = observ[i].cat; if (cat < 0) continue; if (ctype == DB_C_TYPE_INT) { ret = db_CatValArray_get_value_int(&cvarr, cat, &ival); obsVect[i][2] = ival; observ[i].coordZ = ival; } else { /* DB_C_TYPE_DOUBLE */ ret = db_CatValArray_get_value_double(&cvarr, cat, &dval); obsVect[i][2] = dval; observ[i].coordZ = dval; } if (ret != DB_OK) { G_warning(_("Interpolation: (%d,%d): No record for point (cat = %d)"), subregion_row, subregion_col, cat); continue; } } /* use z coordinates of 3D vector */ else { obsVect[i][2] = observ[i].coordZ; } } /* Mean calculation for every point */ mean = P_Mean_Calc(&elaboration_reg, observ, npoints); G_debug(1, "Interpolation: (%d,%d): mean=%lf", subregion_row, subregion_col, mean); G_free(observ); for (i = 0; i < npoints; i++) obsVect[i][2] -= mean; /* Bilinear interpolation */ if (bilin) { G_debug(1, "Interpolation: (%d,%d): Bilinear interpolation...", subregion_row, subregion_col); normalDefBilin(N, TN, Q, obsVect, stepE, stepN, nsplx, nsply, elaboration_reg.west, elaboration_reg.south, npoints, nparameters, BW); nCorrectGrad(N, lambda, nsplx, nsply, stepE, stepN); } /* Bicubic interpolation */ else { G_debug(1, "Interpolation: (%d,%d): Bicubic interpolation...", subregion_row, subregion_col); normalDefBicubic(N, TN, Q, obsVect, stepE, stepN, nsplx, nsply, elaboration_reg.west, elaboration_reg.south, npoints, nparameters, BW); nCorrectGrad(N, lambda, nsplx, nsply, stepE, stepN); } if(G_strncasecmp(solver->answer, "cg", 2) == 0) G_math_solver_cg_sband(N, parVect, TN, nparameters, BW, atoi(iter->answer), atof(error->answer)); else G_math_solver_cholesky_sband(N, parVect, TN, nparameters, BW); G_free_matrix(N); G_free_vector(TN); G_free_vector(Q); if (grid == TRUE) { /* GRID INTERPOLATION ==> INTERPOLATION INTO A RASTER */ G_debug(1, "Interpolation: (%d,%d): Regular_Points...", subregion_row, subregion_col); if (!have_mask) { P_Regular_Points(&elaboration_reg, &original_reg, general_box, overlap_box, &out_seg, parVect, stepN, stepE, dims.overlap, mean, nsplx, nsply, nrows, ncols, bilin); } else { P_Sparse_Raster_Points(&out_seg, &elaboration_reg, &original_reg, general_box, overlap_box, observ_ext, parVect, stepE, stepN, dims.overlap, nsplx, nsply, npoints_ext, bilin, mean); } } else { /* OBSERVATION POINTS INTERPOLATION */ if (ext == FALSE) { G_debug(1, "Interpolation: (%d,%d): Sparse_Points...", subregion_row, subregion_col); P_Sparse_Points(&Out, &elaboration_reg, general_box, overlap_box, obsVect, parVect, lineVect, stepE, stepN, dims.overlap, nsplx, nsply, npoints, bilin, Cats, driver, mean, table_name); } else { /* FLAG_EXT == TRUE */ /* done that earlier */ /* int npoints_ext, *lineVect_ext = NULL; double **obsVect_ext; struct Point *observ_ext; observ_ext = P_Read_Vector_Region_Map(&In_ext, &elaboration_reg, &npoints_ext, dim_vect, 1); */ obsVect_ext = G_alloc_matrix(npoints_ext, 3); /* Observation vector_ext */ lineVect_ext = G_alloc_ivector(npoints_ext); for (i = 0; i < npoints_ext; i++) { /* Setting obsVect_ext vector & Q matrix */ obsVect_ext[i][0] = observ_ext[i].coordX; obsVect_ext[i][1] = observ_ext[i].coordY; obsVect_ext[i][2] = observ_ext[i].coordZ - mean; lineVect_ext[i] = observ_ext[i].lineID; } G_free(observ_ext); G_debug(1, "Interpolation: (%d,%d): Sparse_Points...", subregion_row, subregion_col); P_Sparse_Points(&Out, &elaboration_reg, general_box, overlap_box, obsVect_ext, parVect, lineVect_ext, stepE, stepN, dims.overlap, nsplx, nsply, npoints_ext, bilin, Cats, driver, mean, table_name); G_free_matrix(obsVect_ext); G_free_ivector(lineVect_ext); } /* END FLAG_EXT == TRUE */ } /* END GRID == FALSE */ G_free_vector(parVect); G_free_matrix(obsVect); G_free_ivector(lineVect); } else { if (observ) G_free(observ); if (observ_ext) G_free(observ_ext); if (npoints == 0) G_warning(_("No data within this subregion. " "Consider increasing spline step values.")); } } /*! END WHILE; last_column = TRUE */ } /*! END WHILE; last_row = TRUE */ G_verbose_message(_("Writing output...")); /* Writing the output raster map */ if (grid == TRUE) { int row, col; DCELL *drastbuf, dval; if (have_mask) { Segment_release(&mask_seg); /* release memory */ close(mask_fd); unlink(mask_file); } drastbuf = Rast_allocate_buf(DCELL_TYPE); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); for (col = 0; col < ncols; col++) { Segment_get(&out_seg, &dval, row, col); drastbuf[col] = dval; } Rast_put_d_row(raster, drastbuf); } Rast_close(raster); Segment_release(&out_seg); /* release memory */ close(out_fd); unlink(out_file); /* set map title */ sprintf(title, "%s interpolation with Tykhonov regularization", type_opt->answer); Rast_put_cell_title(out_map_opt->answer, title); /* write map history */ Rast_short_history(out_map_opt->answer, "raster", &history); Rast_command_history(&history); Rast_write_history(out_map_opt->answer, &history); } /* Writing to the output vector map the points from the overlapping zones */ else if (flag_auxiliar == TRUE) { if (ext == FALSE) P_Aux_to_Vector(&In, &Out, driver, table_name); else P_Aux_to_Vector(&In_ext, &Out, driver, table_name); /* Drop auxiliary table */ G_debug(1, "%s: Dropping <%s>", argv[0], table_name); if (P_Drop_Aux_Table(driver, table_name) != DB_OK) G_fatal_error(_("Auxiliary table could not be dropped")); } db_close_database_shutdown_driver(driver); Vect_close(&In); if (ext != FALSE) Vect_close(&In_ext); if (vector) Vect_close(&Out); G_done_msg(" "); exit(EXIT_SUCCESS); } /*END MAIN */
int main(int argc, char *argv[]) { int out_fd, base_raster; char *infile, *outmap; int percent; double zrange_min, zrange_max, d_tmp; double irange_min, irange_max; unsigned long estimated_lines; RASTER_MAP_TYPE rtype, base_raster_data_type; struct History history; char title[64]; SEGMENT base_segment; struct PointBinning point_binning; void *base_array; void *raster_row; struct Cell_head region; struct Cell_head input_region; int rows, last_rows, row0, cols; /* scan box size */ int row; /* counters */ int pass, npasses; unsigned long line, line_total; unsigned int counter; unsigned long n_invalid; char buff[BUFFSIZE]; double x, y, z; double intensity; int arr_row, arr_col; unsigned long count, count_total; int point_class; double zscale = 1.0; double iscale = 1.0; double res = 0.0; struct BinIndex bin_index_nodes; bin_index_nodes.num_nodes = 0; bin_index_nodes.max_nodes = 0; bin_index_nodes.nodes = 0; struct GModule *module; struct Option *input_opt, *output_opt, *percent_opt, *type_opt, *filter_opt, *class_opt; struct Option *method_opt, *base_raster_opt; struct Option *zrange_opt, *zscale_opt; struct Option *irange_opt, *iscale_opt; struct Option *trim_opt, *pth_opt, *res_opt; struct Option *file_list_opt; struct Flag *print_flag, *scan_flag, *shell_style, *over_flag, *extents_flag; struct Flag *intens_flag, *intens_import_flag; struct Flag *set_region_flag; struct Flag *base_rast_res_flag; struct Flag *only_valid_flag; /* LAS */ LASReaderH LAS_reader; LASHeaderH LAS_header; LASSRSH LAS_srs; LASPointH LAS_point; int return_filter; const char *projstr; struct Cell_head cellhd, loc_wind; unsigned int n_filtered; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("import")); G_add_keyword(_("LIDAR")); G_add_keyword(_("statistics")); G_add_keyword(_("conversion")); G_add_keyword(_("aggregation")); G_add_keyword(_("binning")); module->description = _("Creates a raster map from LAS LiDAR points using univariate statistics."); input_opt = G_define_standard_option(G_OPT_F_BIN_INPUT); input_opt->required = NO; input_opt->label = _("LAS input file"); input_opt->description = _("LiDAR input files in LAS format (*.las or *.laz)"); input_opt->guisection = _("Input"); output_opt = G_define_standard_option(G_OPT_R_OUTPUT); output_opt->required = NO; output_opt->guisection = _("Output"); file_list_opt = G_define_standard_option(G_OPT_F_INPUT); file_list_opt->key = "file"; file_list_opt->label = _("File containing names of LAS input files"); file_list_opt->description = _("LiDAR input files in LAS format (*.las or *.laz)"); file_list_opt->required = NO; file_list_opt->guisection = _("Input"); method_opt = G_define_option(); method_opt->key = "method"; method_opt->type = TYPE_STRING; method_opt->required = NO; method_opt->description = _("Statistic to use for raster values"); method_opt->options = "n,min,max,range,sum,mean,stddev,variance,coeff_var,median,percentile,skewness,trimmean"; method_opt->answer = "mean"; method_opt->guisection = _("Statistic"); G_asprintf((char **)&(method_opt->descriptions), "n;%s;" "min;%s;" "max;%s;" "range;%s;" "sum;%s;" "mean;%s;" "stddev;%s;" "variance;%s;" "coeff_var;%s;" "median;%s;" "percentile;%s;" "skewness;%s;" "trimmean;%s", _("Number of points in cell"), _("Minimum value of point values in cell"), _("Maximum value of point values in cell"), _("Range of point values in cell"), _("Sum of point values in cell"), _("Mean (average) value of point values in cell"), _("Standard deviation of point values in cell"), _("Variance of point values in cell"), _("Coefficient of variance of point values in cell"), _("Median value of point values in cell"), _("pth (nth) percentile of point values in cell"), _("Skewness of point values in cell"), _("Trimmed mean of point values in cell")); type_opt = G_define_standard_option(G_OPT_R_TYPE); type_opt->required = NO; type_opt->answer = "FCELL"; base_raster_opt = G_define_standard_option(G_OPT_R_INPUT); base_raster_opt->key = "base_raster"; base_raster_opt->required = NO; base_raster_opt->label = _("Subtract raster values from the Z coordinates"); base_raster_opt->description = _("The scale for Z is applied beforehand, the range filter for" " Z afterwards"); base_raster_opt->guisection = _("Transform"); zrange_opt = G_define_option(); zrange_opt->key = "zrange"; zrange_opt->type = TYPE_DOUBLE; zrange_opt->required = NO; zrange_opt->key_desc = "min,max"; zrange_opt->description = _("Filter range for Z data (min,max)"); zrange_opt->guisection = _("Selection"); zscale_opt = G_define_option(); zscale_opt->key = "zscale"; zscale_opt->type = TYPE_DOUBLE; zscale_opt->required = NO; zscale_opt->answer = "1.0"; zscale_opt->description = _("Scale to apply to Z data"); zscale_opt->guisection = _("Transform"); irange_opt = G_define_option(); irange_opt->key = "intensity_range"; irange_opt->type = TYPE_DOUBLE; irange_opt->required = NO; irange_opt->key_desc = "min,max"; irange_opt->description = _("Filter range for intensity values (min,max)"); irange_opt->guisection = _("Selection"); iscale_opt = G_define_option(); iscale_opt->key = "intensity_scale"; iscale_opt->type = TYPE_DOUBLE; iscale_opt->required = NO; iscale_opt->answer = "1.0"; iscale_opt->description = _("Scale to apply to intensity values"); iscale_opt->guisection = _("Transform"); percent_opt = G_define_option(); percent_opt->key = "percent"; percent_opt->type = TYPE_INTEGER; percent_opt->required = NO; percent_opt->answer = "100"; percent_opt->options = "1-100"; percent_opt->description = _("Percent of map to keep in memory"); /* I would prefer to call the following "percentile", but that has too * much namespace overlap with the "percent" option above */ pth_opt = G_define_option(); pth_opt->key = "pth"; pth_opt->type = TYPE_INTEGER; pth_opt->required = NO; pth_opt->options = "1-100"; pth_opt->description = _("pth percentile of the values"); pth_opt->guisection = _("Statistic"); trim_opt = G_define_option(); trim_opt->key = "trim"; trim_opt->type = TYPE_DOUBLE; trim_opt->required = NO; trim_opt->options = "0-50"; trim_opt->label = _("Discard given percentage of the smallest and largest values"); trim_opt->description = _("Discard <trim> percent of the smallest and <trim> percent of the largest observations"); trim_opt->guisection = _("Statistic"); res_opt = G_define_option(); res_opt->key = "resolution"; res_opt->type = TYPE_DOUBLE; res_opt->required = NO; res_opt->description = _("Output raster resolution"); res_opt->guisection = _("Output"); filter_opt = G_define_option(); filter_opt->key = "return_filter"; filter_opt->type = TYPE_STRING; filter_opt->required = NO; filter_opt->label = _("Only import points of selected return type"); filter_opt->description = _("If not specified, all points are imported"); filter_opt->options = "first,last,mid"; filter_opt->guisection = _("Selection"); class_opt = G_define_option(); class_opt->key = "class_filter"; class_opt->type = TYPE_INTEGER; class_opt->multiple = YES; class_opt->required = NO; class_opt->label = _("Only import points of selected class(es)"); class_opt->description = _("Input is comma separated integers. " "If not specified, all points are imported."); class_opt->guisection = _("Selection"); print_flag = G_define_flag(); print_flag->key = 'p'; print_flag->description = _("Print LAS file info and exit"); extents_flag = G_define_flag(); extents_flag->key = 'e'; extents_flag->label = _("Use the extent of the input for the raster extent"); extents_flag->description = _("Set internally computational region extents based on the" " point cloud"); extents_flag->guisection = _("Output"); set_region_flag = G_define_flag(); set_region_flag->key = 'n'; set_region_flag->label = _("Set computation region to match the new raster map"); set_region_flag->description = _("Set computation region to match the 2D extent and resolution" " of the newly created new raster map"); set_region_flag->guisection = _("Output"); over_flag = G_define_flag(); over_flag->key = 'o'; over_flag->label = _("Override projection check (use current location's projection)"); over_flag->description = _("Assume that the dataset has same projection as the current location"); scan_flag = G_define_flag(); scan_flag->key = 's'; scan_flag->description = _("Scan data file for extent then exit"); shell_style = G_define_flag(); shell_style->key = 'g'; shell_style->description = _("In scan mode, print using shell script style"); intens_flag = G_define_flag(); intens_flag->key = 'i'; intens_flag->label = _("Use intensity values rather than Z values"); intens_flag->description = _("Uses intensity values everywhere as if they would be Z" " coordinates"); intens_import_flag = G_define_flag(); intens_import_flag->key = 'j'; intens_import_flag->description = _("Use Z values for filtering, but intensity values for statistics"); base_rast_res_flag = G_define_flag(); base_rast_res_flag->key = 'd'; base_rast_res_flag->label = _("Use base raster resolution instead of computational region"); base_rast_res_flag->description = _("For getting values from base raster, use its actual" " resolution instead of computational region resolution"); only_valid_flag = G_define_flag(); only_valid_flag->key = 'v'; only_valid_flag->label = _("Use only valid points"); only_valid_flag->description = _("Points invalid according to APSRS LAS specification will be" " filtered out"); only_valid_flag->guisection = _("Selection"); G_option_required(input_opt, file_list_opt, NULL); G_option_exclusive(input_opt, file_list_opt, NULL); G_option_required(output_opt, print_flag, scan_flag, shell_style, NULL); G_option_exclusive(intens_flag, intens_import_flag, NULL); G_option_requires(base_rast_res_flag, base_raster_opt, NULL); if (G_parser(argc, argv)) exit(EXIT_FAILURE); int only_valid = FALSE; n_invalid = 0; if (only_valid_flag->answer) only_valid = TRUE; /* we could use rules but this gives more info and allows continuing */ if (set_region_flag->answer && !(extents_flag->answer || res_opt->answer)) { G_warning(_("Flag %c makes sense only with %s option or -%c flag"), set_region_flag->key, res_opt->key, extents_flag->key); /* avoid the call later on */ set_region_flag->answer = '\0'; } struct StringList infiles; if (file_list_opt->answer) { if (access(file_list_opt->answer, F_OK) != 0) G_fatal_error(_("File <%s> does not exist"), file_list_opt->answer); string_list_from_file(&infiles, file_list_opt->answer); } else { string_list_from_one_item(&infiles, input_opt->answer); } /* parse input values */ outmap = output_opt->answer; if (shell_style->answer && !scan_flag->answer) { scan_flag->answer = 1; /* pointer not int, so set = shell_style->answer ? */ } /* check zrange and extent relation */ if (scan_flag->answer || extents_flag->answer) { if (zrange_opt->answer) G_warning(_("zrange will not be taken into account during scan")); } Rast_get_window(®ion); /* G_get_window seems to be unreliable if the location has been changed */ G_get_set_window(&loc_wind); /* TODO: v.in.lidar uses G_get_default_window() */ estimated_lines = 0; int i; for (i = 0; i < infiles.num_items; i++) { infile = infiles.items[i]; /* don't if file not found */ if (access(infile, F_OK) != 0) G_fatal_error(_("Input file <%s> does not exist"), infile); /* Open LAS file*/ LAS_reader = LASReader_Create(infile); if (LAS_reader == NULL) G_fatal_error(_("Unable to open file <%s> as a LiDAR point cloud"), infile); LAS_header = LASReader_GetHeader(LAS_reader); if (LAS_header == NULL) { G_fatal_error(_("Unable to read LAS header of <%s>"), infile); } LAS_srs = LASHeader_GetSRS(LAS_header); /* print info or check projection if we are actually importing */ if (print_flag->answer) { /* print filename when there is more than one file */ if (infiles.num_items > 1) fprintf(stdout, "File: %s\n", infile); /* Print LAS header */ print_lasinfo(LAS_header, LAS_srs); } else { /* report that we are checking more files */ if (i == 1) G_message(_("First file's projection checked," " checking projection of the other files...")); /* Fetch input map projection in GRASS form. */ projstr = LASSRS_GetWKT_CompoundOK(LAS_srs); /* we are printing the non-warning messages only for first file */ projection_check_wkt(cellhd, loc_wind, projstr, over_flag->answer, shell_style->answer || i); /* if there is a problem in some other file, first OK message * is printed but than a warning, this is not ideal but hopefully * not so confusing when importing multiple files */ } if (scan_flag->answer || extents_flag->answer) { /* we assign to the first one (i==0) but update for the rest */ scan_bounds(LAS_reader, shell_style->answer, extents_flag->answer, i, zscale, ®ion); } /* number of estimated point across all files */ /* TODO: this should be ull which won't work with percent report */ estimated_lines += LASHeader_GetPointRecordsCount(LAS_header); /* We are closing all again and we will be opening them later, * so we don't have to worry about limit for open files. */ LASSRS_Destroy(LAS_srs); LASHeader_Destroy(LAS_header); LASReader_Destroy(LAS_reader); } /* if we are not importing, end */ if (print_flag->answer || scan_flag->answer) exit(EXIT_SUCCESS); return_filter = LAS_ALL; if (filter_opt->answer) { if (strcmp(filter_opt->answer, "first") == 0) return_filter = LAS_FIRST; else if (strcmp(filter_opt->answer, "last") == 0) return_filter = LAS_LAST; else if (strcmp(filter_opt->answer, "mid") == 0) return_filter = LAS_MID; else G_fatal_error(_("Unknown filter option <%s>"), filter_opt->answer); } struct ReturnFilter return_filter_struct; return_filter_struct.filter = return_filter; struct ClassFilter class_filter; class_filter_create_from_strings(&class_filter, class_opt->answers); percent = atoi(percent_opt->answer); /* TODO: we already used zscale */ /* TODO: we don't report intensity range */ if (zscale_opt->answer) zscale = atof(zscale_opt->answer); if (iscale_opt->answer) iscale = atof(iscale_opt->answer); /* parse zrange */ if (zrange_opt->answer != NULL) { if (zrange_opt->answers[0] == NULL) G_fatal_error(_("Invalid zrange")); sscanf(zrange_opt->answers[0], "%lf", &zrange_min); sscanf(zrange_opt->answers[1], "%lf", &zrange_max); if (zrange_min > zrange_max) { d_tmp = zrange_max; zrange_max = zrange_min; zrange_min = d_tmp; } } /* parse irange */ if (irange_opt->answer != NULL) { if (irange_opt->answers[0] == NULL) G_fatal_error(_("Invalid %s"), irange_opt->key); sscanf(irange_opt->answers[0], "%lf", &irange_min); sscanf(irange_opt->answers[1], "%lf", &irange_max); if (irange_min > irange_max) { d_tmp = irange_max; irange_max = irange_min; irange_min = d_tmp; } } point_binning_set(&point_binning, method_opt->answer, pth_opt->answer, trim_opt->answer, FALSE); base_array = NULL; if (strcmp("CELL", type_opt->answer) == 0) rtype = CELL_TYPE; else if (strcmp("DCELL", type_opt->answer) == 0) rtype = DCELL_TYPE; else rtype = FCELL_TYPE; if (point_binning.method == METHOD_N) rtype = CELL_TYPE; if (res_opt->answer) { /* align to resolution */ res = atof(res_opt->answer); if (!G_scan_resolution(res_opt->answer, &res, region.proj)) G_fatal_error(_("Invalid input <%s=%s>"), res_opt->key, res_opt->answer); if (res <= 0) G_fatal_error(_("Option '%s' must be > 0.0"), res_opt->key); region.ns_res = region.ew_res = res; region.north = ceil(region.north / res) * res; region.south = floor(region.south / res) * res; region.east = ceil(region.east / res) * res; region.west = floor(region.west / res) * res; G_adjust_Cell_head(®ion, 0, 0); } else if (extents_flag->answer) { /* align to current region */ Rast_align_window(®ion, &loc_wind); } Rast_set_output_window(®ion); rows = last_rows = region.rows; npasses = 1; if (percent < 100) { rows = (int)(region.rows * (percent / 100.0)); npasses = region.rows / rows; last_rows = region.rows - npasses * rows; if (last_rows) npasses++; else last_rows = rows; } cols = region.cols; G_debug(2, "region.n=%f region.s=%f region.ns_res=%f", region.north, region.south, region.ns_res); G_debug(2, "region.rows=%d [box_rows=%d] region.cols=%d", region.rows, rows, region.cols); /* using row-based chunks (used for output) when input and output * region matches and using segment library when they don't */ int use_segment = 0; int use_base_raster_res = 0; /* TODO: see if the input region extent is smaller than the raster * if yes, the we need to load the whole base raster if the -e * flag was defined (alternatively clip the regions) */ if (base_rast_res_flag->answer) use_base_raster_res = 1; if (base_raster_opt->answer && (res_opt->answer || use_base_raster_res || extents_flag->answer)) use_segment = 1; if (base_raster_opt->answer && !use_segment) { /* TODO: do we need to test existence first? mapset? */ base_raster = Rast_open_old(base_raster_opt->answer, ""); base_raster_data_type = Rast_get_map_type(base_raster); base_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(base_raster_data_type)); } if (base_raster_opt->answer && use_segment) { if (use_base_raster_res) { /* read raster actual extent and resolution */ Rast_get_cellhd(base_raster_opt->answer, "", &input_region); /* TODO: make it only as small as the output is or points are */ Rast_set_input_window(&input_region); /* we have split window */ } else { Rast_get_input_window(&input_region); } rast_segment_open(&base_segment, base_raster_opt->answer, &base_raster_data_type); } if (!scan_flag->answer) { if (!check_rows_cols_fit_to_size_t(rows, cols)) G_fatal_error(_("Unable to process the hole map at once. " "Please set the '%s' option to some value lower than 100."), percent_opt->key); point_binning_memory_test(&point_binning, rows, cols, rtype); } /* open output map */ out_fd = Rast_open_new(outmap, rtype); /* allocate memory for a single row of output data */ raster_row = Rast_allocate_output_buf(rtype); G_message(_("Reading data ...")); count_total = line_total = 0; /* main binning loop(s) */ for (pass = 1; pass <= npasses; pass++) { if (npasses > 1) G_message(_("Pass #%d (of %d) ..."), pass, npasses); /* figure out segmentation */ row0 = (pass - 1) * rows; if (pass == npasses) { rows = last_rows; } if (base_array) { G_debug(2, "filling base raster array"); for (row = 0; row < rows; row++) { Rast_get_row(base_raster, base_array + ((size_t) row * cols * Rast_cell_size(base_raster_data_type)), row, base_raster_data_type); } } G_debug(2, "pass=%d/%d rows=%d", pass, npasses, rows); point_binning_allocate(&point_binning, rows, cols, rtype); line = 0; count = 0; counter = 0; G_percent_reset(); /* loop of input files */ for (i = 0; i < infiles.num_items; i++) { infile = infiles.items[i]; /* we already know file is there, so just do basic checks */ LAS_reader = LASReader_Create(infile); if (LAS_reader == NULL) G_fatal_error(_("Unable to open file <%s>"), infile); while ((LAS_point = LASReader_GetNextPoint(LAS_reader)) != NULL) { line++; counter++; if (counter == 100000) { /* speed */ if (line < estimated_lines) G_percent(line, estimated_lines, 3); counter = 0; } /* We always count them and report because behavior * changed in between 7.0 and 7.2 from undefined (but skipping * invalid points) to filtering them out only when requested. */ if (!LASPoint_IsValid(LAS_point)) { n_invalid++; if (only_valid) continue; } x = LASPoint_GetX(LAS_point); y = LASPoint_GetY(LAS_point); if (intens_flag->answer) /* use intensity as z here to allow all filters (and * modifications) below to be applied for intensity */ z = LASPoint_GetIntensity(LAS_point); else z = LASPoint_GetZ(LAS_point); int return_n = LASPoint_GetReturnNumber(LAS_point); int n_returns = LASPoint_GetNumberOfReturns(LAS_point); if (return_filter_is_out(&return_filter_struct, return_n, n_returns)) { n_filtered++; continue; } point_class = (int) LASPoint_GetClassification(LAS_point); if (class_filter_is_out(&class_filter, point_class)) continue; if (y <= region.south || y > region.north) { continue; } if (x < region.west || x >= region.east) { continue; } /* find the bin in the current array box */ arr_row = (int)((region.north - y) / region.ns_res) - row0; if (arr_row < 0 || arr_row >= rows) continue; arr_col = (int)((x - region.west) / region.ew_res); z = z * zscale; if (base_array) { double base_z; if (row_array_get_value_row_col(base_array, arr_row, arr_col, cols, base_raster_data_type, &base_z)) z -= base_z; else continue; } else if (use_segment) { double base_z; if (rast_segment_get_value_xy(&base_segment, &input_region, base_raster_data_type, x, y, &base_z)) z -= base_z; else continue; } if (zrange_opt->answer) { if (z < zrange_min || z > zrange_max) { continue; } } if (intens_import_flag->answer || irange_opt->answer) { intensity = LASPoint_GetIntensity(LAS_point); intensity *= iscale; if (irange_opt->answer) { if (intensity < irange_min || intensity > irange_max) { continue; } } /* use intensity for statistics */ if (intens_import_flag->answer) z = intensity; } count++; /* G_debug(5, "x: %f, y: %f, z: %f", x, y, z); */ update_value(&point_binning, &bin_index_nodes, cols, arr_row, arr_col, rtype, x, y, z); } /* while !EOF of one input file */ /* close input LAS file */ LASReader_Destroy(LAS_reader); } /* end of loop for all input files files */ G_percent(1, 1, 1); /* flush */ G_debug(2, "pass %d finished, %lu coordinates in box", pass, count); count_total += count; line_total += line; /* calc stats and output */ G_message(_("Writing to map ...")); for (row = 0; row < rows; row++) { /* potentially vector writing can be independent on the binning */ write_values(&point_binning, &bin_index_nodes, raster_row, row, cols, rtype, NULL); /* write out line of raster data */ Rast_put_row(out_fd, raster_row, rtype); } /* free memory */ point_binning_free(&point_binning, &bin_index_nodes); } /* passes loop */ if (base_array) Rast_close(base_raster); if (use_segment) Segment_close(&base_segment); G_percent(1, 1, 1); /* flush */ G_free(raster_row); /* close raster file & write history */ Rast_close(out_fd); sprintf(title, "Raw X,Y,Z data binned into a raster grid by cell %s", method_opt->answer); Rast_put_cell_title(outmap, title); Rast_short_history(outmap, "raster", &history); Rast_command_history(&history); Rast_set_history(&history, HIST_DATSRC_1, infile); Rast_write_history(outmap, &history); /* set computation region to the new raster map */ /* TODO: should be in the done message */ if (set_region_flag->answer) G_put_window(®ion); if (n_invalid && only_valid) G_message(_("%lu input points were invalid and filtered out"), n_invalid); if (n_invalid && !only_valid) G_message(_("%lu input points were invalid, use -%c flag to filter" " them out"), n_invalid, only_valid_flag->key); if (infiles.num_items > 1) { sprintf(buff, _("Raster map <%s> created." " %lu points from %d files found in region."), outmap, count_total, infiles.num_items); } else { sprintf(buff, _("Raster map <%s> created." " %lu points found in region."), outmap, count_total); } G_done_msg("%s", buff); G_debug(1, "Processed %lu points.", line_total); string_list_free(&infiles); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct GModule *module; struct { struct Option *rastin, *rastout, *method, *quantile; } parm; struct { struct Flag *nulls, *weight; } flag; struct History history; char title[64]; char buf_nsres[100], buf_ewres[100]; struct Colors colors; int row; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("resample")); module->description = _("Resamples raster map layers to a coarser grid using aggregation."); parm.rastin = G_define_standard_option(G_OPT_R_INPUT); parm.rastout = G_define_standard_option(G_OPT_R_OUTPUT); parm.method = G_define_option(); parm.method->key = "method"; parm.method->type = TYPE_STRING; parm.method->required = NO; parm.method->description = _("Aggregation method"); parm.method->options = build_method_list(); parm.method->answer = "average"; parm.quantile = G_define_option(); parm.quantile->key = "quantile"; parm.quantile->type = TYPE_DOUBLE; parm.quantile->required = NO; parm.quantile->description = _("Quantile to calculate for method=quantile"); parm.quantile->options = "0.0-1.0"; parm.quantile->answer = "0.5"; flag.nulls = G_define_flag(); flag.nulls->key = 'n'; flag.nulls->description = _("Propagate NULLs"); flag.weight = G_define_flag(); flag.weight->key = 'w'; flag.weight->description = _("Weight according to area (slower)"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); nulls = flag.nulls->answer; method = find_method(parm.method->answer); if (method < 0) G_fatal_error(_("Unknown method <%s>"), parm.method->answer); if (menu[method].method == c_quant) { quantile = atoi(parm.quantile->answer); closure = &quantile; } G_get_set_window(&dst_w); /* set window to old map */ Rast_get_cellhd(parm.rastin->answer, "", &src_w); /* enlarge source window */ { int r0 = (int)floor(Rast_northing_to_row(dst_w.north, &src_w)); int r1 = (int)ceil(Rast_northing_to_row(dst_w.south, &src_w)); int c0 = (int)floor(Rast_easting_to_col(dst_w.west, &src_w)); int c1 = (int)ceil(Rast_easting_to_col(dst_w.east, &src_w)); src_w.south -= src_w.ns_res * (r1 - src_w.rows); src_w.north += src_w.ns_res * (-r0); src_w.west -= src_w.ew_res * (-c0); src_w.east += src_w.ew_res * (c1 - src_w.cols); src_w.rows = r1 - r0; src_w.cols = c1 - c0; } Rast_set_input_window(&src_w); Rast_set_output_window(&dst_w); row_scale = 2 + ceil(dst_w.ns_res / src_w.ns_res); col_scale = 2 + ceil(dst_w.ew_res / src_w.ew_res); /* allocate buffers for input rows */ bufs = G_malloc(row_scale * sizeof(DCELL *)); for (row = 0; row < row_scale; row++) bufs[row] = Rast_allocate_d_input_buf(); /* open old map */ infile = Rast_open_old(parm.rastin->answer, ""); /* allocate output buffer */ outbuf = Rast_allocate_d_output_buf(); /* open new map */ outfile = Rast_open_new(parm.rastout->answer, DCELL_TYPE); if (flag.weight->answer && menu[method].method_w) resamp_weighted(); else resamp_unweighted(); G_percent(dst_w.rows, dst_w.rows, 2); Rast_close(infile); Rast_close(outfile); /* record map metadata/history info */ sprintf(title, "Aggregate resample by %s", parm.method->answer); Rast_put_cell_title(parm.rastout->answer, title); Rast_short_history(parm.rastout->answer, "raster", &history); Rast_set_history(&history, HIST_DATSRC_1, parm.rastin->answer); G_format_resolution(src_w.ns_res, buf_nsres, src_w.proj); G_format_resolution(src_w.ew_res, buf_ewres, src_w.proj); Rast_format_history(&history, HIST_DATSRC_2, "Source map NS res: %s EW res: %s", buf_nsres, buf_ewres); Rast_command_history(&history); Rast_write_history(parm.rastout->answer, &history); /* copy color table from source map */ if (strcmp(parm.method->answer, "sum") != 0) { if (Rast_read_colors(parm.rastin->answer, "", &colors) < 0) G_fatal_error(_("Unable to read color table for %s"), parm.rastin->answer); Rast_mark_colors_as_fp(&colors); Rast_write_colors(parm.rastout->answer, G_mapset(), &colors); } return (EXIT_SUCCESS); }
int main(int argc, char **argv) { unsigned char *hue_n, *hue_r, *hue_g, *hue_b; unsigned char *int_n, *int_r; unsigned char *sat_n, *sat_r; unsigned char *dummy; CELL *r_array, *g_array, *b_array; char *name_h, *name_i, *name_s; int intensity; int saturation; int atrow, atcol; int hue_file; int int_file = 0; int int_used; int sat_file = 0; int sat_used; char *name_r, *name_g, *name_b; int r_file = 0; int r_used; int g_file = 0; int g_used; int b_file = 0; int b_used; struct Cell_head window; struct Colors hue_colors; struct Colors int_colors; struct Colors sat_colors; struct Colors gray_colors; struct History history; struct GModule *module; struct Option *opt_h, *opt_i, *opt_s; struct Option *opt_r, *opt_g, *opt_b; struct Flag *nulldraw; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("color transformation")); G_add_keyword(_("RGB")); G_add_keyword(_("HIS")); module->description = _("Generates red, green and blue raster map layers " "combining hue, intensity and saturation (HIS) " "values from user-specified input raster map layers."); opt_h = G_define_option(); opt_h->key = "h_map"; opt_h->type = TYPE_STRING; opt_h->required = YES; opt_h->gisprompt = "old,cell,raster"; opt_h->description = _("Name of layer to be used for HUE"); opt_i = G_define_option(); opt_i->key = "i_map"; opt_i->type = TYPE_STRING; opt_i->required = NO; opt_i->gisprompt = "old,cell,raster"; opt_i->description = _("Name of layer to be used for INTENSITY"); opt_s = G_define_option(); opt_s->key = "s_map"; opt_s->type = TYPE_STRING; opt_s->required = NO; opt_s->gisprompt = "old,cell,raster"; opt_s->description = _("Name of layer to be used for SATURATION"); opt_r = G_define_option(); opt_r->key = "r_map"; opt_r->type = TYPE_STRING; opt_r->required = YES; opt_r->gisprompt = "new,cell,raster"; opt_r->description = _("Name of output layer to be used for RED"); opt_g = G_define_option(); opt_g->key = "g_map"; opt_g->type = TYPE_STRING; opt_g->required = YES; opt_g->gisprompt = "new,cell,raster"; opt_g->description = _("Name of output layer to be used for GREEN"); opt_b = G_define_option(); opt_b->key = "b_map"; opt_b->type = TYPE_STRING; opt_b->required = YES; opt_b->gisprompt = "new,cell,raster"; opt_b->description = _("Name of output layer to be used for BLUE"); nulldraw = G_define_flag(); nulldraw->key = 'n'; nulldraw->description = _("Respect NULL values while drawing"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* read in current window */ G_get_window(&window); /* Get name of layer to be used for hue */ name_h = opt_h->answer; /* Make sure map is available */ hue_file = Rast_open_old(name_h, ""); hue_r = G_malloc(window.cols); hue_g = G_malloc(window.cols); hue_b = G_malloc(window.cols); hue_n = G_malloc(window.cols); dummy = G_malloc(window.cols); /* Reading color lookup table */ if (Rast_read_colors(name_h, "", &hue_colors) == -1) G_fatal_error(_("Color file for <%s> not available"), name_h); int_used = 0; if (opt_i->answer != NULL) { /* Get name of layer to be used for intensity */ name_i = opt_i->answer; int_used = 1; /* Make sure map is available */ int_file = Rast_open_old(name_i, ""); int_r = G_malloc(window.cols); int_n = G_malloc(window.cols); /* Reading color lookup table */ if (Rast_read_colors(name_i, "", &int_colors) == -1) G_fatal_error(_("Color file for <%s> not available"), name_i); } sat_used = 0; if (opt_s->answer != NULL) { /* Get name of layer to be used for saturation */ name_s = opt_s->answer; sat_used = 1; /* Make sure map is available */ sat_file = Rast_open_old(name_s, ""); sat_r = G_malloc(window.cols); sat_n = G_malloc(window.cols); /* Reading color lookup table */ if (Rast_read_colors(name_s, "", &sat_colors) == -1) G_fatal_error(_("Color file for <%s> not available"), name_s); } r_used = 0; if (opt_r->answer != NULL) { name_r = opt_r->answer; r_file = Rast_open_c_new(name_r); r_used = 1; } g_used = 0; if (opt_g->answer != NULL) { name_g = opt_g->answer; g_file = Rast_open_c_new(name_g); g_used = 1; } b_used = 0; if (opt_b->answer != NULL) { name_b = opt_b->answer; b_file = Rast_open_c_new(name_b); b_used = 1; } r_array = Rast_allocate_c_buf(); g_array = Rast_allocate_c_buf(); b_array = Rast_allocate_c_buf(); /* Make color table */ make_gray_scale(&gray_colors); /* Now do the work */ intensity = 255; /* default is to not change intensity */ saturation = 255; /* default is to not change saturation */ for (atrow = 0; atrow < window.rows; atrow++) { G_percent(atrow, window.rows, 2); Rast_get_row_colors(hue_file, atrow, &hue_colors, hue_r, hue_g, hue_b, hue_n); if (int_used) Rast_get_row_colors(int_file, atrow, &int_colors, int_r, dummy, dummy, int_n); if (sat_used) Rast_get_row_colors(sat_file, atrow, &sat_colors, sat_r, dummy, dummy, sat_n); for (atcol = 0; atcol < window.cols; atcol++) { if (nulldraw->answer) { if (hue_n[atcol] || (int_used && int_n[atcol]) || (sat_used && sat_n[atcol])) { Rast_set_c_null_value(&r_array[atcol], 1); Rast_set_c_null_value(&g_array[atcol], 1); Rast_set_c_null_value(&b_array[atcol], 1); continue; } } if (int_used) intensity = int_r[atcol]; if (sat_used) saturation = sat_r[atcol]; HIS_to_RGB(hue_r[atcol], hue_g[atcol], hue_b[atcol], intensity, saturation, &r_array[atcol], &g_array[atcol], &b_array[atcol]); } if (r_used) Rast_put_row(r_file, r_array, CELL_TYPE); if (g_used) Rast_put_row(g_file, g_array, CELL_TYPE); if (b_used) Rast_put_row(b_file, b_array, CELL_TYPE); } G_percent(window.rows, window.rows, 5); /* Close the cell files */ Rast_close(hue_file); if (int_used) Rast_close(int_file); if (sat_used) Rast_close(sat_file); if (r_used) { Rast_close(r_file); Rast_write_colors(name_r, G_mapset(), &gray_colors); Rast_short_history(name_r, "raster", &history); Rast_command_history(&history); Rast_write_history(name_r, &history); Rast_put_cell_title(name_r, "Red extracted from HIS"); } if (g_used) { Rast_close(g_file); Rast_write_colors(name_g, G_mapset(), &gray_colors); Rast_short_history(name_g, "raster", &history); Rast_command_history(&history); Rast_write_history(name_g, &history); Rast_put_cell_title(name_g, "Green extracted from HIS"); } if (b_used) { Rast_close(b_file); Rast_write_colors(name_b, G_mapset(), &gray_colors); Rast_short_history(name_b, "raster", &history); Rast_command_history(&history); Rast_write_history(name_b, &history); Rast_put_cell_title(name_b, "Blue extracted from HIS"); } return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { char *title; FILE *srcfp; struct GModule *module; struct { struct Option *input, *output, *title, *rules; struct Flag *a, *d; } parm; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("recode categories")); G_add_keyword(_("reclassification")); module->description = _("Recodes categorical raster maps."); parm.input = G_define_standard_option(G_OPT_R_INPUT); parm.input->description = _("Name of raster map to be recoded"); parm.output = G_define_standard_option(G_OPT_R_OUTPUT); parm.rules = G_define_standard_option(G_OPT_F_INPUT); parm.rules->key = "rules"; parm.rules->label = _("File containing recode rules"); parm.rules->description = _("'-' for standard input"); parm.title = G_define_option(); parm.title->key = "title"; parm.title->required = NO; parm.title->type = TYPE_STRING; parm.title->description = _("Title for output raster map"); parm.a = G_define_flag(); parm.a->key = 'a'; parm.a->description = _("Align the current region to the input raster map"); parm.d = G_define_flag(); parm.d->key = 'd'; parm.d->description = _("Force output to 'double' raster map type (DCELL)"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); name = parm.input->answer; result = parm.output->answer; title = parm.title->answer; align_wind = parm.a->answer; make_dcell = parm.d->answer; srcfp = stdin; if (strcmp(parm.rules->answer, "-") != 0) { srcfp = fopen(parm.rules->answer, "r"); if (!srcfp) G_fatal_error(_("Unable to open file <%s>"), parm.rules->answer); } if (!read_rules(srcfp)) { if (isatty(fileno(srcfp))) G_fatal_error(_("No rules specified. Raster map <%s> not created."), result); else G_fatal_error(_("No rules specified")); } no_mask = 0; do_recode(); if(title) Rast_put_cell_title(result, title); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct GModule *module; struct Option *rastin, *rastout, *method; struct History history; char title[64]; char buf_nsres[100], buf_ewres[100]; struct Colors colors; int infile, outfile; DCELL *outbuf; int row, col; struct Cell_head dst_w, src_w; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("resample")); module->description = _("Resamples raster map layers to a finer grid using interpolation."); rastin = G_define_standard_option(G_OPT_R_INPUT); rastout = G_define_standard_option(G_OPT_R_OUTPUT); method = G_define_option(); method->key = "method"; method->type = TYPE_STRING; method->required = NO; method->description = _("Interpolation method"); method->options = "nearest,bilinear,bicubic,lanczos"; method->answer = "bilinear"; if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (G_strcasecmp(method->answer, "nearest") == 0) neighbors = 1; else if (G_strcasecmp(method->answer, "bilinear") == 0) neighbors = 2; else if (G_strcasecmp(method->answer, "bicubic") == 0) neighbors = 4; else if (G_strcasecmp(method->answer, "lanczos") == 0) neighbors = 5; else G_fatal_error(_("Invalid method: %s"), method->answer); G_get_set_window(&dst_w); /* set window to old map */ Rast_get_cellhd(rastin->answer, "", &src_w); /* enlarge source window */ { double north = Rast_row_to_northing(0.5, &dst_w); double south = Rast_row_to_northing(dst_w.rows - 0.5, &dst_w); int r0 = (int)floor(Rast_northing_to_row(north, &src_w) - 0.5) - 2; int r1 = (int)floor(Rast_northing_to_row(south, &src_w) - 0.5) + 3; double west = Rast_col_to_easting(0.5, &dst_w); double east = Rast_col_to_easting(dst_w.cols - 0.5, &dst_w); int c0 = (int)floor(Rast_easting_to_col(west, &src_w) - 0.5) - 2; int c1 = (int)floor(Rast_easting_to_col(east, &src_w) - 0.5) + 3; src_w.south -= src_w.ns_res * (r1 - src_w.rows); src_w.north += src_w.ns_res * (-r0); src_w.west -= src_w.ew_res * (-c0); src_w.east += src_w.ew_res * (c1 - src_w.cols); src_w.rows = r1 - r0; src_w.cols = c1 - c0; } Rast_set_input_window(&src_w); /* allocate buffers for input rows */ for (row = 0; row < neighbors; row++) bufs[row] = Rast_allocate_d_input_buf(); cur_row = -100; /* open old map */ infile = Rast_open_old(rastin->answer, ""); /* reset window to current region */ Rast_set_output_window(&dst_w); outbuf = Rast_allocate_d_output_buf(); /* open new map */ outfile = Rast_open_new(rastout->answer, DCELL_TYPE); switch (neighbors) { case 1: /* nearest */ for (row = 0; row < dst_w.rows; row++) { double north = Rast_row_to_northing(row + 0.5, &dst_w); double maprow_f = Rast_northing_to_row(north, &src_w) - 0.5; int maprow0 = (int)floor(maprow_f + 0.5); G_percent(row, dst_w.rows, 2); read_rows(infile, maprow0); for (col = 0; col < dst_w.cols; col++) { double east = Rast_col_to_easting(col + 0.5, &dst_w); double mapcol_f = Rast_easting_to_col(east, &src_w) - 0.5; int mapcol0 = (int)floor(mapcol_f + 0.5); double c = bufs[0][mapcol0]; if (Rast_is_d_null_value(&c)) { Rast_set_d_null_value(&outbuf[col], 1); } else { outbuf[col] = c; } } Rast_put_d_row(outfile, outbuf); } break; case 2: /* bilinear */ for (row = 0; row < dst_w.rows; row++) { double north = Rast_row_to_northing(row + 0.5, &dst_w); double maprow_f = Rast_northing_to_row(north, &src_w) - 0.5; int maprow0 = (int)floor(maprow_f); double v = maprow_f - maprow0; G_percent(row, dst_w.rows, 2); read_rows(infile, maprow0); for (col = 0; col < dst_w.cols; col++) { double east = Rast_col_to_easting(col + 0.5, &dst_w); double mapcol_f = Rast_easting_to_col(east, &src_w) - 0.5; int mapcol0 = (int)floor(mapcol_f); int mapcol1 = mapcol0 + 1; double u = mapcol_f - mapcol0; double c00 = bufs[0][mapcol0]; double c01 = bufs[0][mapcol1]; double c10 = bufs[1][mapcol0]; double c11 = bufs[1][mapcol1]; if (Rast_is_d_null_value(&c00) || Rast_is_d_null_value(&c01) || Rast_is_d_null_value(&c10) || Rast_is_d_null_value(&c11)) { Rast_set_d_null_value(&outbuf[col], 1); } else { outbuf[col] = Rast_interp_bilinear(u, v, c00, c01, c10, c11); } } Rast_put_d_row(outfile, outbuf); } break; case 4: /* bicubic */ for (row = 0; row < dst_w.rows; row++) { double north = Rast_row_to_northing(row + 0.5, &dst_w); double maprow_f = Rast_northing_to_row(north, &src_w) - 0.5; int maprow1 = (int)floor(maprow_f); int maprow0 = maprow1 - 1; double v = maprow_f - maprow1; G_percent(row, dst_w.rows, 2); read_rows(infile, maprow0); for (col = 0; col < dst_w.cols; col++) { double east = Rast_col_to_easting(col + 0.5, &dst_w); double mapcol_f = Rast_easting_to_col(east, &src_w) - 0.5; int mapcol1 = (int)floor(mapcol_f); int mapcol0 = mapcol1 - 1; int mapcol2 = mapcol1 + 1; int mapcol3 = mapcol1 + 2; double u = mapcol_f - mapcol1; double c00 = bufs[0][mapcol0]; double c01 = bufs[0][mapcol1]; double c02 = bufs[0][mapcol2]; double c03 = bufs[0][mapcol3]; double c10 = bufs[1][mapcol0]; double c11 = bufs[1][mapcol1]; double c12 = bufs[1][mapcol2]; double c13 = bufs[1][mapcol3]; double c20 = bufs[2][mapcol0]; double c21 = bufs[2][mapcol1]; double c22 = bufs[2][mapcol2]; double c23 = bufs[2][mapcol3]; double c30 = bufs[3][mapcol0]; double c31 = bufs[3][mapcol1]; double c32 = bufs[3][mapcol2]; double c33 = bufs[3][mapcol3]; if (Rast_is_d_null_value(&c00) || Rast_is_d_null_value(&c01) || Rast_is_d_null_value(&c02) || Rast_is_d_null_value(&c03) || Rast_is_d_null_value(&c10) || Rast_is_d_null_value(&c11) || Rast_is_d_null_value(&c12) || Rast_is_d_null_value(&c13) || Rast_is_d_null_value(&c20) || Rast_is_d_null_value(&c21) || Rast_is_d_null_value(&c22) || Rast_is_d_null_value(&c23) || Rast_is_d_null_value(&c30) || Rast_is_d_null_value(&c31) || Rast_is_d_null_value(&c32) || Rast_is_d_null_value(&c33)) { Rast_set_d_null_value(&outbuf[col], 1); } else { outbuf[col] = Rast_interp_bicubic(u, v, c00, c01, c02, c03, c10, c11, c12, c13, c20, c21, c22, c23, c30, c31, c32, c33); } } Rast_put_d_row(outfile, outbuf); } break; case 5: /* lanczos */ for (row = 0; row < dst_w.rows; row++) { double north = Rast_row_to_northing(row + 0.5, &dst_w); double maprow_f = Rast_northing_to_row(north, &src_w) - 0.5; int maprow1 = (int)floor(maprow_f + 0.5); int maprow0 = maprow1 - 2; double v = maprow_f - maprow1; G_percent(row, dst_w.rows, 2); read_rows(infile, maprow0); for (col = 0; col < dst_w.cols; col++) { double east = Rast_col_to_easting(col + 0.5, &dst_w); double mapcol_f = Rast_easting_to_col(east, &src_w) - 0.5; int mapcol2 = (int)floor(mapcol_f + 0.5); int mapcol0 = mapcol2 - 2; int mapcol4 = mapcol2 + 2; double u = mapcol_f - mapcol2; double c[25]; int ci = 0, i, j, do_lanczos = 1; for (i = 0; i < 5; i++) { for (j = mapcol0; j <= mapcol4; j++) { c[ci] = bufs[i][j]; if (Rast_is_d_null_value(&(c[ci]))) { Rast_set_d_null_value(&outbuf[col], 1); do_lanczos = 0; break; } ci++; } if (!do_lanczos) break; } if (do_lanczos) { outbuf[col] = Rast_interp_lanczos(u, v, c); } } Rast_put_d_row(outfile, outbuf); } break; } G_percent(dst_w.rows, dst_w.rows, 2); Rast_close(infile); Rast_close(outfile); /* record map metadata/history info */ sprintf(title, "Resample by %s interpolation", method->answer); Rast_put_cell_title(rastout->answer, title); Rast_short_history(rastout->answer, "raster", &history); Rast_set_history(&history, HIST_DATSRC_1, rastin->answer); G_format_resolution(src_w.ns_res, buf_nsres, src_w.proj); G_format_resolution(src_w.ew_res, buf_ewres, src_w.proj); Rast_format_history(&history, HIST_DATSRC_2, "Source map NS res: %s EW res: %s", buf_nsres, buf_ewres); Rast_command_history(&history); Rast_write_history(rastout->answer, &history); /* copy color table from source map */ if (Rast_read_colors(rastin->answer, "", &colors) < 0) G_fatal_error(_("Unable to read color table for %s"), rastin->answer); Rast_mark_colors_as_fp(&colors); Rast_write_colors(rastout->answer, G_mapset(), &colors); return (EXIT_SUCCESS); }
int main(int argc, char *argv[]) { char *input; char *output; char *title; char *temp; FILE *fd, *ft; int cf, direction, sz; struct Cell_head cellhd; struct History history; void *rast, *rast_ptr; int row, col; int nrows, ncols; double x; char y[128]; struct GModule *module; struct { struct Option *input, *output, *title, *mult, *nv, *type; } parm; struct { struct Flag *s; } flag; char *null_val_str; DCELL mult; RASTER_MAP_TYPE data_type; double atof(); G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("import")); G_add_keyword(_("conversion")); G_add_keyword("ASCII"); module->description = _("Converts a GRASS ASCII raster file to binary raster map."); parm.input = G_define_standard_option(G_OPT_F_INPUT); parm.input->label = _("Name of input file to be imported"); parm.input->description = _("'-' for standard input"); parm.output = G_define_standard_option(G_OPT_R_OUTPUT); parm.type = G_define_option(); parm.type->key = "type"; parm.type->type = TYPE_STRING; parm.type->required = NO; parm.type->options = "CELL,FCELL,DCELL"; parm.type->label = _("Storage type for resultant raster map"); parm.type->description = _("Default: CELL for integer values, DCELL for floating-point values"); parm.title = G_define_option(); parm.title->key = "title"; parm.title->key_desc = "phrase"; parm.title->type = TYPE_STRING; parm.title->required = NO; parm.title->description = _("Title for resultant raster map"); parm.mult = G_define_option(); parm.mult->key = "multiplier"; parm.mult->type = TYPE_DOUBLE; parm.mult->description = _("Default: read from header"); parm.mult->required = NO; parm.mult->label = _("Multiplier for ASCII data"); parm.nv = G_define_standard_option(G_OPT_M_NULL_VALUE); parm.nv->description = _("Default: read from header"); parm.nv->label = _("String representing NULL value data cell"); parm.nv->guisection = _("NULL data"); flag.s = G_define_flag(); flag.s->key = 's'; flag.s->description = _("SURFER (Golden Software) ASCII file will be imported"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); input = parm.input->answer; output = parm.output->answer; temp = G_tempfile(); ft = fopen(temp, "w+"); if (ft == NULL) G_fatal_error(_("Unable to open temporary file <%s>"), temp); if ((title = parm.title->answer)) G_strip(title); if (!parm.mult->answer) Rast_set_d_null_value(&mult, 1); else if ((sscanf(parm.mult->answer, "%lf", &mult)) != 1) G_fatal_error(_("Wrong entry for multiplier: %s"), parm.mult->answer); null_val_str = parm.nv->answer; data_type = -1; if (parm.type->answer) { switch(parm.type->answer[0]) { case 'C': data_type = CELL_TYPE; break; case 'F': data_type = FCELL_TYPE; break; case 'D': data_type = DCELL_TYPE; break; } } if (strcmp(input, "-") == 0) { Tmp_file = G_tempfile(); if (NULL == (Tmp_fd = fopen(Tmp_file, "w+"))) G_fatal_error(_("Unable to open temporary file <%s>"), Tmp_file); unlink(Tmp_file); if (0 > file_cpy(stdin, Tmp_fd)) G_fatal_error(_("Unable to read input from stdin")); fd = Tmp_fd; } else fd = fopen(input, "r"); if (fd == NULL) { G_fatal_error(_("Unable to read input from <%s>"), input); } direction = 1; sz = 0; if (flag.s->answer) { sz = getgrdhead(fd, &cellhd); /* for Surfer files, the data type is always FCELL_TYPE, the multiplier and the null_val_str are never used */ data_type = FCELL_TYPE; mult = 1.; null_val_str = ""; /* rows in surfer files are ordered from bottom to top, opposite of normal GRASS ordering */ direction = -1; } else sz = gethead(fd, &cellhd, &data_type, &mult, &null_val_str); if (!sz) G_fatal_error(_("Can't get cell header")); nrows = cellhd.rows; ncols = cellhd.cols; Rast_set_window(&cellhd); if (nrows != Rast_window_rows()) G_fatal_error(_("OOPS: rows changed from %d to %d"), nrows, Rast_window_rows()); if (ncols != Rast_window_cols()) G_fatal_error(_("OOPS: cols changed from %d to %d"), ncols, Rast_window_cols()); rast_ptr = Rast_allocate_buf(data_type); rast = rast_ptr; cf = Rast_open_new(output, data_type); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); for (col = 0; col < ncols; col++) { if (fscanf(fd, "%s", y) != 1) { Rast_unopen(cf); G_fatal_error(_("Data conversion failed at row %d, col %d"), row + 1, col + 1); } if (strcmp(y, null_val_str)) { x = atof(y); if ((float)x == GS_BLANK) { Rast_set_null_value(rast_ptr, 1, data_type); } else { Rast_set_d_value(rast_ptr, (DCELL) (x * mult), data_type); } } else { Rast_set_null_value(rast_ptr, 1, data_type); } rast_ptr = G_incr_void_ptr(rast_ptr, Rast_cell_size(data_type)); } fwrite(rast, Rast_cell_size(data_type), ncols, ft); rast_ptr = rast; } G_percent(nrows, nrows, 2); G_debug(1, "Creating support files for %s", output); sz = 0; if (direction < 0) { sz = -ncols * Rast_cell_size(data_type); G_fseek(ft, sz, SEEK_END); sz *= 2; } else { G_fseek(ft, 0L, SEEK_SET); } for (row = 0; row < nrows; row += 1) { fread(rast, Rast_cell_size(data_type), ncols, ft); Rast_put_row(cf, rast, data_type); G_fseek(ft, sz, SEEK_CUR); } fclose(ft); unlink(temp); Rast_close(cf); if (title) Rast_put_cell_title(output, title); Rast_short_history(output, "raster", &history); Rast_command_history(&history); Rast_write_history(output, &history); G_done_msg(" "); exit(EXIT_SUCCESS); }
static void read_png(void) { unsigned char sig_buf[8]; png_bytep png_buffer; png_bytep *png_rows; int linesize; struct Cell_head cellhd; unsigned int y, c; png_color_8p sig_bit; int sbit, interlace; FILE *ifp; /* initialize input stream and PNG library */ ifp = fopen(input, "rb"); if (!ifp) G_fatal_error(_("Unable to open PNG file '%s'"), input); if (fread(sig_buf, sizeof(sig_buf), 1, ifp) != 1) G_fatal_error(_("Input file empty or too short")); if (png_sig_cmp(sig_buf, 0, sizeof(sig_buf)) != 0) G_fatal_error(_("Input file not a PNG file")); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) G_fatal_error(_("Unable to allocate PNG structure")); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) G_fatal_error(_("Unable to allocate PNG structure")); if (setjmp(png_jmpbuf(png_ptr))) G_fatal_error(_("PNG error")); png_init_io(png_ptr, ifp); png_set_sig_bytes(png_ptr, sizeof(sig_buf)); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type); if (Header || G_verbose() == G_verbose_max()) print_header(); if (Header) { fclose(ifp); exit(0); } /* read image parameters and set up data conversions */ if (png_get_bit_depth(png_ptr, info_ptr) < 8) png_set_packing(png_ptr); sbit = png_get_sBIT(png_ptr, info_ptr, &sig_bit); if (sbit) png_set_shift(png_ptr, sig_bit); if (!png_get_gAMA(png_ptr, info_ptr, &f_gamma)) f_gamma = 0.0; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); if (Float && color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); png_read_update_info(png_ptr, info_ptr); interlace = (interlace_type != PNG_INTERLACE_NONE); ialpha = (int) (alpha * channels[C_A].maxval); t_gamma = (f_gamma != 0.0 && d_gamma != 0.0) ? f_gamma * d_gamma : 1.0; /* allocate input buffer */ linesize = png_get_rowbytes(png_ptr, info_ptr); png_buffer = G_malloc(interlace ? height * linesize : linesize); if (interlace) { png_rows = G_malloc(height * sizeof(png_bytep)); for (y = 0; y < height; y++) png_rows[y] = png_buffer + y * linesize; } /* initialize cell header */ Rast_get_window(&cellhd); cellhd.rows = height; cellhd.cols = width; cellhd.north = cellhd.rows; cellhd.south = 0.0; cellhd.east = cellhd.cols; cellhd.west = 0.0; cellhd.ns_res = 1; cellhd.ew_res = 1; Rast_set_window(&cellhd); /* initialize channel information */ switch (color_type) { case PNG_COLOR_TYPE_GRAY: init_channel(&channels[C_Y]); break; case PNG_COLOR_TYPE_GRAY_ALPHA: init_channel(&channels[C_Y]); init_channel(&channels[C_A]); break; case PNG_COLOR_TYPE_PALETTE: init_channel(&channels[C_P]); break; case PNG_COLOR_TYPE_RGB: init_channel(&channels[C_R]); init_channel(&channels[C_G]); init_channel(&channels[C_B]); break; case PNG_COLOR_TYPE_RGB_ALPHA: init_channel(&channels[C_R]); init_channel(&channels[C_G]); init_channel(&channels[C_B]); init_channel(&channels[C_A]); break; } if (sbit) { channels[C_R].maxval = (1 << sig_bit->red ) - 1; channels[C_G].maxval = (1 << sig_bit->green) - 1; channels[C_B].maxval = (1 << sig_bit->blue ) - 1; channels[C_Y].maxval = (1 << sig_bit->gray ) - 1; channels[C_A].maxval = (1 << sig_bit->alpha) - 1; } else { channels[C_R].maxval = (1 << bit_depth) - 1; channels[C_G].maxval = (1 << bit_depth) - 1; channels[C_B].maxval = (1 << bit_depth) - 1; channels[C_Y].maxval = (1 << bit_depth) - 1; channels[C_A].maxval = (1 << bit_depth) - 1; } /* read image and write raster layers */ if (interlace) png_read_image(png_ptr, png_rows); for (y = 0; y < height; y++) { png_bytep p; if (interlace) p = png_rows[y]; else { png_read_row(png_ptr, png_buffer, NULL); p = png_buffer; } if (Float) write_row_float(p); else write_row_int(p); } png_read_end(png_ptr, NULL); fclose(ifp); /* close output files */ for (c = 0; c < 6; c++) { channel *ch = &channels[c]; if (!ch->active) continue; Rast_close(ch->fd); if (Float) G_free(ch->fbuf); else G_free(ch->buf); } /* write title and color table */ G_verbose_message(_("Creating support files for <%s>..."), output); for (c = 0; c < 6; c++) { channel *ch = &channels[c]; if (!ch->active) continue; if (title && *title) Rast_put_cell_title(ch->name, title); if (Float) write_colors_float(c); else write_colors_int(c); } G_free(png_buffer); if (interlace) G_free(png_rows); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); }