123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- /****************************************************************************
- *
- * MODULE: r.to.vect
- *
- * AUTHOR(S): Bill Brown, Mike Baba, Jean Ezell and Andrew Heekin,
- * David Satnik, Andrea Aime, Radim Blazek
- *
- * PURPOSE: Converts a raster map into a vector map layer
- *
- * COPYRIGHT: (C) 2007, 2011, 2017 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public
- * License (>=v2). Read the file COPYING that comes with GRASS
- * for details.
- *
- *****************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/raster.h>
- #include <grass/dbmi.h>
- #include <grass/vector.h>
- #include <grass/glocale.h>
- #include "global.h"
- /*
- * Attributes for lines are ignored. For points and area by default unique new
- * category is assigned to each and raster value is written to 'value' column.
- * Labels are written to 'label' column if exists. If value flag (-v) is used
- * and type is CELL, raster values are used as categories.
- *
- * 2007/2: attributes for lines supported
- */
- int data_type;
- int data_size;
- struct Map_info Map;
- int input_fd; /* input raster map descriptor */
- struct line_cats *Cats;
- struct Cell_head cell_head;
- int direction;
- int first_read, last_read;
- int input_fd;
- int row_length, row_count, n_rows;
- int total_areas;
- int n_alloced_ptrs;
- int smooth_flag; /* this is 0 for no smoothing, 1 for smoothing of lines */
- int value_flag; /* use raster values as categories */
- struct Categories RastCats;
- int has_cats; /* Category labels available */
- struct field_info *Fi;
- dbDriver *driver;
- dbString sql, label;
- static int cmp_int(const void *a, const void *b)
- {
- return (*(int *)a - *(int *)b);
- }
- int main(int argc, char *argv[])
- {
- struct GModule *module;
- struct Option *in_opt, *out_opt, *feature_opt, *column_name;
- struct Flag *smooth_flg, *value_flg, *z_flg, *no_topol, *notab_flg;
- int feature, notab_flag;
- G_gisinit(argv[0]);
- module = G_define_module();
- G_add_keyword(_("raster"));
- G_add_keyword(_("conversion"));
- G_add_keyword(_("geometry"));
- G_add_keyword(_("vectorization"));
- module->description = _("Converts a raster map into a vector map.");
- in_opt = G_define_standard_option(G_OPT_R_INPUT);
- out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
-
- feature_opt = G_define_standard_option(G_OPT_V_TYPE);
- feature_opt->description = _("Output feature type");
- feature_opt->required = YES;
- feature_opt->multiple = NO;
- feature_opt->options = "point,line,area";
- feature_opt->answer = NULL;
- column_name = G_define_standard_option(G_OPT_DB_COLUMN);
- column_name->label = _("Name of attribute column to store value");
- column_name->description = _("Name must be SQL compliant");
- column_name->answer = "value";
- smooth_flg = G_define_flag();
- smooth_flg->key = 's';
- smooth_flg->description = _("Smooth corners of area features");
- value_flg = G_define_flag();
- value_flg->key = 'v';
- value_flg->description =
- _("Use raster values as categories instead of unique sequence (CELL only)");
- value_flg->guisection = _("Attributes");
- z_flg = G_define_flag();
- z_flg->key = 'z';
- z_flg->label = _("Write raster values as z coordinate");
- z_flg->description = _("Table is not created. "
- "Currently supported only for points.");
- z_flg->guisection = _("Attributes");
- no_topol = G_define_flag();
- no_topol->key = 'b';
- no_topol->label = _("Do not build vector topology");
- no_topol->description = _("Recommended for massive point conversion");
- notab_flg = G_define_standard_flag(G_FLG_V_TABLE);
- if (G_parser(argc, argv))
- exit(EXIT_FAILURE);
- feature = Vect_option_to_types(feature_opt);
- smooth_flag = (smooth_flg->answer) ? SMOOTH : NO_SMOOTH;
- value_flag = value_flg->answer;
- notab_flag = notab_flg->answer;
- if (z_flg->answer && (feature != GV_POINT))
- G_fatal_error(_("z flag is supported only for points"));
- /* Open files */
- input_fd = Rast_open_old(in_opt->answer, "");
- data_type = Rast_get_map_type(input_fd);
- data_size = Rast_cell_size(data_type);
- G_get_window(&cell_head);
- if (value_flag && data_type != CELL_TYPE) {
- if (!notab_flag)
- G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be written to the table."));
- else if (z_flg->answer)
- G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be z coordinate."));
- else
- G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be lost."));
- value_flag = 0;
- }
- if (!value_flag && notab_flag) {
- G_warning(_("Categories will be unique sequence, raster values will be lost."));
- }
- set_error_handler(&Map, &driver);
- if (Vect_open_new(&Map, out_opt->answer, z_flg->answer) < 0)
- G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer);
- Vect_hist_command(&Map);
- Cats = Vect_new_cats_struct();
- /* Open category labels */
- if (data_type == CELL_TYPE) {
- if (0 == Rast_read_cats(in_opt->answer, "", &RastCats))
- has_cats = 1;
- }
- else
- has_cats = 0;
- db_init_string(&sql);
- db_init_string(&label);
- /* Create table */
- if ((feature & (GV_AREA | GV_POINT | GV_LINE)) &&
- (!value_flag || (value_flag && has_cats)) && !(z_flg->answer)
- && !notab_flag) {
- char buf[1000];
- Fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE);
- Vect_map_add_dblink(&Map, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
- Fi->driver);
- driver =
- db_start_driver_open_database(Fi->driver,
- Vect_subst_var(Fi->database, &Map));
- if (driver == NULL)
- G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
- Fi->database, Fi->driver);
- /* Create new table */
- db_zero_string(&sql);
- sprintf(buf, "create table %s ( cat integer", Fi->table);
- db_append_string(&sql, buf);
- if (!value_flag) { /* add value to the table */
- if (data_type == CELL_TYPE) {
- db_append_string(&sql, ", ");
- db_append_string(&sql, column_name->answer);
- db_append_string(&sql, " integer");
- } else {
- db_append_string(&sql, ",");
- db_append_string(&sql, column_name->answer);
- db_append_string(&sql, " double precision");
- }
- }
- if (has_cats) {
- int i, len;
- int clen = 0;
- /* Get maximum column length */
- for (i = 0; i < RastCats.ncats; i++) {
- len = strlen(RastCats.labels[i]);
- if (len > clen)
- clen = len;
- }
- clen += 10;
- sprintf(buf, ", label varchar(%d)", clen);
- db_append_string(&sql, buf);
- }
- db_append_string(&sql, ")");
- 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));
- if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK)
- G_warning(_("Unable to create index"));
- if (db_grant_on_table
- (driver, Fi->table, DB_PRIV_SELECT,
- DB_GROUP | DB_PUBLIC) != DB_OK)
- G_fatal_error(_("Unable to grant privileges on table <%s>"),
- Fi->table);
- db_begin_transaction(driver);
- }
- else {
- driver = NULL;
- }
- /* init variables for lines and areas */
- first_read = 1;
- last_read = 0;
- direction = FORWARD;
- row_length = cell_head.cols;
- n_rows = cell_head.rows;
- row_count = 0;
- if (feature == GV_LINE) {
- alloc_lines_bufs(row_length + 2);
- extract_lines();
- }
- else if (feature == GV_AREA) {
- alloc_areas_bufs(row_length + 2);
- extract_areas();
- }
- else { /* GV_POINT */
- extract_points(z_flg->answer);
- }
- Rast_close(input_fd);
- /* insert cats and optionally labels if raster cats were used */
- if (driver && value_flag) {
- char buf[1000];
- int c, i, j, cat;
- struct ilist *clist;
- int type;
- clist = G_new_ilist();
- /* create category list */
- Vect_rewind(&Map);
- while (1) {
- /* register line */
- type = Vect_read_next_line(&Map, NULL, Cats);
- /* Note: check for dead lines is not needed, because they are skipped by V1_read_next_line_nat() */
- if (type == -1) {
- G_warning(_("Unable to read vector map"));
- break;
- }
- else if (type == -2) {
- break;
- }
-
- for (i = 0; i < Cats->n_cats; i++)
- G_ilist_add(clist, Cats->cat[i]);
- }
-
- if (clist->n_values > 0) {
- qsort(clist->value, clist->n_values, sizeof(int), cmp_int);
- j = 1;
- for (i = 1; i < clist->n_values; i++) {
- if (clist->value[i] != clist->value[j - 1]) {
- clist->value[j] = clist->value[i];
- j++;
- }
- }
- clist->n_values = j;
- G_important_message(_("Updating attributes..."));
- for (c = 0; c < clist->n_values; c++) {
- G_percent(c, clist->n_values, 4);
-
- cat = clist->value[c];
- /* find label, slow -> TODO faster */
- db_set_string(&label, "");
- for (i = 0; i < RastCats.ncats; i++) {
- if (cat == (int)RastCats.q.table[i].dLow) { /* cats are in dLow/High not in cLow/High !!! */
- db_set_string(&label, RastCats.labels[i]);
- db_double_quote_string(&label);
- break;
- }
- }
- G_debug(3, "cat = %d label = %s", cat, db_get_string(&label));
- sprintf(buf, "insert into %s values ( %d, '%s')", Fi->table,
- cat, db_get_string(&label));
- db_set_string(&sql, buf);
- G_debug(3, "%s", db_get_string(&sql));
- if (db_execute_immediate(driver, &sql) != DB_OK)
- G_fatal_error(_("Unable to insert into table: %s"),
- db_get_string(&sql));
- }
- G_percent(1, 1, 1);
- }
- G_free_ilist(clist);
- }
- if (has_cats)
- Rast_free_cats(&RastCats);
- if (driver != NULL) {
- db_commit_transaction(driver);
- db_close_database_shutdown_driver(driver);
- }
- if (!no_topol->answer)
- Vect_build(&Map);
- Vect_close(&Map);
- G_done_msg(" ");
- exit(EXIT_SUCCESS);
- }
|