/*! * \brief Read floating-point range * * Read the floating point range file <i>drange</i>. This file is * written in binary using XDR format. * * An empty range file indicates that the min, max are undefined. This * is a valid case, and the result should be an initialized range * struct with no defined min/max. If the range file is missing and * the map is a floating-point map, this function will create a * default range by calling G_construct_default_range(). * * \param name map name * \param mapset mapset name * \param drange pointer to FPRange structure which holds fp range * * \return 1 on success * \return 2 range is empty * \return -1 on error */ int Rast_read_fp_range(const char *name, const char *mapset, struct FPRange *drange) { struct Range range; int fd; char xdr_buf[2][XDR_DOUBLE_NBYTES]; DCELL dcell1, dcell2; Rast_init(); Rast_init_fp_range(drange); if (Rast_map_type(name, mapset) == CELL_TYPE) { /* if map is integer read integer range and convert it to double */ if (Rast_read_range(name, mapset, &range) >= 0) { /* if the integer range is empty */ if (range.first_time) return 2; Rast_update_fp_range((DCELL) range.min, drange); Rast_update_fp_range((DCELL) range.max, drange); return 1; } return -1; } fd = -1; if (G_find_file2_misc("cell_misc", "f_range", name, mapset)) { fd = G_open_old_misc("cell_misc", "f_range", name, mapset); if (fd < 0) { G_warning(_("Unable to read fp range file for <%s>"), G_fully_qualified_name(name, mapset)); return -1; } if (read(fd, xdr_buf, sizeof(xdr_buf)) != sizeof(xdr_buf)) { /* if the f_range file exists, but empty file, meaning Nulls */ close(fd); G_debug(1, "Empty fp range file meaning Nulls for <%s>", G_fully_qualified_name(name, mapset)); return 2; } G_xdr_get_double(&dcell1, xdr_buf[0]); G_xdr_get_double(&dcell2, xdr_buf[1]); Rast_update_fp_range(dcell1, drange); Rast_update_fp_range(dcell2, drange); close(fd); } return 1; }
int main(int argc, char **argv) { struct Cell_head window; RASTER_MAP_TYPE raster_type, mag_raster_type = -1; int layer_fd; void *raster_row, *ptr; int nrows, ncols; int aspect_c = -1; float aspect_f = -1.0; double scale; int skip, no_arrow; char *mag_map = NULL; void *mag_raster_row = NULL, *mag_ptr = NULL; double length = -1; int mag_fd = -1; struct FPRange range; double mag_min, mag_max; struct GModule *module; struct Option *opt1, *opt2, *opt3, *opt4, *opt5, *opt6, *opt7, *opt8, *opt9; struct Flag *align; double t, b, l, r; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("display")); G_add_keyword(_("raster")); module->description = _("Draws arrows representing cell aspect direction " "for a raster map containing aspect data."); opt1 = G_define_standard_option(G_OPT_R_MAP); opt1->description = _("Name of raster aspect map to be displayed"); opt2 = G_define_option(); opt2->key = "type"; opt2->type = TYPE_STRING; opt2->required = NO; opt2->answer = "grass"; opt2->options = "grass,compass,agnps,answers"; opt2->description = _("Type of existing raster aspect map"); opt3 = G_define_option(); opt3->key = "arrow_color"; opt3->type = TYPE_STRING; opt3->required = NO; opt3->answer = "green"; opt3->gisprompt = "old_color,color,color"; opt3->description = _("Color for drawing arrows"); opt3->guisection = _("Colors"); opt4 = G_define_option(); opt4->key = "grid_color"; opt4->type = TYPE_STRING; opt4->required = NO; opt4->answer = "gray"; opt4->gisprompt = "old_color,color,color_none"; opt4->description = _("Color for drawing grid or \"none\""); opt4->guisection = _("Colors"); opt5 = G_define_option(); opt5->key = "x_color"; opt5->type = TYPE_STRING; opt5->required = NO; opt5->answer = DEFAULT_FG_COLOR; opt5->gisprompt = "old_color,color,color_none"; opt5->description = _("Color for drawing X's (null values)"); opt5->guisection = _("Colors"); opt6 = G_define_option(); opt6->key = "unknown_color"; opt6->type = TYPE_STRING; opt6->required = NO; opt6->answer = "red"; opt6->gisprompt = "old_color,color,color_none"; opt6->description = _("Color for showing unknown information"); opt6->guisection = _("Colors"); opt9 = G_define_option(); opt9->key = "skip"; opt9->type = TYPE_INTEGER; opt9->required = NO; opt9->answer = "1"; opt9->description = _("Draw arrow every Nth grid cell"); opt7 = G_define_option(); opt7->key = "magnitude_map"; opt7->type = TYPE_STRING; opt7->required = NO; opt7->multiple = NO; opt7->gisprompt = "old,cell,raster"; opt7->description = _("Raster map containing values used for arrow length"); opt8 = G_define_option(); opt8->key = "scale"; opt8->type = TYPE_DOUBLE; opt8->required = NO; opt8->answer = "1.0"; opt8->description = _("Scale factor for arrows (magnitude map)"); align = G_define_flag(); align->key = 'a'; align->description = _("Align grids with raster cells"); /* Check command line */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); layer_name = opt1->answer; arrow_color = D_translate_color(opt3->answer); x_color = D_translate_color(opt5->answer); unknown_color = D_translate_color(opt6->answer); if (strcmp("none", opt4->answer) == 0) grid_color = -1; else grid_color = D_translate_color(opt4->answer); if (strcmp("grass", opt2->answer) == 0) map_type = 1; else if (strcmp("agnps", opt2->answer) == 0) map_type = 2; else if (strcmp("answers", opt2->answer) == 0) map_type = 3; else if (strcmp("compass", opt2->answer) == 0) map_type = 4; scale = atof(opt8->answer); if (scale <= 0.0) G_fatal_error(_("Illegal value for scale factor")); skip = atoi(opt9->answer); if (skip <= 0) G_fatal_error(_("Illegal value for skip factor")); if (opt7->answer) { if (map_type != 1 && map_type != 4) G_fatal_error(_("Magnitude is only supported for GRASS and compass aspect maps.")); mag_map = opt7->answer; } else if (scale != 1.0) G_warning(_("Scale option requires magnitude_map")); /* Setup driver and check important information */ if (D_open_driver() != 0) G_fatal_error(_("No graphics device selected. " "Use d.mon to select graphics device.")); D_setup(0); /* Read in the map window associated with window */ G_get_window(&window); if (align->answer) { struct Cell_head wind; Rast_get_cellhd(layer_name, "", &wind); /* expand window extent by one wind resolution */ wind.west += wind.ew_res * ((int)((window.west - wind.west) / wind.ew_res) - (window.west < wind.west)); wind.east += wind.ew_res * ((int)((window.east - wind.east) / wind.ew_res) + (window.east > wind.east)); wind.south += wind.ns_res * ((int)((window.south - wind.south) / wind.ns_res) - (window.south < wind.south)); wind.north += wind.ns_res * ((int)((window.north - wind.north) / wind.ns_res) + (window.north > wind.north)); wind.rows = (wind.north - wind.south) / wind.ns_res; wind.cols = (wind.east - wind.west) / wind.ew_res; Rast_set_window(&wind); nrows = wind.rows; ncols = wind.cols; t = (wind.north - window.north) * nrows / (wind.north - wind.south); b = t + (window.north - window.south) * nrows / (wind.north - wind.south); l = (window.west - wind.west) * ncols / (wind.east - wind.west); r = l + (window.east - window.west) * ncols / (wind.east - wind.west); } else { nrows = window.rows; ncols = window.cols; t = 0; b = nrows; l = 0; r = ncols; } D_set_src(t, b, l, r); D_update_conversions(); /* figure out arrow scaling if using a magnitude map */ if (opt7->answer) { Rast_init_fp_range(&range); /* really needed? */ if (Rast_read_fp_range(mag_map, "", &range) != 1) G_fatal_error(_("Problem reading range file")); Rast_get_fp_range_min_max(&range, &mag_min, &mag_max); scale *= 1.5 / fabs(mag_max); G_debug(3, "scaling=%.2f rast_max=%.2f", scale, mag_max); } if (grid_color > 0) { /* ie not "none" */ /* Set color */ D_use_color(grid_color); /* Draw vertical grids */ for (col = 0; col < ncols; col++) D_line_abs(col, 0, col, nrows); /* Draw horizontal grids */ for (row = 0; row < nrows; row++) D_line_abs(0, row, ncols, row); } /* open the raster map */ layer_fd = Rast_open_old(layer_name, ""); raster_type = Rast_get_map_type(layer_fd); /* allocate the cell array */ raster_row = Rast_allocate_buf(raster_type); if (opt7->answer) { /* open the magnitude raster map */ mag_fd = Rast_open_old(mag_map, ""); mag_raster_type = Rast_get_map_type(mag_fd); /* allocate the cell array */ mag_raster_row = Rast_allocate_buf(mag_raster_type); } /* loop through cells, find value, determine direction (n,s,e,w,ne,se,sw,nw), and call appropriate function to draw an arrow on the cell */ for (row = 0; row < nrows; row++) { Rast_get_row(layer_fd, raster_row, row, raster_type); ptr = raster_row; if (opt7->answer) { Rast_get_row(mag_fd, mag_raster_row, row, mag_raster_type); mag_ptr = mag_raster_row; } for (col = 0; col < ncols; col++) { if (row % skip != 0) no_arrow = TRUE; else no_arrow = FALSE; if (col % skip != 0) no_arrow = TRUE; /* find aspect direction based on cell value */ if (raster_type == CELL_TYPE) aspect_f = *((CELL *) ptr); else if (raster_type == FCELL_TYPE) aspect_f = *((FCELL *) ptr); else if (raster_type == DCELL_TYPE) aspect_f = *((DCELL *) ptr); if (opt7->answer) { if (mag_raster_type == CELL_TYPE) length = *((CELL *) mag_ptr); else if (mag_raster_type == FCELL_TYPE) length = *((FCELL *) mag_ptr); else if (mag_raster_type == DCELL_TYPE) length = *((DCELL *) mag_ptr); length *= scale; if (Rast_is_null_value(mag_ptr, mag_raster_type)) { G_debug(5, "Invalid arrow length [NULL]. Skipping."); no_arrow = TRUE; } else if (length <= 0.0) { /* use fabs() or theta+=180? */ G_debug(5, "Illegal arrow length [%.3f]. Skipping.", length); no_arrow = TRUE; } } if (no_arrow) { ptr = G_incr_void_ptr(ptr, Rast_cell_size(raster_type)); if (opt7->answer) mag_ptr = G_incr_void_ptr(mag_ptr, Rast_cell_size(mag_raster_type)); no_arrow = FALSE; continue; } /* treat AGNPS and ANSWERS data like old zero-as-null CELL */ /* TODO: update models */ if (map_type == 2 || map_type == 3) { if (Rast_is_null_value(ptr, raster_type)) aspect_c = 0; else aspect_c = (int)(aspect_f + 0.5); } /** Now draw the arrows **/ /* case switch for standard GRASS aspect map measured in degrees counter-clockwise from east */ if (map_type == 1) { D_use_color(arrow_color); if (Rast_is_null_value(ptr, raster_type)) { D_use_color(x_color); draw_x(); D_use_color(arrow_color); } else if (aspect_f >= 0.0 && aspect_f <= 360.0) { if (opt7->answer) arrow_mag(aspect_f, length); else arrow_360(aspect_f); } else { D_use_color(unknown_color); unknown_(); D_use_color(arrow_color); } } /* case switch for AGNPS type aspect map */ else if (map_type == 2) { D_use_color(arrow_color); switch (aspect_c) { case 0: D_use_color(x_color); draw_x(); D_use_color(arrow_color); break; case 1: arrow_n(); break; case 2: arrow_ne(); break; case 3: arrow_e(); break; case 4: arrow_se(); break; case 5: arrow_s(); break; case 6: arrow_sw(); break; case 7: arrow_w(); break; case 8: arrow_nw(); break; default: D_use_color(unknown_color); unknown_(); D_use_color(arrow_color); break; } } /* case switch for ANSWERS type aspect map */ else if (map_type == 3) { D_use_color(arrow_color); if (aspect_c >= 15 && aspect_c <= 360) /* start at zero? */ arrow_360((double)aspect_c); else if (aspect_c == 400) { D_use_color(unknown_color); unknown_(); D_use_color(arrow_color); } else { D_use_color(x_color); draw_x(); D_use_color(arrow_color); } } /* case switch for compass type aspect map measured in degrees clockwise from north */ else if (map_type == 4) { D_use_color(arrow_color); if (Rast_is_null_value(ptr, raster_type)) { D_use_color(x_color); draw_x(); D_use_color(arrow_color); } else if (aspect_f >= 0.0 && aspect_f <= 360.0) { if (opt7->answer) arrow_mag(90 - aspect_f, length); else arrow_360(90 - aspect_f); } else { D_use_color(unknown_color); unknown_(); D_use_color(arrow_color); } } ptr = G_incr_void_ptr(ptr, Rast_cell_size(raster_type)); if (opt7->answer) mag_ptr = G_incr_void_ptr(mag_ptr, Rast_cell_size(mag_raster_type)); } } Rast_close(layer_fd); if (opt7->answer) Rast_close(mag_fd); D_save_command(G_recreate_command()); D_close_driver(); exit(EXIT_SUCCESS); }
/* * check_stats() - Check and update statistics * * RETURN: 0 on success / 1 on failure */ int check_stats(const char *name) { RASTER_MAP_TYPE data_type; struct Histogram histogram; struct Categories cats; struct Range range; struct FPRange fprange; int i, histo_num; int cats_ok; int max; data_type = Rast_map_type(name, ""); G_message(_("Updating statistics for [%s]..."), name); if (!do_histogram(name)) return 1; if (Rast_read_histogram(name, "", &histogram) <= 0) return 1; /* Init histogram range */ if (data_type == CELL_TYPE) Rast_init_range(&range); else Rast_init_fp_range(&fprange); G_message(_("Updating histogram range...")); i = histo_num = Rast_get_histogram_num(&histogram); while (i >= 0) { G_percent(i, histo_num, 2); if (data_type == CELL_TYPE) Rast_update_range(Rast_get_histogram_cat(i--, &histogram), &range); else Rast_update_fp_range((DCELL) Rast_get_histogram_cat(i--, &histogram), &fprange); } /* Write histogram range */ if (data_type == CELL_TYPE) Rast_write_range(name, &range); else Rast_write_fp_range(name, &fprange); /* Get category status and max */ cats_ok = (Rast_read_cats(name, "", &cats) >= 0); max = (data_type == CELL_TYPE ? range.max : fprange.max); /* Further category checks */ if (!cats_ok) Rast_init_cats("", &cats); else if (cats.num != max) { cats.num = max; cats_ok = 0; } /* Update categories if needed */ if (!cats_ok) { G_message(_("Updating the number of categories for [%s]..."), name); Rast_write_cats(name, &cats); } Rast_free_histogram(&histogram); Rast_free_cats(&cats); return 0; }
int main(int argc, char *argv[]) { struct Cell_head cellhd; char *name, *result; char **mapname; FCELL **fbuf; int n_measures, n_outputs, *measure_idx; int nrows, ncols; int row, col, first_row, last_row, first_col, last_col; int i, j; CELL **data; /* Data structure containing image */ DCELL *dcell_row; struct FPRange range; DCELL min, max, inscale; FCELL measure; /* Containing measure done */ int dist, size; /* dist = value of distance, size = s. of moving window */ int offset; int have_px, have_py, have_sentr, have_pxpys, have_pxpyd; int infd, *outfd; RASTER_MAP_TYPE data_type, out_data_type; struct GModule *module; struct Option *opt_input, *opt_output, *opt_size, *opt_dist, *opt_measure; struct Flag *flag_ind, *flag_all; struct History history; char p[1024]; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("algebra")); G_add_keyword(_("statistics")); G_add_keyword(_("texture")); module->description = _("Generate images with textural features from a raster map."); module->overwrite = 1; /* Define the different options */ opt_input = G_define_standard_option(G_OPT_R_INPUT); opt_output = G_define_standard_option(G_OPT_R_BASENAME_OUTPUT); opt_size = G_define_option(); opt_size->key = "size"; opt_size->key_desc = "value"; opt_size->type = TYPE_INTEGER; opt_size->required = NO; opt_size->description = _("The size of moving window (odd and >= 3)"); opt_size->answer = "3"; /* Textural character is in direct relation of the spatial size of the texture primitives. */ opt_dist = G_define_option(); opt_dist->key = "distance"; opt_dist->key_desc = "value"; opt_dist->type = TYPE_INTEGER; opt_dist->required = NO; opt_dist->description = _("The distance between two samples (>= 1)"); opt_dist->answer = "1"; for (i = 0; menu[i].name; i++) { if (i) strcat(p, ","); else *p = 0; strcat(p, menu[i].name); } opt_measure = G_define_option(); opt_measure->key = "method"; opt_measure->type = TYPE_STRING; opt_measure->required = NO; opt_measure->multiple = YES; opt_measure->options = p; opt_measure->description = _("Textural measurement method"); flag_ind = G_define_flag(); flag_ind->key = 's'; flag_ind->description = _("Separate output for each angle (0, 45, 90, 135)"); flag_all = G_define_flag(); flag_all->key = 'a'; flag_all->description = _("Calculate all textural measurements"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); name = opt_input->answer; result = opt_output->answer; size = atoi(opt_size->answer); if (size <= 0) G_fatal_error(_("Size of the moving window must be > 0")); if (size % 2 != 1) G_fatal_error(_("Size of the moving window must be odd")); dist = atoi(opt_dist->answer); if (dist <= 0) G_fatal_error(_("The distance between two samples must be > 0")); n_measures = 0; if (flag_all->answer) { for (i = 0; menu[i].name; i++) { menu[i].useme = 1; } n_measures = i; } else { for (i = 0; opt_measure->answers[i]; i++) { if (opt_measure->answers[i]) { const char *measure_name = opt_measure->answers[i]; int n = find_measure(measure_name); menu[n].useme = 1; n_measures++; } } } if (!n_measures) G_fatal_error(_("Nothing to compute. Use at least one textural measure.")); measure_idx = G_malloc(n_measures * sizeof(int)); j = 0; for (i = 0; menu[i].name; i++) { if (menu[i].useme == 1) { measure_idx[j] = menu[i].idx; j++; } } /* variables needed */ if (menu[2].useme || menu[11].useme || menu[12].useme) have_px = 1; else have_px = 0; if (menu[11].useme || menu[12].useme) have_py = 1; else have_py = 0; if (menu[6].useme || menu[7].useme) have_sentr = 1; else have_sentr = 0; if (menu[5].useme || menu[6].useme || menu[7].useme) have_pxpys = 1; else have_pxpys = 0; if (menu[9].useme || menu[10].useme) have_pxpyd = 1; else have_pxpyd = 0; infd = Rast_open_old(name, ""); /* determine the inputmap type (CELL/FCELL/DCELL) */ data_type = Rast_get_map_type(infd); Rast_get_cellhd(name, "", &cellhd); out_data_type = FCELL_TYPE; /* Allocate output buffers, use FCELL data_type */ n_outputs = n_measures; if (flag_ind->answer) { n_outputs = n_measures * 4; } fbuf = G_malloc(n_outputs * sizeof(FCELL *)); mapname = G_malloc(n_outputs * sizeof(char *)); for (i = 0; i < n_outputs; i++) { mapname[i] = G_malloc(GNAME_MAX * sizeof(char)); fbuf[i] = Rast_allocate_buf(out_data_type); } /* open output maps */ outfd = G_malloc(n_outputs * sizeof(int)); for (i = 0; i < n_measures; i++) { if (flag_ind->answer) { for (j = 0; j < 4; j++) { sprintf(mapname[i * 4 + j], "%s%s_%d", result, menu[measure_idx[i]].suffix, j * 45); outfd[i * 4 + j] = Rast_open_new(mapname[i * 4 + j], out_data_type); } } else { sprintf(mapname[i], "%s%s", result, menu[measure_idx[i]].suffix); outfd[i] = Rast_open_new(mapname[i], out_data_type); } } nrows = Rast_window_rows(); ncols = Rast_window_cols(); /* Load raster map. */ /* allocate the space for one row of cell map data *A* */ dcell_row = Rast_allocate_d_buf(); /* Allocate appropriate memory for the structure containing the image */ data = (int **)G_malloc(nrows * sizeof(int *)); for (i = 0; i < nrows; i++) { data[i] = (int *)G_malloc(ncols * sizeof(int)); } /* read input range */ Rast_init_fp_range(&range); Rast_read_fp_range(name, "", &range); Rast_get_fp_range_min_max(&range, &min, &max); inscale = 0; if (min < 0 || max > 255) { inscale = 255. / (max - min); } /* input has 0 - 1 range */ else if (max <= 1.) { inscale = 255. / (max - min); } /* Read in cell map values */ /* TODO: use r.proj cache */ G_important_message(_("Reading raster map...")); for (j = 0; j < nrows; j++) { Rast_get_row(infd, dcell_row, j, DCELL_TYPE); for (i = 0; i < ncols; i++) { if (Rast_is_d_null_value(&(dcell_row[i]))) data[j][i] = -1; else if (inscale) { data[j][i] = (CELL)((dcell_row[i] - min) * inscale); } else data[j][i] = (CELL)dcell_row[i]; } } /* close input cell map and release the row buffer */ Rast_close(infd); G_free(dcell_row); /* Now raster map is loaded to memory. */ /* ************************************************************************************************* * * Compute of the matrix S.G.L.D. (Spatial Gray-Level Dependence Matrices) or co-occurrence matrix. * The image is analized for piece, every piece is naming moving window (s.w.). The s.w. must be * square with number of size's samples odd, that because we want the sample at the center of matrix. * ***************************************************************************************************/ offset = size / 2; first_row = first_col = offset; last_row = nrows - offset; last_col = ncols - offset; Rast_set_f_null_value(fbuf[0], ncols); for (row = 0; row < first_row; row++) { for (i = 0; i < n_outputs; i++) { Rast_put_row(outfd[i], fbuf[0], out_data_type); } } if (n_measures > 1) G_message(n_("Calculating %d texture measure", "Calculating %d texture measures", n_measures), n_measures); else G_message(_("Calculating %s"), menu[measure_idx[0]].desc); alloc_vars(size, dist); for (row = first_row; row < last_row; row++) { G_percent(row, nrows, 2); for (i = 0; i < n_outputs; i++) Rast_set_f_null_value(fbuf[i], ncols); /*process the data */ for (col = first_col; col < last_col; col++) { if (!set_vars(data, row, col, size, offset, dist)) { for (i = 0; i < n_outputs; i++) Rast_set_f_null_value(&(fbuf[i][col]), 1); continue; } /* for all angles (0, 45, 90, 135) */ for (i = 0; i < 4; i++) { set_angle_vars(i, have_px, have_py, have_sentr, have_pxpys, have_pxpyd); /* for all requested textural measures */ for (j = 0; j < n_measures; j++) { measure = (FCELL) h_measure(measure_idx[j]); if (flag_ind->answer) { /* output for each angle separately */ fbuf[j * 4 + i][col] = measure; } else { /* use average over all angles for each measure */ if (i == 0) fbuf[j][col] = measure; else if (i < 3) fbuf[j][col] += measure; else fbuf[j][col] = (fbuf[j][col] + measure) / 4.0; } } } } for (i = 0; i < n_outputs; i++) { Rast_put_row(outfd[i], fbuf[i], out_data_type); } } Rast_set_f_null_value(fbuf[0], ncols); for (row = last_row; row < nrows; row++) { for (i = 0; i < n_outputs; i++) { Rast_put_row(outfd[i], fbuf[0], out_data_type); } } G_percent(nrows, nrows, 1); for (i = 0; i < n_outputs; i++) { Rast_close(outfd[i]); Rast_short_history(mapname[i], "raster", &history); Rast_command_history(&history); Rast_write_history(mapname[i], &history); G_free(fbuf[i]); } G_free(fbuf); G_free(data); exit(EXIT_SUCCESS); }