/*! \brief Allocate memory for new vector set \return pointer to geovect struct \return NULL on failure */ geovect *gv_get_new_vect(void) { geovect *nv, *lv; nv = (geovect *) G_malloc(sizeof(geovect)); if (!nv) { /* G_fatal_error */ return NULL; } G_zero(nv, sizeof(geovect)); if ((lv = gv_get_last_vect())) { lv->next = nv; nv->gvect_id = lv->gvect_id + 1; } else { Vect_top = nv; nv->gvect_id = FIRST_VECT_ID; } nv->style = (gvstyle *) G_malloc(sizeof(gvstyle)); if (NULL == nv->style) return NULL; G_zero(nv->style, sizeof (gvstyle)); nv->hstyle = (gvstyle *) G_malloc(sizeof(gvstyle)); if (NULL == nv->hstyle) return NULL; G_zero(nv->hstyle, sizeof (gvstyle)); G_debug(5, "gv_get_new_vect() id=%d", nv->gvect_id); return nv; }
/*! \brief Insert scatter plot data. \param scatt_data pointer to existing struct scdScattData \param type SC_SCATT_DATA for scatter plots or SC_SCATT_CONDITIONS for selected areas in scatter plot \param n_vals number of data values \param data array of values (unsigned char for SC_SCATT_CONDITIONS, unsigned int for SC_SCATT_DATA) */ void I_scd_init_scatt_data(struct scdScattData *scatt_data, int type, int n_vals, void *data) { scatt_data->n_vals = n_vals; if (type == SC_SCATT_DATA) { if (data) scatt_data->scatt_vals_arr = (unsigned int *)data; else { scatt_data->scatt_vals_arr = (unsigned int *)G_malloc(n_vals * sizeof(unsigned int)); G_zero(scatt_data->scatt_vals_arr, n_vals * sizeof(unsigned int)); } scatt_data->b_conds_arr = NULL; } else if (type == SC_SCATT_CONDITIONS) { if (data) scatt_data->b_conds_arr = (unsigned char *)data; else { scatt_data->b_conds_arr = (unsigned char *)G_malloc(n_vals * sizeof(unsigned char)); G_zero(scatt_data->b_conds_arr, n_vals * sizeof(unsigned char)); } scatt_data->scatt_vals_arr = NULL; } return; }
/*! \brief Create new geosite instance and add it to list \return pointer to geosite struct \return NULL on error */ geosite *gp_get_new_site(void) { geosite *np, *lp; np = (geosite *) G_malloc(sizeof(geosite)); /* G_fatal_error */ if (!np) { return NULL; } G_zero(np, sizeof(geosite)); lp = gp_get_last_site(); if (lp) { lp->next = np; np->gsite_id = lp->gsite_id + 1; } else { Site_top = np; np->gsite_id = FIRST_SITE_ID; } np->style = (gvstyle *) G_malloc(sizeof(gvstyle)); if (!np->style) return NULL; G_zero(np->style, sizeof (gvstyle)); np->hstyle = (gvstyle *) G_malloc(sizeof(gvstyle)); if (!np->hstyle) return NULL; G_zero(np->hstyle, sizeof (gvstyle)); G_debug(5, "gp_get_new_site id=%d", np->gsite_id); return np; }
/*! \brief Initialize geovol structure \param gvl pointer to geovol struct \param ox,oy,oz \param rows number of rows \param cols number of cols \param xres,yres,zres x/y/z resolution value \return -1 on failure \return 1 on success */ int gvl_init_vol(geovol * gvl, double ox, double oy, double oz, int rows, int cols, int depths, double xres, double yres, double zres) { G_debug(5, "gvl_init_vol() id=%d", gvl->gvol_id); if (!gvl) { return (-1); } gvl->ox = ox; gvl->oy = oy; gvl->oz = oz; gvl->rows = rows; gvl->cols = cols; gvl->depths = depths; gvl->xres = xres; gvl->yres = yres; gvl->zres = zres; gvl->xmin = ox; gvl->xmax = ox + (cols - 1) * xres; gvl->xrange = gvl->xmax - gvl->xmin; gvl->ymin = oy; gvl->ymax = oy + (rows - 1) * yres; gvl->yrange = gvl->ymax - gvl->ymin; gvl->zmin = oz; gvl->zmax = oz + (depths - 1) * zres; gvl->zrange = gvl->zmax - gvl->zmin; gvl->x_trans = gvl->y_trans = gvl->z_trans = 0.0; gvl->draw_wire = 0; gvl->n_isosurfs = 0; G_zero(gvl->isosurf, sizeof(geovol_isosurf *) * MAX_ISOSURFS); gvl->isosurf_x_mod = 1; gvl->isosurf_y_mod = 1; gvl->isosurf_z_mod = 1; gvl->isosurf_draw_mode = DM_GOURAUD; gvl->n_slices = 0; G_zero(gvl->slice, sizeof(geovol_slice *) * MAX_SLICES); gvl->slice_x_mod = 1; gvl->slice_y_mod = 1; gvl->slice_z_mod = 1; gvl->slice_draw_mode = DM_GOURAUD; gvl->hfile = -1; gvl->clientdata = NULL; return (1); }
/*! \brief Initialize structure for storing scatter plots data. \param cats pointer to scCats struct \param n_bands number of bands \param type SC_SCATT_DATA - stores scatter plots \param type SC_SCATT_CONDITIONS - stores selected areas in scatter plots */ void I_sc_init_cats(struct scCats *cats, int n_bands, int type) { int i_cat; cats->type = type; cats->n_cats = 100; cats->n_a_cats = 0; cats->n_bands = n_bands; cats->n_scatts = (n_bands - 1) * n_bands / 2; cats->cats_arr = (struct scScatts **)G_malloc(cats->n_cats * sizeof(struct scScatts *)); G_zero(cats->cats_arr, cats->n_cats * sizeof(struct scScatts *)); cats->cats_ids = (int *)G_malloc(cats->n_cats * sizeof(int)); cats->cats_idxs = (int *)G_malloc(cats->n_cats * sizeof(int)); for (i_cat = 0; i_cat < cats->n_cats; i_cat++) cats->cats_idxs[i_cat] = -1; return; }
/*! \brief Set point set style for thematic mapping Updates also style for each geopoint. \param id point set id \param layer layer number for thematic mapping \param color icon color column name \param width icon line width column name \param size icon size column name \param symbol icon symbol column name \param colors pointer to Colors structure or NULL \return 1 on success \return -1 on error (point set not found) */ int GP_set_style_thematic(int id, int layer, const char* color, const char* width, const char* size, const char* symbol, struct Colors *color_rules) { geosite *gp; G_debug(4, "GP_set_style_thematic(id=%d, layer=%d, color=%s, width=%s, size=%s, symbol=%s)", id, layer, color, width, size, symbol); if (NULL == (gp = gp_get_site(id))) { return -1; } if(!gp->tstyle) gp->tstyle = (gvstyle_thematic *)G_malloc(sizeof(gvstyle_thematic)); G_zero(gp->tstyle, sizeof(gvstyle_thematic)); gp->tstyle->active = 1; gp->tstyle->layer = layer; if (color) gp->tstyle->color_column = G_store(color); if (symbol) gp->tstyle->symbol_column = G_store(symbol); if (size) gp->tstyle->size_column = G_store(size); if (width) gp->tstyle->width_column = G_store(width); Gp_load_sites_thematic(gp, color_rules); return 1; }
/*! \brief converts a buffer of zero's and ones to bitstream. Stores this bitstream in memory. (the null rows from memory are written into null file after the limit is reached, and the place for new null rows to be kept in memory is freed. Should not be used by application programs. \param fd file descriptor where data is to be written \param buf buffer holding null data \return void */ static void put_raster_row(int fd, const void *buf, RASTER_MAP_TYPE data_type, int zeros_r_nulls) { static void (*convert_and_write_FtypeOtype[3][3])(int, const void *) = { {NULL, convert_and_write_if, convert_and_write_id}, {convert_and_write_fi, NULL, convert_and_write_fd}, {convert_and_write_di, convert_and_write_df, NULL} }; struct fileinfo *fcb = &R__.fileinfo[fd]; char *null_buf; switch (fcb->open_mode) { case OPEN_OLD: G_fatal_error(_("put_raster_row: raster map <%s> not open for write - request ignored"), fcb->name); break; case OPEN_NEW_COMPRESSED: case OPEN_NEW_UNCOMPRESSED: break; default: G_fatal_error(_("put_raster_row: unopened file descriptor - request ignored")); break; } if (fcb->map_type != data_type) { convert_and_write_FtypeOtype[data_type][fcb->map_type](fd, buf); return; } null_buf = G__alloca(fcb->cellhd.cols); G_zero(null_buf, fcb->cellhd.cols); put_raster_data(fd, null_buf, buf, fcb->cur_row, fcb->cellhd.cols, zeros_r_nulls, data_type); /* only for integer maps */ if (data_type == CELL_TYPE) { if (fcb->want_histogram) Rast_update_cell_stats(buf, fcb->cellhd.cols, &fcb->statf); Rast__row_update_range(buf, fcb->cellhd.cols, &fcb->range, zeros_r_nulls); } else Rast_row_update_fp_range(buf, fcb->cellhd.cols, &fcb->fp_range, data_type); fcb->cur_row++; /* write the null row for the data row */ if (!fcb->gdal) put_null_value_row(fd, null_buf); G__freea(null_buf); }
/*! \brief Allocate memory for cat_list structure. \return pointer to allocated structure \return NULL if out of memory */ struct cat_list *Vect_new_cat_list() { struct cat_list *p; p = (struct cat_list *)G_malloc(sizeof(struct cat_list)); /* n_ranges MUST be initialized to zero */ if (p) G_zero(p, sizeof(struct cat_list)); return p; }
/* \brief Parse connection string in form: 1) 'database_name' 2) 'host=xx,port=xx,dbname=xx' \returns DB_OK on success \return DB_FAILED on failure */ int parse_conn(const char *str, PGCONN * pgconn) { int i; char **tokens, delm[2]; /* reset */ G_zero(pgconn, sizeof(PGCONN)); G_debug(3, "parse_conn: '%s'", str); if (strchr(str, '=') == NULL) { /* db name only */ pgconn->dbname = G_store(str); } else { delm[0] = ','; delm[1] = '\0'; tokens = G_tokenize(str, delm); i = 0; while (tokens[i]) { G_chop(tokens[i]); G_debug(3, "token %d : %s", i, tokens[i]); if (strncmp(tokens[i], "host", 4) == 0) pgconn->host = G_store(tokens[i] + 5); else if (strncmp(tokens[i], "port", 4) == 0) pgconn->port = G_store(tokens[i] + 5); else if (strncmp(tokens[i], "options", 7) == 0) pgconn->options = G_store(tokens[i] + 8); else if (strncmp(tokens[i], "tty", 3) == 0) pgconn->tty = G_store(tokens[i] + 4); else if (strncmp(tokens[i], "dbname", 6) == 0) pgconn->dbname = G_store(tokens[i] + 7); else if (strncmp(tokens[i], "user", 4) == 0) G_warning(_("'user' in database definition is not supported, use db.login")); /* pgconn->user = G_store ( tokens[i] + 5 ); */ else if (strncmp(tokens[i], "password", 8) == 0) /* pgconn->password = G_store ( tokens[i] + 9 ); */ G_warning(_("'password' in database definition is not supported, use db.login")); else if (strncmp(tokens[i], "schema", 6) == 0) pgconn->schema = G_store(tokens[i] + 7); else { db_d_append_error("%s %s", _("Unknown option in database definition " "for PostgreSQL: "), tokens[i]); return DB_FAILED; } i++; } G_free_tokens(tokens); } return DB_OK; }
/*! \brief Build pseudo-topology (simple features) for OGR layer Build levels: - GV_BUILD_NONE - GV_BUILD_BASE - GV_BUILD_ATTACH_ISLES - GV_BUILD_CENTROIDS - GV_BUILD_ALL \param Map pointer to Map_info structure \param build build level \return 1 on success \return 0 on error */ int Vect_build_ogr(struct Map_info *Map, int build) { #ifdef HAVE_OGR struct Plus_head *plus; struct Format_info_ogr *ogr_info; plus = &(Map->plus); ogr_info = &(Map->fInfo.ogr); G_debug(1, "Vect_build_ogr(): dsn='%s' layer='%s', build=%d", ogr_info->dsn, ogr_info->layer_name, build); if (build == plus->built) return 1; /* do nothing */ /* TODO move this init to better place (Vect_open_ ?), because in theory build may be reused on level2 */ if (build >= plus->built && build > GV_BUILD_BASE) { G_free((void *) ogr_info->offset.array); G_zero(&(ogr_info->offset), sizeof(struct Format_info_offset)); } if (!ogr_info->layer) { G_warning(_("Empty OGR layer, nothing to build")); return 0; } if (OGR_L_TestCapability(ogr_info->layer, OLCTransactions)) OGR_L_CommitTransaction(ogr_info->layer); /* test layer capabilities */ if (!OGR_L_TestCapability(ogr_info->layer, OLCRandomRead)) { if (strcmp(OGR_Dr_GetName(OGR_DS_GetDriver(Map->fInfo.ogr.ds)), "PostgreSQL") == 0) G_warning(_("Feature table <%s> has no primary key defined"), ogr_info->layer_name); G_warning(_("Random read is not supported by OGR for this layer. " "Unable to build topology.")); return 0; } if (build > GV_BUILD_NONE) G_message(_("Using external data format '%s' (feature type '%s')"), Vect_get_finfo_format_info(Map), Vect_get_finfo_geometry_type(Map)); return Vect__build_sfa(Map, build); #else G_fatal_error(_("GRASS is not compiled with OGR support")); return 0; #endif }
/*! \brief Create and init new dblinks structure \return pointer to new dblinks structure \return NULL on failure */ struct dblinks *Vect_new_dblinks_struct(void) { struct dblinks *p; p = (struct dblinks *)G_malloc(sizeof(struct dblinks)); if (p) { /* initialize members */ G_zero(p, sizeof(struct dblinks)); } return p; }
/*! \brief Select one (first) value from table/column for key/id \param driver DB driver \param tab table name \param key key column name \param id identifier in key column \param col name of column to select the value from \param[out] val dbValue to store within \return number of selected values \return -1 on error */ int db_select_value(dbDriver * driver, const char *tab, const char *key, int id, const char *col, dbValue * val) { int more, count; char buf[1024]; dbString stmt; dbCursor cursor; dbColumn *column; dbValue *value; dbTable *table; if (key == NULL || strlen(key) == 0) { G_warning(_("Missing key column name")); return -1; } if (col == NULL || strlen(col) == 0) { G_warning(_("Missing column name")); return -1; } G_zero(val, sizeof(dbValue)); sprintf(buf, "SELECT %s FROM %s WHERE %s = %d\n", col, tab, key, id); db_init_string(&stmt); db_append_string(&stmt, buf); if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK) return (-1); table = db_get_cursor_table(&cursor); column = db_get_table_column(table, 0); /* first column */ value = db_get_column_value(column); /* fetch the data */ count = 0; while (1) { if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) return (-1); if (!more) break; if (count == 0) db_copy_value(val, value); count++; } db_close_cursor(&cursor); db_free_string(&stmt); return (count); }
/*! \brief Build color table (256) Calling function must have already allocated space in buff for range of data (256 for now) - simply calls get_color for each cat in color range \param filename raster map name \param[out] buff data buffer \return 1 on success \return 0 on failure */ int Gs_build_256lookup(const char *filename, int *buff) { const char *mapset; struct Colors colrules; CELL min, max, cats[256]; int i; unsigned char r[256], g[256], b[256], set[256]; G_debug(3, "building color table"); mapset = G_find_raster2(filename, ""); if (!mapset) { G_warning(_("Raster map <%s> not found"), filename); return 0; } Rast_read_colors(filename, mapset, &colrules); Rast_get_c_color_range(&min, &max, &colrules); if (min < 0 || max > 255) { G_warning(_("Color table range doesn't match data (mincol=%d, maxcol=%d"), min, max); min = min < 0 ? 0 : min; max = max > 255 ? 255 : max; } G_zero(cats, 256 * sizeof(CELL)); for (i = min; i <= max; i++) { cats[i] = i; } Rast_lookup_c_colors(cats, r, g, b, set, 256, &colrules); for (i = 0; i < 256; i++) { if (set[i]) { buff[i] = (r[i] & 0xff) | ((g[i] & 0xff) << 8) | ((b[i] & 0xff) << 16); } else { buff[i] = NO_DATA_COL; } } return (1); }
static void get_null_value_row_nomask(int fd, char *flags, int row) { struct fileinfo *fcb = &R__.fileinfo[fd]; int j; if (row > R__.rd_window.rows || row < 0) { G_warning(_("Reading raster map <%s@%s> request for row %d is outside region"), fcb->name, fcb->mapset, row); for (j = 0; j < R__.rd_window.cols; j++) flags[j] = 1; return; } if (row != fcb->null_cur_row) { if (!Rast__read_null_bits(fd, row, fcb->null_bits)) { fcb->null_cur_row = -1; if (fcb->map_type == CELL_TYPE) { /* If can't read null row, assume that all map 0's are nulls */ CELL *mask_buf = G_alloca(R__.rd_window.cols * sizeof(CELL)); get_map_row_nomask(fd, mask_buf, row, CELL_TYPE); for (j = 0; j < R__.rd_window.cols; j++) flags[j] = (mask_buf[j] == 0); G_freea(mask_buf); } else { /* fp map */ /* if can't read null row, assume that all data is valid */ G_zero(flags, sizeof(char) * R__.rd_window.cols); /* the flags row is ready now */ } return; } /*if no null file */ else fcb->null_cur_row = row; } /* copy null row to flags row translated by window column mapping */ for (j = 0; j < R__.rd_window.cols; j++) { if (!fcb->col_map[j]) flags[j] = 1; else flags[j] = check_null_bit(fcb->null_bits, fcb->col_map[j] - 1); } }
/*! \brief Get default DB connection settings \param[out] connection pointer to dbConnection to be modified \return DB_OK */ int db_get_connection(dbConnection * connection) { /* TODO: add checks and return DB_* error code if needed */ G_zero(connection, sizeof(dbConnection)); connection->driverName = (char *)G__getenv2("DB_DRIVER", G_VAR_MAPSET); connection->databaseName = (char *)G__getenv2("DB_DATABASE", G_VAR_MAPSET); connection->schemaName = (char *)G__getenv2("DB_SCHEMA", G_VAR_MAPSET); connection->group = (char *)G__getenv2("DB_GROUP", G_VAR_MAPSET); /* below commented due to new mechanism: connection->hostName = G__getenv("DB_HOST"); connection->location = G__getenv("DB_LOCATION"); connection->user = G__getenv("DB_USER"); connection->password = G__getenv("DB_PASSWORD"); */ return DB_OK; }
static int organize_lookup (struct Colors *colors, int mod) { int i,n; CELL x; CELL cat[LOOKUP_COLORS]; struct _Color_Info_ *cp; /* don't do anything if the color structure is float */ if(colors->is_float) return 0; if (mod) cp = &colors->modular; else cp = &colors->fixed; if (cp->lookup.active) return 0; n = (CELL )cp->max - (CELL )cp->min + 1; if (n >= LOOKUP_COLORS || n <= 0) return 0; x = (CELL ) cp->min; for (i=0; i < n; i++) cat[i] = x++;; cp->lookup.nalloc = n; cp->lookup.red = (unsigned char *) G_malloc(n); cp->lookup.grn = (unsigned char *) G_malloc(n); cp->lookup.blu = (unsigned char *) G_malloc(n); cp->lookup.set = (unsigned char *) G_malloc(n); G_zero (cp->lookup.set, n*sizeof(unsigned char)); G__lookup_colors ((void *) cat, cp->lookup.red, cp->lookup.grn, cp->lookup.blu, cp->lookup.set, n, colors, mod, 1, CELL_TYPE); cp->lookup.active = 1; return 0; }
/*! \brief Open existing OGR layer on topological level This functions reads feature index (fidx) file required for pseudo-topology. \param[in,out] Map pointer to Map_info structure \return 0 success \return -1 error */ int V2_open_old_ogr(struct Map_info *Map) { #ifdef HAVE_OGR G_debug(3, "V2_open_old_ogr(): name = %s mapset = %s", Map->name, Map->mapset); if (Vect_open_fidx(Map, &(Map->fInfo.ogr.offset)) != 0) { G_warning(_("Unable to open feature index file for vector map <%s>"), Vect_get_full_name(Map)); G_zero(&(Map->fInfo.ogr.offset), sizeof(struct Format_info_offset)); } Map->fInfo.ogr.next_line = 1; /* reset feature cache */ return 0; #else G_fatal_error(_("GRASS is not compiled with OGR support")); return -1; #endif }
/*! \brief Add category. Category represents group of scatter plots. \param cats pointer to scCats struct \return assigned category id (starts with 0) \return -1 if maximum nuber of categories was reached */ int I_sc_add_cat(struct scCats *cats) { int i_scatt, i_cat_id, cat_id; int n_a_cats = cats->n_a_cats; if (cats->n_a_cats >= cats->n_cats) return -1; for (i_cat_id = 0; i_cat_id < cats->n_cats; i_cat_id++) if (cats->cats_idxs[i_cat_id] < 0) { cat_id = i_cat_id; break; } cats->cats_ids[n_a_cats] = cat_id; cats->cats_idxs[cat_id] = n_a_cats; cats->cats_arr[n_a_cats] = (struct scScatts *)G_malloc(sizeof(struct scScatts)); cats->cats_arr[n_a_cats]->scatts_arr = (struct scdScattData **)G_malloc(cats->n_scatts * sizeof(struct scdScattData *)); G_zero((cats->cats_arr[n_a_cats]->scatts_arr), cats->n_scatts * sizeof(struct scdScattData *)); cats->cats_arr[n_a_cats]->n_a_scatts = 0; cats->cats_arr[n_a_cats]->scatts_bands = (int *)G_malloc(cats->n_scatts * 2 * sizeof(int)); cats->cats_arr[n_a_cats]->scatt_idxs = (int *)G_malloc(cats->n_scatts * sizeof(int)); for (i_scatt = 0; i_scatt < cats->n_scatts; i_scatt++) cats->cats_arr[n_a_cats]->scatt_idxs[i_scatt] = -1; ++cats->n_a_cats; return cat_id; }
/*! \brief Set vector set style for thematic mapping Updates also style for each geoline. \param id vector set id \param layer layer number for thematic mapping \param color color column name \param width width column name \param colors pointer to Colors structure or NULL \return 1 on success \return -1 on error (point set not found) */ int GV_set_style_thematic(int id, int layer, const char* color, const char* width, struct Colors *color_rules) { geovect *gv; if (NULL == (gv = gv_get_vect(id))) { return -1; } if(!gv->tstyle) gv->tstyle = (gvstyle_thematic *)G_malloc(sizeof(gvstyle_thematic)); G_zero(gv->tstyle, sizeof(gvstyle_thematic)); gv->tstyle->active = 1; gv->tstyle->layer = layer; if (color) gv->tstyle->color_column = G_store(color); if (width) gv->tstyle->width_column = G_store(width); Gv_load_vect_thematic(gv, color_rules); return 1; }
CELL clump(int in_fd, int out_fd, int diag, int print) { register int col; register int n; CELL NEW, OLD; CELL *temp_cell, *temp_clump; CELL *prev_in, *cur_in, *out_cell; CELL *prev_clump, *cur_clump; CELL X, LEFT; CELL *index, *renumber; CELL label; int nrows, ncols; int row; int len; int nalloc; long cur_time; char *cname; int cfd, csize; CELL cat; nrows = Rast_window_rows(); ncols = Rast_window_cols(); /* allocate clump index */ nalloc = INCR; index = (CELL *) G_malloc(nalloc * sizeof(CELL)); index[0] = 0; renumber = NULL; /* allocate CELL buffers two columns larger than current window */ len = (ncols + 2) * sizeof(CELL); prev_in = (CELL *) G_malloc(len); cur_in = (CELL *) G_malloc(len); prev_clump = (CELL *) G_malloc(len); cur_clump = (CELL *) G_malloc(len); out_cell = (CELL *) G_malloc(len); /* temp file for initial clump IDs */ cname = G_tempfile(); if ((cfd = open(cname, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) G_fatal_error(_("Unable to open temp file")); csize = ncols * sizeof(CELL); time(&cur_time); /* fake a previous row which is all NULL */ Rast_set_c_null_value(prev_in, ncols + 2); /* set left and right edge to NULL */ Rast_set_c_null_value(&cur_in[0], 1); Rast_set_c_null_value(&cur_in[ncols + 1], 1); /* initialize clump labels */ G_zero(cur_clump, len); G_zero(prev_clump, len); label = 0; /**************************************************** * PASS 1 * * pass thru the input, create initial clump labels * ****************************************************/ G_message(_("Pass 1 of 2...")); for (row = 0; row < nrows; row++) { Rast_get_c_row(in_fd, cur_in + 1, row); G_percent(row, nrows, 4); Rast_set_c_null_value(&X, 1); for (col = 1; col <= ncols; col++) { LEFT = X; X = cur_in[col]; if (Rast_is_c_null_value(&X)) { /* don't clump NULL data */ cur_clump[col] = 0; continue; } /* * if the cell value is different to the left and above * (diagonal: and above left and above right) * then we must start a new clump * * this new clump may eventually collide with another * clump and will have to be merged */ /* try to connect the current cell to an existing clump */ OLD = NEW = 0; /* same clump as to the left */ if (X == LEFT) { OLD = cur_clump[col] = cur_clump[col - 1]; } if (diag) { /* check above right, center, left, in that order */ n = 2; temp_clump = prev_clump + col + 1; temp_cell = prev_in + col + 1; do { if (X == *temp_cell) { cur_clump[col] = *temp_clump; if (OLD == 0) { OLD = *temp_clump; } else { NEW = *temp_clump; break; } } temp_cell--; temp_clump--; } while (n-- > 0); } else { /* check above */ if (X == prev_in[col]) { temp_clump = prev_clump + col; cur_clump[col] = *temp_clump; if (OLD == 0) { OLD = *temp_clump; } else { NEW = *temp_clump; } } } if (NEW == 0 || OLD == NEW) { /* ok */ if (OLD == 0) { /* start a new clump */ label++; cur_clump[col] = label; if (label >= nalloc) { nalloc += INCR; index = (CELL *) G_realloc(index, nalloc * sizeof(CELL)); } index[label] = label; } continue; } /* conflict! preserve NEW clump ID and change OLD clump ID. * Must go back to the left in the current row and to the right * in the previous row to change all the clump values as well. */ /* left of the current row from 1 to col - 1 */ temp_clump = cur_clump; n = col - 1; while (n-- > 0) { temp_clump++; /* skip left edge */ if (*temp_clump == OLD) *temp_clump = NEW; } /* right of previous row from col + 1 to ncols */ temp_clump = prev_clump; temp_clump += col; n = ncols - col; while (n-- > 0) { temp_clump++; /* skip col */ if (*temp_clump == OLD) *temp_clump = NEW; } /* modify the OLD index */ index[OLD] = NEW; } /* write initial clump IDs */ /* this works also with writing out cur_clump, but only * prev_clump is complete and will not change any more */ if (row > 0) { if (write(cfd, prev_clump + 1, csize) != csize) G_fatal_error(_("Unable to write to temp file")); } /* switch the buffers so that the current buffer becomes the previous */ temp_cell = cur_in; cur_in = prev_in; prev_in = temp_cell; temp_clump = cur_clump; cur_clump = prev_clump; prev_clump = temp_clump; } /* write last row with initial clump IDs */ if (write(cfd, prev_clump + 1, csize) != csize) G_fatal_error(_("Unable to write to temp file")); G_percent(1, 1, 1); /* generate a renumbering scheme */ G_message(_("Generating renumbering scheme...")); G_debug(1, "%d initial labels", label); /* allocate final clump ID */ renumber = (CELL *) G_malloc((label + 1) * sizeof(CELL)); renumber[0] = 0; cat = 1; G_percent(0, label, 1); for (n = 1; n <= label; n++) { G_percent(n, label, 1); OLD = n; NEW = index[n]; if (OLD != NEW) { renumber[n] = 0; /* find valid clump ID */ while (OLD != NEW) { OLD = NEW; NEW = index[OLD]; } index[n] = NEW; } else /* set final clump id */ renumber[n] = cat++; } /* rewind temp file */ lseek(cfd, 0, SEEK_SET); if (print) { fprintf(stdout, "clumps=%d\n", cat - 1); } else { /**************************************************** * PASS 2 * * apply renumbering scheme to initial clump labels * ****************************************************/ /* the input raster is no longer needed, * using instead the temp file with initial clump labels */ G_message(_("Pass 2 of 2...")); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 4); if (read(cfd, cur_clump, csize) != csize) G_fatal_error(_("Unable to read from temp file")); temp_clump = cur_clump; temp_cell = out_cell; for (col = 0; col < ncols; col++) { *temp_cell = renumber[index[*temp_clump]]; if (*temp_cell == 0) Rast_set_c_null_value(temp_cell, 1); temp_clump++; temp_cell++; } Rast_put_row(out_fd, out_cell, CELL_TYPE); } G_percent(1, 1, 1); } close(cfd); unlink(cname); print_time(&cur_time); return 0; }
int main(int argc, char *argv[]) { struct History history; struct GModule *module; char *desc; struct Cell_head cellhd, orig_cellhd; void *inrast, *outrast; int infd, outfd; void *ptr; int nrows, ncols, row, col; RASTER_MAP_TYPE in_data_type; struct Option *input_prefix, *output_prefix, *metfn, *sensor, *adate, *pdate, *elev, *bgain, *metho, *perc, *dark, *atmo, *lsatmet, *oscale; char *inputname, *met, *outputname, *sensorname; struct Flag *frad, *print_meta, *named; lsat_data lsat; char band_in[GNAME_MAX], band_out[GNAME_MAX]; int i, j, q, method, pixel, dn_dark[MAX_BANDS], dn_mode[MAX_BANDS], dn_sat; int overwrite; double qcal, rad, ref, percent, ref_mode, rayleigh, scale; unsigned long hist[QCALMAX], h_max; struct Colors colors; struct FPRange range; double min, max; /* initialize GIS environment */ G_gisinit(argv[0]); /* initialize module */ module = G_define_module(); module->description = _("Calculates top-of-atmosphere radiance or reflectance and temperature for Landsat MSS/TM/ETM+/OLI"); G_add_keyword(_("imagery")); G_add_keyword(_("radiometric conversion")); G_add_keyword(_("radiance")); G_add_keyword(_("reflectance")); G_add_keyword(_("brightness temperature")); G_add_keyword(_("Landsat")); G_add_keyword(_("atmospheric correction")); module->overwrite = TRUE; /* It defines the different parameters */ input_prefix = G_define_standard_option(G_OPT_R_BASENAME_INPUT); input_prefix->label = _("Base name of input raster bands"); input_prefix->description = _("Example: 'B.' for B.1, B.2, ..."); output_prefix = G_define_standard_option(G_OPT_R_BASENAME_OUTPUT); output_prefix->label = _("Prefix for output raster maps"); output_prefix->description = _("Example: 'B.toar.' generates B.toar.1, B.toar.2, ..."); metfn = G_define_standard_option(G_OPT_F_INPUT); metfn->key = "metfile"; metfn->required = NO; metfn->description = _("Name of Landsat metadata file (.met or MTL.txt)"); metfn->guisection = _("Metadata"); sensor = G_define_option(); sensor->key = "sensor"; sensor->type = TYPE_STRING; sensor->label = _("Spacecraft sensor"); sensor->description = _("Required only if 'metfile' not given (recommended for sanity)"); sensor->options = "mss1,mss2,mss3,mss4,mss5,tm4,tm5,tm7,oli8"; desc = NULL; G_asprintf(&desc, "mss1;%s;mss2;%s;mss3;%s;mss4;%s;mss5;%s;tm4;%s;tm5;%s;tm7;%s;oli8;%s", _("Landsat-1 MSS"), _("Landsat-2 MSS"), _("Landsat-3 MSS"), _("Landsat-4 MSS"), _("Landsat-5 MSS"), _("Landsat-4 TM"), _("Landsat-5 TM"), _("Landsat-7 ETM+"), _("Landsat_8 OLI/TIRS")); sensor->descriptions = desc; sensor->required = NO; /* perhaps YES for clarity */ sensor->guisection = _("Metadata"); metho = G_define_option(); metho->key = "method"; metho->type = TYPE_STRING; metho->required = NO; metho->options = "uncorrected,dos1,dos2,dos2b,dos3,dos4"; metho->label = _("Atmospheric correction method"); metho->description = _("Atmospheric correction method"); metho->answer = "uncorrected"; metho->guisection = _("Metadata"); adate = G_define_option(); adate->key = "date"; adate->type = TYPE_STRING; adate->required = NO; adate->key_desc = "yyyy-mm-dd"; adate->label = _("Image acquisition date (yyyy-mm-dd)"); adate->description = _("Required only if 'metfile' not given"); adate->guisection = _("Metadata"); elev = G_define_option(); elev->key = "sun_elevation"; elev->type = TYPE_DOUBLE; elev->required = NO; elev->label = _("Sun elevation in degrees"); elev->description = _("Required only if 'metfile' not given"); elev->guisection = _("Metadata"); pdate = G_define_option(); pdate->key = "product_date"; pdate->type = TYPE_STRING; pdate->required = NO; pdate->key_desc = "yyyy-mm-dd"; pdate->label = _("Image creation date (yyyy-mm-dd)"); pdate->description = _("Required only if 'metfile' not given"); pdate->guisection = _("Metadata"); bgain = G_define_option(); bgain->key = "gain"; bgain->type = TYPE_STRING; bgain->required = NO; bgain->label = _("Gain (H/L) of all Landsat ETM+ bands (1-5,61,62,7,8)"); bgain->description = _("Required only if 'metfile' not given"); bgain->guisection = _("Settings"); perc = G_define_option(); perc->key = "percent"; perc->type = TYPE_DOUBLE; perc->required = NO; perc->label = _("Percent of solar radiance in path radiance"); perc->description = _("Required only if 'method' is any DOS"); perc->answer = "0.01"; perc->guisection = _("Settings"); dark = G_define_option(); dark->key = "pixel"; dark->type = TYPE_INTEGER; dark->required = NO; dark->label = _("Minimum pixels to consider digital number as dark object"); dark->description = _("Required only if 'method' is any DOS"); dark->answer = "1000"; dark->guisection = _("Settings"); atmo = G_define_option(); atmo->key = "rayleigh"; atmo->type = TYPE_DOUBLE; atmo->required = NO; atmo->label = _("Rayleigh atmosphere (diffuse sky irradiance)"); /* scattering coefficient? */ atmo->description = _("Required only if 'method' is DOS3"); atmo->answer = "0.0"; atmo->guisection = _("Settings"); lsatmet = G_define_option(); lsatmet->key = "lsatmet"; lsatmet->type = TYPE_STRING; lsatmet->required = NO; lsatmet->multiple = YES; lsatmet->label = _("return value stored for a given metadata"); lsatmet->description = _("Required only if 'metfile' and -p given"); lsatmet->options = "number,creation,date,sun_elev,sensor,bands,sunaz,time"; desc = NULL; G_asprintf(&desc, "number;%s;creation;%s;date;%s;sun_elev;%s;sensor;%s;bands;%s;sunaz;%s;time;%s", _("Landsat Number"), _("Creation timestamp"), _("Date"), _("Sun Elevation"), _("Sensor"), _("Bands count"), _("Sun Azimuth Angle"), _("Time")); lsatmet->descriptions = desc; lsatmet->guisection = _("Settings"); oscale = G_define_option(); oscale->key = "scale"; oscale->type = TYPE_DOUBLE; oscale->answer = "1.0"; oscale->required = NO; oscale->description = _("Scale factor for output"); /* define the different flags */ frad = G_define_flag(); frad->key = 'r'; frad->description = _("Output at-sensor radiance instead of reflectance for all bands"); named = G_define_flag(); named->key = 'n'; named->description = _("Input raster maps use as extension the number of the band instead the code"); print_meta = G_define_flag(); print_meta->key = 'p'; print_meta->description = _("Print output metadata info"); /* options and afters parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); /***************************************** * ---------- START -------------------- * Stores options and flags to variables *****************************************/ met = metfn->answer; inputname = input_prefix->answer; outputname = output_prefix->answer; sensorname = sensor->answer ? sensor->answer : ""; overwrite = G_check_overwrite(argc, argv); Rast_get_window(&orig_cellhd); G_zero(&lsat, sizeof(lsat)); if (adate->answer != NULL) { strncpy(lsat.date, adate->answer, 11); lsat.date[10] = '\0'; if (strlen(lsat.date) != 10) G_fatal_error(_("Illegal date format: [%s] (yyyy-mm-dd)"), lsat.date); } if (pdate->answer != NULL) { strncpy(lsat.creation, pdate->answer, 11); lsat.creation[10] = '\0'; if (strlen(lsat.creation) != 10) G_fatal_error(_("Illegal date format: [%s] (yyyy-mm-dd)"), lsat.creation); } lsat.sun_elev = elev->answer == NULL ? 0. : atof(elev->answer); percent = atof(perc->answer); pixel = atoi(dark->answer); rayleigh = atof(atmo->answer); scale = atof(oscale->answer); /* * Data from metadata file */ lsat.flag = NOMETADATAFILE; /* Unnecessary because G_zero filled, but for sanity */ if (met != NULL) { lsat.flag = METADATAFILE; lsat_metadata(met, &lsat); if (print_meta->answer) { char *lsatmeta; if (lsatmet->answer == NULL) { G_fatal_error(_("Please use a metadata keyword with -p")); } for (i = 0; lsatmet->answers[i] != NULL; i++) { lsatmeta = lsatmet->answers[i]; if (strcmp(lsatmeta, "number") == 0) { fprintf(stdout, "number=%d\n", lsat.number); } if (strcmp(lsatmeta, "creation") == 0) { fprintf(stdout, "creation=%s\n", lsat.creation); } if (strcmp(lsatmeta, "date") == 0) { fprintf(stdout, "date=%s\n", lsat.date); } if (strcmp(lsatmeta, "sun_elev") == 0) { fprintf(stdout, "sun_elev=%f\n", lsat.sun_elev); } if (strcmp(lsatmeta, "sunaz") == 0) { fprintf(stdout, "sunaz=%f\n", lsat.sun_az); } if (strcmp(lsatmeta, "sensor") == 0) { fprintf(stdout, "sensor=%s\n", lsat.sensor); } if (strcmp(lsatmeta, "bands") == 0) { fprintf(stdout, "bands=%d\n", lsat.bands); } if (strcmp(lsatmet->answer, "time") == 0) { fprintf(stdout, "%f\n", lsat.time); } } exit(EXIT_SUCCESS); } G_debug(1, "lsat.number = %d, lsat.sensor = [%s]", lsat.number, lsat.sensor); if (!lsat.sensor || lsat.number > 8 || lsat.number < 1) G_fatal_error(_("Failed to identify satellite")); G_debug(1, "Landsat-%d %s with data set in metadata file [%s]", lsat.number, lsat.sensor, met); if (elev->answer != NULL) { lsat.sun_elev = atof(elev->answer); G_warning("Overwriting solar elevation of metadata file"); } } /* * Data from command line */ else if (adate->answer == NULL || elev->answer == NULL) { G_fatal_error(_("Lacking '%s' and/or '%s' for this satellite"), adate->key, elev->key); } else { if (strcmp(sensorname, "tm7") == 0) { if (bgain->answer == NULL || strlen(bgain->answer) != 9) G_fatal_error(_("Landsat-7 requires band gain with 9 (H/L) characters")); set_ETM(&lsat, bgain->answer); } else if (strcmp(sensorname, "oli8") == 0) set_OLI(&lsat); else if (strcmp(sensorname, "tm5") == 0) set_TM5(&lsat); else if (strcmp(sensorname, "tm4") == 0) set_TM4(&lsat); else if (strcmp(sensorname, "mss5") == 0) set_MSS5(&lsat); else if (strcmp(sensorname, "mss4") == 0) set_MSS4(&lsat); else if (strcmp(sensorname, "mss3") == 0) set_MSS3(&lsat); else if (strcmp(sensorname, "mss2") == 0) set_MSS2(&lsat); else if (strcmp(sensorname, "mss1") == 0) set_MSS1(&lsat); else G_fatal_error(_("Unknown satellite type (defined by '%s')"), sensorname); } /***************************************** * ------------ PREPARATION -------------- *****************************************/ if (strcasecmp(metho->answer, "corrected") == 0) /* deleted 2013 */ method = CORRECTED; else if (strcasecmp(metho->answer, "dos1") == 0) method = DOS1; else if (strcasecmp(metho->answer, "dos2") == 0) method = DOS2; else if (strcasecmp(metho->answer, "dos2b") == 0) method = DOS2b; else if (strcasecmp(metho->answer, "dos3") == 0) method = DOS3; else if (strcasecmp(metho->answer, "dos4") == 0) method = DOS4; else method = UNCORRECTED; /* if (metho->answer[3] == '2') method = (metho->answer[4] == '\0') ? DOS2 : DOS2b; else if (metho->answer[3] == '1') method = DOS1; else if (metho->answer[3] == '3') method = DOS3; else if (metho->answer[3] == '4') method = DOS4; else method = UNCORRECTED; */ for (i = 0; i < lsat.bands; i++) { dn_mode[i] = 0; dn_dark[i] = (int)lsat.band[i].qcalmin; dn_sat = (int)(0.90 * lsat.band[i].qcalmax); /* Begin: calculate dark pixel */ if (method > DOS && !lsat.band[i].thermal) { for (q = 0; q <= lsat.band[i].qcalmax; q++) hist[q] = 0L; sprintf(band_in, "%s%d", inputname, lsat.band[i].code); Rast_get_cellhd(band_in, "", &cellhd); Rast_set_window(&cellhd); if ((infd = Rast_open_old(band_in, "")) < 0) G_fatal_error(_("Unable to open raster map <%s>"), band_in); in_data_type = Rast_get_map_type(infd); if (in_data_type < 0) G_fatal_error(_("Unable to read data type of raster map <%s>"), band_in); inrast = Rast_allocate_buf(in_data_type); nrows = Rast_window_rows(); ncols = Rast_window_cols(); G_message("Calculating dark pixel of <%s>... ", band_in); for (row = 0; row < nrows; row++) { Rast_get_row(infd, inrast, row, in_data_type); for (col = 0; col < ncols; col++) { switch (in_data_type) { case CELL_TYPE: ptr = (void *)((CELL *) inrast + col); q = (int)*((CELL *) ptr); break; case FCELL_TYPE: ptr = (void *)((FCELL *) inrast + col); q = (int)*((FCELL *) ptr); break; case DCELL_TYPE: ptr = (void *)((DCELL *) inrast + col); q = (int)*((DCELL *) ptr); break; default: ptr = NULL; q = -1.; } if (!Rast_is_null_value(ptr, in_data_type) && q >= lsat.band[i].qcalmin && q <= lsat.band[i].qcalmax) hist[q]++; } } /* DN of dark object */ for (j = lsat.band[i].qcalmin; j <= lsat.band[i].qcalmax; j++) { if (hist[j] >= (unsigned int)pixel) { dn_dark[i] = j; break; } } /* Mode of DN (exclude potentially saturated) */ h_max = 0L; for (j = lsat.band[i].qcalmin; j < dn_sat; j++) { /* G_debug(5, "%d-%ld", j, hist[j]); */ if (hist[j] > h_max) { h_max = hist[j]; dn_mode[i] = j; } } G_verbose_message ("... DN = %.2d [%lu] : mode %.2d [%lu], excluding DN > %d", dn_dark[i], hist[dn_dark[i]], dn_mode[i], hist[dn_mode[i]], dn_sat); G_free(inrast); Rast_close(infd); } /* End: calculate dark pixel */ /* Calculate transformation constants */ lsat_bandctes(&lsat, i, method, percent, dn_dark[i], rayleigh); } /* * unnecessary or necessary with more checking as acquisition date,... * if (strlen(lsat.creation) == 0) * G_fatal_error(_("Unknown production date (defined by '%s')"), pdate->key); */ if (G_verbose() > G_verbose_std()) { fprintf(stderr, "\n LANDSAT: %d SENSOR: %s\n", lsat.number, lsat.sensor); fprintf(stderr, " ACQUISITION DATE %s [production date %s]\n", lsat.date, lsat.creation); fprintf(stderr, " Earth-sun distance = %.8lf\n", lsat.dist_es); fprintf(stderr, " Solar elevation angle = %.8lf\n", lsat.sun_elev); fprintf(stderr, " Atmospheric correction: %s\n", (method == UNCORRECTED ? "UNCORRECTED" : metho->answer)); if (method > DOS) { fprintf(stderr, " Percent of solar irradiance in path radiance = %.4lf\n", percent); } for (i = 0; i < lsat.bands; i++) { fprintf(stderr, "-------------------\n"); fprintf(stderr, " BAND %d %s(code %d)\n", lsat.band[i].number, (lsat.band[i].thermal ? "thermal " : ""), lsat.band[i].code); fprintf(stderr, " calibrated digital number (DN): %.1lf to %.1lf\n", lsat.band[i].qcalmin, lsat.band[i].qcalmax); fprintf(stderr, " calibration constants (L): %.5lf to %.5lf\n", lsat.band[i].lmin, lsat.band[i].lmax); fprintf(stderr, " at-%s radiance = %.8lf * DN + %.5lf\n", (method > DOS ? "surface" : "sensor"), lsat.band[i].gain, lsat.band[i].bias); if (lsat.band[i].thermal) { fprintf(stderr, " at-sensor temperature = %.5lf / log[(%.5lf / radiance) + 1.0]\n", lsat.band[i].K2, lsat.band[i].K1); } else { fprintf(stderr, " mean solar exoatmospheric irradiance (ESUN): %.5lf\n", lsat.band[i].esun); fprintf(stderr, " at-%s reflectance = radiance / %.5lf\n", (method > DOS ? "surface" : "sensor"), lsat.band[i].K1); if (method > DOS) { fprintf(stderr, " the darkness DN with a least %d pixels is %d\n", pixel, dn_dark[i]); fprintf(stderr, " the DN mode is %d\n", dn_mode[i]); } } } fprintf(stderr, "-------------------\n"); fflush(stderr); } /***************************************** * ------------ CALCULUS ----------------- *****************************************/ G_message(_("Calculating...")); for (i = 0; i < lsat.bands; i++) { sprintf(band_in, "%s%d", inputname, (named->answer ? lsat.band[i].number : lsat.band[i].code)); sprintf(band_out, "%s%d", outputname, lsat.band[i].code); /* set same size as original band raster */ Rast_get_cellhd(band_in, "", &cellhd); Rast_set_window(&cellhd); if ((infd = Rast_open_old(band_in, "")) < 0) G_fatal_error(_("Unable to open raster map <%s>"), band_in); if (G_find_raster2(band_out, "")) { if (overwrite) { G_warning(_("Raster map <%s> already exists and will be overwritten"), band_out); } else { G_warning(_("Raster map <%s> exists. Skipping."), band_out); continue; } } in_data_type = Rast_get_map_type(infd); if (in_data_type < 0) G_fatal_error(_("Unable to read data type of raster map <%s>"), band_in); /* controlling, if we can write the raster */ if (G_legal_filename(band_out) < 0) G_fatal_error(_("<%s> is an illegal file name"), band_out); if ((outfd = Rast_open_new(band_out, DCELL_TYPE)) < 0) G_fatal_error(_("Unable to create raster map <%s>"), band_out); /* allocate input and output buffer */ inrast = Rast_allocate_buf(in_data_type); outrast = Rast_allocate_buf(DCELL_TYPE); nrows = Rast_window_rows(); ncols = Rast_window_cols(); G_important_message(_("Writing %s of <%s> to <%s>..."), (frad-> answer ? _("radiance") : (lsat.band[i]. thermal) ? _("temperature") : _("reflectance")), band_in, band_out); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); Rast_get_row(infd, inrast, row, in_data_type); for (col = 0; col < ncols; col++) { switch (in_data_type) { case CELL_TYPE: ptr = (void *)((CELL *) inrast + col); qcal = (double)((CELL *) inrast)[col]; break; case FCELL_TYPE: ptr = (void *)((FCELL *) inrast + col); qcal = (double)((FCELL *) inrast)[col]; break; case DCELL_TYPE: ptr = (void *)((DCELL *) inrast + col); qcal = (double)((DCELL *) inrast)[col]; break; default: ptr = NULL; qcal = -1.; } if (Rast_is_null_value(ptr, in_data_type) || qcal < lsat.band[i].qcalmin) { Rast_set_d_null_value((DCELL *) outrast + col, 1); } else { rad = lsat_qcal2rad(qcal, &lsat.band[i]); if (frad->answer) { ref = rad; } else { if (lsat.band[i].thermal) { ref = lsat_rad2temp(rad, &lsat.band[i]); } else { ref = lsat_rad2ref(rad, &lsat.band[i]) * scale; if (ref < 0. && method > DOS) ref = 0.; } } ((DCELL *) outrast)[col] = ref; } } Rast_put_row(outfd, outrast, DCELL_TYPE); } G_percent(1, 1, 1); ref_mode = 0.; if (method > DOS && !lsat.band[i].thermal) { ref_mode = lsat_qcal2rad(dn_mode[i], &lsat.band[i]); ref_mode = lsat_rad2ref(ref_mode, &lsat.band[i]); } G_free(inrast); Rast_close(infd); G_free(outrast); Rast_close(outfd); /* * needed? * if (out_type != CELL_TYPE) * G_quantize_fp_map_range(band_out, G_mapset(), 0., 360., 0, * 360); */ /* set grey255 colortable */ Rast_init_colors(&colors); Rast_read_fp_range(band_out, G_mapset(), &range); Rast_get_fp_range_min_max(&range, &min, &max); Rast_make_grey_scale_fp_colors(&colors, min, max); Rast_write_colors(band_out, G_mapset(), &colors); /* Initialize the 'history' structure with basic info */ Rast_short_history(band_out, "raster", &history); Rast_append_format_history(&history, " %s of Landsat-%d %s (method %s)", (frad-> answer ? "Radiance" : (lsat.band[i]. thermal ? "Temperature" : "Reflectance")), lsat.number, lsat.sensor, metho->answer); Rast_append_history(&history, "-----------------------------------------------------------------"); Rast_append_format_history(&history, " Acquisition date (and time) ........... %s (%.4lf h)", lsat.date, lsat.time); Rast_append_format_history(&history, " Production date ....................... %s\n", lsat.creation); Rast_append_format_history(&history, " Earth-sun distance (d) ................ %.7lf", lsat.dist_es); Rast_append_format_history(&history, " Sun elevation (and azimuth) ........... %.5lf (%.5lf)", lsat.sun_elev, lsat.sun_az); Rast_append_format_history(&history, " Digital number (DN) range ............. %.0lf to %.0lf", lsat.band[i].qcalmin, lsat.band[i].qcalmax); Rast_append_format_history(&history, " Calibration constants (Lmin to Lmax) .. %+.5lf to %+.5lf", lsat.band[i].lmin, lsat.band[i].lmax); Rast_append_format_history(&history, " DN to Radiance (gain and bias) ........ %+.5lf and %+.5lf", lsat.band[i].gain, lsat.band[i].bias); if (lsat.band[i].thermal) { Rast_append_format_history(&history, " Temperature (K1 and K2) ............... %.3lf and %.3lf", lsat.band[i].K1, lsat.band[i].K2); } else { Rast_append_format_history(&history, " Mean solar irradiance (ESUN) .......... %.3lf", lsat.band[i].esun); Rast_append_format_history(&history, " Radiance to Reflectance (divide by) ... %+.5lf", lsat.band[i].K1); if (method > DOS) { Rast_append_format_history(&history, " "); Rast_append_format_history(&history, " Dark object (%4d pixels) DN = ........ %d", pixel, dn_dark[i]); Rast_append_format_history(&history, " Mode in reflectance histogram ......... %.5lf", ref_mode); } } Rast_append_history(&history, "------------------------------------------------------------------"); Rast_command_history(&history); Rast_write_history(band_out, &history); if (lsat.band[i].thermal) Rast_write_units(band_out, "Kelvin"); else if (frad->answer) Rast_write_units(band_out, "W/(m^2 sr um)"); else Rast_write_units(band_out, "unitless"); /* set raster timestamp from acq date? (see r.timestamp module) */ } Rast_set_window(&orig_cellhd); exit(EXIT_SUCCESS); }
int QgsGrassGisLib::readRasterRow( int fd, void * buf, int row, RASTER_MAP_TYPE data_type, bool noDataAsZero ) { if ( row < 0 || row >= mRows ) { QgsDebugMsg( QString( "row %1 out of range 0 - %2" ).arg( row ).arg( mRows ) ); return 0; } // TODO: use cached block with more rows Raster raster = mRasters.value( fd ); //if ( !raster.provider ) return -1; if ( !raster.input ) return -1; // Create extent for current row QgsRectangle blockRect = mExtent; double yRes = mExtent.height() / mRows; double yMax = mExtent.yMaximum() - yRes * row; //QgsDebugMsg( QString( "height = %1 mRows = %2" ).arg( mExtent.height() ).arg( mRows ) ); //QgsDebugMsg( QString( "row = %1 yRes = %2 yRes * row = %3" ).arg( row ).arg( yRes ).arg( yRes * row ) ); //QgsDebugMsg( QString( "mExtent.yMaximum() = %1 yMax = %2" ).arg( mExtent.yMaximum() ).arg( yMax ) ); blockRect.setYMaximum( yMax ); blockRect.setYMinimum( yMax - yRes ); QgsRasterBlock *block = raster.input->block( raster.band, blockRect, mColumns, 1 ); if ( !block ) return -1; QGis::DataType requestedType = qgisRasterType( data_type ); //QgsDebugMsg( QString("data_type = %1").arg(data_type) ); //QgsDebugMsg( QString("requestedType = %1").arg(requestedType) ); //QgsDebugMsg( QString("requestedType size = %1").arg( QgsRasterBlock::typeSize( requestedType ) ) ); //QgsDebugMsg( QString("block->dataType = %1").arg( block->dataType() ) ); block->convert( requestedType ); memcpy( buf, block->bits( 0 ), QgsRasterBlock::typeSize( requestedType ) * mColumns ); for ( int i = 0; i < mColumns; i++ ) { QgsDebugMsgLevel( QString( "row = %1 i = %2 val = %3 isNoData = %4" ).arg( row ).arg( i ).arg( block->value( i ) ).arg( block->isNoData( i ) ), 5 ); //(( CELL * ) buf )[i] = i; if ( block->isNoData( 0, i ) ) { if ( noDataAsZero ) { switch ( data_type ) { case CELL_TYPE: G_zero(( char * ) &(( CELL * ) buf )[i], G_raster_size( data_type ) ); break; case FCELL_TYPE: G_zero(( char * ) &(( FCELL * ) buf )[i], G_raster_size( data_type ) ); break; case DCELL_TYPE: G_zero(( char * ) &(( DCELL * ) buf )[i], G_raster_size( data_type ) ); break; default: break; } } else { switch ( data_type ) { case CELL_TYPE: G_set_c_null_value( &(( CELL * ) buf )[i], 1 ); break; case FCELL_TYPE: G_set_f_null_value( &(( FCELL * ) buf )[i], 1 ); break; case DCELL_TYPE: G_set_d_null_value( &(( DCELL * ) buf )[i], 1 ); break; default: break; } } } //else //{ //memcpy( &( buf[i] ), block->bits( 0, i ), 4 ); //buf[i] = (int) block->value( 0, i); //QgsDebugMsg( QString("buf[i] = %1").arg(buf[i])); //} } delete block; return 1; }
/*! \brief Get default information about link to database for new dblink \param Map pointer to Map_info structure \param field layer number \param field_name layer name \param type how many tables are linked to map: GV_1TABLE / GV_MTABLE \return pointer to allocated field_info structure */ struct field_info *Vect_default_field_info(struct Map_info *Map, int field, const char *field_name, int type) { struct field_info *fi; char buf[GNAME_MAX], buf2[GNAME_MAX]; const char *schema; dbConnection connection; G_debug(1, "Vect_default_field_info(): map = %s field = %d", Map->name, field); if (Map->format == GV_FORMAT_OGR_DIRECT) { G_zero(&connection, sizeof(dbConnection)); connection.driverName = G_store("ogr"); connection.databaseName = G_store(Map->fInfo.ogr.dsn); } else { db_get_connection(&connection); } G_debug(2, "drv = %s db = %s", connection.driverName, connection.databaseName); if (!connection.driverName && !connection.databaseName) { /* Set default values */ db_set_default_connection(); db_get_connection(&connection); G_important_message(_("Default driver / database set to:\n" "driver: %s\ndatabase: %s"), connection.driverName, connection.databaseName); } /* they must be a matched pair, so if one is set but not the other then give up and let the user figure it out */ else if (!connection.driverName) { G_fatal_error(_("Default driver is not set")); } else if (!connection.databaseName) { G_fatal_error(_("Default database is not set")); } fi = (struct field_info *)G_malloc(sizeof(struct field_info)); fi->number = field; /* Table name */ if (type == GV_1TABLE) { sprintf(buf, "%s", Map->name); } else { if (field_name != NULL && strlen(field_name) > 0) sprintf(buf, "%s_%s", Map->name, field_name); else sprintf(buf, "%s_%d", Map->name, field); } schema = connection.schemaName; if (schema && strlen(schema) > 0) { sprintf(buf2, "%s.%s", schema, buf); fi->table = G_store(buf2); } else { fi->table = G_store(buf); } /* Field name */ if (field_name) fi->name = G_store(field_name); else fi->name = G_store(buf); fi->key = G_store(GV_KEY_COLUMN); /* Should be: id/fid/gfid/... ? */ fi->database = G_store(connection.databaseName); fi->driver = G_store(connection.driverName); return fi; }
/*! \brief Load to points to memory The other alternative may be to load to a tmp file. \param name name of vector map to be loaded \param[out] nsites number of loaded points \param[out] has_z 2D or 3D points data loaded? \return pointer to geopoint struct (array) \return NULL on failure */ geopoint *Gp_load_sites(const char *name, int *nsites, int *has_z) { struct Map_info map; static struct line_pnts *Points = NULL; struct line_cats *Cats = NULL; geopoint *top, *gpt, *prev; int np, ltype, eof; struct Cell_head wind; int ndim; const char *mapset; np = 0; eof = 0; mapset = G_find_vector2(name, ""); if (!mapset) { G_warning(_("Vector map <%s> not found"), name); return NULL; } Vect_set_open_level(1); if (Vect_open_old(&map, name, "") == -1) { G_fatal_error(_("Unable to open vector map <%s>"), G_fully_qualified_name(name, mapset)); } Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); top = gpt = (geopoint *) G_malloc(sizeof(geopoint)); G_zero(gpt, sizeof(geopoint)); if (!top) { return NULL; } G_get_set_window(&wind); Vect_set_constraint_region(&map, wind.north, wind.south, wind.east, wind.west, PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX); /* get ndim */ *has_z = 0; ndim = 2; if (Vect_is_3d(&map)) { *has_z = 1; ndim = 3; } while (eof == 0) { ltype = Vect_read_next_line(&map, Points, Cats); switch (ltype) { case -1: { G_warning(_("Unable to read vector map <%s>"), G_fully_qualified_name(name, mapset)); return NULL; } case -2: /* EOF */ { eof = 1; continue; } } if ((ltype & GV_POINTS)) { np++; gpt->p3[X] = Points->x[0]; gpt->p3[Y] = Points->y[0]; if (ndim > 2) { gpt->dims = 3; gpt->p3[Z] = Points->z[0]; } else { gpt->dims = 2; } /* Store category info for thematic display */ if (Cats->n_cats > 0) { gpt->cats = Cats; Cats = Vect_new_cats_struct(); } else { Vect_reset_cats(Cats); } /* initialize style */ gpt->highlighted = 0; G_debug(5, "loading vector point %d x=%f y=%f ncats=%d", np, Points->x[0], Points->y[0], Cats->n_cats); gpt->next = (geopoint *) G_malloc(sizeof(geopoint)); /* G_fatal_error */ G_zero(gpt->next, sizeof(geopoint)); if (!gpt->next) { return NULL; } prev = gpt; gpt = gpt->next; } } if (np > 0) { prev->next = NULL; G_free(gpt); } Vect_close(&map); if (!np) { G_warning(_("No points from vector map <%s> fall within current region"), G_fully_qualified_name(name, mapset)); return (NULL); } else { G_message(_("Vector map <%s> loaded (%d points)"), G_fully_qualified_name(name, mapset), np); } *nsites = np; return top; }
int main(int argc, char **argv) { struct GModule *module; struct Option *map_opt, *field_opt, *fs_opt, *vs_opt, *nv_opt, *col_opt, *where_opt, *file_opt; struct Flag *c_flag, *v_flag, *r_flag; dbDriver *driver; dbString sql, value_string; dbCursor cursor; dbTable *table; dbColumn *column; dbValue *value; struct field_info *Fi; int ncols, col, more; struct Map_info Map; char query[1024]; struct ilist *list_lines; struct bound_box *min_box, *line_box; int i, line, area, init_box, cat; module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("database")); G_add_keyword(_("attribute table")); module->description = _("Prints vector map attributes."); map_opt = G_define_standard_option(G_OPT_V_MAP); field_opt = G_define_standard_option(G_OPT_V_FIELD); col_opt = G_define_standard_option(G_OPT_DB_COLUMNS); where_opt = G_define_standard_option(G_OPT_DB_WHERE); fs_opt = G_define_standard_option(G_OPT_F_SEP); fs_opt->description = _("Output field separator"); fs_opt->guisection = _("Format"); vs_opt = G_define_standard_option(G_OPT_F_SEP); vs_opt->key = "vs"; vs_opt->description = _("Output vertical record separator"); vs_opt->answer = NULL; vs_opt->guisection = _("Format"); nv_opt = G_define_option(); nv_opt->key = "nv"; nv_opt->type = TYPE_STRING; nv_opt->required = NO; nv_opt->description = _("Null value indicator"); nv_opt->guisection = _("Format"); file_opt = G_define_standard_option(G_OPT_F_OUTPUT); file_opt->key = "file"; file_opt->required = NO; file_opt->description = _("Name for output file (if omitted or \"-\" output to stdout)"); r_flag = G_define_flag(); r_flag->key = 'r'; r_flag->description = _("Print minimal region extent of selected vector features instead of attributes"); c_flag = G_define_flag(); c_flag->key = 'c'; c_flag->description = _("Do not include column names in output"); c_flag->guisection = _("Format"); v_flag = G_define_flag(); v_flag->key = 'v'; v_flag->description = _("Vertical output (instead of horizontal)"); v_flag->guisection = _("Format"); G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* set input vector map name and mapset */ if (file_opt->answer && strcmp(file_opt->answer, "-") != 0) { if (NULL == freopen(file_opt->answer, "w", stdout)) { G_fatal_error(_("Unable to open file <%s> for writing"), file_opt->answer); } } if (r_flag->answer) { min_box = (struct bound_box *) G_malloc(sizeof(struct bound_box)); G_zero((void *)min_box, sizeof(struct bound_box)); line_box = (struct bound_box *) G_malloc(sizeof(struct bound_box)); list_lines = Vect_new_list(); } else { min_box = line_box = NULL; list_lines = NULL; } db_init_string(&sql); db_init_string(&value_string); /* open input vector */ if (!r_flag->answer) Vect_open_old_head2(&Map, map_opt->answer, "", field_opt->answer); else { if (2 > Vect_open_old2(&Map, map_opt->answer, "", field_opt->answer)) { Vect_close(&Map); G_fatal_error(_("Unable to open vector map <%s> at topology level. " "Flag '%c' requires topology level."), map_opt->answer, r_flag->key); } } if ((Fi = Vect_get_field2(&Map, field_opt->answer)) == NULL) G_fatal_error(_("Database connection not defined for layer <%s>"), field_opt->answer); driver = db_start_driver_open_database(Fi->driver, Fi->database); if (!driver) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); if (col_opt->answer) sprintf(query, "SELECT %s FROM ", col_opt->answer); else sprintf(query, "SELECT * FROM "); db_set_string(&sql, query); db_append_string(&sql, Fi->table); if (where_opt->answer) { char *buf = NULL; buf = G_malloc((strlen(where_opt->answer) + 8)); sprintf(buf, " WHERE %s", where_opt->answer); db_append_string(&sql, buf); G_free(buf); } if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) G_fatal_error(_("Unable to open select cursor")); table = db_get_cursor_table(&cursor); ncols = db_get_table_number_of_columns(table); /* column names if horizontal output (ignore for -r) */ if (!v_flag->answer && !c_flag->answer && !r_flag->answer) { for (col = 0; col < ncols; col++) { column = db_get_table_column(table, col); if (col) fprintf(stdout, "%s", fs_opt->answer); fprintf(stdout, "%s", db_get_column_name(column)); } fprintf(stdout, "\n"); } init_box = 1; /* fetch the data */ while (1) { if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) G_fatal_error(_("Unable to fetch data from table <%s>"), Fi->table); if (!more) break; cat = -1; for (col = 0; col < ncols; col++) { column = db_get_table_column(table, col); value = db_get_column_value(column); if (cat < 0 && strcmp(Fi->key, db_get_column_name(column)) == 0) { cat = db_get_value_int(value); if (r_flag->answer) break; } if (r_flag->answer) continue; db_convert_column_value_to_string(column, &value_string); if (!c_flag->answer && v_flag->answer) fprintf(stdout, "%s%s", db_get_column_name(column), fs_opt->answer); if (col && !v_flag->answer) fprintf(stdout, "%s", fs_opt->answer); if (nv_opt->answer && db_test_value_isnull(value)) fprintf(stdout, "%s", nv_opt->answer); else fprintf(stdout, "%s", db_get_string(&value_string)); if (v_flag->answer) fprintf(stdout, "\n"); } if (r_flag->answer) { /* get minimal region extent */ Vect_cidx_find_all(&Map, Vect_get_field_number(&Map, field_opt->answer), -1, cat, list_lines); for (i = 0; i < list_lines->n_values; i++) { line = list_lines->value[i]; area = Vect_get_centroid_area(&Map, line); if (area > 0) { if (!Vect_get_area_box(&Map, area, line_box)) G_fatal_error(_("Unable to get bounding box of area %d"), area); } else { if (!Vect_get_line_box(&Map, line, line_box)) G_fatal_error(_("Unable to get bounding box of line %d"), line); } if (init_box) { Vect_box_copy(min_box, line_box); init_box = 0; } else { Vect_box_extend(min_box, line_box); } } } else { if (!v_flag->answer) fprintf(stdout, "\n"); else if (vs_opt->answer) fprintf(stdout, "%s\n", vs_opt->answer); } } if (r_flag->answer) { fprintf(stdout, "n=%f\n", min_box->N); fprintf(stdout, "s=%f\n", min_box->S); fprintf(stdout, "w=%f\n", min_box->W); fprintf(stdout, "e=%f\n", min_box->E); if (Vect_is_3d(&Map)) { fprintf(stdout, "t=%f\n", min_box->T); fprintf(stdout, "b=%f\n", min_box->B); } fflush(stdout); G_free((void *)min_box); G_free((void *)line_box); Vect_destroy_list(list_lines); } db_close_cursor(&cursor); db_close_database_shutdown_driver(driver); Vect_close(&Map); exit(EXIT_SUCCESS); }
/*! \brief Write data to GRASS ASCII vector format Prints message if some features without category are skipped. \param[out] ascii pointer to the output ASCII file \param[out] att att file (< version 5 only) \param Map pointer to Map_info structure \param ver version number 4 or 5 \param format format GV_ASCII_FORMAT_POINT or GV_ASCII_FORMAT_STD \param dp number of significant digits \param fs field separator \param region_flag check region \param type feature type filter \param field field number \param Clist list of categories to filter features or NULL \param where SQL select where statement to filter features or NULL \param column_names array of columns to be included to the output or NULL "*" as the first item in the array indicates all columns \param header TRUE to print also header \return number of written features \return -1 on error */ int Vect_write_ascii(FILE *ascii, FILE *att, struct Map_info *Map, int ver, int format, int dp, char *fs, int region_flag, int type, int field, const struct cat_list *Clist, const char* where, const char **column_names, int header) { int ltype, ctype, i, cat, line, left, right, found; double *xptr, *yptr, *zptr, x, y; static struct line_pnts *Points; struct line_cats *Cats, *ACats; char *xstring, *ystring, *zstring; size_t xsize, ysize, zsize; struct Cell_head window; struct ilist *fcats; int count, n_skipped; /* where || columns */ struct field_info *Fi; dbDriver *driver; dbValue value; dbHandle handle; int *cats, ncats, more; dbTable *Table; dbString dbstring; dbColumn *Column; dbValue *Value; char *buf; size_t bufsize; dbCursor cursor; /* columns */ char **columns; int *coltypes; char *all_columns; Fi = NULL; driver = NULL; columns = NULL; coltypes = NULL; all_columns = NULL; G_zero(&value, sizeof(dbValue)); db_init_string(&dbstring); xstring = NULL; ystring = NULL; zstring = NULL; xsize = 0; ysize = 0; zsize = 0; buf = NULL; bufsize = 0; /* get the region */ G_get_window(&window); count = ncats = 0; xstring = ystring = zstring = NULL; cats = NULL; if (field > 0 && (where || column_names)) { Fi = Vect_get_field(Map, field); if (!Fi) { G_fatal_error(_("Database connection not defined for layer %d"), field); } driver = db_start_driver(Fi->driver); if (!driver) G_fatal_error(_("Unable to start driver <%s>"), Fi->driver); db_init_handle(&handle); db_set_handle(&handle, Fi->database, NULL); if (db_open_database(driver, &handle) != DB_OK) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); /* select cats (sorted array) */ ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats); G_debug(3, "%d categories selected from table <%s>", ncats, Fi->table); if (!column_names) { db_close_database(driver); db_shutdown_driver(driver); } else { int icol, ncols; const char *col_name; int len_all = 0; db_set_string(&dbstring, Fi->table); if (db_describe_table(driver, &dbstring, &Table) != DB_OK) { G_warning(_("Unable to describe table <%s>"), Fi->table); return -1; } ncols = db_get_table_number_of_columns(Table); columns = (char **) G_malloc((ncols + 1) * sizeof(char *)); if (column_names[0] && strcmp(column_names[0], "*") == 0) { /* all columns */ icol = 0; for (i = 0; i < ncols; i++) { col_name = db_get_column_name(db_get_table_column(Table, i)); /* key column skipped */ if (strcmp(Fi->key, col_name) != 0) columns[icol++] = G_store(col_name); } columns[icol] = NULL; } else { int j; icol = 0; i = 0; while (column_names[i]) { /* key column skipped */ if (strcmp(Fi->key, column_names[i]) != 0) { found = 0; for (j = 0; j < ncols; j++) { col_name = db_get_column_name(db_get_table_column(Table, j)); if (strcmp(col_name, column_names[i]) == 0) { columns[icol++] = G_store(col_name); found = 1; break; } } if (!found) { G_warning(_("Column <%s> does not exist"), column_names[i]); G_important_message(_("Available columns:")); for (j = 0; j < ncols; j++) { col_name = db_get_column_name(db_get_table_column(Table, j)); G_important_message("%s", col_name); } G_warning(_("Export cancelled")); db_close_database(driver); db_shutdown_driver(driver); return -1; } } i++; } columns[icol] = NULL; } db_zero_string(&dbstring); db_free_table(Table); Table = NULL; if (columns[0]) { /* selected columns only */ i = 0; while (columns[i]) len_all += strlen(columns[i++]); coltypes = G_malloc(i * sizeof(int)); all_columns = G_malloc(len_all + i + 2); i = 0; strcpy(all_columns, columns[0]); while (columns[i]) { /* get column types */ coltypes[i] = db_column_Ctype(driver, Fi->table, columns[i]); if (coltypes[i] < 0) { db_close_database(driver); db_shutdown_driver(driver); G_warning(_("Unknown type of column <%s>, export cancelled"), columns[i]); return -1; } if (i > 0) { strcat(all_columns, ","); strcat(all_columns, columns[i]); } i++; } } else { /* no column or only key column selected */ G_free(columns); columns = NULL; db_close_database(driver); db_shutdown_driver(driver); } } } if (format == GV_ASCII_FORMAT_POINT && header) { /* print header */ if (Map->head.with_z) fprintf(ascii, "east%snorth%sheight%scat", fs, fs, fs); else fprintf(ascii, "east%snorth%scat", fs, fs); if (columns) { for (i = 0; columns[i]; i++) { if (db_select_value (driver, Fi->table, Fi->key, cat, columns[i], &value) < 0) G_fatal_error(_("Unable to select record from table <%s> (key %s, column %s)"), Fi->table, Fi->key, columns[i]); if (columns[i]) fprintf(ascii, "%s%s", fs, columns[i]); else fprintf(ascii, "%s", columns[i]); /* can not happen */ } } fprintf(ascii, "%s", HOST_NEWLINE); } Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); ACats = Vect_new_cats_struct(); fcats = Vect_new_list(); /* by default, read_next_line will NOT read Dead lines */ /* but we can override that (in Level I only) by specifying */ /* the type -1, which means match all line types */ Vect_rewind(Map); count = n_skipped = line = 0; while (TRUE) { ltype = Vect_read_next_line(Map, Points, Cats); if (ltype == -1 ) { /* failure */ if (columns) { db_close_database(driver); db_shutdown_driver(driver); free_col_arrays(coltypes, all_columns, column_names && strcmp(column_names[0], "*") == 0 ? columns : NULL); } return -1; } if (ltype == -2) { /* EOF */ if (columns) { db_close_database(driver); db_shutdown_driver(driver); free_col_arrays(coltypes, all_columns, column_names && strcmp(column_names[0], "*") == 0 ? columns : NULL); } break; } line++; if (!(ltype & type)) continue; if (format == GV_ASCII_FORMAT_POINT && !(ltype & GV_POINTS)) continue; found = get_cat(Cats, Clist, cats, ncats, field, &cat); if (!found && field > 0 && ltype == GV_BOUNDARY && type & GV_AREA && Vect_level(Map) > 1) { Vect_get_line_areas(Map, line, &left, &right); if (left < 0) left = Vect_get_isle_area(Map, abs(left)); if (left > 0) { Vect_get_area_cats(Map, left, ACats); found = get_cat(ACats, Clist, cats, ncats, field, &cat); } if (right < 0) right = Vect_get_isle_area(Map, abs(right)); if (!found && right > 0) { Vect_get_area_cats(Map, right, ACats); found = get_cat(ACats, Clist, cats, ncats, field, &cat); } } if (!found) { if (Cats->n_cats < 1) n_skipped++; continue; } if (ver < 5) { Vect_cat_get(Cats, 1, &cat); } switch (ltype) { case GV_BOUNDARY: if (ver == 5) ctype = 'B'; else ctype = 'A'; break; case GV_CENTROID: if (ver < 5) { if (att != NULL) { if (cat > 0) { G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]); G_trim_decimal(xstring); G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]); G_trim_decimal(ystring); fprintf(att, "A %s %s %d%s", xstring, ystring, cat, HOST_NEWLINE); } } continue; } ctype = 'C'; break; case GV_LINE: ctype = 'L'; break; case GV_POINT: ctype = 'P'; break; case GV_FACE: ctype = 'F'; break; case GV_KERNEL: ctype = 'K'; break; default: ctype = 'X'; G_warning(_("Unknown feature type %d"), (int)ltype); break; } if (format == GV_ASCII_FORMAT_POINT) { if (region_flag) { if ((window.east < Points->x[0]) || (window.west > Points->x[0])) continue; } G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]); G_trim_decimal(xstring); if (region_flag) { if ((window.north < Points->y[0]) || (window.south > Points->y[0])) continue; } G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]); G_trim_decimal(ystring); Vect_field_cat_get(Cats, field, fcats); if (Map->head.with_z && ver == 5) { if (region_flag) { if ((window.top < Points->z[0]) || (window.bottom > Points->z[0])) continue; } G_rasprintf(&zstring, &zsize, "%.*f", dp, Points->z[0]); G_trim_decimal(zstring); fprintf(ascii, "%s%s%s%s%s", xstring, fs, ystring, fs, zstring); } else { fprintf(ascii, "%s%s%s", xstring, fs, ystring); } if (fcats->n_values > 0 && cat > -1) { if (fcats->n_values > 1) { G_warning(_("Feature has more categories. Only one category (%d) " "is exported."), cat); } fprintf(ascii, "%s%d", fs, cat); /* print attributes */ if (columns) { G_rasprintf(&buf, &bufsize, "SELECT %s FROM %s WHERE %s = %d", all_columns, Fi->table, Fi->key, cat); G_debug(2, "SQL: %s", buf); db_set_string(&dbstring, buf); if (db_open_select_cursor (driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Cannot select attributes for cat = %d"), cat); } if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to fetch data from table")); } Table = db_get_cursor_table(&cursor); for (i = 0; columns[i]; i++) { Column = db_get_table_column(Table, i); Value = db_get_column_value(Column); if (db_test_value_isnull(Value)) { fprintf(ascii, "%s", fs); } else { switch(coltypes[i]) { case DB_C_TYPE_INT: { fprintf(ascii, "%s%d", fs, db_get_value_int(Value)); break; } case DB_C_TYPE_DOUBLE: { fprintf(ascii, "%s%.*f", fs, dp, db_get_value_double(Value)); break; } case DB_C_TYPE_STRING: { fprintf(ascii, "%s%s", fs, db_get_value_string(Value)); break; } case DB_C_TYPE_DATETIME: { break; } case -1: G_fatal_error(_("Column <%s> not found in table <%s>"), columns[i], Fi->table); default: G_fatal_error(_("Column <%s>: unsupported data type"), columns[i]); } } } db_close_cursor(&cursor); } } fprintf(ascii, "%s", HOST_NEWLINE); } else if (format == GV_ASCII_FORMAT_STD) { /* FORMAT_STANDARD */ if (ver == 5 && Cats->n_cats > 0) fprintf(ascii, "%c %d %d%s", ctype, Points->n_points, Cats->n_cats, HOST_NEWLINE); else fprintf(ascii, "%c %d%s", ctype, Points->n_points, HOST_NEWLINE); xptr = Points->x; yptr = Points->y; zptr = Points->z; while (Points->n_points--) { G_rasprintf(&xstring, &xsize, "%.*f", dp, *xptr++); G_trim_decimal(xstring); G_rasprintf(&ystring, &ysize, "%.*f", dp, *yptr++); G_trim_decimal(ystring); if (ver == 5) { if (Map->head.with_z) { G_rasprintf(&zstring, &zsize, "%.*f", dp, *zptr++); G_trim_decimal(zstring); fprintf(ascii, " %-12s %-12s %-12s%s", xstring, ystring, zstring, HOST_NEWLINE); } else { fprintf(ascii, " %-12s %-12s%s", xstring, ystring, HOST_NEWLINE); } } /*Version 4 */ else { fprintf(ascii, " %-12s %-12s%s", ystring, xstring, HOST_NEWLINE); } } if (ver == 5) { for (i = 0; i < Cats->n_cats; i++) { fprintf(ascii, " %-5d %-10d%s", Cats->field[i], Cats->cat[i], HOST_NEWLINE); } } else { if (cat > -1) { if (ltype == GV_POINT) { G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]); G_trim_decimal(xstring); G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]); G_trim_decimal(ystring); fprintf(att, "P %s %s %d%s", xstring, ystring, cat, HOST_NEWLINE); } else { x = (Points->x[1] + Points->x[0]) / 2; y = (Points->y[1] + Points->y[0]) / 2; G_rasprintf(&xstring, &xsize, "%.*f", dp, x); G_trim_decimal(xstring); G_rasprintf(&ystring, &ysize, "%.*f", dp, y); G_trim_decimal(ystring); fprintf(att, "L %s %s %d%s", xstring, ystring, cat, HOST_NEWLINE); } } } } else if (format == GV_ASCII_FORMAT_WKT) { if (ltype & (GV_BOUNDARY | GV_CENTROID | GV_FACE | GV_KERNEL)) continue; /* Well-Known Text */ Vect_sfa_line_astext(Points, ltype, Vect_is_3d(Map), dp, ascii); count++; } else { G_fatal_error(_("Unknown format")); } count++; } if (format == GV_ASCII_FORMAT_WKT) { /* process areas - topology required */ int i, area, nareas, isle, nisles; if (Vect_level(Map) < 2) { G_warning(_("Topology not available, unable to process areas")); nareas = 0; } else { nareas = Vect_get_num_areas(Map); } for (area = 1; area <= nareas; area++) { if (!Vect_area_alive(Map, area)) /* skip dead areas */ continue; if (Vect_get_area_cat(Map, area, field) < 0) continue; /* get boundary -> linearring */ if (Vect_get_area_points(Map, area, Points) < 0) { G_warning(_("Unable to get boundary of area id %d"), area); continue; } fprintf(ascii, "POLYGON("); /* write outter ring */ Vect_sfa_line_astext(Points, GV_BOUNDARY, 0, dp, ascii); /* boundary is always 2D */ /* get isles (holes) -> inner rings */ nisles = Vect_get_area_num_isles(Map, area); for (i = 0; i < nisles; i++) { /* get isle boundary -> linearring */ isle = Vect_get_area_isle(Map, area, i); if (Vect_get_isle_points(Map, isle, Points) < 0) { G_warning(_("Unable to get boundary of isle id %d (area id %d)"), isle, area); continue; } fprintf(ascii, ", "); /* write inner ring */ Vect_sfa_line_astext(Points, GV_BOUNDARY, 0, dp, ascii); /* boundary is always 2D */ } fprintf(ascii, ")%s", HOST_NEWLINE); count++; } } if (n_skipped > 0) G_important_message(_("%d features without category skipped. To export also " "features without category use '%s=-1'."), n_skipped, "layer"); Vect_destroy_line_struct(Points); Vect_destroy_cats_struct(Cats); Vect_destroy_cats_struct(ACats); return count; }
CELL clump_n(int *in_fd, char **inname, int nin, double threshold, int out_fd, int diag, int print) { register int col; register int i, n; /* input */ DCELL **prev_in, **cur_in, **temp_in; int bcol; DCELL *rng, maxdiff; double thresh2; /* output */ CELL OLD, NEW; CELL *temp_clump, *out_cell, *out_cellp; CELL *prev_clump, *cur_clump; CELL *index, *renumber; CELL label; int nrows, ncols; int row; int isnull; int len; int nalloc; long cur_time; char *cname; int cfd, csize; CELL cat; G_message(_("%d-band clumping with threshold %g"), nin, threshold); nrows = Rast_window_rows(); ncols = Rast_window_cols(); thresh2 = threshold * threshold; /* allocate clump index */ nalloc = INCR; index = (CELL *) G_malloc(nalloc * sizeof(CELL)); index[0] = 0; renumber = NULL; /* allocate DCELL buffers two columns larger than current window */ len = (ncols + 2) * sizeof(DCELL); prev_in = (DCELL **) G_malloc(sizeof(DCELL *) * nin); cur_in = (DCELL **) G_malloc(sizeof(DCELL *) * nin); rng = G_malloc(sizeof(DCELL) * nin); maxdiff = 0; for (i = 0; i < nin; i++) { struct FPRange fp_range; /* min/max values of each input raster */ DCELL min, max; if (Rast_read_fp_range(inname[i], "", &fp_range) != 1) G_fatal_error(_("No min/max found in raster map <%s>"), inname[i]); Rast_get_fp_range_min_max(&fp_range, &min, &max); rng[i] = max - min; maxdiff += rng[i] * rng[i]; prev_in[i] = (DCELL *) G_malloc(len); cur_in[i] = (DCELL *) G_malloc(len); /* fake a previous row which is all NULL */ Rast_set_d_null_value(prev_in[i], ncols + 2); /* set left and right edge to NULL */ Rast_set_d_null_value(&cur_in[i][0], 1); Rast_set_d_null_value(&cur_in[i][ncols + 1], 1); } G_debug(1, "maximum possible difference: %g", maxdiff); /* allocate CELL buffers two columns larger than current window */ len = (ncols + 2) * sizeof(CELL); prev_clump = (CELL *) G_malloc(len); cur_clump = (CELL *) G_malloc(len); out_cell = (CELL *) G_malloc(len); /* temp file for initial clump IDs */ cname = G_tempfile(); if ((cfd = open(cname, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) G_fatal_error(_("Unable to open temp file")); csize = ncols * sizeof(CELL); time(&cur_time); /* initialize clump labels */ G_zero(cur_clump, len); G_zero(prev_clump, len); label = 0; /**************************************************** * PASS 1 * * pass thru the input, create initial clump labels * ****************************************************/ G_message(_("Pass 1 of 2...")); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); for (i = 0; i < nin; i++) { Rast_get_d_row(in_fd[i], cur_in[i] + 1, row); } for (col = 1; col <= ncols; col++) { isnull = 0; for (i = 0; i < nin; i++) { if (Rast_is_d_null_value(&cur_in[i][col])) { /* don't clump NULL data */ cur_clump[col] = 0; isnull = 1; break; } } if (isnull) continue; /* * if the cell values are different to the left and above * (diagonal: and above left and above right) * then we must start a new clump * * this new clump may eventually collide with another * clump and will have to be merged */ /* try to connect the current cell to an existing clump */ OLD = NEW = 0; /* same clump as to the left */ if (cmp_cells(cur_in, col, cur_in, col - 1, rng, nin, thresh2)) { OLD = cur_clump[col] = cur_clump[col - 1]; } if (diag) { /* check above right, center, left, in that order */ temp_clump = prev_clump + col + 1; bcol = col + 1; do { if (cmp_cells(cur_in, col, prev_in, bcol, rng, nin, thresh2)) { cur_clump[col] = *temp_clump; if (OLD == 0) { OLD = *temp_clump; } else { NEW = *temp_clump; /* threshold > 0 and diagonal requires a bit of extra work * because of bridge cells: * A similar to B, B similar to C, but A not similar to C * -> B is bridge cell */ if (NEW != OLD) { CELL *temp_clump2; /* conflict! preserve NEW clump ID and change OLD clump ID. * Must go back to the left in the current row and to the right * in the previous row to change all the clump values as well. */ /* left of the current row from 1 to col - 1 */ temp_clump2 = cur_clump; n = col - 1; while (n-- > 0) { temp_clump2++; /* skip left edge */ if (*temp_clump2 == OLD) *temp_clump2 = NEW; } /* right of previous row from col - 1 to ncols */ temp_clump2 = prev_clump + col - 1; n = ncols - col + 2; while (n-- > 0) { if (*temp_clump2 == OLD) *temp_clump2 = NEW; temp_clump2++; } /* modify the OLD index */ index[OLD] = NEW; OLD = NEW; NEW = 0; } } } temp_clump--; } while (bcol-- > col - 1); } else { /* check above */ if (cmp_cells(cur_in, col, prev_in, col, rng, nin, thresh2)) { temp_clump = prev_clump + col; cur_clump[col] = *temp_clump; if (OLD == 0) { OLD = *temp_clump; } else { NEW = *temp_clump; if (NEW != OLD) { /* conflict! preserve NEW clump ID and change OLD clump ID. * Must go back to the left in the current row and to the right * in the previous row to change all the clump values as well. */ /* left of the current row from 1 to col - 1 */ temp_clump = cur_clump; n = col - 1; while (n-- > 0) { temp_clump++; /* skip left edge */ if (*temp_clump == OLD) *temp_clump = NEW; } /* right of previous row from col + 1 to ncols */ temp_clump = prev_clump + col; n = ncols - col; while (n-- > 0) { temp_clump++; /* skip col */ if (*temp_clump == OLD) *temp_clump = NEW; } /* modify the OLD index */ index[OLD] = NEW; OLD = NEW; NEW = 0; } } } } if (NEW == 0 || OLD == NEW) { /* ok */ if (OLD == 0) { /* start a new clump */ label++; cur_clump[col] = label; if (label >= nalloc) { nalloc += INCR; index = (CELL *) G_realloc(index, nalloc * sizeof(CELL)); } index[label] = label; } } /* else the relabelling above failed */ } /* write initial clump IDs */ /* this works also with writing out cur_clump, but only * prev_clump is complete and will not change any more */ if (row > 0) { if (write(cfd, prev_clump + 1, csize) != csize) G_fatal_error(_("Unable to write to temp file")); } /* switch the buffers so that the current buffer becomes the previous */ temp_in = cur_in; cur_in = prev_in; prev_in = temp_in; temp_clump = cur_clump; cur_clump = prev_clump; prev_clump = temp_clump; } /* write last row with initial clump IDs */ if (write(cfd, prev_clump + 1, csize) != csize) G_fatal_error(_("Unable to write to temp file")); G_percent(1, 1, 1); /* generate a renumbering scheme */ G_message(_("Generating renumbering scheme...")); G_debug(1, "%d initial labels", label); /* allocate final clump ID */ renumber = (CELL *) G_malloc((label + 1) * sizeof(CELL)); renumber[0] = 0; cat = 1; G_percent(0, label, 1); for (n = 1; n <= label; n++) { G_percent(n, label, 1); OLD = n; NEW = index[n]; if (OLD != NEW) { renumber[n] = 0; /* find valid clump ID */ while (OLD != NEW) { OLD = NEW; NEW = index[OLD]; if (NEW == n) G_fatal_error("Circular relabelling for %d", n); } index[n] = NEW; } else /* set final clump id */ renumber[n] = cat++; } /* rewind temp file */ lseek(cfd, 0, SEEK_SET); if (print) { fprintf(stdout, "clumps=%d\n", cat - 1); } else { /**************************************************** * PASS 2 * * apply renumbering scheme to initial clump labels * ****************************************************/ /* the input raster is no longer needed, * using instead the temp file with initial clump labels */ G_message(_("Pass 2 of 2...")); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); if (read(cfd, cur_clump, csize) != csize) G_fatal_error(_("Unable to read from temp file")); temp_clump = cur_clump; out_cellp = out_cell; for (col = 0; col < ncols; col++) { *out_cellp = renumber[index[*temp_clump]]; if (*out_cellp == 0) Rast_set_c_null_value(out_cellp, 1); temp_clump++; out_cellp++; } Rast_put_row(out_fd, out_cell, CELL_TYPE); } G_percent(1, 1, 1); } close(cfd); unlink(cname); print_time(&cur_time); return 0; }
int main(int argc, char *argv[]) { /* variables */ DCELL *data_buf; CELL *clump_buf; CELL i, max; int row, col, rows, cols; int out_mode, use_MASK, *n, *e; long int *count; int fd_data, fd_clump; const char *datamap, *clumpmap, *centroidsmap; double avg, vol, total_vol, east, north, *sum; struct Cell_head window; struct Map_info *fd_centroids; struct line_pnts *Points; struct line_cats *Cats; struct field_info *Fi; char buf[DB_SQL_MAX]; dbString sql; dbDriver *driver; struct GModule *module; struct { struct Option *input, *clump, *centroids, *output; } opt; struct { struct Flag *report; } flag; /* define parameters and flags */ G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("volume")); G_add_keyword(_("clumps")); module->label = _("Calculates the volume of data \"clumps\"."); module->description = _("Optionally produces a GRASS vector points map " "containing the calculated centroids of these clumps."); opt.input = G_define_standard_option(G_OPT_R_INPUT); opt.input->description = _("Name of input raster map representing data that will be summed within clumps"); opt.clump = G_define_standard_option(G_OPT_R_INPUT); opt.clump->key = "clump"; opt.clump->required = NO; opt.clump->label = _("Name of input clump raster map"); opt.clump->description = _("Preferably the output of r.clump. " "If no clump map is given than MASK is used."); opt.centroids = G_define_standard_option(G_OPT_V_OUTPUT); opt.centroids->key = "centroids"; opt.centroids->required = NO; opt.centroids->description = _("Name for output vector points map to contain clump centroids"); opt.output = G_define_standard_option(G_OPT_F_OUTPUT); opt.output->required = NO; opt.output->label = _("Name for output file to hold the report"); opt.output->description = _("If no output file given report is printed to standard output"); flag.report = G_define_flag(); flag.report->key = 'f'; flag.report->description = _("Generate unformatted report (items separated by colon)"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* get arguments */ datamap = opt.input->answer; clumpmap = NULL; if (opt.clump->answer) clumpmap = opt.clump->answer; centroidsmap = NULL; fd_centroids = NULL; Points = NULL; Cats = NULL; driver = NULL; if (opt.centroids->answer) { centroidsmap = opt.centroids->answer; fd_centroids = G_malloc(sizeof(struct Map_info)); } out_mode = (!flag.report->answer); /* * see if MASK or a separate "clumpmap" raster map is to be used * -- it must(!) be one of those two choices. */ use_MASK = 0; if (!clumpmap) { clumpmap = "MASK"; use_MASK = 1; if (!G_find_raster2(clumpmap, G_mapset())) G_fatal_error(_("No MASK found. If no clump map is given than the MASK is required. " "You need to define a clump raster map or create a MASK by r.mask command.")); G_important_message(_("No clump map given, using MASK")); } /* open input and clump raster maps */ fd_data = Rast_open_old(datamap, ""); fd_clump = Rast_open_old(clumpmap, use_MASK ? G_mapset() : ""); /* initialize vector map (for centroids) if needed */ if (centroidsmap) { if (Vect_open_new(fd_centroids, centroidsmap, WITHOUT_Z) < 0) G_fatal_error(_("Unable to create vector map <%s>"), centroidsmap); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); /* initialize data structures */ Vect_append_point(Points, 0., 0., 0.); Vect_cat_set(Cats, 1, 1); } /* initialize output file */ if (opt.output->answer && strcmp(opt.output->answer, "-") != 0) { if (freopen(opt.output->answer, "w", stdout) == NULL) { perror(opt.output->answer); exit(EXIT_FAILURE); } } /* initialize data accumulation arrays */ max = Rast_get_max_c_cat(clumpmap, use_MASK ? G_mapset() : ""); sum = (double *)G_malloc((max + 1) * sizeof(double)); count = (long int *)G_malloc((max + 1) * sizeof(long int)); G_zero(sum, (max + 1) * sizeof(double)); G_zero(count, (max + 1) * sizeof(long int)); data_buf = Rast_allocate_d_buf(); clump_buf = Rast_allocate_c_buf(); /* get window size */ G_get_window(&window); rows = window.rows; cols = window.cols; /* now get the data -- first pass */ for (row = 0; row < rows; row++) { G_percent(row, rows, 2); Rast_get_d_row(fd_data, data_buf, row); Rast_get_c_row(fd_clump, clump_buf, row); for (col = 0; col < cols; col++) { i = clump_buf[col]; if (i > max) G_fatal_error(_("Invalid category value %d (max=%d): row=%d col=%d"), i, max, row, col); if (i < 1) { G_debug(3, "row=%d col=%d: zero or negs ignored", row, col); continue; /* ignore zeros and negs */ } if (Rast_is_d_null_value(&data_buf[col])) { G_debug(3, "row=%d col=%d: NULL ignored", row, col); continue; } sum[i] += data_buf[col]; count[i]++; } } G_percent(1, 1, 1); /* free some buffer space */ G_free(data_buf); G_free(clump_buf); /* data lists for centroids of clumps */ e = (int *)G_malloc((max + 1) * sizeof(int)); n = (int *)G_malloc((max + 1) * sizeof(int)); i = centroids(fd_clump, e, n, 1, max); /* close raster maps */ Rast_close(fd_data); Rast_close(fd_clump); /* got everything, now do output */ if (centroidsmap) { G_message(_("Creating vector point map <%s>..."), centroidsmap); /* set comment */ sprintf(buf, _("From '%s' on raster map <%s> using clumps from <%s>"), argv[0], datamap, clumpmap); Vect_set_comment(fd_centroids, buf); /* create attribute table */ Fi = Vect_default_field_info(fd_centroids, 1, NULL, GV_1TABLE); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, fd_centroids)); if (driver == NULL) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Vect_subst_var(Fi->database, fd_centroids), Fi->driver); } db_set_error_handler_driver(driver); db_begin_transaction(driver); db_init_string(&sql); sprintf(buf, "create table %s (cat integer, volume double precision, " "average double precision, sum double precision, count integer)", Fi->table); db_set_string(&sql, buf); Vect_map_add_dblink(fd_centroids, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); G_debug(3, "%s", db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Unable to create table: %s"), db_get_string(&sql)); } } /* print header */ if (out_mode) { fprintf(stdout, _("\nVolume report on data from <%s> using clumps on <%s> raster map"), datamap, clumpmap); fprintf(stdout, "\n\n"); fprintf(stdout, _("Category Average Data # Cells Centroid Total\n")); fprintf(stdout, _("Number in clump Total in clump Easting Northing Volume")); fprintf(stdout, "\n%s\n", SEP); } total_vol = 0.0; /* print output, write centroids */ for (i = 1; i <= max; i++) { if (count[i]) { avg = sum[i] / (double)count[i]; vol = sum[i] * window.ew_res * window.ns_res; total_vol += vol; east = window.west + (e[i] + 0.5) * window.ew_res; north = window.north - (n[i] + 0.5) * window.ns_res; if (fd_centroids) { /* write centroids if requested */ Points->x[0] = east; Points->y[0] = north; Cats->cat[0] = i; Vect_write_line(fd_centroids, GV_POINT, Points, Cats); sprintf(buf, "insert into %s values (%d, %f, %f, %f, %ld)", Fi->table, i, vol, avg, sum[i], count[i]); db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) G_fatal_error(_("Cannot insert new row: %s"), db_get_string(&sql)); } if (out_mode) fprintf(stdout, "%8d%10.2f%10.0f %7ld %10.2f %10.2f %16.2f\n", i, avg, sum[i], count[i], east, north, vol); else fprintf(stdout, "%d:%.2f:%.0f:%ld:%.2f:%.2f:%.2f\n", i, avg, sum[i], count[i], east, north, vol); } } /* write centroid attributes and close the map*/ if (fd_centroids) { db_commit_transaction(driver); Vect_close(fd_centroids); } /* print total value */ if (total_vol > 0.0 && out_mode) { fprintf(stdout, "%s\n", SEP); fprintf(stdout, "%60s = %14.2f", _("Total Volume"), total_vol); fprintf(stdout, "\n"); } exit(EXIT_SUCCESS); }
/*! \brief Load styles for geolines based on thematic mapping \param gv pointer to geovect structure \param colors pointer to Colors structure or NULL \return number of features defined by thematic mapping \return -1 on error */ int Gv_load_vect_thematic(geovect *gv, struct Colors *colors) { geoline *gvt; struct Map_info Map; struct field_info *Fi; int nvals, cat, nlines, nskipped; int red, blu, grn; const char *str; const char *mapset; dbDriver *driver; dbValue value; if(!gv || !gv->tstyle || !gv->filename) return -1; mapset = G_find_vector2(gv->filename, ""); if (!mapset) { G_fatal_error(_("Vector map <%s> not found"), gv->filename); } Vect_set_open_level(1); if (Vect_open_old(&Map, gv->filename, "") == -1) { G_fatal_error(_("Unable to open vector map <%s>"), G_fully_qualified_name(gv->filename, mapset)); } Fi = Vect_get_field(&Map, gv->tstyle->layer); if (!Fi) { G_warning(_("Database connection not defined for layer %d"), gv->tstyle->layer); } else { driver = db_start_driver_open_database(Fi->driver, Fi->database); if (!driver) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); } G_message(_("Loading thematic vector layer <%s>..."), G_fully_qualified_name(gv->filename, mapset)); nlines = nskipped = 0; for(gvt = gv->lines; gvt; gvt = gvt->next) { gvt->style = (gvstyle *) G_malloc(sizeof(gvstyle)); G_zero(gvt->style, sizeof(gvstyle)); /* use default style */ gvt->style->color = gv->style->color; gvt->style->symbol = gv->style->symbol; gvt->style->size = gv->style->size; gvt->style->width = gv->style->width; cat = -1; if (gvt->cats) Vect_cat_get(gvt->cats, gv->tstyle->layer, &cat); if (cat < 0) { nskipped++; continue; } /* color */ if (colors) { if (!Rast_get_c_color((const CELL *) &cat, &red, &grn, &blu, colors)) { G_warning(_("No color rule defined for category %d"), cat); gvt->style->color = gv->style->color; } gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) + ((int)((blu) << 16) & BLU_MASK); } if (gv->tstyle->color_column) { nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->color_column, &value); if (nvals < 1) continue; str = db_get_value_string(&value); if (!str) continue; if (G_str_to_color(str, &red, &grn, &blu) != 1) { G_warning(_("Invalid color definition (%s)"), str); gvt->style->color = gv->style->color; } else { gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) + ((int)((blu) << 16) & BLU_MASK); } } /* width */ if (gv->tstyle->width_column) { nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->width_column, &value); if (nvals < 1) continue; gvt->style->width = db_get_value_int(&value); } nlines++; } if (nskipped > 0) G_warning(_("%d features without category. " "Unable to determine color rules for features without category."), nskipped); return nlines; }