/*! \brief Copy table linked to vector map based on category numbers. \param In input vector map \param[out] Out output vector map \param field_in input layer number \param field_out output layer number \param field_name layer name \param type feature type \param cats pointer to array of cats or NULL \param ncats number of cats in 'cats' \return 0 on success \return -1 on error */ int Vect_copy_table_by_cats(const struct Map_info *In, struct Map_info *Out, int field_in, int field_out, const char *field_name, int type, int *cats, int ncats) { int ret; struct field_info *Fi, *Fin; const char *name, *key; G_debug(2, "Vect_copy_table(): field_in = %d field_out = %d", field_in, field_out); Fi = Vect_get_field(In, field_in); if (Fi == NULL) { G_warning(_("Database connection not defined for layer %d"), field_in); return -1; } if (field_name != NULL) name = field_name; else name = Fi->name; Fin = Vect_default_field_info(Out, field_out, name, type); G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table); ret = Vect_map_add_dblink(Out, Fin->number, Fin->name, Fin->table, Fi->key, Fin->database, Fin->driver); if (ret == -1) { G_warning(_("Unable to add database link for vector map <%s>"), Out->name); return -1; } if (cats) key = Fi->key; else key = NULL; ret = db_copy_table_by_ints(Fi->driver, Fi->database, Fi->table, Fin->driver, Vect_subst_var(Fin->database, Out), Fin->table, key, cats, ncats); if (ret == DB_FAILED) { G_warning(_("Unable to copy table <%s>"), Fin->table); return -1; } return 0; }
static void create_table(struct Map_info *flowline_vec, struct field_info **f_info, dbDriver ** driver, int write_scalar, int use_sampled_map) { dbString sql; char buf[200]; dbDriver *drvr; struct field_info *fi; db_init_string(&sql); fi = Vect_default_field_info(flowline_vec, 1, NULL, GV_1TABLE); *f_info = fi; Vect_map_add_dblink(flowline_vec, 1, NULL, fi->table, GV_KEY_COLUMN, fi->database, fi->driver); drvr = db_start_driver_open_database(fi->driver, Vect_subst_var(fi->database, flowline_vec)); if (drvr == NULL) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Vect_subst_var(fi->database, flowline_vec), fi->driver); } db_set_error_handler_driver(drvr); *driver = drvr; sprintf(buf, "create table %s (cat integer, velocity double precision", fi->table); db_set_string(&sql, buf); if (write_scalar) db_append_string(&sql, ", input double precision"); if (use_sampled_map) db_append_string(&sql, ", sampled double precision"); db_append_string(&sql, ")"); db_begin_transaction(drvr); /* Create table */ if (db_execute_immediate(drvr, &sql) != DB_OK) { G_fatal_error(_("Unable to create table: %s"), db_get_string(&sql)); } if (db_create_index2(drvr, fi->table, fi->key) != DB_OK) G_warning(_("Unable to create index for table <%s>, key <%s>"), fi->table, fi->key); /* Grant */ if (db_grant_on_table (drvr, fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) { G_fatal_error(_("Unable to grant privileges on table <%s>"), fi->table); } }
/*! \brief Copy DB links from input vector map to output vector map \param In pointer to Map_info structure (input) \param Out pointer to Map_info structure (output) \param first_only TRUE to copy only first link otherwise all DB links are copied */ void Vect_copy_map_dblinks(const struct Map_info *In, struct Map_info *Out, int first_only) { int i, ndblinks; struct field_info *Fi; ndblinks = Vect_get_num_dblinks(In); for (i = 0; i < ndblinks; i++) { Fi = Vect_get_dblink(In, 0); if (!Fi) { G_warning(_("Database connection not defined. Skipping.")); continue; } Vect_map_add_dblink(Out, Fi->number, Fi->name, Fi->table, Fi->key, Fi->database, Fi->driver); if (first_only && ndblinks > 1) G_warning(_("More DB links defined for input vector map. " "Using only first DB link for output.")); } }
/*! \brief Copy tables linked to vector map. All if field = 0, or table defined by given field if field > 0 Notice, that if input map has no tables defined, it will copy nothing and return 0 (success). \param In input vector map \param[out] Out output vector map \param field layer number \return 0 on success \return -1 on error */ int Vect_copy_tables(const struct Map_info *In, struct Map_info *Out, int field) { int i, n, ret, type; struct field_info *Fi, *Fin; dbDriver *driver; n = Vect_get_num_dblinks(In); G_debug(2, "Vect_copy_tables(): copying %d tables", n); type = GV_1TABLE; if (n > 1) type = GV_MTABLE; for (i = 0; i < n; i++) { Fi = Vect_get_dblink(In, i); if (Fi == NULL) { G_warning(_("Database connection not defined for layer %d"), In->dblnk->field[i].number); return -1; } if (field > 0 && Fi->number != field) continue; Fin = Vect_default_field_info(Out, Fi->number, Fi->name, type); G_debug(2, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table); ret = Vect_map_add_dblink(Out, Fi->number, Fi->name, Fin->table, Fi->key, Fin->database, Fin->driver); if (ret == -1) { G_warning(_("Unable to add database link for vector map <%s>"), Out->name); return -1; } ret = db_copy_table(Fi->driver, Fi->database, Fi->table, Fin->driver, Vect_subst_var(Fin->database, Out), Fin->table); if (ret == DB_FAILED) { G_warning(_("Unable to copy table <%s>"), Fin->table); return -1; } driver = db_start_driver_open_database(Fin->driver, Vect_subst_var(Fin->database, Out)); if (driver == NULL) { G_warning(_("Unable to open database <%s> by driver <%s>"), Fin->database, Fin->driver); } else { if (db_create_index2(driver, Fin->table, Fi->key) != DB_OK) G_warning(_("Unable to create index for table <%s>, key <%s>"), Fin->table, Fin->key); db_close_database_shutdown_driver(driver); } } return 0; }
void copy_tabs(struct Map_info *In, struct Map_info *Out, int nfields, int *fields, int *ncats, int **cats) { int i, ttype, ntabs; struct field_info *IFi, *OFi; ntabs = 0; G_message(_("Writing attributes...")); /* Number of output tabs */ for (i = 0; i < Vect_get_num_dblinks(In); i++) { int f, j; IFi = Vect_get_dblink(In, i); for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == IFi->number) { f = j; break; } } if (ncats[f] > 0) ntabs++; } if (ntabs > 1) ttype = GV_MTABLE; else ttype = GV_1TABLE; for (i = 0; i < nfields; i++) { int ret; if (fields[i] == 0) continue; /* Make a list of categories */ IFi = Vect_get_field(In, fields[i]); if (!IFi) { /* no table */ G_warning(_("No table for layer %d"), fields[i]); continue; } OFi = Vect_default_field_info(Out, IFi->number, IFi->name, ttype); ret = db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table, OFi->driver, Vect_subst_var(OFi->database, Out), OFi->table, IFi->key, cats[i], ncats[i]); if (ret == DB_FAILED) { G_warning(_("Unable to copy table for layer %d"), fields[i]); } else { Vect_map_add_dblink(Out, OFi->number, OFi->name, OFi->table, IFi->key, OFi->database, OFi->driver); } } }
int close_streamvect(char *stream_vect) { int r, c, r_nbr, c_nbr, done; GW_LARGE_INT i; CELL stream_id, stream_nbr; ASP_FLAG af; int next_node; struct sstack { int stream_id; int next_trib; } *nodestack; int top = 0, stack_step = 1000; int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 }; int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 }; struct Map_info Out; static struct line_pnts *Points; struct line_cats *Cats; dbDriver *driver; dbHandle handle; dbString table_name, dbsql, valstr; struct field_info *Fi; char *cat_col_name = "cat", buf[2000]; struct Cell_head window; double north_offset, west_offset, ns_res, ew_res; int next_cat; G_message(_("Writing vector map <%s>..."), stream_vect); if (Vect_open_new(&Out, stream_vect, 0) < 0) G_fatal_error(_("Unable to create vector map <%s>"), stream_vect); nodestack = (struct sstack *)G_malloc(stack_step * sizeof(struct sstack)); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); G_get_set_window(&window); ns_res = window.ns_res; ew_res = window.ew_res; north_offset = window.north - 0.5 * ns_res; west_offset = window.west + 0.5 * ew_res; next_cat = n_stream_nodes + 1; for (i = 0; i < n_outlets; i++, next_cat++) { G_percent(i, n_outlets, 2); r = outlets[i].r; c = outlets[i].c; cseg_get(&stream, &stream_id, r, c); if (!stream_id) continue; Vect_reset_line(Points); Vect_reset_cats(Cats); /* outlet */ Vect_cat_set(Cats, 1, stream_id); Vect_cat_set(Cats, 2, 2); Vect_append_point(Points, west_offset + c * ew_res, north_offset - r * ns_res, 0); Vect_write_line(&Out, GV_POINT, Points, Cats); /* add root node to stack */ G_debug(3, "add root node"); top = 0; nodestack[top].stream_id = stream_id; nodestack[top].next_trib = 0; /* depth first post order traversal */ G_debug(3, "traverse"); while (top >= 0) { done = 1; stream_id = nodestack[top].stream_id; G_debug(3, "stream_id %d", stream_id); if (nodestack[top].next_trib < stream_node[stream_id].n_trib) { /* add to stack */ next_node = stream_node[stream_id].trib[nodestack[top].next_trib]; G_debug(3, "add to stack: next %d, trib %d, n trib %d", next_node, nodestack[top].next_trib, stream_node[stream_id].n_trib); nodestack[top].next_trib++; top++; if (top >= stack_step) { /* need more space */ stack_step += 1000; nodestack = (struct sstack *)G_realloc(nodestack, stack_step * sizeof(struct sstack)); } nodestack[top].next_trib = 0; nodestack[top].stream_id = next_node; done = 0; G_debug(3, "go further down"); } if (done) { G_debug(3, "write stream segment"); Vect_reset_line(Points); Vect_reset_cats(Cats); r_nbr = stream_node[stream_id].r; c_nbr = stream_node[stream_id].c; cseg_get(&stream, &stream_nbr, r_nbr, c_nbr); if (stream_nbr <= 0) G_fatal_error(_("Stream id %d not set, top is %d, parent is %d"), stream_id, top, nodestack[top - 1].stream_id); Vect_cat_set(Cats, 1, stream_id); if (stream_node[stream_id].n_trib == 0) Vect_cat_set(Cats, 2, 0); else Vect_cat_set(Cats, 2, 1); Vect_append_point(Points, west_offset + c_nbr * ew_res, north_offset - r_nbr * ns_res, 0); Vect_write_line(&Out, GV_POINT, Points, Cats); seg_get(&aspflag, (char *)&af, r_nbr, c_nbr); while (af.asp > 0) { r_nbr = r_nbr + asp_r[(int)af.asp]; c_nbr = c_nbr + asp_c[(int)af.asp]; cseg_get(&stream, &stream_nbr, r_nbr, c_nbr); if (stream_nbr <= 0) G_fatal_error(_("Stream id not set while tracing")); Vect_append_point(Points, west_offset + c_nbr * ew_res, north_offset - r_nbr * ns_res, 0); if (stream_nbr != stream_id) { /* first point of parent stream */ break; } seg_get(&aspflag, (char *)&af, r_nbr, c_nbr); } Vect_write_line(&Out, GV_LINE, Points, Cats); top--; } } } G_percent(n_outlets, n_outlets, 1); /* finish it */ G_message(_("Writing attribute data...")); /* Prepeare strings for use in db_* calls */ db_init_string(&dbsql); db_init_string(&valstr); db_init_string(&table_name); db_init_handle(&handle); /* Preparing database for use */ /* Create database for new vector map */ Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Out)); if (driver == NULL) { G_fatal_error(_("Unable to start driver <%s>"), Fi->driver); } db_set_error_handler_driver(driver); G_debug(1, "table: %s", Fi->table); G_debug(1, "driver: %s", Fi->driver); G_debug(1, "database: %s", Fi->database); sprintf(buf, "create table %s (%s integer, stream_type varchar(20), type_code integer)", Fi->table, cat_col_name); db_set_string(&dbsql, buf); if (db_execute_immediate(driver, &dbsql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&dbsql)); } if (db_create_index2(driver, Fi->table, cat_col_name) != DB_OK) G_warning(_("Unable to create index on table <%s>"), Fi->table); 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); /* stream nodes */ for (i = 1; i <= n_stream_nodes; i++) { sprintf(buf, "insert into %s values ( %lld, \'%s\', %d )", Fi->table, i, (stream_node[i].n_trib > 0 ? "intermediate" : "start"), (stream_node[i].n_trib > 0)); db_set_string(&dbsql, buf); if (db_execute_immediate(driver, &dbsql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to insert new row: '%s'"), db_get_string(&dbsql)); } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, cat_col_name, Fi->database, Fi->driver); G_debug(1, "close vector"); Vect_hist_command(&Out); Vect_build(&Out); Vect_close(&Out); G_free(nodestack); return 1; }
int main(int argc, char *argv[]) { struct GModule *module; struct _param { struct Option *dsn, *out, *layer, *spat, *where, *min_area; struct Option *snap, *type, *outloc, *cnames; } param; struct _flag { struct Flag *list, *tlist, *no_clean, *z, *notab, *region; struct Flag *over, *extend, *formats, *tolower, *no_import; } flag; int i, j, layer, arg_s_num, nogeom, ncnames; float xmin, ymin, xmax, ymax; int ncols = 0, type; double min_area, snap; char buf[2000], namebuf[2000], tempvect[GNAME_MAX]; char *separator; struct Key_Value *loc_proj_info, *loc_proj_units; struct Key_Value *proj_info, *proj_units; struct Cell_head cellhd, loc_wind, cur_wind; char error_msg[8192]; /* Vector */ struct Map_info Map, Tmp, *Out; int cat; /* Attributes */ struct field_info *Fi; dbDriver *driver; dbString sql, strval; int dim, with_z; /* OGR */ OGRDataSourceH Ogr_ds; OGRLayerH Ogr_layer; OGRFieldDefnH Ogr_field; char *Ogr_fieldname; OGRFieldType Ogr_ftype; OGRFeatureH Ogr_feature; OGRFeatureDefnH Ogr_featuredefn; OGRGeometryH Ogr_geometry, Ogr_oRing, poSpatialFilter; OGRSpatialReferenceH Ogr_projection; OGREnvelope oExt; OGRwkbGeometryType Ogr_geom_type; int OFTIntegerListlength; char *output; char **layer_names; /* names of layers to be imported */ int *layers; /* layer indexes */ int nlayers; /* number of layers to import */ char **available_layer_names; /* names of layers to be imported */ int navailable_layers; int layer_id; unsigned int n_features, feature_count; int overwrite; double area_size; int use_tmp_vect; xmin = ymin = xmax = ymax = 0.0; loc_proj_info = loc_proj_units = NULL; Ogr_ds = Ogr_oRing = poSpatialFilter = NULL; OFTIntegerListlength = 40; /* hack due to limitation in OGR */ area_size = 0.0; use_tmp_vect = FALSE; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("import")); module->description = _("Converts vector data into a GRASS vector map using OGR library."); param.dsn = G_define_option(); param.dsn->key = "dsn"; param.dsn->type = TYPE_STRING; param.dsn->required =YES; param.dsn->label = _("OGR datasource name"); param.dsn->description = _("Examples:\n" "\t\tESRI Shapefile: directory containing shapefiles\n" "\t\tMapInfo File: directory containing mapinfo files"); param.layer = G_define_option(); param.layer->key = "layer"; param.layer->type = TYPE_STRING; param.layer->required = NO; param.layer->multiple = YES; param.layer->label = _("OGR layer name. If not given, all available layers are imported"); param.layer->description = _("Examples:\n" "\t\tESRI Shapefile: shapefile name\n" "\t\tMapInfo File: mapinfo file name"); param.layer->guisection = _("Selection"); param.out = G_define_standard_option(G_OPT_V_OUTPUT); param.out->required = NO; param.out->guisection = _("Output"); param.spat = G_define_option(); param.spat->key = "spatial"; param.spat->type = TYPE_DOUBLE; param.spat->multiple = YES; param.spat->required = NO; param.spat->key_desc = "xmin,ymin,xmax,ymax"; param.spat->label = _("Import subregion only"); param.spat->guisection = _("Selection"); param.spat->description = _("Format: xmin,ymin,xmax,ymax - usually W,S,E,N"); param.where = G_define_standard_option(G_OPT_DB_WHERE); param.where->guisection = _("Selection"); param.min_area = G_define_option(); param.min_area->key = "min_area"; param.min_area->type = TYPE_DOUBLE; param.min_area->required = NO; param.min_area->answer = "0.0001"; param.min_area->label = _("Minimum size of area to be imported (square units)"); param.min_area->guisection = _("Selection"); param.min_area->description = _("Smaller areas and " "islands are ignored. Should be greater than snap^2"); param.type = G_define_standard_option(G_OPT_V_TYPE); param.type->options = "point,line,boundary,centroid"; param.type->answer = ""; param.type->description = _("Optionally change default input type"); param.type->descriptions = _("point;import area centroids as points;" "line;import area boundaries as lines;" "boundary;import lines as area boundaries;" "centroid;import points as centroids"); param.type->guisection = _("Selection"); param.snap = G_define_option(); param.snap->key = "snap"; param.snap->type = TYPE_DOUBLE; param.snap->required = NO; param.snap->answer = "-1"; param.snap->label = _("Snapping threshold for boundaries"); param.snap->description = _("'-1' for no snap"); param.outloc = G_define_option(); param.outloc->key = "location"; param.outloc->type = TYPE_STRING; param.outloc->required = NO; param.outloc->description = _("Name for new location to create"); param.outloc->key_desc = "name"; param.cnames = G_define_option(); param.cnames->key = "cnames"; param.cnames->type = TYPE_STRING; param.cnames->required = NO; param.cnames->multiple = YES; param.cnames->description = _("List of column names to be used instead of original names, " "first is used for category column"); param.cnames->guisection = _("Attributes"); flag.list = G_define_flag(); flag.list->key = 'l'; flag.list->description = _("List available OGR layers in data source and exit"); flag.list->suppress_required = YES; flag.list->guisection = _("Print"); flag.tlist = G_define_flag(); flag.tlist->key = 'a'; flag.tlist->description = _("List available OGR layers including feature types " "in data source and exit"); flag.tlist->suppress_required = YES; flag.tlist->guisection = _("Print"); flag.formats = G_define_flag(); flag.formats->key = 'f'; flag.formats->description = _("List supported formats and exit"); flag.formats->suppress_required = YES; flag.formats->guisection = _("Print"); /* if using -c, you lose topological information ! */ flag.no_clean = G_define_flag(); flag.no_clean->key = 'c'; flag.no_clean->description = _("Do not clean polygons (not recommended)"); flag.no_clean->guisection = _("Output"); flag.z = G_define_flag(); flag.z->key = 'z'; flag.z->description = _("Create 3D output"); flag.z->guisection = _("Output"); flag.notab = G_define_flag(); flag.notab->key = 't'; flag.notab->description = _("Do not create attribute table"); flag.notab->guisection = _("Attributes"); flag.over = G_define_flag(); flag.over->key = 'o'; flag.over->description = _("Override dataset projection (use location's projection)"); flag.region = G_define_flag(); flag.region->key = 'r'; flag.region->guisection = _("Selection"); flag.region->description = _("Limit import to the current region"); flag.extend = G_define_flag(); flag.extend->key = 'e'; flag.extend->description = _("Extend location extents based on new dataset"); flag.tolower = G_define_flag(); flag.tolower->key = 'w'; flag.tolower->description = _("Change column names to lowercase characters"); flag.tolower->guisection = _("Attributes"); flag.no_import = G_define_flag(); flag.no_import->key = 'i'; flag.no_import->description = _("Create the location specified by the \"location\" parameter and exit." " Do not import the vector data."); /* The parser checks if the map already exists in current mapset, this is * wrong if location options is used, so we switch out the check and do it * in the module after the parser */ overwrite = G_check_overwrite(argc, argv); if (G_parser(argc, argv)) exit(EXIT_FAILURE); G_begin_polygon_area_calculations(); /* Used in geom() */ OGRRegisterAll(); /* list supported formats */ if (flag.formats->answer) { int iDriver; G_message(_("Available OGR Drivers:")); for (iDriver = 0; iDriver < OGRGetDriverCount(); iDriver++) { OGRSFDriverH poDriver = OGRGetDriver(iDriver); const char *pszRWFlag; if (OGR_Dr_TestCapability(poDriver, ODrCCreateDataSource)) pszRWFlag = "rw"; else pszRWFlag = "ro"; fprintf(stdout, " %s (%s): %s\n", OGR_Dr_GetName(poDriver), pszRWFlag, OGR_Dr_GetName(poDriver)); } exit(EXIT_SUCCESS); } if (param.dsn->answer == NULL) { G_fatal_error(_("Required parameter <%s> not set"), param.dsn->key); } min_area = atof(param.min_area->answer); snap = atof(param.snap->answer); type = Vect_option_to_types(param.type); ncnames = 0; if (param.cnames->answers) { i = 0; while (param.cnames->answers[i++]) { ncnames++; } } /* Open OGR DSN */ Ogr_ds = NULL; if (strlen(param.dsn->answer) > 0) Ogr_ds = OGROpen(param.dsn->answer, FALSE, NULL); if (Ogr_ds == NULL) G_fatal_error(_("Unable to open data source <%s>"), param.dsn->answer); /* Make a list of available layers */ navailable_layers = OGR_DS_GetLayerCount(Ogr_ds); available_layer_names = (char **)G_malloc(navailable_layers * sizeof(char *)); if (flag.list->answer || flag.tlist->answer) G_message(_("Data source <%s> (format '%s') contains %d layers:"), param.dsn->answer, OGR_Dr_GetName(OGR_DS_GetDriver(Ogr_ds)), navailable_layers); for (i = 0; i < navailable_layers; i++) { Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i); Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer); Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn); available_layer_names[i] = G_store((char *)OGR_FD_GetName(Ogr_featuredefn)); if (flag.tlist->answer) fprintf(stdout, "%s (%s)\n", available_layer_names[i], OGRGeometryTypeToName(Ogr_geom_type)); else if (flag.list->answer) fprintf(stdout, "%s\n", available_layer_names[i]); } if (flag.list->answer || flag.tlist->answer) { fflush(stdout); exit(EXIT_SUCCESS); } /* Make a list of layers to be imported */ if (param.layer->answer) { /* From option */ nlayers = 0; while (param.layer->answers[nlayers]) nlayers++; layer_names = (char **)G_malloc(nlayers * sizeof(char *)); layers = (int *)G_malloc(nlayers * sizeof(int)); for (i = 0; i < nlayers; i++) { layer_names[i] = G_store(param.layer->answers[i]); /* Find it in the source */ layers[i] = -1; for (j = 0; j < navailable_layers; j++) { if (strcmp(available_layer_names[j], layer_names[i]) == 0) { layers[i] = j; break; } } if (layers[i] == -1) G_fatal_error(_("Layer <%s> not available"), layer_names[i]); } } else { /* use list of all layers */ nlayers = navailable_layers; layer_names = available_layer_names; layers = (int *)G_malloc(nlayers * sizeof(int)); for (i = 0; i < nlayers; i++) layers[i] = i; } if (param.out->answer) { output = G_store(param.out->answer); } else { if (nlayers < 1) G_fatal_error(_("No OGR layers available")); output = G_store(layer_names[0]); G_message(_("All available OGR layers will be imported into vector map <%s>"), output); } if (!param.outloc->answer) { /* Check if the map exists */ if (G_find_vector2(output, G_mapset()) && !overwrite) G_fatal_error(_("Vector map <%s> already exists"), output); } /* Get first imported layer to use for extents and projection check */ Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layers[0]); if (flag.region->answer) { if (param.spat->answer) G_fatal_error(_("Select either the current region flag or the spatial option, not both")); G_get_window(&cur_wind); xmin = cur_wind.west; xmax = cur_wind.east; ymin = cur_wind.south; ymax = cur_wind.north; } if (param.spat->answer) { /* See as reference: gdal/ogr/ogr_capi_test.c */ /* cut out a piece of the map */ /* order: xmin,ymin,xmax,ymax */ arg_s_num = 0; i = 0; while (param.spat->answers[i]) { if (i == 0) xmin = atof(param.spat->answers[i]); if (i == 1) ymin = atof(param.spat->answers[i]); if (i == 2) xmax = atof(param.spat->answers[i]); if (i == 3) ymax = atof(param.spat->answers[i]); arg_s_num++; i++; } if (arg_s_num != 4) G_fatal_error(_("4 parameters required for 'spatial' parameter")); } if (param.spat->answer || flag.region->answer) { G_debug(2, "cut out with boundaries: xmin:%f ymin:%f xmax:%f ymax:%f", xmin, ymin, xmax, ymax); /* in theory this could be an irregular polygon */ poSpatialFilter = OGR_G_CreateGeometry(wkbPolygon); Ogr_oRing = OGR_G_CreateGeometry(wkbLinearRing); OGR_G_AddPoint(Ogr_oRing, xmin, ymin, 0.0); OGR_G_AddPoint(Ogr_oRing, xmin, ymax, 0.0); OGR_G_AddPoint(Ogr_oRing, xmax, ymax, 0.0); OGR_G_AddPoint(Ogr_oRing, xmax, ymin, 0.0); OGR_G_AddPoint(Ogr_oRing, xmin, ymin, 0.0); OGR_G_AddGeometryDirectly(poSpatialFilter, Ogr_oRing); OGR_L_SetSpatialFilter(Ogr_layer, poSpatialFilter); } if (param.where->answer) { /* select by attribute */ OGR_L_SetAttributeFilter(Ogr_layer, param.where->answer); } /* fetch boundaries */ if ((OGR_L_GetExtent(Ogr_layer, &oExt, 1)) == OGRERR_NONE) { G_get_window(&cellhd); cellhd.north = oExt.MaxY; cellhd.south = oExt.MinY; cellhd.west = oExt.MinX; cellhd.east = oExt.MaxX; cellhd.rows = 20; /* TODO - calculate useful values */ cellhd.cols = 20; cellhd.ns_res = (cellhd.north - cellhd.south) / cellhd.rows; cellhd.ew_res = (cellhd.east - cellhd.west) / cellhd.cols; } else { cellhd.north = 1.; cellhd.south = 0.; cellhd.west = 0.; cellhd.east = 1.; cellhd.top = 1.; cellhd.bottom = 1.; cellhd.rows = 1; cellhd.rows3 = 1; cellhd.cols = 1; cellhd.cols3 = 1; cellhd.depths = 1; cellhd.ns_res = 1.; cellhd.ns_res3 = 1.; cellhd.ew_res = 1.; cellhd.ew_res3 = 1.; cellhd.tb_res = 1.; } /* suppress boundary splitting ? */ if (flag.no_clean->answer) { split_distance = -1.; } else { split_distance = 0.; area_size = sqrt((cellhd.east - cellhd.west) * (cellhd.north - cellhd.south)); } /* Fetch input map projection in GRASS form. */ proj_info = NULL; proj_units = NULL; Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer); /* should not be freed later */ /* Do we need to create a new location? */ if (param.outloc->answer != NULL) { /* Convert projection information non-interactively as we can't * assume the user has a terminal open */ if (GPJ_osr_to_grass(&cellhd, &proj_info, &proj_units, Ogr_projection, 0) < 0) { G_fatal_error(_("Unable to convert input map projection to GRASS " "format; cannot create new location.")); } else { G_make_location(param.outloc->answer, &cellhd, proj_info, proj_units, NULL); G_message(_("Location <%s> created"), param.outloc->answer); } /* If the i flag is set, clean up? and exit here */ if(flag.no_import->answer) { exit(EXIT_SUCCESS); } } else { int err = 0; /* Projection only required for checking so convert non-interactively */ if (GPJ_osr_to_grass(&cellhd, &proj_info, &proj_units, Ogr_projection, 0) < 0) G_warning(_("Unable to convert input map projection information to " "GRASS format for checking")); /* Does the projection of the current location match the dataset? */ /* G_get_window seems to be unreliable if the location has been changed */ G__get_window(&loc_wind, "", "DEFAULT_WIND", "PERMANENT"); /* fetch LOCATION PROJ info */ if (loc_wind.proj != PROJECTION_XY) { loc_proj_info = G_get_projinfo(); loc_proj_units = G_get_projunits(); } if (flag.over->answer) { cellhd.proj = loc_wind.proj; cellhd.zone = loc_wind.zone; G_message(_("Over-riding projection check")); } else if (loc_wind.proj != cellhd.proj || (err = G_compare_projections(loc_proj_info, loc_proj_units, proj_info, proj_units)) != TRUE) { int i_value; strcpy(error_msg, _("Projection of dataset does not" " appear to match current location.\n\n")); /* TODO: output this info sorted by key: */ if (loc_wind.proj != cellhd.proj || err != -2) { if (loc_proj_info != NULL) { strcat(error_msg, _("GRASS LOCATION PROJ_INFO is:\n")); for (i_value = 0; i_value < loc_proj_info->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", loc_proj_info->key[i_value], loc_proj_info->value[i_value]); strcat(error_msg, "\n"); } if (proj_info != NULL) { strcat(error_msg, _("Import dataset PROJ_INFO is:\n")); for (i_value = 0; i_value < proj_info->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", proj_info->key[i_value], proj_info->value[i_value]); } else { strcat(error_msg, _("Import dataset PROJ_INFO is:\n")); if (cellhd.proj == PROJECTION_XY) sprintf(error_msg + strlen(error_msg), "Dataset proj = %d (unreferenced/unknown)\n", cellhd.proj); else if (cellhd.proj == PROJECTION_LL) sprintf(error_msg + strlen(error_msg), "Dataset proj = %d (lat/long)\n", cellhd.proj); else if (cellhd.proj == PROJECTION_UTM) sprintf(error_msg + strlen(error_msg), "Dataset proj = %d (UTM), zone = %d\n", cellhd.proj, cellhd.zone); else if (cellhd.proj == PROJECTION_SP) sprintf(error_msg + strlen(error_msg), "Dataset proj = %d (State Plane), zone = %d\n", cellhd.proj, cellhd.zone); else sprintf(error_msg + strlen(error_msg), "Dataset proj = %d (unknown), zone = %d\n", cellhd.proj, cellhd.zone); } } else { if (loc_proj_units != NULL) { strcat(error_msg, "GRASS LOCATION PROJ_UNITS is:\n"); for (i_value = 0; i_value < loc_proj_units->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", loc_proj_units->key[i_value], loc_proj_units->value[i_value]); strcat(error_msg, "\n"); } if (proj_units != NULL) { strcat(error_msg, "Import dataset PROJ_UNITS is:\n"); for (i_value = 0; i_value < proj_units->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", proj_units->key[i_value], proj_units->value[i_value]); } } sprintf(error_msg + strlen(error_msg), _("\nYou can use the -o flag to %s to override this projection check.\n"), G_program_name()); strcat(error_msg, _("Consider generating a new location with 'location' parameter" " from input data set.\n")); G_fatal_error(error_msg); } else { G_message(_("Projection of input dataset and current location " "appear to match")); } } db_init_string(&sql); db_init_string(&strval); /* open output vector */ /* strip any @mapset from vector output name */ G_find_vector(output, G_mapset()); Vect_open_new(&Map, output, flag.z->answer != 0); Out = ⤅ n_polygon_boundaries = 0; if (!flag.no_clean->answer) { /* check if we need a tmp vector */ /* estimate distance for boundary splitting --> */ for (layer = 0; layer < nlayers; layer++) { layer_id = layers[layer]; Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id); Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer); n_features = feature_count = 0; n_features = OGR_L_GetFeatureCount(Ogr_layer, 1); OGR_L_ResetReading(Ogr_layer); /* count polygons and isles */ G_message(_("Counting polygons for %d features (OGR layer <%s>)..."), n_features, layer_names[layer]); while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) { G_percent(feature_count++, n_features, 1); /* show something happens */ /* Geometry */ Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature); if (Ogr_geometry != NULL) { poly_count(Ogr_geometry, (type & GV_BOUNDARY)); } OGR_F_Destroy(Ogr_feature); } } G_debug(1, "n polygon boundaries: %d", n_polygon_boundaries); if (n_polygon_boundaries > 50) { split_distance = area_size / log(n_polygon_boundaries); /* divisor is the handle: increase divisor to decrease split_distance */ split_distance = split_distance / 5.; G_debug(1, "root of area size: %f", area_size); G_verbose_message(_("Boundary splitting distance in map units: %G"), split_distance); } /* <-- estimate distance for boundary splitting */ use_tmp_vect = n_polygon_boundaries > 0; if (use_tmp_vect) { /* open temporary vector, do the work in the temporary vector * at the end copy alive lines to output vector * in case of polygons this reduces the coor file size by a factor of 2 to 5 * only needed when cleaning polygons */ sprintf(tempvect, "%s_tmp", output); G_verbose_message(_("Using temporary vector <%s>"), tempvect); Vect_open_new(&Tmp, tempvect, flag.z->answer != 0); Out = &Tmp; } } Vect_hist_command(&Map); /* Points and lines are written immediately with categories. Boundaries of polygons are * written to the vector then cleaned and centroids are calculated for all areas in cleaan vector. * Then second pass through finds all centroids in each polygon feature and adds its category * to the centroid. The result is that one centroids may have 0, 1 ore more categories * of one ore more (more input layers) fields. */ with_z = 0; for (layer = 0; layer < nlayers; layer++) { layer_id = layers[layer]; Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id); Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer); /* Add DB link */ if (!flag.notab->answer) { char *cat_col_name = GV_KEY_COLUMN; if (nlayers == 1) { /* one layer only */ Fi = Vect_default_field_info(&Map, layer + 1, NULL, GV_1TABLE); } else { Fi = Vect_default_field_info(&Map, layer + 1, NULL, GV_MTABLE); } if (ncnames > 0) { cat_col_name = param.cnames->answers[0]; } Vect_map_add_dblink(&Map, layer + 1, layer_names[layer], Fi->table, cat_col_name, Fi->database, Fi->driver); ncols = OGR_FD_GetFieldCount(Ogr_featuredefn); G_debug(2, "%d columns", ncols); /* Create table */ sprintf(buf, "create table %s (%s integer", Fi->table, cat_col_name); db_set_string(&sql, buf); for (i = 0; i < ncols; i++) { Ogr_field = OGR_FD_GetFieldDefn(Ogr_featuredefn, i); Ogr_ftype = OGR_Fld_GetType(Ogr_field); G_debug(3, "Ogr_ftype: %i", Ogr_ftype); /* look up below */ if (i < ncnames - 1) { Ogr_fieldname = G_store(param.cnames->answers[i + 1]); } else { /* Change column names to [A-Za-z][A-Za-z0-9_]* */ Ogr_fieldname = G_store(OGR_Fld_GetNameRef(Ogr_field)); G_debug(3, "Ogr_fieldname: '%s'", Ogr_fieldname); G_str_to_sql(Ogr_fieldname); G_debug(3, "Ogr_fieldname: '%s'", Ogr_fieldname); } /* avoid that we get the 'cat' column twice */ if (strcmp(Ogr_fieldname, GV_KEY_COLUMN) == 0) { sprintf(namebuf, "%s_", Ogr_fieldname); Ogr_fieldname = G_store(namebuf); } /* captial column names are a pain in SQL */ if (flag.tolower->answer) G_str_to_lower(Ogr_fieldname); if (strcmp(OGR_Fld_GetNameRef(Ogr_field), Ogr_fieldname) != 0) { G_warning(_("Column name changed: '%s' -> '%s'"), OGR_Fld_GetNameRef(Ogr_field), Ogr_fieldname); } /** Simple 32bit integer OFTInteger = 0 **/ /** List of 32bit integers OFTIntegerList = 1 **/ /** Double Precision floating point OFTReal = 2 **/ /** List of doubles OFTRealList = 3 **/ /** String of ASCII chars OFTString = 4 **/ /** Array of strings OFTStringList = 5 **/ /** Double byte string (unsupported) OFTWideString = 6 **/ /** List of wide strings (unsupported) OFTWideStringList = 7 **/ /** Raw Binary data (unsupported) OFTBinary = 8 **/ /** OFTDate = 9 **/ /** OFTTime = 10 **/ /** OFTDateTime = 11 **/ if (Ogr_ftype == OFTInteger) { sprintf(buf, ", %s integer", Ogr_fieldname); } else if (Ogr_ftype == OFTIntegerList) { /* hack: treat as string */ sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname, OFTIntegerListlength); G_warning(_("Writing column <%s> with fixed length %d chars (may be truncated)"), Ogr_fieldname, OFTIntegerListlength); } else if (Ogr_ftype == OFTReal) { sprintf(buf, ", %s double precision", Ogr_fieldname); #if GDAL_VERSION_NUM >= 1320 } else if (Ogr_ftype == OFTDate) { sprintf(buf, ", %s date", Ogr_fieldname); } else if (Ogr_ftype == OFTTime) { sprintf(buf, ", %s time", Ogr_fieldname); } else if (Ogr_ftype == OFTDateTime) { sprintf(buf, ", %s datetime", Ogr_fieldname); #endif } else if (Ogr_ftype == OFTString) { int fwidth; fwidth = OGR_Fld_GetWidth(Ogr_field); /* TODO: read all records first and find the longest string length */ if (fwidth == 0) { G_warning(_("Width for column %s set to 255 (was not specified by OGR), " "some strings may be truncated!"), Ogr_fieldname); fwidth = 255; } sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname, fwidth); } else if (Ogr_ftype == OFTStringList) { /* hack: treat as string */ sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname, OFTIntegerListlength); G_warning(_("Writing column %s with fixed length %d chars (may be truncated)"), Ogr_fieldname, OFTIntegerListlength); } else { G_warning(_("Column type not supported (%s)"), Ogr_fieldname); buf[0] = 0; } db_append_string(&sql, buf); G_free(Ogr_fieldname); } db_append_string(&sql, ")"); G_debug(3, db_get_string(&sql)); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Map)); if (driver == NULL) { G_fatal_error(_("Unable open database <%s> by driver <%s>"), Vect_subst_var(Fi->database, &Map), Fi->driver); } if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql)); } if (db_create_index2(driver, Fi->table, cat_col_name) != DB_OK) G_warning(_("Unable to create index for table <%s>, key <%s>"), Fi->table, cat_col_name); 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); } /* Import feature */ cat = 1; nogeom = 0; OGR_L_ResetReading(Ogr_layer); n_features = feature_count = 0; n_features = OGR_L_GetFeatureCount(Ogr_layer, 1); G_important_message(_("Importing %d features (OGR layer <%s>)..."), n_features, layer_names[layer]); while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) { G_percent(feature_count++, n_features, 1); /* show something happens */ /* Geometry */ Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature); if (Ogr_geometry == NULL) { nogeom++; } else { dim = OGR_G_GetCoordinateDimension(Ogr_geometry); if (dim > 2) with_z = 1; geom(Ogr_geometry, Out, layer + 1, cat, min_area, type, flag.no_clean->answer); } /* Attributes */ if (!flag.notab->answer) { sprintf(buf, "insert into %s values ( %d", Fi->table, cat); db_set_string(&sql, buf); for (i = 0; i < ncols; i++) { Ogr_field = OGR_FD_GetFieldDefn(Ogr_featuredefn, i); Ogr_ftype = OGR_Fld_GetType(Ogr_field); if (OGR_F_IsFieldSet(Ogr_feature, i)) { if (Ogr_ftype == OFTInteger || Ogr_ftype == OFTReal) { sprintf(buf, ", %s", OGR_F_GetFieldAsString(Ogr_feature, i)); #if GDAL_VERSION_NUM >= 1320 /* should we use OGR_F_GetFieldAsDateTime() here ? */ } else if (Ogr_ftype == OFTDate || Ogr_ftype == OFTTime || Ogr_ftype == OFTDateTime) { char *newbuf; db_set_string(&strval, (char *) OGR_F_GetFieldAsString(Ogr_feature, i)); db_double_quote_string(&strval); sprintf(buf, ", '%s'", db_get_string(&strval)); newbuf = G_str_replace(buf, "/", "-"); /* fix 2001/10/21 to 2001-10-21 */ sprintf(buf, "%s", newbuf); #endif } else if (Ogr_ftype == OFTString || Ogr_ftype == OFTIntegerList) { db_set_string(&strval, (char *) OGR_F_GetFieldAsString(Ogr_feature, i)); db_double_quote_string(&strval); sprintf(buf, ", '%s'", db_get_string(&strval)); } } else { /* G_warning (_("Column value not set" )); */ if (Ogr_ftype == OFTInteger || Ogr_ftype == OFTReal) { sprintf(buf, ", NULL"); #if GDAL_VERSION_NUM >= 1320 } else if (Ogr_ftype == OFTString || Ogr_ftype == OFTIntegerList || Ogr_ftype == OFTDate) { #else } else if (Ogr_ftype == OFTString || Ogr_ftype == OFTIntegerList) { #endif sprintf(buf, ", ''"); } } db_append_string(&sql, buf); } db_append_string(&sql, " )"); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Cannot insert new row: %s"), db_get_string(&sql)); } } OGR_F_Destroy(Ogr_feature); cat++; } G_percent(1, 1, 1); /* finish it */ if (!flag.notab->answer) { db_commit_transaction(driver); db_close_database_shutdown_driver(driver); } if (nogeom > 0) G_warning(_("%d %s without geometry"), nogeom, nogeom == 1 ? "feature" : "features"); } separator = "-----------------------------------------------------"; G_message("%s", separator); if (use_tmp_vect) { /* TODO: is it necessary to build here? probably not, consumes time */ /* GV_BUILD_BASE is sufficient to toggle boundary cleaning */ Vect_build_partial(&Tmp, GV_BUILD_BASE); } if (use_tmp_vect && !flag.no_clean->answer && Vect_get_num_primitives(Out, GV_BOUNDARY) > 0) { int ret, centr, ncentr, otype, n_overlaps, n_nocat; CENTR *Centr; struct spatial_index si; double x, y, total_area, overlap_area, nocat_area; struct bound_box box; struct line_pnts *Points; int nmodif; Points = Vect_new_line_struct(); G_message("%s", separator); G_warning(_("Cleaning polygons, result is not guaranteed!")); if (snap >= 0) { G_message("%s", separator); G_message(_("Snapping boundaries (threshold = %.3e)..."), snap); Vect_snap_lines(&Tmp, GV_BOUNDARY, snap, NULL); } /* It is not to clean to snap centroids, but I have seen data with 2 duplicate polygons * (as far as decimal places were printed) and centroids were not identical */ /* Disabled, because overlapping polygons result in many duplicate centroids anyway */ /* fprintf ( stderr, separator ); fprintf ( stderr, "Snap centroids (threshold 0.000001):\n" ); Vect_snap_lines ( &Map, GV_CENTROID, 0.000001, NULL, stderr ); */ G_message("%s", separator); G_message(_("Breaking polygons...")); Vect_break_polygons(&Tmp, GV_BOUNDARY, NULL); /* It is important to remove also duplicate centroids in case of duplicate input polygons */ G_message("%s", separator); G_message(_("Removing duplicates...")); Vect_remove_duplicates(&Tmp, GV_BOUNDARY | GV_CENTROID, NULL); /* in non-pathological cases, the bulk of the cleaning is now done */ /* Vect_clean_small_angles_at_nodes() can change the geometry so that new intersections * are created. We must call Vect_break_lines(), Vect_remove_duplicates() * and Vect_clean_small_angles_at_nodes() until no more small angles are found */ do { G_message("%s", separator); G_message(_("Breaking boundaries...")); Vect_break_lines(&Tmp, GV_BOUNDARY, NULL); G_message("%s", separator); G_message(_("Removing duplicates...")); Vect_remove_duplicates(&Tmp, GV_BOUNDARY, NULL); G_message("%s", separator); G_message(_("Cleaning boundaries at nodes...")); nmodif = Vect_clean_small_angles_at_nodes(&Tmp, GV_BOUNDARY, NULL); } while (nmodif > 0); /* merge boundaries */ G_message("%s", separator); G_message(_("Merging boundaries...")); Vect_merge_lines(&Tmp, GV_BOUNDARY, NULL, NULL); G_message("%s", separator); if (type & GV_BOUNDARY) { /* that means lines were converted to boundaries */ G_message(_("Changing boundary dangles to lines...")); Vect_chtype_dangles(&Tmp, -1.0, NULL); } else { G_message(_("Removing dangles...")); Vect_remove_dangles(&Tmp, GV_BOUNDARY, -1.0, NULL); } G_message("%s", separator); if (type & GV_BOUNDARY) { G_message(_("Changing boundary bridges to lines...")); Vect_chtype_bridges(&Tmp, NULL); } else { G_message(_("Removing bridges...")); Vect_remove_bridges(&Tmp, NULL); } /* Boundaries are hopefully clean, build areas */ G_message("%s", separator); Vect_build_partial(&Tmp, GV_BUILD_ATTACH_ISLES); /* Calculate new centroids for all areas, centroids have the same id as area */ ncentr = Vect_get_num_areas(&Tmp); G_debug(3, "%d centroids/areas", ncentr); Centr = (CENTR *) G_calloc(ncentr + 1, sizeof(CENTR)); Vect_spatial_index_init(&si, 0); for (centr = 1; centr <= ncentr; centr++) { Centr[centr].valid = 0; Centr[centr].cats = Vect_new_cats_struct(); ret = Vect_get_point_in_area(&Tmp, centr, &x, &y); if (ret < 0) { G_warning(_("Unable to calculate area centroid")); continue; } Centr[centr].x = x; Centr[centr].y = y; Centr[centr].valid = 1; box.N = box.S = y; box.E = box.W = x; box.T = box.B = 0; Vect_spatial_index_add_item(&si, centr, &box); } /* Go through all layers and find centroids for each polygon */ for (layer = 0; layer < nlayers; layer++) { G_message("%s", separator); G_message(_("Finding centroids for OGR layer <%s>..."), layer_names[layer]); layer_id = layers[layer]; Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id); n_features = OGR_L_GetFeatureCount(Ogr_layer, 1); OGR_L_ResetReading(Ogr_layer); cat = 0; /* field = layer + 1 */ G_percent(cat, n_features, 2); while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) { cat++; G_percent(cat, n_features, 2); /* Geometry */ Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature); if (Ogr_geometry != NULL) { centroid(Ogr_geometry, Centr, &si, layer + 1, cat, min_area, type); } OGR_F_Destroy(Ogr_feature); } } /* Write centroids */ G_message("%s", separator); G_message(_("Writing centroids...")); n_overlaps = n_nocat = 0; total_area = overlap_area = nocat_area = 0.0; for (centr = 1; centr <= ncentr; centr++) { double area; G_percent(centr, ncentr, 2); area = Vect_get_area_area(&Tmp, centr); total_area += area; if (!(Centr[centr].valid)) { continue; } if (Centr[centr].cats->n_cats == 0) { nocat_area += area; n_nocat++; continue; } if (Centr[centr].cats->n_cats > 1) { Vect_cat_set(Centr[centr].cats, nlayers + 1, Centr[centr].cats->n_cats); overlap_area += area; n_overlaps++; } Vect_reset_line(Points); Vect_append_point(Points, Centr[centr].x, Centr[centr].y, 0.0); if (type & GV_POINT) otype = GV_POINT; else otype = GV_CENTROID; Vect_write_line(&Tmp, otype, Points, Centr[centr].cats); } if (Centr) G_free(Centr); Vect_spatial_index_destroy(&si); if (n_overlaps > 0) { G_warning(_("%d areas represent more (overlapping) features, because polygons overlap " "in input layer(s). Such areas are linked to more than 1 row in attribute table. " "The number of features for those areas is stored as category in layer %d"), n_overlaps, nlayers + 1); } G_message("%s", separator); Vect_hist_write(&Map, separator); Vect_hist_write(&Map, "\n"); sprintf(buf, _("%d input polygons\n"), n_polygons); G_message(_("%d input polygons"), n_polygons); Vect_hist_write(&Map, buf); sprintf(buf, _("Total area: %G (%d areas)\n"), total_area, ncentr); G_message(_("Total area: %G (%d areas)"), total_area, ncentr); Vect_hist_write(&Map, buf); sprintf(buf, _("Overlapping area: %G (%d areas)\n"), overlap_area, n_overlaps); G_message(_("Overlapping area: %G (%d areas)"), overlap_area, n_overlaps); Vect_hist_write(&Map, buf); sprintf(buf, _("Area without category: %G (%d areas)\n"), nocat_area, n_nocat); G_message(_("Area without category: %G (%d areas)"), nocat_area, n_nocat); Vect_hist_write(&Map, buf); G_message("%s", separator); } /* needed? * OGR_DS_Destroy( Ogr_ds ); */ if (use_tmp_vect) { /* Copy temporary vector to output vector */ Vect_copy_map_lines(&Tmp, &Map); /* release memory occupied by topo, we may need that memory for main output */ Vect_set_release_support(&Tmp); Vect_close(&Tmp); Vect_delete(tempvect); } Vect_build(&Map); Vect_close(&Map); /* -------------------------------------------------------------------- */ /* Extend current window based on dataset. */ /* -------------------------------------------------------------------- */ if (flag.extend->answer) { G_get_default_window(&loc_wind); loc_wind.north = MAX(loc_wind.north, cellhd.north); loc_wind.south = MIN(loc_wind.south, cellhd.south); loc_wind.west = MIN(loc_wind.west, cellhd.west); loc_wind.east = MAX(loc_wind.east, cellhd.east); loc_wind.rows = (int)ceil((loc_wind.north - loc_wind.south) / loc_wind.ns_res); loc_wind.south = loc_wind.north - loc_wind.rows * loc_wind.ns_res; loc_wind.cols = (int)ceil((loc_wind.east - loc_wind.west) / loc_wind.ew_res); loc_wind.east = loc_wind.west + loc_wind.cols * loc_wind.ew_res; G__put_window(&loc_wind, "../PERMANENT", "DEFAULT_WIND"); } if (with_z && !flag.z->answer) G_warning(_("Input data contains 3D features. Created vector is 2D only, " "use -z flag to import 3D vector.")); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct Map_info In, Out; static struct line_pnts *Points; struct line_cats *Cats; struct GModule *module; /* GRASS module for parsing arguments */ struct Option *map_in, *map_out; struct Option *method_opt, *afield_opt, *nfield_opt, *abcol, *afcol, *ncol; struct Flag *add_f; int with_z; int afield, nfield, mask_type; dglGraph_s *graph; int *component, nnodes, type, i, nlines, components, max_cat; char buf[2000], *covered; char *desc; /* Attribute table */ dbString sql; dbDriver *driver; struct field_info *Fi; /* initialize GIS environment */ G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */ /* initialize module */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("network")); G_add_keyword(_("components")); module->description = _("Computes strongly and weakly connected components in the network."); /* Define the different options as defined in gis.h */ map_in = G_define_standard_option(G_OPT_V_INPUT); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "arc_layer"; afield_opt->answer = "1"; afield_opt->label = _("Arc layer"); afield_opt->guisection = _("Cost"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "node_layer"; nfield_opt->answer = "2"; nfield_opt->label = _("Node layer"); nfield_opt->guisection = _("Cost"); afcol = G_define_standard_option(G_OPT_DB_COLUMN); afcol->key = "arc_column"; afcol->required = NO; afcol->description = _("Arc forward/both direction(s) cost column (number)"); afcol->guisection = _("Cost"); abcol = G_define_standard_option(G_OPT_DB_COLUMN); abcol->key = "arc_backward_column"; abcol->required = NO; abcol->description = _("Arc backward direction cost column (number)"); abcol->guisection = _("Cost"); ncol = G_define_option(); ncol->key = "node_column"; ncol->type = TYPE_STRING; ncol->required = NO; ncol->description = _("Node cost column (number)"); ncol->guisection = _("Cost"); map_out = G_define_standard_option(G_OPT_V_OUTPUT); method_opt = G_define_option(); method_opt->key = "method"; method_opt->type = TYPE_STRING; method_opt->required = YES; method_opt->multiple = NO; method_opt->options = "weak,strong"; desc = NULL; G_asprintf(&desc, "weak;%s;strong;%s", _("Weakly connected components"), _("Strongly connected components")); method_opt->descriptions = desc; method_opt->description = _("Type of components"); add_f = G_define_flag(); add_f->key = 'a'; add_f->description = _("Add points on nodes"); /* options and flags parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* TODO: make an option for this */ mask_type = GV_LINE | GV_BOUNDARY; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Vect_check_input_output_name(map_in->answer, map_out->answer, G_FATAL_EXIT); Vect_set_open_level(2); if (1 > Vect_open_old(&In, map_in->answer, "")) G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer); with_z = Vect_is_3d(&In); if (0 > Vect_open_new(&Out, map_out->answer, with_z)) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer); } /* parse filter option and select appropriate lines */ afield = Vect_get_field_number(&In, afield_opt->answer); nfield = Vect_get_field_number(&In, nfield_opt->answer); if (0 != Vect_net_build_graph(&In, mask_type, afield, nfield, afcol->answer, abcol->answer, ncol->answer, 0, 2)) G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In)); graph = Vect_net_get_graph(&In); nnodes = Vect_get_num_nodes(&In); component = (int *)G_calloc(nnodes + 1, sizeof(int)); covered = (char *)G_calloc(nnodes + 1, sizeof(char)); if (!component || !covered) { G_fatal_error(_("Out of memory")); exit(EXIT_FAILURE); } /* Create table */ Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); db_init_string(&sql); driver = db_start_driver_open_database(Fi->driver, Fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); sprintf(buf, "create table %s ( cat integer, comp integer)", Fi->table); db_set_string(&sql, buf); G_debug(2, "%s", db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database_shutdown_driver(driver); 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(_("Cannot create index")); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); if (method_opt->answer[0] == 'w') { G_message(_("Computing weakly connected components...")); components = NetA_weakly_connected_components(graph, component); } else { G_message(_("Computing strongly connected components...")); components = NetA_strongly_connected_components(graph, component); } G_debug(3, "Components: %d", components); G_message(_("Writing output...")); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); nlines = Vect_get_num_lines(&In); max_cat = 1; G_percent(0, nlines, 4); for (i = 1; i <= nlines; i++) { int comp, cat; G_percent(i, nlines, 4); type = Vect_read_line(&In, Points, Cats, i); if (!Vect_cat_get(Cats, afield, &cat)) continue; if (type == GV_LINE || type == GV_BOUNDARY) { int node1, node2; Vect_get_line_nodes(&In, i, &node1, &node2); if (component[node1] == component[node2]) { comp = component[node1]; } else { continue; } } else if (type == GV_POINT) { int node; /* Vect_get_line_nodes(&In, i, &node, NULL); */ node = Vect_find_node(&In, Points->x[0], Points->y[0], Points->z[0], 0, 0); if (!node) continue; comp = component[node]; covered[node] = 1; } else continue; cat = max_cat++; Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, type, Points, Cats); insert_new_record(driver, Fi, &sql, cat, comp); } /*add points on nodes not covered by any point in the network */ if (add_f->answer) { for (i = 1; i <= nnodes; i++) if (!covered[i]) { Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, max_cat); NetA_add_point_on_node(&In, &Out, i, Cats); insert_new_record(driver, Fi, &sql, max_cat++, component[i]); } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); Vect_close(&In); Vect_build(&Out); Vect_close(&Out); G_done_msg(_("Found %d components."), components); exit(EXIT_SUCCESS); }
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); }
int main(int argc, char *argv[]) { int npmin; int ii; double x_orig, y_orig, dnorm, deltx, delty, xm, ym; char dmaxchar[200]; char dminchar[200]; struct quaddata *data; struct multfunc *functions; struct multtree *tree; int open_check, with_z; char buf[1024]; struct GModule *module; struct { struct Option *input, *field, *zcol, *wheresql, *scol, *elev, *slope, *aspect, *pcurv, *tcurv, *mcurv, *treefile, *overfile, *maskmap, *dmin, *dmax, *zmult, *fi, *rsm, *segmax, *npmin, *cvdev, *devi, *theta, *scalex; } parm; struct { struct Flag *deriv, *cprght, *cv; } flag; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("surface")); G_add_keyword(_("interpolation")); G_add_keyword(_("3D")); module->label = _("Performs surface interpolation from vector points map by splines."); module->description = _("Spatial approximation and topographic analysis from given " "point or isoline data in vector format to floating point " "raster format using regularized spline with tension."); flag.cv = G_define_flag(); flag.cv->key = 'c'; flag.cv->description = _("Perform cross-validation procedure without raster approximation"); flag.cv->guisection = _("Parameters"); flag.cprght = G_define_flag(); flag.cprght->key = 't'; flag.cprght->description = _("Use scale dependent tension"); flag.cprght->guisection = _("Parameters"); flag.deriv = G_define_flag(); flag.deriv->key = 'd'; flag.deriv->description = _("Output partial derivatives instead of topographic parameters"); flag.deriv->guisection = _("Outputs"); parm.input = G_define_standard_option(G_OPT_V_INPUT); parm.field = G_define_standard_option(G_OPT_V_FIELD); parm.field->answer = "1"; parm.field->guisection = _("Selection"); parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN); parm.zcol->key = "zcolumn"; parm.zcol->required = NO; parm.zcol->label = _("Name of the attribute column with values to be used for approximation"); parm.zcol->description = _("If not given and input is 2D vector map then category values are used. " "If input is 3D vector map then z-coordinates are used."); parm.zcol->guisection = _("Parameters"); parm.wheresql = G_define_standard_option(G_OPT_DB_WHERE); parm.wheresql->guisection = _("Selection"); parm.elev = G_define_standard_option(G_OPT_R_OUTPUT); parm.elev->key = "elevation"; parm.elev->required = NO; parm.elev->description = _("Name for output surface elevation raster map"); parm.elev->guisection = _("Outputs"); parm.slope = G_define_standard_option(G_OPT_R_OUTPUT); parm.slope->key = "slope"; parm.slope->required = NO; parm.slope->description = _("Name for output slope raster map"); parm.slope->guisection = _("Outputs"); parm.aspect = G_define_standard_option(G_OPT_R_OUTPUT); parm.aspect->key = "aspect"; parm.aspect->required = NO; parm.aspect->description = _("Name for output aspect raster map"); parm.aspect->guisection = _("Outputs"); parm.pcurv = G_define_standard_option(G_OPT_R_OUTPUT); parm.pcurv->key = "pcurvature"; parm.pcurv->required = NO; parm.pcurv->description = _("Name for output profile curvature raster map"); parm.pcurv->guisection = _("Outputs"); parm.tcurv = G_define_standard_option(G_OPT_R_OUTPUT); parm.tcurv->key = "tcurvature"; parm.tcurv->required = NO; parm.tcurv->description = _("Name for output tangential curvature raster map"); parm.tcurv->guisection = _("Outputs"); parm.mcurv = G_define_standard_option(G_OPT_R_OUTPUT); parm.mcurv->key = "mcurvature"; parm.mcurv->required = NO; parm.mcurv->description = _("Name for output mean curvature raster map"); parm.mcurv->guisection = _("Outputs"); parm.devi = G_define_standard_option(G_OPT_V_OUTPUT); parm.devi->key = "deviations"; parm.devi->required = NO; parm.devi->description = _("Name for output deviations vector point map"); parm.devi->guisection = _("Outputs"); parm.cvdev = G_define_standard_option(G_OPT_V_OUTPUT); parm.cvdev->key = "cvdev"; parm.cvdev->required = NO; parm.cvdev->description = _("Name for output cross-validation errors vector point map"); parm.cvdev->guisection = _("Outputs"); parm.treefile = G_define_standard_option(G_OPT_V_OUTPUT); parm.treefile->key = "treeseg"; parm.treefile->required = NO; parm.treefile->description = _("Name for output vector map showing quadtree segmentation"); parm.treefile->guisection = _("Outputs"); parm.overfile = G_define_standard_option(G_OPT_V_OUTPUT); parm.overfile->key = "overwin"; parm.overfile->required = NO; parm.overfile->description = _("Name for output vector map showing overlapping windows"); parm.overfile->guisection = _("Outputs"); parm.maskmap = G_define_standard_option(G_OPT_R_INPUT); parm.maskmap->key = "mask"; parm.maskmap->required = NO; parm.maskmap->description = _("Name of raster map used as mask"); parm.maskmap->guisection = _("Parameters"); parm.fi = G_define_option(); parm.fi->key = "tension"; parm.fi->type = TYPE_DOUBLE; parm.fi->answer = TENSION; parm.fi->required = NO; parm.fi->description = _("Tension parameter"); parm.fi->guisection = _("Parameters"); parm.rsm = G_define_option(); parm.rsm->key = "smooth"; parm.rsm->type = TYPE_DOUBLE; parm.rsm->required = NO; parm.rsm->description = _("Smoothing parameter"); parm.rsm->guisection = _("Parameters"); parm.scol = G_define_option(); parm.scol->key = "smooth_column"; parm.scol->type = TYPE_STRING; parm.scol->required = NO; parm.scol->description = _("Name of the attribute column with smoothing parameters"); parm.scol->guisection = _("Parameters"); parm.segmax = G_define_option(); parm.segmax->key = "segmax"; parm.segmax->type = TYPE_INTEGER; parm.segmax->answer = MAXSEGM; parm.segmax->required = NO; parm.segmax->description = _("Maximum number of points in a segment"); parm.segmax->guisection = _("Parameters"); parm.npmin = G_define_option(); parm.npmin->key = "npmin"; parm.npmin->type = TYPE_INTEGER; parm.npmin->answer = MINPOINTS; parm.npmin->required = NO; parm.npmin->description = _("Minimum number of points for approximation in a segment (>segmax)"); parm.npmin->guisection = _("Parameters"); parm.dmin = G_define_option(); parm.dmin->key = "dmin"; parm.dmin->type = TYPE_DOUBLE; parm.dmin->required = NO; parm.dmin->description = _("Minimum distance between points (to remove almost identical points)"); parm.dmin->guisection = _("Parameters"); parm.dmax = G_define_option(); parm.dmax->key = "dmax"; parm.dmax->type = TYPE_DOUBLE; parm.dmax->required = NO; parm.dmax->description = _("Maximum distance between points on isoline (to insert additional points)"); parm.dmax->guisection = _("Parameters"); parm.zmult = G_define_option(); parm.zmult->key = "zscale"; parm.zmult->type = TYPE_DOUBLE; parm.zmult->answer = ZMULT; parm.zmult->required = NO; parm.zmult->description = _("Conversion factor for values used for approximation"); parm.zmult->guisection = _("Parameters"); parm.theta = G_define_option(); parm.theta->key = "theta"; parm.theta->type = TYPE_DOUBLE; parm.theta->required = NO; parm.theta->description = _("Anisotropy angle (in degrees counterclockwise from East)"); parm.theta->guisection = _("Parameters"); parm.scalex = G_define_option(); parm.scalex->key = "scalex"; parm.scalex->type = TYPE_DOUBLE; parm.scalex->required = NO; parm.scalex->description = _("Anisotropy scaling factor"); parm.scalex->guisection = _("Parameters"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); G_get_set_window(&cellhd); ew_res = cellhd.ew_res; ns_res = cellhd.ns_res; n_cols = cellhd.cols; n_rows = cellhd.rows; x_orig = cellhd.west; y_orig = cellhd.south; xm = cellhd.east; ym = cellhd.north; if (ew_res < ns_res) dmin = ew_res / 2; else dmin = ns_res / 2; disk = n_rows * n_cols * sizeof(int); sdisk = n_rows * n_cols * sizeof(short int); sprintf(dmaxchar, "%f", dmin * 5); sprintf(dminchar, "%f", dmin); if (!parm.dmin->answer) { parm.dmin->answer = G_store(dminchar); parm.dmin->answers = (char **) G_malloc(2 * sizeof(char *)); parm.dmin->answers[0] = G_store(dminchar); parm.dmin->answers[1] = NULL; } if (!parm.dmax->answer) { parm.dmax->answer = G_store(dmaxchar); parm.dmax->answers = (char **) G_malloc(2 * sizeof(char *)); parm.dmax->answers[0] = G_store(dmaxchar); parm.dmax->answers[1] = NULL; } input = parm.input->answer; zcol = parm.zcol->answer; scol = parm.scol->answer; wheresql = parm.wheresql->answer; maskmap = parm.maskmap->answer; elev = parm.elev->answer; devi = parm.devi->answer; cvdev = parm.cvdev->answer; slope = parm.slope->answer; aspect = parm.aspect->answer; pcurv = parm.pcurv->answer; tcurv = parm.tcurv->answer; mcurv = parm.mcurv->answer; treefile = parm.treefile->answer; overfile = parm.overfile->answer; if (devi) { if (Vect_legal_filename(devi) == -1) G_fatal_error(_("Output vector map name <%s> is not valid map name"), devi); } if (cvdev) { if (Vect_legal_filename(cvdev) == -1) G_fatal_error(_("Output vector map name <%s> is not valid map name"), cvdev); } if (treefile) { if (Vect_legal_filename(treefile) == -1) G_fatal_error(_("Output vector map name <%s> is not valid map name"), treefile); } if (overfile) { if (Vect_legal_filename(overfile) == -1) G_fatal_error(_("Output vector map name <%s> is not valid map name"), overfile); } /* if (treefile) Vect_check_input_output_name(input, treefile, G_FATAL_EXIT); if (overfile) Vect_check_input_output_name(input, overfile, G_FATAL_EXIT); */ if ((elev == NULL) && (pcurv == NULL) && (tcurv == NULL) && (mcurv == NULL) && (slope == NULL) && (aspect == NULL) && (devi == NULL) && (cvdev == NULL)) G_warning(_("You are not outputting any raster or vector maps")); cond2 = ((pcurv != NULL) || (tcurv != NULL) || (mcurv != NULL)); cond1 = ((slope != NULL) || (aspect != NULL) || cond2); deriv = flag.deriv->answer; dtens = flag.cprght->answer; cv = flag.cv->answer; if ((cv && cvdev == NULL) || (!(cv) && cvdev != NULL)) G_fatal_error(_("Both cross-validation options (-c flag and cvdev vector output) must be specified")); if ((elev != NULL || cond1 || cond2 || devi != NULL) && cv) G_fatal_error(_("The cross-validation cannot be computed simultaneously with output raster or devi file")); ertre = 0.1; sscanf(parm.dmax->answer, "%lf", &dmax); sscanf(parm.dmin->answer, "%lf", &dmin); sscanf(parm.fi->answer, "%lf", &fi); sscanf(parm.segmax->answer, "%d", &KMAX); sscanf(parm.npmin->answer, "%d", &npmin); sscanf(parm.zmult->answer, "%lf", &zmult); /* if (fi=0.000000) G_fatal_error("Tension must be > 0.000000") */ if (parm.theta->answer) sscanf(parm.theta->answer, "%lf", &theta); if (parm.scalex->answer) { sscanf(parm.scalex->answer, "%lf", &scalex); if (!parm.theta->answer) G_fatal_error(_("Using anisotropy - both theta and scalex have to be specified")); } if (parm.rsm->answer) { sscanf(parm.rsm->answer, "%lf", &rsm); if (rsm < 0.0) G_fatal_error("Smoothing must be a positive value"); if (scol != NULL) G_warning(_("Both smatt and smooth options specified - using constant")); } else { sscanf(SMOOTH, "%lf", &rsm); if (scol != NULL) rsm = -1; /* used in InterpLib to indicate variable smoothing */ } if (npmin > MAXPOINTS - 50) { G_warning(_("The computation will last too long - lower npmin is suggested")); KMAX2 = 2 * npmin; /* was: KMAX2 = npmin + 50; */ } else KMAX2 = 2 * npmin; /* was: KMAX2 = MAXPOINTS; fixed by JH in 12/01 */ /* handling of KMAX2 in GRASS4 v.surf.rst if (npmin > MAXPOINTS - 50) KMAX2 = npmin + 50; else KMAX2 = MAXPOINTS; */ dmin = dmin * dmin; KMIN = npmin; az = G_alloc_vector(n_cols + 1); if (!az) { G_fatal_error(_("Not enough memory for %s"), "az"); } if (cond1) { adx = G_alloc_vector(n_cols + 1); if (!adx) { G_fatal_error(_("Not enough memory for %s"), "adx"); } ady = G_alloc_vector(n_cols + 1); if (!ady) { G_fatal_error(_("Not enough memory for %s"), "ady"); } if (cond2) { adxx = G_alloc_vector(n_cols + 1); if (!adxx) { G_fatal_error(_("Not enough memory for %s"), "adxx"); } adyy = G_alloc_vector(n_cols + 1); if (!adyy) { G_fatal_error(_("Not enough memory for %s"), "adyy"); } adxy = G_alloc_vector(n_cols + 1); if (!adxy) { G_fatal_error(_("Not enough memory for %s"), "adxy"); } } } if ((data = quad_data_new(x_orig, y_orig, xm, ym, n_rows, n_cols, 0, KMAX)) == NULL) G_fatal_error(_("Unable to create %s"), "quaddata"); if ((functions = MT_functions_new(quad_compare, quad_divide_data, quad_add_data, quad_intersect, quad_division_check, quad_get_points)) == NULL) G_fatal_error(_("Unable to create %s"), "quadfunc"); if ((tree = MT_tree_new(data, NULL, NULL, 0)) == NULL) G_fatal_error(_("Unable to create %s"), "tree"); root = tree; if ((info = MT_tree_info_new(root, functions, dmin, KMAX)) == NULL) G_fatal_error(_("Unable to create %s"), "tree info"); open_check = Vect_open_old2(&Map, input, "", parm.field->answer); if (open_check < 1) G_fatal_error(_("Unable to open vector map <%s>"), input); /* if (open_check < 2) G_fatal_error(_("You first need to run v.build on vector map <%s>"), input); */ /* get value used for approximation */ with_z = !parm.zcol->answer && Vect_is_3d(&Map); field = Vect_get_field_number(&Map, parm.field->answer); if (!with_z && field < 1) G_fatal_error(_("Layer <%s> not found"), parm.field->answer); if (Vect_is_3d(&Map)) { if (!with_z) G_verbose_message(_("Input is 3D: using attribute values instead of z-coordinates for approximation")); else G_verbose_message(_("Input is 3D: using z-coordinates for approximation")); } else { /* 2D */ if (parm.zcol->answer) G_verbose_message(_("Input is 2D: using attribute values for approximation")); else G_verbose_message(_("Input is 2D: using category values for approximation")); } /* we can't read the input file's timestamp as they don't exist in */ /* the new vector format. Even so, a TimeStamp structure is needed */ /* for IL_init_params_2d(), so we set it to NULL. */ /* If anyone is ever motivated to add it, the Plus_head struct has */ /* 'long coor_mtime' and dig_head has 'char *date; char *source_date;' */ /* which could be read in. */ if (devi != NULL || cvdev != NULL) { Pnts = Vect_new_line_struct(); Cats2 = Vect_new_cats_struct(); db_init_string(&sql2); if (devi != NULL) { if (Vect_open_new(&Map2, devi, 1) < 0) G_fatal_error(_("Unable to create vector map <%s>"), devi); } else { if (Vect_open_new(&Map2, cvdev, 1) < 0) G_fatal_error(_("Unable to create vector map <%s>"), cvdev); } Vect_hist_command(&Map2); ff = Vect_default_field_info(&Map2, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Map2, 1, NULL, ff->table, GV_KEY_COLUMN, ff->database, ff->driver); /* Create new table */ db_zero_string(&sql2); sprintf(buf, "create table %s ( ", ff->table); db_append_string(&sql2, buf); db_append_string(&sql2, "cat integer"); db_append_string(&sql2, ", flt1 double precision"); db_append_string(&sql2, ")"); G_debug(1, "%s", db_get_string(&sql2)); driver2 = db_start_driver_open_database(ff->driver, ff->database); if (driver2 == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), ff->database, ff->driver); db_set_error_handler_driver(driver2); if (db_execute_immediate(driver2, &sql2) != DB_OK) { G_fatal_error(_("Unable to create table '%s'"), db_get_string(&sql2)); } db_begin_transaction(driver2); count = 1; } ertot = 0.; create_temp_files(); IL_init_params_2d(¶ms, NULL, 1, 1, zmult, KMIN, KMAX, maskmap, n_rows, n_cols, az, adx, ady, adxx, adyy, adxy, fi, KMAX2, SCIK1, SCIK2, SCIK3, rsm, elev, slope, aspect, pcurv, tcurv, mcurv, dmin, x_orig, y_orig, deriv, theta, scalex, Tmp_fd_z, Tmp_fd_dx, Tmp_fd_dy, Tmp_fd_xx, Tmp_fd_yy, Tmp_fd_xy, devi, NULL, cv, parm.wheresql->answer); IL_init_func_2d(¶ms, IL_grid_calc_2d, IL_matrix_create, IL_check_at_points_2d, IL_secpar_loop_2d, IL_crst, IL_crstg, IL_write_temp_2d); totsegm = IL_vector_input_data_2d(¶ms, &Map, with_z ? 0 : field, zcol, scol, info, &xmin, &xmax, &ymin, &ymax, &zmin, &zmax, &NPOINT, &dmax); if (totsegm <= 0) { clean(); G_fatal_error(_("Input failed")); } /*Vect_set_release_support(&Map); */ Vect_close(&Map); if (treefile != NULL) { if (0 > Vect_open_new(&TreeMap, treefile, 0)) { clean(); G_fatal_error(_("Unable to open vector map <%s>"), treefile); } Vect_hist_command(&TreeMap); /* sprintf (TreeMap.head.your_name, "grass"); sprintf (TreeMap.head.map_name, "Quad tree for %s", input); TreeMap.head.orig_scale = 100000; TreeMap.head.plani_zone = G_zone (); */ print_tree(root, x_orig, y_orig, &TreeMap); Vect_build(&TreeMap); Vect_close(&TreeMap); } disk = disk + totsegm * sizeof(int) * 4; sdisk = sdisk + totsegm * sizeof(int) * 4; if (elev != NULL) ddisk += disk; if (slope != NULL) sddisk += sdisk; if (aspect != NULL) sddisk += sdisk; if (pcurv != NULL) ddisk += disk; if (tcurv != NULL) ddisk += disk; if (mcurv != NULL) ddisk += disk; ddisk += sddisk; G_verbose_message(_("Processing all selected output files " "will require %d bytes of disk space for temp files"), ddisk); deltx = xmax - xmin; delty = ymax - ymin; dnorm = sqrt((deltx * delty * KMIN) / NPOINT); if (dtens) { params.fi = params.fi * dnorm / 1000.; G_verbose_message("dnorm = %f, rescaled tension = %f", dnorm, params.fi); } bitmask = IL_create_bitmask(¶ms); if (totsegm <= 0) { clean(); G_fatal_error(_("Input failed")); } ertot = 0.; G_message(_("Processing segments...")); if (IL_interp_segments_2d(¶ms, info, info->root, bitmask, zmin, zmax, &zminac, &zmaxac, &gmin, &gmax, &c1min, &c1max, &c2min, &c2max, &ertot, totsegm, n_cols, dnorm) < 0) { clean(); G_fatal_error(_("Interp_segmets failed")); } G_free_vector(az); if (cond1) { G_free_vector(adx); G_free_vector(ady); if (cond2) { G_free_vector(adxx); G_free_vector(adyy); G_free_vector(adxy); } } ii = IL_output_2d(¶ms, &cellhd, zmin, zmax, zminac, zmaxac, c1min, c1max, c2min, c2max, gmin, gmax, ertot, input, dnorm, dtens, 1, NPOINT); if (ii < 0) { clean(); G_fatal_error(_("Unable to write raster maps - try to increase resolution")); } G_free(zero_array_cell); if (elev != NULL) fclose(Tmp_fd_z); if (slope != NULL) fclose(Tmp_fd_dx); if (aspect != NULL) fclose(Tmp_fd_dy); if (pcurv != NULL) fclose(Tmp_fd_xx); if (tcurv != NULL) fclose(Tmp_fd_yy); if (mcurv != NULL) fclose(Tmp_fd_xy); if (overfile != NULL) { if (0 > Vect_open_new(&OverMap, overfile, 0)) { clean(); G_fatal_error(_("Unable to create vector map <%s>"), overfile); } Vect_hist_command(&OverMap); /* sprintf (OverMap.head.your_name, "grass"); sprintf (OverMap.head.map_name, "Overlap segments for %s", input); OverMap.head.orig_scale = 100000; OverMap.head.plani_zone = G_zone (); */ print_tree(root, x_orig, y_orig, &OverMap); Vect_build(&OverMap); Vect_close(&OverMap); } if (elev != NULL) unlink(Tmp_file_z); if (slope != NULL) unlink(Tmp_file_dx); if (aspect != NULL) unlink(Tmp_file_dy); if (pcurv != NULL) unlink(Tmp_file_xx); if (tcurv != NULL) unlink(Tmp_file_yy); if (mcurv != NULL) unlink(Tmp_file_xy); if (cvdev != NULL || devi != NULL) { db_commit_transaction(driver2); db_close_database_shutdown_driver(driver2); Vect_build(&Map2); Vect_close(&Map2); } G_done_msg(" "); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int i; int **cats, *ncats, nfields, *fields; struct Flag *line_flag; /* struct Flag *all_flag; */ struct Option *in_opt, *out_opt; struct Flag *table_flag; struct GModule *module; struct line_pnts *Points; struct line_cats *Cats; int node, nnodes; COOR *coor; int ncoor, acoor; int line, nlines, type, ctype, area, nareas; int err_boundaries, err_centr_out, err_centr_dupl, err_nocentr; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); G_add_keyword(_("triangulation")); module->description = _("Creates a Voronoi diagram from an input vector " "map containing points or centroids."); in_opt = G_define_standard_option(G_OPT_V_INPUT); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); /* all_flag = G_define_flag (); all_flag->key = 'a'; all_flag->description = _("Use all points (do not limit to current region)"); */ line_flag = G_define_flag(); line_flag->key = 'l'; line_flag->description = _("Output tessellation as a graph (lines), not areas"); table_flag = G_define_flag(); table_flag->key = 't'; table_flag->description = _("Do not create attribute table"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (line_flag->answer) Type = GV_LINE; else Type = GV_BOUNDARY; All = 0; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); /* open files */ Vect_set_open_level(2); Vect_open_old(&In, in_opt->answer, ""); if (Vect_open_new(&Out, out_opt->answer, 0) < 0) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); /* initialize working region */ G_get_window(&Window); Vect_region_box(&Window, &Box); Box.T = 0.5; Box.B = -0.5; freeinit(&sfl, sizeof(struct Site)); G_message(_("Reading sites...")); readsites(); siteidx = 0; geominit(); triangulate = 0; plot = 0; debug = 0; G_message(_("Voronoi triangulation...")); voronoi(triangulate, nextone); /* Close free ends by current region */ Vect_build_partial(&Out, GV_BUILD_BASE); ncoor = 0; acoor = 100; coor = (COOR *) G_malloc(sizeof(COOR) * acoor); nnodes = Vect_get_num_nodes(&Out); for (node = 1; node <= nnodes; node++) { double x, y; if (Vect_get_node_n_lines(&Out, node) < 2) { /* add coordinates */ Vect_get_node_coor(&Out, node, &x, &y, NULL); if (ncoor == acoor - 5) { /* always space for 5 region corners */ acoor += 100; coor = (COOR *) G_realloc(coor, sizeof(COOR) * acoor); } coor[ncoor].x = x; coor[ncoor].y = y; ncoor++; } } /* Add region corners */ coor[ncoor].x = Box.W; coor[ncoor].y = Box.S; ncoor++; coor[ncoor].x = Box.E; coor[ncoor].y = Box.S; ncoor++; coor[ncoor].x = Box.E; coor[ncoor].y = Box.N; ncoor++; coor[ncoor].x = Box.W; coor[ncoor].y = Box.N; ncoor++; /* Sort */ qsort(coor, ncoor, sizeof(COOR), (void *)cmp); /* add last (first corner) */ coor[ncoor].x = Box.W; coor[ncoor].y = Box.S; ncoor++; for (i = 1; i < ncoor; i++) { if (coor[i].x == coor[i - 1].x && coor[i].y == coor[i - 1].y) continue; /* duplicate */ Vect_reset_line(Points); Vect_append_point(Points, coor[i].x, coor[i].y, 0.0); Vect_append_point(Points, coor[i - 1].x, coor[i - 1].y, 0.0); Vect_write_line(&Out, Type, Points, Cats); } G_free(coor); /* Copy input points as centroids */ nfields = Vect_cidx_get_num_fields(&In); cats = (int **)G_malloc(nfields * sizeof(int *)); ncats = (int *)G_malloc(nfields * sizeof(int)); fields = (int *)G_malloc(nfields * sizeof(int)); for (i = 0; i < nfields; i++) { ncats[i] = 0; cats[i] = (int *)G_malloc(Vect_cidx_get_num_cats_by_index(&In, i) * sizeof(int)); fields[i] = Vect_cidx_get_field_number(&In, i); } if (line_flag->answer) ctype = GV_POINT; else ctype = GV_CENTROID; nlines = Vect_get_num_lines(&In); G_message(_("Writing sites to output...")); for (line = 1; line <= nlines; line++) { G_percent(line, nlines, 2); type = Vect_read_line(&In, Points, Cats, line); if (!(type & GV_POINTS)) continue; if (!Vect_point_in_box(Points->x[0], Points->y[0], 0.0, &Box)) continue; Vect_write_line(&Out, ctype, Points, Cats); for (i = 0; i < Cats->n_cats; i++) { int f, j; f = -1; for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == Cats->field[i]) { f = j; break; } } if (f > -1) { cats[f][ncats[f]] = Cats->cat[i]; ncats[f]++; } } } /* Copy tables */ if (!(table_flag->answer)) { int ttype, ntabs = 0; struct field_info *IFi, *OFi; /* Number of output tabs */ for (i = 0; i < Vect_get_num_dblinks(&In); i++) { int f, j; IFi = Vect_get_dblink(&In, i); f = -1; for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == IFi->number) { f = j; break; } } if (f > -1) { if (ncats[f] > 0) ntabs++; } } if (ntabs > 1) ttype = GV_MTABLE; else ttype = GV_1TABLE; for (i = 0; i < nfields; i++) { int ret; if (fields[i] == 0) continue; G_message(_("Layer %d"), fields[i]); /* Make a list of categories */ IFi = Vect_get_field(&In, fields[i]); if (!IFi) { /* no table */ G_message(_("No table")); continue; } OFi = Vect_default_field_info(&Out, IFi->number, IFi->name, ttype); ret = db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table, OFi->driver, Vect_subst_var(OFi->database, &Out), OFi->table, IFi->key, cats[i], ncats[i]); if (ret == DB_FAILED) { G_warning(_("Cannot copy table")); } else { Vect_map_add_dblink(&Out, OFi->number, OFi->name, OFi->table, IFi->key, OFi->database, OFi->driver); } } } Vect_close(&In); /* cleaning part 1: count errors */ Vect_build_partial(&Out, GV_BUILD_CENTROIDS); err_boundaries = err_centr_out = err_centr_dupl = err_nocentr = 0; nlines = Vect_get_num_lines(&Out); for (line = 1; line <= nlines; line++) { if (!Vect_line_alive(&Out, line)) continue; type = Vect_get_line_type(&Out, line); if (type == GV_BOUNDARY) { int left, right; Vect_get_line_areas(&Out, line, &left, &right); if (left == 0 || right == 0) { G_debug(3, "line = %d left = %d right = %d", line, left, right); err_boundaries++; } } if (type == GV_CENTROID) { area = Vect_get_centroid_area(&Out, line); if (area == 0) err_centr_out++; else if (area < 0) err_centr_dupl++; } } err_nocentr = 0; nareas = Vect_get_num_areas(&Out); for (area = 1; area <= nareas; area++) { if (!Vect_area_alive(&Out, area)) continue; line = Vect_get_area_centroid(&Out, area); if (line == 0) err_nocentr++; } /* cleaning part 2: snap */ if (err_nocentr || err_centr_dupl || err_centr_out) { int nmod; G_important_message(_("Output needs topological cleaning")); Vect_snap_lines(&Out, GV_BOUNDARY, 1e-7, NULL); do { Vect_break_lines(&Out, GV_BOUNDARY, NULL); Vect_remove_duplicates(&Out, GV_BOUNDARY, NULL); nmod = Vect_clean_small_angles_at_nodes(&Out, GV_BOUNDARY, NULL); } while (nmod > 0); err_boundaries = 0; nlines = Vect_get_num_lines(&Out); for (line = 1; line <= nlines; line++) { if (!Vect_line_alive(&Out, line)) continue; type = Vect_get_line_type(&Out, line); if (type == GV_BOUNDARY) { int left, right; Vect_get_line_areas(&Out, line, &left, &right); if (left == 0 || right == 0) { G_debug(3, "line = %d left = %d right = %d", line, left, right); err_boundaries++; } } } } /* cleaning part 3: remove remaining incorrect boundaries */ if (err_boundaries) { G_important_message(_("Removing incorrect boundaries from output")); nlines = Vect_get_num_lines(&Out); for (line = 1; line <= nlines; line++) { if (!Vect_line_alive(&Out, line)) continue; type = Vect_get_line_type(&Out, line); if (type == GV_BOUNDARY) { int left, right; Vect_get_line_areas(&Out, line, &left, &right); /* &&, not ||, no typo */ if (left == 0 && right == 0) { G_debug(3, "line = %d left = %d right = %d", line, left, right); Vect_delete_line(&Out, line); } } } } /* build clean topology */ Vect_build_partial(&Out, GV_BUILD_NONE); Vect_build(&Out); Vect_close(&Out); G_done_msg(" "); exit(EXIT_SUCCESS); }
/* TODO: The collection of categories is horrible in current version! * Everything repeats many times. We need some data structure * implementing set! */ int copy_tables_by_cats(struct Map_info *In, struct Map_info *Out) { /* this is the (mostly) code from v.extract, it should be moved to * some vector library (probably) */ int nlines, line, nfields; int ttype, ntabs = 0; struct field_info *IFi, *OFi; struct line_cats *Cats; int **ocats, *nocats, *fields; int i; /* Collect list of output cats */ Cats = Vect_new_cats_struct(); nfields = Vect_cidx_get_num_fields(In); ocats = (int **)G_malloc(nfields * sizeof(int *)); nocats = (int *)G_malloc(nfields * sizeof(int)); fields = (int *)G_malloc(nfields * sizeof(int)); for (i = 0; i < nfields; i++) { nocats[i] = 0; ocats[i] = (int *)G_malloc(Vect_cidx_get_num_cats_by_index(In, i) * sizeof(int)); fields[i] = Vect_cidx_get_field_number(In, i); } nlines = Vect_get_num_lines(Out); for (line = 1; line <= nlines; line++) { Vect_read_line(Out, NULL, Cats, line); for (i = 0; i < Cats->n_cats; i++) { int f = 0, j; for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == Cats->field[i]) { f = j; break; } } ocats[f][nocats[f]] = Cats->cat[i]; nocats[f]++; } } /* Copy tables */ G_message(_("Writing attributes...")); /* Number of output tabs */ for (i = 0; i < Vect_get_num_dblinks(In); i++) { int j, f = -1; IFi = Vect_get_dblink(In, i); for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == IFi->number) { f = j; break; } } if (f >= 0 && nocats[f] > 0) ntabs++; } if (ntabs > 1) ttype = GV_MTABLE; else ttype = GV_1TABLE; for (i = 0; i < nfields; i++) { int ret; if (fields[i] == 0) continue; if (nocats[i] == 0) continue; /* if ( fields[i] == field && new_cat != -1 ) continue; */ G_message(_("Layer %d"), fields[i]); /* Make a list of categories */ IFi = Vect_get_field(In, fields[i]); if (!IFi) { /* no table */ G_warning(_("Database connection not defined for layer %d"), fields[i]); continue; } OFi = Vect_default_field_info(Out, IFi->number, IFi->name, ttype); ret = db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table, OFi->driver, Vect_subst_var(OFi->database, Out), OFi->table, IFi->key, ocats[i], nocats[i]); if (ret == DB_FAILED) { G_warning(_("Unable to copy table <%s>"), IFi->table); } else { Vect_map_add_dblink(Out, OFi->number, OFi->name, OFi->table, IFi->key, OFi->database, OFi->driver); } } for (i = 0; i < nfields; i++) G_free(ocats[i]); G_free(ocats); G_free(nocats); G_free(fields); return 1; }
int main(int argc, char *argv[]) { struct Map_info In, Out, cut_map; static struct line_pnts *Points; struct line_cats *Cats; struct GModule *module; /* GRASS module for parsing arguments */ struct Option *map_in, *map_out, *cut_out; struct Option *afield_opt, *nfield_opt, *abcol, *afcol, *ncol; struct Option *catsource_opt, *wheresource_opt; struct Option *catsink_opt, *wheresink_opt; int with_z; int afield, nfield, mask_type; struct varray *varray_source, *varray_sink; dglGraph_s *graph; int i, nlines, *flow, total_flow; struct ilist *source_list, *sink_list, *cut; int find_cut; char buf[2000]; /* Attribute table */ dbString sql; dbDriver *driver; struct field_info *Fi; /* initialize GIS environment */ G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */ /* initialize module */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("network")); G_add_keyword(_("flow")); module->description = _("Computes the maximum flow between two sets of nodes in the network."); /* Define the different options as defined in gis.h */ map_in = G_define_standard_option(G_OPT_V_INPUT); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "arc_layer"; afield_opt->answer = "1"; afield_opt->label = _("Arc layer"); afield_opt->guisection = _("Cost"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "node_layer"; nfield_opt->answer = "2"; nfield_opt->label = _("Node layer"); nfield_opt->guisection = _("Cost"); map_out = G_define_standard_option(G_OPT_V_OUTPUT); cut_out = G_define_standard_option(G_OPT_V_OUTPUT); cut_out->key = "cut"; cut_out->description = _("Name for output vector map containing a minimum cut"); afcol = G_define_standard_option(G_OPT_DB_COLUMN); afcol->key = "arc_column"; afcol->required = NO; afcol->description = _("Arc forward/both direction(s) cost column (number)"); afcol->guisection = _("Cost"); abcol = G_define_standard_option(G_OPT_DB_COLUMN); abcol->key = "arc_backward_column"; abcol->required = NO; abcol->description = _("Arc backward direction cost column (number)"); abcol->guisection = _("Cost"); ncol = G_define_standard_option(G_OPT_DB_COLUMN); ncol->key = "node_column"; ncol->required = NO; ncol->description = _("Node cost column (number)"); ncol->guisection = _("Cost"); catsource_opt = G_define_standard_option(G_OPT_V_CATS); catsource_opt->key = "source_cats"; catsource_opt->label = _("Source category values"); catsource_opt->guisection = _("Source"); wheresource_opt = G_define_standard_option(G_OPT_DB_WHERE); wheresource_opt->key = "source_where"; wheresource_opt->label = _("Source WHERE conditions of SQL statement without 'where' keyword"); wheresource_opt->guisection = _("Source"); catsink_opt = G_define_standard_option(G_OPT_V_CATS); catsink_opt->key = "sink_cats"; catsink_opt->label = _("Sink category values"); catsink_opt->guisection = _("Sink"); wheresink_opt = G_define_standard_option(G_OPT_DB_WHERE); wheresink_opt->key = "sink_where"; wheresink_opt->label = _("Sink WHERE conditions of SQL statement without 'where' keyword"); wheresink_opt->guisection = _("Sink"); /* options and flags parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); find_cut = (cut_out->answer[0]); /* TODO: make an option for this */ mask_type = GV_LINE | GV_BOUNDARY; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Vect_check_input_output_name(map_in->answer, map_out->answer, G_FATAL_EXIT); Vect_set_open_level(2); if (1 > Vect_open_old(&In, map_in->answer, "")) G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer); with_z = Vect_is_3d(&In); if (0 > Vect_open_new(&Out, map_out->answer, with_z)) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer); } if (find_cut && 0 > Vect_open_new(&cut_map, cut_out->answer, with_z)) { Vect_close(&In); Vect_close(&Out); G_fatal_error(_("Unable to create vector map <%s>"), cut_out->answer); } /* parse filter option and select appropriate lines */ afield = Vect_get_field_number(&In, afield_opt->answer); nfield = Vect_get_field_number(&In, nfield_opt->answer); /* Create table */ Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); db_init_string(&sql); driver = db_start_driver_open_database(Fi->driver, Fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_set_error_handler_driver(driver); sprintf(buf, "create table %s (cat integer, flow double precision)", Fi->table); db_set_string(&sql, buf); G_debug(2, "%s", db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database_shutdown_driver(driver); 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(_("Cannot create index")); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); source_list = Vect_new_list(); sink_list = Vect_new_list(); if (NetA_initialise_varray (&In, nfield, GV_POINT, wheresource_opt->answer, catsource_opt->answer, &varray_source) <= 0) { G_fatal_error(_("No source features selected. " "Please check options '%s', '%s'."), catsource_opt->key, wheresource_opt->key); } if (NetA_initialise_varray (&In, nfield, GV_POINT, wheresink_opt->answer, catsink_opt->answer, &varray_sink) <= 0) { G_fatal_error(_("No sink features selected. " "Please check options '%s', '%s'."), catsink_opt->key, wheresink_opt->key); } NetA_varray_to_nodes(&In, varray_source, source_list, NULL); NetA_varray_to_nodes(&In, varray_sink, sink_list, NULL); if (source_list->n_values == 0) G_fatal_error(_("No sources")); if (sink_list->n_values == 0) G_fatal_error(_("No sinks")); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); if (0 != Vect_net_build_graph(&In, mask_type, afield, nfield, afcol->answer, abcol->answer, ncol->answer, 0, 0)) G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In)); graph = Vect_net_get_graph(&In); nlines = Vect_get_num_lines(&In); flow = (int *)G_calloc(nlines + 1, sizeof(int)); if (!flow) G_fatal_error(_("Out of memory")); total_flow = NetA_flow(graph, source_list, sink_list, flow); G_debug(3, "Max flow: %d", total_flow); if (find_cut) { cut = Vect_new_list(); total_flow = NetA_min_cut(graph, source_list, sink_list, flow, cut); G_debug(3, "Min cut: %d", total_flow); } G_message(_("Writing the output...")); G_percent_reset(); for (i = 1; i <= nlines; i++) { G_percent(i, nlines, 1); int type = Vect_read_line(&In, Points, Cats, i); Vect_write_line(&Out, type, Points, Cats); if (type == GV_LINE) { int cat; Vect_cat_get(Cats, afield, &cat); if (cat == -1) continue; /*TODO: warning? */ sprintf(buf, "insert into %s values (%d, %f)", Fi->table, cat, flow[i] / (double)In.dgraph.cost_multip); db_set_string(&sql, buf); G_debug(3, "%s", db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database_shutdown_driver(driver); G_fatal_error(_("Cannot insert new record: %s"), db_get_string(&sql)); }; } } if (find_cut) { for (i = 0; i < cut->n_values; i++) { int type = Vect_read_line(&In, Points, Cats, cut->value[i]); Vect_write_line(&cut_map, type, Points, Cats); } Vect_destroy_list(cut); Vect_build(&cut_map); Vect_close(&cut_map); } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); G_free(flow); Vect_destroy_list(source_list); Vect_destroy_list(sink_list); Vect_build(&Out); Vect_close(&In); Vect_close(&Out); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { char *output, buf[DB_SQL_MAX]; double (*rng)(void) = G_drand48; double zmin, zmax; int seed; int i, j, k, n, type, usefloat; int area, nareas, field; struct boxlist *List = NULL; BOX_SIZE *size_list = NULL; int alloc_size_list = 0; struct Map_info In, Out; struct line_pnts *Points; struct line_cats *Cats; struct cat_list *cat_list; struct bound_box box; struct Cell_head window; struct GModule *module; struct { struct Option *input, *field, *cats, *where, *output, *nsites, *zmin, *zmax, *zcol, *ztype, *seed; } parm; struct { struct Flag *z, *notopo, *a; } flag; struct field_info *Fi; dbDriver *driver; dbTable *table; dbString sql; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("sampling")); G_add_keyword(_("statistics")); G_add_keyword(_("random")); module->description = _("Generates random 2D/3D vector points."); parm.output = G_define_standard_option(G_OPT_V_OUTPUT); parm.nsites = G_define_option(); parm.nsites->key = "n"; parm.nsites->type = TYPE_INTEGER; parm.nsites->required = YES; parm.nsites->description = _("Number of points to be created"); parm.input = G_define_standard_option(G_OPT_V_INPUT); parm.input->required = NO; parm.input->description = _("Restrict points to areas in input vector"); parm.input->guisection = _("Selection"); parm.field = G_define_standard_option(G_OPT_V_FIELD_ALL); parm.field->guisection = _("Selection"); parm.cats = G_define_standard_option(G_OPT_V_CATS); parm.cats->guisection = _("Selection"); parm.where = G_define_standard_option(G_OPT_DB_WHERE); parm.where->guisection = _("Selection"); parm.zmin = G_define_option(); parm.zmin->key = "zmin"; parm.zmin->type = TYPE_DOUBLE; parm.zmin->required = NO; parm.zmin->description = _("Minimum z height (needs -z flag or column name)"); parm.zmin->answer = "0.0"; parm.zmin->guisection = _("3D output"); parm.zmax = G_define_option(); parm.zmax->key = "zmax"; parm.zmax->type = TYPE_DOUBLE; parm.zmax->required = NO; parm.zmax->description = _("Maximum z height (needs -z flag or column name)"); parm.zmax->answer = "0.0"; parm.zmax->guisection = _("3D output"); parm.seed = G_define_option(); parm.seed->key = "seed"; parm.seed->type = TYPE_INTEGER; parm.seed->required = NO; parm.seed->description = _("The seed to initialize the random generator. If not set the process ID is used"); parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN); parm.zcol->label = _("Name of column for z values"); parm.zcol->description = _("Writes z values to column"); parm.zcol->guisection = _("3D output"); parm.ztype = G_define_option(); parm.ztype->key = "column_type"; parm.ztype->type = TYPE_STRING; parm.ztype->required = NO; parm.ztype->multiple = NO; parm.ztype->description = _("Type of column for z values"); parm.ztype->options = "integer,double precision"; parm.ztype->answer = "double precision"; parm.ztype->guisection = _("3D output"); flag.z = G_define_flag(); flag.z->key = 'z'; flag.z->description = _("Create 3D output"); flag.z->guisection = _("3D output"); flag.a = G_define_flag(); flag.a->key = 'a'; flag.a->description = _("Generate n points for each individual area"); flag.notopo = G_define_standard_flag(G_FLG_V_TOPO); if (G_parser(argc, argv)) exit(EXIT_FAILURE); output = parm.output->answer; n = atoi(parm.nsites->answer); if(parm.seed->answer) seed = atoi(parm.seed->answer); if (n <= 0) { G_fatal_error(_("Number of points must be > 0 (%d given)"), n); } nareas = 0; cat_list = NULL; field = -1; if (parm.input->answer) { Vect_set_open_level(2); /* topology required */ if (2 > Vect_open_old2(&In, parm.input->answer, "", parm.field->answer)) G_fatal_error(_("Unable to open vector map <%s>"), parm.input->answer); if (parm.field->answer) field = Vect_get_field_number(&In, parm.field->answer); if ((parm.cats->answer || parm.where->answer) && field == -1) { G_warning(_("Invalid layer number (%d). Parameter '%s' or '%s' specified, assuming layer '1'."), field, parm.cats->key, parm.where->key); field = 1; } if (field > 0) cat_list = Vect_cats_set_constraint(&In, field, parm.where->answer, parm.cats->answer); nareas = Vect_get_num_areas(&In); if (nareas == 0) { Vect_close(&In); G_fatal_error(_("No areas in vector map <%s>"), parm.input->answer); } } else { if (flag.a->answer) G_fatal_error(_("The <-%c> flag requires an input vector with areas"), flag.a->key); } /* create new vector map */ if (-1 == Vect_open_new(&Out, output, flag.z->answer ? WITH_Z : WITHOUT_Z)) G_fatal_error(_("Unable to create vector map <%s>"), output); Vect_set_error_handler_io(NULL, &Out); /* Do we need to write random values into attribute table? */ usefloat = -1; if (parm.zcol->answer) { Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Out)); if (driver == NULL) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Vect_subst_var(Fi->database, &Out), Fi->driver); } db_set_error_handler_driver(driver); db_begin_transaction(driver); db_init_string(&sql); sprintf(buf, "create table %s (%s integer, %s %s)", Fi->table, GV_KEY_COLUMN, parm.zcol->answer, parm.ztype->answer); db_set_string(&sql, buf); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); /* Create table */ G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Unable to create table: %s"), db_get_string(&sql)); } /* Create index */ if (db_create_index2(driver, Fi->table, Fi->key) != DB_OK) G_warning(_("Unable to create index")); /* Grant */ 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); } /* OK. Let's check what type of column user has created */ db_set_string(&sql, Fi->table); if (db_describe_table(driver, &sql, &table) != DB_OK) { G_fatal_error(_("Unable to describe table <%s>"), Fi->table); } if (db_get_table_number_of_columns(table) != 2) { G_fatal_error(_("Table should contain only two columns")); } type = db_get_column_sqltype(db_get_table_column(table, 1)); if (type == DB_SQL_TYPE_SMALLINT || type == DB_SQL_TYPE_INTEGER) usefloat = 0; if (type == DB_SQL_TYPE_REAL || type == DB_SQL_TYPE_DOUBLE_PRECISION) usefloat = 1; if (usefloat < 0) { G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER" " and DOUBLE PRECISION column types.")); } } Vect_hist_command(&Out); /* Init the random seed */ if(parm.seed->answer) G_srand48(seed); else G_srand48_auto(); G_get_window(&window); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); if (nareas > 0) { int first = 1, count; struct bound_box abox, bbox; box.W = window.west; box.E = window.east; box.S = window.south; box.N = window.north; box.B = -PORT_DOUBLE_MAX; box.T = PORT_DOUBLE_MAX; count = 0; for (i = 1; i <= nareas; i++) { if (!Vect_get_area_centroid(&In, i)) continue; if (field > 0) { if (Vect_get_area_cats(&In, i, Cats)) continue; if (!Vect_cats_in_constraint(Cats, field, cat_list)) continue; } Vect_get_area_box(&In, i, &abox); if (!Vect_box_overlap(&abox, &box)) continue; if (first) { Vect_box_copy(&bbox, &abox); first = 0; } else Vect_box_extend(&bbox, &abox); count++; } if (count == 0) { Vect_close(&In); Vect_close(&Out); Vect_delete(output); G_fatal_error(_("Selected areas in input vector <%s> do not overlap with the current region"), parm.input->answer); } Vect_box_copy(&box, &bbox); /* does the vector overlap with the current region ? */ if (box.W >= window.east || box.E <= window.west || box.S >= window.north || box.N <= window.south) { Vect_close(&In); Vect_close(&Out); Vect_delete(output); G_fatal_error(_("Input vector <%s> does not overlap with the current region"), parm.input->answer); } /* try to reduce the current region */ if (window.east > box.E) window.east = box.E; if (window.west < box.W) window.west = box.W; if (window.north > box.N) window.north = box.N; if (window.south < box.S) window.south = box.S; List = Vect_new_boxlist(1); alloc_size_list = 10; size_list = G_malloc(alloc_size_list * sizeof(BOX_SIZE)); } zmin = zmax = 0; if (flag.z->answer || parm.zcol->answer) { zmax = atof(parm.zmax->answer); zmin = atof(parm.zmin->answer); } G_message(_("Generating points...")); if (flag.a->answer && nareas > 0) { struct bound_box abox, bbox; int cat = 1; /* n points for each area */ nareas = Vect_get_num_areas(&In); G_percent(0, nareas, 1); for (area = 1; area <= nareas; area++) { G_percent(area, nareas, 1); if (!Vect_get_area_centroid(&In, area)) continue; if (field > 0) { if (Vect_get_area_cats(&In, area, Cats)) continue; if (!Vect_cats_in_constraint(Cats, field, cat_list)) { continue; } } box.W = window.west; box.E = window.east; box.S = window.south; box.N = window.north; box.B = -PORT_DOUBLE_MAX; box.T = PORT_DOUBLE_MAX; Vect_get_area_box(&In, area, &abox); if (!Vect_box_overlap(&box, &abox)) continue; bbox = abox; if (bbox.W < box.W) bbox.W = box.W; if (bbox.E > box.E) bbox.E = box.E; if (bbox.S < box.S) bbox.S = box.S; if (bbox.N > box.N) bbox.N = box.N; for (i = 0; i < n; ++i) { double x, y, z; int outside = 1; int ret; Vect_reset_line(Points); Vect_reset_cats(Cats); while (outside) { x = rng() * (bbox.W - bbox.E) + bbox.E; y = rng() * (bbox.N - bbox.S) + bbox.S; z = rng() * (zmax - zmin) + zmin; ret = Vect_point_in_area(x, y, &In, area, &abox); G_debug(3, " area = %d Vect_point_in_area() = %d", area, ret); if (ret >= 1) { outside = 0; } } if (flag.z->answer) Vect_append_point(Points, x, y, z); else Vect_append_point(Points, x, y, 0.0); if (parm.zcol->answer) { sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1); db_set_string(&sql, buf); /* Round random value if column is integer type */ if (usefloat) sprintf(buf, "%f )", z); else sprintf(buf, "%.0f )", z); db_append_string(&sql, buf); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Cannot insert new row: %s"), db_get_string(&sql)); } } Vect_cat_set(Cats, 1, cat++); Vect_write_line(&Out, GV_POINT, Points, Cats); } } } else { /* n points in total */ for (i = 0; i < n; ++i) { double x, y, z; G_percent(i, n, 4); Vect_reset_line(Points); Vect_reset_cats(Cats); x = rng() * (window.west - window.east) + window.east; y = rng() * (window.north - window.south) + window.south; z = rng() * (zmax - zmin) + zmin; if (nareas) { int outside = 1; do { /* select areas by box */ box.E = x; box.W = x; box.N = y; box.S = y; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_areas_by_box(&In, &box, List); G_debug(3, " %d areas selected by box", List->n_values); /* sort areas by size, the smallest is likely to be the nearest */ if (alloc_size_list < List->n_values) { alloc_size_list = List->n_values; size_list = G_realloc(size_list, alloc_size_list * sizeof(BOX_SIZE)); } k = 0; for (j = 0; j < List->n_values; j++) { area = List->id[j]; if (!Vect_get_area_centroid(&In, area)) continue; if (field > 0) { if (Vect_get_area_cats(&In, area, Cats)) continue; if (!Vect_cats_in_constraint(Cats, field, cat_list)) { continue; } } List->id[k] = List->id[j]; List->box[k] = List->box[j]; size_list[k].i = List->id[k]; box = List->box[k]; size_list[k].box = List->box[k]; size_list[k].size = (box.N - box.S) * (box.E - box.W); k++; } List->n_values = k; if (List->n_values == 2) { /* simple swap */ if (size_list[1].size < size_list[0].size) { size_list[0].i = List->id[1]; size_list[1].i = List->id[0]; size_list[0].box = List->box[1]; size_list[1].box = List->box[0]; } } else if (List->n_values > 2) qsort(size_list, List->n_values, sizeof(BOX_SIZE), sort_by_size); for (j = 0; j < List->n_values; j++) { int ret; area = size_list[j].i; ret = Vect_point_in_area(x, y, &In, area, &size_list[j].box); G_debug(3, " area = %d Vect_point_in_area() = %d", area, ret); if (ret >= 1) { outside = 0; break; } } if (outside) { x = rng() * (window.west - window.east) + window.east; y = rng() * (window.north - window.south) + window.south; z = rng() * (zmax - zmin) + zmin; } } while (outside); } if (flag.z->answer) Vect_append_point(Points, x, y, z); else Vect_append_point(Points, x, y, 0.0); if (parm.zcol->answer) { sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1); db_set_string(&sql, buf); /* Round random value if column is integer type */ if (usefloat) sprintf(buf, "%f )", z); else sprintf(buf, "%.0f )", z); db_append_string(&sql, buf); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Cannot insert new row: %s"), db_get_string(&sql)); } } Vect_cat_set(Cats, 1, i + 1); Vect_write_line(&Out, GV_POINT, Points, Cats); } G_percent(1, 1, 1); } if (parm.zcol->answer) { db_commit_transaction(driver); db_close_database_shutdown_driver(driver); } if (!flag.notopo->answer) { Vect_build(&Out); } Vect_close(&Out); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int i, iopt; int operator; int aline, nalines, nskipped; int ltype, itype[2], ifield[2]; int **cats, *ncats, nfields, *fields; char *mapset[2], *pre[2]; struct GModule *module; struct GParm parm; struct GFlag flag; struct Map_info In[2], Out; struct field_info *IFi, *OFi; struct line_pnts *APoints, *BPoints; struct line_cats *ACats, *BCats; int *ALines; /* List of lines: 0 do not output, 1 - write to output */ struct ilist *List, *TmpList, *BoundList; G_gisinit(argv[0]); pre[0] = "a"; pre[1] = "b"; module = G_define_module(); module->keywords = _("vector, spatial query"); module->description = _("Selects features from vector map (A) by features from other vector map (B)."); parse_options(&parm, &flag); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (parm.operator->answer[0] == 'e') operator = OP_EQUALS; else if (parm.operator->answer[0] == 'd') { /* operator = OP_DISJOINT; */ operator = OP_INTERSECTS; flag.reverse->answer = YES; } else if (parm.operator->answer[0] == 'i') operator = OP_INTERSECTS; else if (parm.operator->answer[0] == 't') operator = OP_TOUCHES; else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'r') operator = OP_CROSSES; else if (parm.operator->answer[0] == 'w') operator = OP_WITHIN; else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'o') operator = OP_CONTAINS; else if (parm.operator->answer[0] == 'o') { if (strcmp(parm.operator->answer, "overlaps") == 0) operator = OP_OVERLAPS; else operator = OP_OVERLAP; } else if (parm.operator->answer[0] == 'r') operator = OP_RELATE; else G_fatal_error(_("Unknown operator")); if (operator == OP_RELATE && !parm.relate->answer) { G_fatal_error(_("Required parameter <%s> not set"), parm.relate->key); } for (iopt = 0; iopt < 2; iopt++) { itype[iopt] = Vect_option_to_types(parm.type[iopt]); ifield[iopt] = atoi(parm.field[iopt]->answer); Vect_check_input_output_name(parm.input[iopt]->answer, parm.output->answer, GV_FATAL_EXIT); if ((mapset[iopt] = G_find_vector2(parm.input[iopt]->answer, NULL)) == NULL) { G_fatal_error(_("Vector map <%s> not found"), parm.input[iopt]->answer); } Vect_set_open_level(2); Vect_open_old(&(In[iopt]), parm.input[iopt]->answer, mapset[iopt]); } /* Read field info */ IFi = Vect_get_field(&(In[0]), ifield[0]); APoints = Vect_new_line_struct(); BPoints = Vect_new_line_struct(); ACats = Vect_new_cats_struct(); BCats = Vect_new_cats_struct(); List = Vect_new_list(); TmpList = Vect_new_list(); BoundList = Vect_new_list(); /* Open output */ Vect_open_new(&Out, parm.output->answer, Vect_is_3d(&(In[0]))); Vect_set_map_name(&Out, _("Output from v.select")); Vect_set_person(&Out, G_whoami()); Vect_copy_head_data(&(In[0]), &Out); Vect_hist_copy(&(In[0]), &Out); Vect_hist_command(&Out); nskipped = 0; nalines = Vect_get_num_lines(&(In[0])); #ifdef HAVE_GEOS initGEOS(G_message, G_fatal_error); GEOSGeometry *AGeom = NULL; #else void *AGeom = NULL; #endif /* Alloc space for input lines array */ ALines = (int *)G_calloc(nalines + 1, sizeof(int)); G_message(_("Building spatial index...")); Vect_build_spatial_index(&In[0]); Vect_build_spatial_index(&In[1]); /* Lines in A. Go through all lines and mark those that meets condition */ if (itype[0] & (GV_POINTS | GV_LINES)) { G_message(_("Processing features...")); for (aline = 1; aline <= nalines; aline++) { BOUND_BOX abox; G_debug(3, "aline = %d", aline); G_percent(aline, nalines, 2); /* must be before any continue */ /* Check category */ if (!flag.cat->answer && Vect_get_line_cat(&(In[0]), aline, ifield[0]) < 0) { nskipped++; continue; } /* Read line and check type */ if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS AGeom = Vect_read_line_geos(&(In[0]), aline, <ype); #endif if (!(ltype & (GV_POINT | GV_LINE))) continue; if (!AGeom) G_fatal_error(_("Unable to read line id %d from vector map <%s>"), aline, Vect_get_full_name(&(In[0]))); } else { ltype = Vect_read_line(&(In[0]), APoints, NULL, aline); } if (!(ltype & itype[0])) continue; Vect_get_line_box(&(In[0]), aline, &abox); abox.T = PORT_DOUBLE_MAX; abox.B = -PORT_DOUBLE_MAX; /* Check if this line overlaps any feature in B */ /* x Lines in B */ if (itype[1] & (GV_POINTS | GV_LINES)) { int i; int found = 0; /* Lines */ Vect_select_lines_by_box(&(In[1]), &abox, itype[1], List); for (i = 0; i < List->n_values; i++) { int bline; bline = List->value[i]; G_debug(3, " bline = %d", bline); /* Check category */ if (!flag.cat->answer && Vect_get_line_cat(&(In[1]), bline, ifield[1]) < 0) { nskipped++; continue; } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(line_relate_geos(&(In[1]), AGeom, bline, operator, parm.relate->answer)) { found = 1; break; } #endif } else { Vect_read_line(&(In[1]), BPoints, NULL, bline); if (Vect_line_check_intersection(APoints, BPoints, 0)) { found = 1; break; } } } if (found) { ALines[aline] = 1; continue; /* Go to next A line */ } } /* x Areas in B. */ if (itype[1] & GV_AREA) { int i; Vect_select_areas_by_box(&(In[1]), &abox, List); for (i = 0; i < List->n_values; i++) { int barea; barea = List->value[i]; G_debug(3, " barea = %d", barea); if (Vect_get_area_cat(&(In[1]), barea, ifield[1]) < 0) { nskipped++; continue; } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(area_relate_geos(&(In[1]), AGeom, barea, operator, parm.relate->answer)) { ALines[aline] = 1; break; } #endif } else { if (line_overlap_area(&(In[0]), aline, &(In[1]), barea)) { ALines[aline] = 1; break; } } } } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS GEOSGeom_destroy(AGeom); #endif AGeom = NULL; } } } /* Areas in A. */ if (itype[0] & GV_AREA) { int aarea, naareas; G_message(_("Processing areas...")); naareas = Vect_get_num_areas(&(In[0])); for (aarea = 1; aarea <= naareas; aarea++) { BOUND_BOX abox; G_percent(aarea, naareas, 2); /* must be before any continue */ if (Vect_get_area_cat(&(In[0]), aarea, ifield[0]) < 0) { nskipped++; continue; } Vect_get_area_box(&(In[0]), aarea, &abox); abox.T = PORT_DOUBLE_MAX; abox.B = -PORT_DOUBLE_MAX; if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS AGeom = Vect_read_area_geos(&(In[0]), aarea); #endif if (!AGeom) G_fatal_error(_("Unable to read area id %d from vector map <%s>"), aline, Vect_get_full_name(&(In[0]))); } /* x Lines in B */ if (itype[1] & (GV_POINTS | GV_LINES)) { Vect_select_lines_by_box(&(In[1]), &abox, itype[1], List); for (i = 0; i < List->n_values; i++) { int bline; bline = List->value[i]; if (!flag.cat->answer && Vect_get_line_cat(&(In[1]), bline, ifield[1]) < 0) { nskipped++; continue; } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(line_relate_geos(&(In[1]), AGeom, bline, operator, parm.relate->answer)) { add_aarea(&(In[0]), aarea, ALines); break; } #endif } else { if (line_overlap_area(&(In[1]), bline, &(In[0]), aarea)) { add_aarea(&(In[0]), aarea, ALines); continue; } } } } /* x Areas in B */ if (itype[1] & GV_AREA) { int naisles; int found = 0; /* List of areas B */ /* Make a list of features forming area A */ Vect_reset_list(List); Vect_get_area_boundaries(&(In[0]), aarea, BoundList); for (i = 0; i < BoundList->n_values; i++) { Vect_list_append(List, abs(BoundList->value[i])); } naisles = Vect_get_area_num_isles(&(In[0]), aarea); for (i = 0; i < naisles; i++) { int j, aisle; aisle = Vect_get_area_isle(&(In[0]), aarea, i); Vect_get_isle_boundaries(&(In[0]), aisle, BoundList); for (j = 0; j < BoundList->n_values; j++) { Vect_list_append(List, BoundList->value[j]); } } Vect_select_areas_by_box(&(In[1]), &abox, TmpList); for (i = 0; i < List->n_values; i++) { int j, aline; aline = abs(List->value[i]); for (j = 0; j < TmpList->n_values; j++) { int barea, bcentroid; barea = TmpList->value[j]; G_debug(3, " barea = %d", barea); if (Vect_get_area_cat(&(In[1]), barea, ifield[1]) < 0) { nskipped++; continue; } /* Check if any centroid of area B is in area A. * This test is important in if area B is completely within area A */ bcentroid = Vect_get_area_centroid(&(In[1]), barea); Vect_read_line(&(In[1]), BPoints, NULL, bcentroid); if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(area_relate_geos(&(In[1]), AGeom, barea, operator, parm.relate->answer)) { found = 1; break; } #endif } else { if (Vect_point_in_area(&(In[0]), aarea, BPoints->x[0], BPoints->y[0])) { found = 1; break; } /* Check intersectin of lines from List with area B */ if (line_overlap_area(&(In[0]), aline, &(In[1]), barea)) { found = 1; break; } } } if (found) { add_aarea(&(In[0]), aarea, ALines); break; } } } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS GEOSGeom_destroy(AGeom); #endif AGeom = NULL; } } } Vect_close(&(In[1])); #ifdef HAVE_GEOS finishGEOS(); #endif /* Write lines */ nfields = Vect_cidx_get_num_fields(&(In[0])); cats = (int **)G_malloc(nfields * sizeof(int *)); ncats = (int *)G_malloc(nfields * sizeof(int)); fields = (int *)G_malloc(nfields * sizeof(int)); for (i = 0; i < nfields; i++) { ncats[i] = 0; cats[i] = (int *)G_malloc(Vect_cidx_get_num_cats_by_index(&(In[0]), i) * sizeof(int)); fields[i] = Vect_cidx_get_field_number(&(In[0]), i); } G_message(_("Writing selected features...")); for (aline = 1; aline <= nalines; aline++) { int atype; G_debug(4, "aline = %d ALines[aline] = %d", aline, ALines[aline]); G_percent(aline, nalines, 2); if ((!flag.reverse->answer && !(ALines[aline])) || (flag.reverse->answer && ALines[aline])) continue; atype = Vect_read_line(&(In[0]), APoints, ACats, aline); Vect_write_line(&Out, atype, APoints, ACats); if (!(flag.table->answer) && (IFi != NULL)) { for (i = 0; i < ACats->n_cats; i++) { int f, j; for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == ACats->field[i]) { f = j; break; } } cats[f][ncats[f]] = ACats->cat[i]; ncats[f]++; } } } /* Copy tables */ if (!(flag.table->answer)) { int ttype, ntabs = 0; G_message(_("Writing attributes...")); /* Number of output tabs */ for (i = 0; i < Vect_get_num_dblinks(&(In[0])); i++) { int f, j; IFi = Vect_get_dblink(&(In[0]), i); for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == IFi->number) { f = j; break; } } if (ncats[f] > 0) ntabs++; } if (ntabs > 1) ttype = GV_MTABLE; else ttype = GV_1TABLE; for (i = 0; i < nfields; i++) { int ret; if (fields[i] == 0) continue; /* Make a list of categories */ IFi = Vect_get_field(&(In[0]), fields[i]); if (!IFi) { /* no table */ G_warning(_("Layer %d - no table"), fields[i]); continue; } OFi = Vect_default_field_info(&Out, IFi->number, IFi->name, ttype); ret = db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table, OFi->driver, Vect_subst_var(OFi->database, &Out), OFi->table, IFi->key, cats[i], ncats[i]); if (ret == DB_FAILED) { G_warning(_("Layer %d - unable to copy table"), fields[i]); } else { Vect_map_add_dblink(&Out, OFi->number, OFi->name, OFi->table, IFi->key, OFi->database, OFi->driver); } } } Vect_close(&(In[0])); Vect_build(&Out); Vect_close(&Out); if (nskipped > 0) { G_warning(_("%d features without category skipped"), nskipped); } G_done_msg(_("%d features written to output."), Vect_get_num_lines(&Out)); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct Map_info In, Out; static struct line_pnts *Points, *PPoints; struct line_cats *Cats, *TCats; struct ilist *slist; struct GModule *module; /* GRASS module for parsing arguments */ struct Option *map_in, *map_out; struct Option *catf_opt, *fieldf_opt, *wheref_opt; struct Option *catt_opt, *fieldt_opt, *wheret_opt, *typet_opt; struct Option *afield_opt, *nfield_opt, *abcol, *afcol, *ncol, *atype_opt; struct Flag *geo_f, *segments_f; int with_z, geo, segments; int atype, ttype; struct varray *varrayf, *varrayt; int flayer, tlayer; int afield, nfield; dglGraph_s *graph; struct ilist *nodest; int i, j, nnodes, nlines; int *dst, *nodes_to_features; int from_nr; /* 'from' features not reachable */ dglInt32_t **nxt; struct line_cats **on_path; char *segdir; char buf[2000]; /* Attribute table */ dbString sql; dbDriver *driver; struct field_info *Fi; /* initialize GIS environment */ G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */ /* initialize module */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("network")); G_add_keyword(_("shortest path")); module->label = _("Computes shortest distance via the network between " "the given sets of features."); module->description = _("Finds the shortest paths from each 'from' point to the nearest 'to' feature " "and various information about this relation are uploaded to the attribute table."); /* Define the different options as defined in gis.h */ map_in = G_define_standard_option(G_OPT_V_INPUT); map_out = G_define_standard_option(G_OPT_V_OUTPUT); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "arc_layer"; afield_opt->answer = "1"; afield_opt->label = _("Arc layer"); afield_opt->guisection = _("Cost"); atype_opt = G_define_standard_option(G_OPT_V_TYPE); atype_opt->key = "arc_type"; atype_opt->options = "line,boundary"; atype_opt->answer = "line,boundary"; atype_opt->label = _("Arc type"); atype_opt->guisection = _("Cost"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "node_layer"; nfield_opt->answer = "2"; nfield_opt->label = _("Node layer"); nfield_opt->guisection = _("Cost"); fieldf_opt = G_define_standard_option(G_OPT_V_FIELD); fieldf_opt->key = "from_layer"; fieldf_opt->label = _("From layer number or name"); fieldf_opt->guisection = _("From"); catf_opt = G_define_standard_option(G_OPT_V_CATS); catf_opt->key = "from_cats"; catf_opt->label = _("From category values"); catf_opt->guisection = _("From"); wheref_opt = G_define_standard_option(G_OPT_DB_WHERE); wheref_opt->key = "from_where"; wheref_opt->label = _("From WHERE conditions of SQL statement without 'where' keyword"); wheref_opt->guisection = _("From"); fieldt_opt = G_define_standard_option(G_OPT_V_FIELD); fieldt_opt->key = "to_layer"; fieldt_opt->description = _("To layer number or name"); fieldt_opt->guisection = _("To"); typet_opt = G_define_standard_option(G_OPT_V_TYPE); typet_opt->key = "to_type"; typet_opt->options = "point,line,boundary"; typet_opt->answer = "point"; typet_opt->description = _("To feature type"); typet_opt->guisection = _("To"); catt_opt = G_define_standard_option(G_OPT_V_CATS); catt_opt->key = "to_cats"; catt_opt->label = _("To category values"); catt_opt->guisection = _("To"); wheret_opt = G_define_standard_option(G_OPT_DB_WHERE); wheret_opt->key = "to_where"; wheret_opt->label = _("To WHERE conditions of SQL statement without 'where' keyword"); wheret_opt->guisection = _("To"); afcol = G_define_standard_option(G_OPT_DB_COLUMN); afcol->key = "arc_column"; afcol->required = NO; afcol->description = _("Arc forward/both direction(s) cost column (number)"); afcol->guisection = _("Cost"); abcol = G_define_standard_option(G_OPT_DB_COLUMN); abcol->key = "arc_backward_column"; abcol->required = NO; abcol->description = _("Arc backward direction cost column (number)"); abcol->guisection = _("Cost"); ncol = G_define_standard_option(G_OPT_DB_COLUMN); ncol->key = "node_column"; ncol->required = NO; ncol->description = _("Node cost column (number)"); ncol->guisection = _("Cost"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); segments_f = G_define_flag(); #if 0 /* use this to sync with v.net.path */ segments_f->key = 's'; segments_f->description = _("Write output as original input segments, " "not each path as one line."); #else segments_f->key = 'l'; segments_f->description = _("Write each output path as one line, " "not as original input segments."); #endif /* options and flags parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); atype = Vect_option_to_types(atype_opt); ttype = Vect_option_to_types(typet_opt); Points = Vect_new_line_struct(); PPoints = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); TCats = Vect_new_cats_struct(); slist = G_new_ilist(); Vect_check_input_output_name(map_in->answer, map_out->answer, G_FATAL_EXIT); Vect_set_open_level(2); if (1 > Vect_open_old(&In, map_in->answer, "")) G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer); with_z = Vect_is_3d(&In); if (0 > Vect_open_new(&Out, map_out->answer, with_z)) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer); } if (geo_f->answer) { geo = 1; if (G_projection() != PROJECTION_LL) G_warning(_("The current projection is not longitude-latitude")); } else geo = 0; #if 0 /* use this to sync with v.net.path */ segments = segments_f->answer; #else segments = !segments_f->answer; #endif nnodes = Vect_get_num_nodes(&In); nlines = Vect_get_num_lines(&In); dst = (int *)G_calloc(nnodes + 1, sizeof(int)); nxt = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *)); nodes_to_features = (int *)G_calloc(nnodes + 1, sizeof(int)); on_path = (struct line_cats **)G_calloc(nlines + 1, sizeof(struct line_cats *)); segdir = (char *)G_calloc(nlines + 1, sizeof(char)); if (!dst || !nxt || !nodes_to_features || !on_path || !segdir) G_fatal_error(_("Out of memory")); for (i = 1; i <= nlines; i++) { on_path[i] = Vect_new_cats_struct(); segdir[i] = 0; } /*initialise varrays and nodes list appropriatelly */ afield = Vect_get_field_number(&In, afield_opt->answer); nfield = Vect_get_field_number(&In, nfield_opt->answer); flayer = atoi(fieldf_opt->answer); tlayer = atoi(fieldt_opt->answer); if (NetA_initialise_varray(&In, flayer, GV_POINT, wheref_opt->answer, catf_opt->answer, &varrayf) <= 0) { G_fatal_error(_("No 'from' features selected. " "Please check options '%s', '%s', '%s'."), fieldf_opt->key, wheref_opt->key, catf_opt->key); } if (NetA_initialise_varray(&In, tlayer, ttype, wheret_opt->answer, catt_opt->answer, &varrayt) <= 0) { G_fatal_error(_("No 'to' features selected. " "Please check options '%s', '%s', '%s'."), fieldt_opt->key, wheret_opt->key, catt_opt->key); } nodest = Vect_new_list(); NetA_varray_to_nodes(&In, varrayt, nodest, nodes_to_features); if (nodest->n_values == 0) G_fatal_error(_("No 'to' features")); if (0 != Vect_net_build_graph(&In, atype, afield, nfield, afcol->answer, abcol->answer, ncol->answer, geo, 2)) G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In)); graph = Vect_net_get_graph(&In); G_message(_("Distances to 'to' features ...")); NetA_distance_to_points(graph, nodest, dst, nxt); /* Create table */ Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); db_init_string(&sql); driver = db_start_driver_open_database(Fi->driver, Fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_set_error_handler_driver(driver); sprintf(buf, "create table %s ( cat integer, tcat integer, dist double precision)", Fi->table); db_set_string(&sql, buf); G_debug(2, "%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(_("Cannot create index")); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); G_message(_("Tracing paths from 'from' features ...")); from_nr = 0; for (i = 1; i <= nlines; i++) { if (varrayf->c[i]) { int type = Vect_read_line(&In, Points, Cats, i); int node, tcat, cat; double cost; dglInt32_t *vertex, vertex_id; if (!Vect_cat_get(Cats, flayer, &cat)) continue; if (type & GV_POINTS) { node = Vect_find_node(&In, Points->x[0], Points->y[0], Points->z[0], 0, 0); } else { Vect_get_line_nodes(&In, i, &node, NULL); } if (node < 1) continue; if (dst[node] < 0) { /* unreachable */ from_nr++; continue; } cost = dst[node] / (double)In.dgraph.cost_multip; vertex = dglGetNode(graph, node); vertex_id = node; slist->n_values = 0; while (nxt[vertex_id] != NULL) { int edge_id; edge_id = (int) dglEdgeGet_Id(graph, nxt[vertex_id]); if (segments) { Vect_cat_set(on_path[abs(edge_id)], 1, cat); if (edge_id < 0) { segdir[abs(edge_id)] = 1; } } else G_ilist_add(slist, edge_id); vertex = dglEdgeGet_Tail(graph, nxt[vertex_id]); vertex_id = dglNodeGet_Id(graph, vertex); } G_debug(3, "read line %d, vertex id %d", nodes_to_features[vertex_id], (int)vertex_id); Vect_read_line(&In, NULL, TCats, nodes_to_features[vertex_id]); if (!Vect_cat_get(TCats, tlayer, &tcat)) continue; Vect_write_line(&Out, type, Points, Cats); sprintf(buf, "insert into %s values (%d, %d, %f)", Fi->table, cat, tcat, cost); db_set_string(&sql, buf); G_debug(3, "%s", db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Cannot insert new record: %s"), db_get_string(&sql)); }; if (!segments) { Vect_reset_line(PPoints); for (j = 0; j < slist->n_values; j++) { Vect_read_line(&In, Points, NULL, abs(slist->value[j])); if (slist->value[j] > 0) Vect_append_points(PPoints, Points, GV_FORWARD); else Vect_append_points(PPoints, Points, GV_BACKWARD); PPoints->n_points--; } PPoints->n_points++; Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, GV_LINE, PPoints, Cats); } } } if (segments) { for (i = 1; i <= nlines; i++) { if (on_path[i]->n_cats > 0) { int type; if (segdir[i]) { type = Vect_read_line(&In, PPoints, NULL, i); Vect_reset_line(Points); Vect_append_points(Points, PPoints, GV_BACKWARD); } else type = Vect_read_line(&In, Points, NULL, i); Vect_write_line(&Out, type, Points, on_path[i]); } } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); Vect_build(&Out); Vect_close(&In); Vect_close(&Out); for (i = 1; i <= nlines; i++) Vect_destroy_cats_struct(on_path[i]); G_free(on_path); G_free(nodes_to_features); G_free(dst); G_free(nxt); G_free(segdir); if (from_nr) G_warning(n_("%d 'from' feature was not reachable", "%d 'from' features were not reachable", from_nr), from_nr); exit(EXIT_SUCCESS); }
/* Create GRASS vector output map. Create attribute table. Calculate geometries and write them into the output map. Calculate attributes and write them into the output map's attribute table. */ void writeMap() { int i, j; double xlength, ylength, zlength; double length, flatLength, bailLength; double xoffset, yoffset, zoffset; double xys[12]; int ratio; double zRatio; /* attributes to be written to output map */ int boneID; int skelID; int unitID; int oldID; int cat; char *organization; char buf[MAXSTR]; if ( numPoints < 2 ) { G_fatal_error ("Less than two valid measurement points in input file"); } G_message (_("Constructing geometries for %i valid points:"), numPoints ); /* CREATE OUTPUT VECTOR MAP */ if (Vect_legal_filename(output->answer) < 0) { G_fatal_error(_("Use '%s' option to change vector map name"), output->key); } Map = (struct Map_info *) G_malloc (sizeof ( struct Map_info ) ); if (Vect_open_new(Map, output->answer, WITH_Z) < 0) { G_fatal_error(_("Unable to create vector map <%s>"), output->answer); } Vect_set_map_name(Map, output->answer); Vect_hist_command(Map); if ((organization = getenv("GRASS_ORGANIZATION"))) { Vect_set_organization(Map, organization); } else { Vect_set_organization(Map, "UNKNOWN ORGANIZATION"); } Vect_set_date(Map, G_date()); Vect_set_person(Map, G_whoami()); Vect_set_map_date(Map, ""); Vect_set_scale(Map, 2400); Vect_set_comment(Map, ""); Vect_set_zone(Map, 0); Vect_set_thresh(Map, 0.0); /* START DBMS INTERFACE */ /* prepare strings for use in db_* calls */ db_init_string(&sql); /* start default database driver */ Fi = Vect_default_field_info(Map, 1, NULL, GV_1TABLE); driver = db_start_driver_open_database(Fi->driver,Vect_subst_var(Fi->database, Map)); if (driver == NULL) { Vect_delete(output->answer); G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Vect_subst_var(Fi->database, Map), Fi->driver); } /* create attribute table */ db_begin_transaction ( driver ); sprintf(buf, "create table %s (cat integer, skel_id integer, bone_id integer, unit_id integer, GRASSRGB varchar(11),BONERGB varchar(11));", Fi->table); if ( DEBUG ) { fprintf ( stderr, "Creating attribute table: %s\n", buf ); } db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) { Vect_delete(output->answer); G_fatal_error(_("Unable to create attribute table: %s"), db_get_string(&sql)); } if (db_grant_on_table (driver, output->answer, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) { Vect_delete(output->answer); G_fatal_error(_("Unable to grant privileges on table <%s>"), output->answer); } if (db_create_index2(driver, output->answer, "cat") != DB_OK) { G_warning(_("Unable to create index for table <%s>, key <%s>"), output->answer, "cat"); } /* link vector map to attribute table */ if (Vect_map_add_dblink(Map, 1, NULL, Fi->table, "cat", Fi->database, Fi->driver) ) { Vect_delete(output->answer); G_fatal_error(_("Unable to add database link for vector map <%s>"), Vect_get_full_name(Map)); } /* PROCESS POINTS AND WRITE GEOMETRIES */ /* Now process point measurements and write geometries into output vector map. */ /* At this stage, the global points array has an even number of valid points. */ oldID = pointTable[0].SKEL_ID; unitID = 1; cat = 0; for ( i = 0; i < numPoints; i = i + 2 ) { /* This boneID is a generalized ID that does not differentiate between start and end measurement. */ boneID = (int) pointTable[i+1].BONE_ID / 2; skelID = pointTable[i+1].SKEL_ID; /* get coordinates for top and bottom of bone */ ax = pointTable[i].X; ay = pointTable[i].Y; az = pointTable[i].Z; bx = pointTable[i+1].X; by = pointTable[i+1].Y; bz = pointTable[i+1].Z; /* get vector lengths */ xlength = fabs (ax - bx); ylength = fabs (ay - by); zlength = fabs (az - bz); /* get real length */ length = sqrt ( (xlength*xlength) + (ylength*ylength) + (zlength*zlength) ); /* get length in x/y plane */ flatLength = sqrt ( (xlength*xlength) + (ylength*ylength) ); /* determine ratio for triangles, depending on bone type */ ratio = 12; /* default */ for ( j = 0; j < NUM_RATIOS; j ++ ) { if ( boneID == RATIO_ID[j] ) { ratio = RATIO_VAL[j]; } } /* get bail length */ bailLength = (double) ( length / (double) ratio); /* calculate bail offsets from top point (one bail is mirror of the other) */ xoffset = (bailLength * ylength) / flatLength; yoffset = ( (bailLength * xlength) / flatLength ) * (-1); zoffset = 0; xys[0]= ax + xoffset; xys[1]= ay + yoffset; xys[2]= az + zoffset; xys[6]= ax - xoffset; xys[7]= ay - yoffset; xys[8]= az - zoffset; /* get 3rd axis offsets */ zRatio = (zlength/ratio) / flatLength; xoffset = xlength * zRatio; yoffset = ylength * zRatio; zoffset = (flatLength/ratio) * (-1); xys[3]= ax + xoffset; xys[4]= ay + yoffset; xys[5]= az + zoffset; xys[9]= ax - xoffset; xys[10]= ay - yoffset; xys[11]= az - zoffset; /* Increase unit ID by "1", if we have another skeleton ID */ if ( oldID != pointTable[i+1].SKEL_ID ) { unitID ++; oldID = pointTable[i+1].SKEL_ID; /* switch to next colour for next geometry */ RGBNUM ++; if ( RGBNUM == RGBMAX ) { RGBNUM = 0; } } /* write geometries */ if ( MODE == MODE_DARTS ) { writeTriangle ( cat, skelID, boneID, unitID, xys, 0, 6 ); cat ++; writeTriangle ( cat, skelID, boneID, unitID, xys, 3, 9 ); cat ++; } if ( MODE == MODE_LINES ) { writeLine ( cat, skelID, boneID, unitID ); cat ++; } if ( MODE == MODE_PLANES_H ) { writeTriangle ( cat, skelID, boneID, unitID, xys, 0, 6 ); cat ++; } if ( MODE == MODE_PLANES_V ) { writeTriangle ( cat, skelID, boneID, unitID, xys, 3, 9 ); cat ++; } if ( MODE == MODE_POINTS ) { writePoints ( cat, skelID, boneID, unitID ); cat = cat + 2; } if ( MODE == MODE_PYRAMIDS ) { writeTriangle ( cat, skelID, boneID, unitID, xys, 0, 3 ); cat ++; writeTriangle ( cat, skelID, boneID, unitID, xys, 3, 6 ); cat ++; writeTriangle ( cat, skelID, boneID, unitID, xys, 6, 9 ); cat ++; writeTriangle ( cat, skelID, boneID, unitID, xys, 9, 0 ); cat ++; writeSquare ( cat, skelID, boneID, unitID, xys ); cat ++; } /* switch to next colour for bone colouring */ RGBNUM_BONE ++; if ( RGBNUM_BONE == RGBMAX ) { RGBNUM_BONE = 0; } G_percent ( i, numPoints - 2, 1 ); } fprintf ( stdout, "\n" ); /* commit DBMS actions */ db_commit_transaction(driver); db_close_database_shutdown_driver(driver); if (!Vect_build(Map)) { G_warning("Building topology failed"); } Vect_close(Map); db_free_string(&sql); }
int main(int argc, char **argv) { int field, type, vertex_type; double dmax; struct Option *in_opt, *out_opt, *type_opt, *dmax_opt, *lfield_opt; struct Flag *inter_flag, *vertex_flag, *table_flag, *node_flag; struct GModule *module; char *mapset; struct Map_info In, Out; struct line_cats *LCats; struct line_pnts *LPoints; char buf[2000]; G_gisinit(argv[0]); module = G_define_module(); module->keywords = _("vector, geometry"); module->description = _("Create points along input lines in new vector with 2 layers."); in_opt = G_define_standard_option(G_OPT_V_INPUT); in_opt->description = _("Input vector map containing lines"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->description = _("Output vector map where points will be written"); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->answer = "point,line,boundary,centroid"; lfield_opt = G_define_standard_option(G_OPT_V_FIELD); lfield_opt->key = "llayer"; lfield_opt->answer = "1"; lfield_opt->description = "Line layer"; node_flag = G_define_flag(); node_flag->key = 'n'; node_flag->description = _("Write line nodes"); vertex_flag = G_define_flag(); vertex_flag->key = 'v'; vertex_flag->description = _("Write line vertices"); inter_flag = G_define_flag(); inter_flag->key = 'i'; inter_flag->description = _("Interpolate points between line vertices"); dmax_opt = G_define_option(); dmax_opt->key = "dmax"; dmax_opt->type = TYPE_DOUBLE; dmax_opt->required = NO; dmax_opt->answer = "100"; dmax_opt->description = _("Maximum distance between points in map units"); table_flag = G_define_flag(); table_flag->key = 't'; table_flag->description = _("Do not create attribute table"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); LCats = Vect_new_cats_struct(); PCats = Vect_new_cats_struct(); LPoints = Vect_new_line_struct(); PPoints = Vect_new_line_struct(); db_init_string(&stmt); field = atoi(lfield_opt->answer); type = Vect_option_to_types(type_opt); dmax = atof(dmax_opt->answer); if (node_flag->answer && vertex_flag->answer) G_fatal_error(_("Use either -n or -v flag, not both")); if (node_flag->answer) vertex_type = GV_NODE; else if (vertex_flag->answer) vertex_type = GV_VERTEX; else vertex_type = 0; Vect_check_input_output_name(in_opt->answer, out_opt->answer, GV_FATAL_EXIT); /* Open input lines */ mapset = G_find_vector2(in_opt->answer, NULL); if (mapset == NULL) G_fatal_error(_("Vector map <%s> not found"), in_opt->answer); Vect_set_open_level(2); Vect_open_old(&In, in_opt->answer, mapset); /* Open output segments */ Vect_open_new(&Out, out_opt->answer, Vect_is_3d(&In)); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); /* Table */ if (!table_flag->answer) { struct field_info *Fin; /* copy input table */ Fin = Vect_get_field(&In, field); if (Fin) { /* table defined */ int ret; Fi = Vect_default_field_info(&Out, 1, NULL, GV_MTABLE); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, Fin->key, Fi->database, Fi->driver); ret = db_copy_table(Fin->driver, Fin->database, Fin->table, Fi->driver, Vect_subst_var(Fi->database, &Out), Fi->table); if (ret == DB_FAILED) { G_fatal_error(_("Unable to copy table <%s>"), Fin->table); } } Fi = Vect_default_field_info(&Out, 2, NULL, GV_MTABLE); Vect_map_add_dblink(&Out, 2, NULL, Fi->table, "cat", Fi->database, Fi->driver); /* Open driver */ driver = db_start_driver_open_database(Fi->driver, Fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); sprintf(buf, "create table %s ( cat int, lcat int, along double precision )", Fi->table); db_append_string(&stmt, buf); if (db_execute_immediate(driver, &stmt) != DB_OK) { db_close_database_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&stmt)); } if (db_create_index2(driver, Fi->table, "cat") != DB_OK) G_warning(_("Unable to create index for table <%s>, key <%s>"), Fi->table, "cat"); 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); } point_cat = 1; if (type & (GV_POINTS | GV_LINES)) { int line, nlines; nlines = Vect_get_num_lines(&In); for (line = 1; line <= nlines; line++) { int ltype, cat; G_debug(3, "line = %d", line); ltype = Vect_read_line(&In, LPoints, LCats, line); if (!(ltype & type)) continue; Vect_cat_get(LCats, field, &cat); if (LPoints->n_points <= 1) { write_point(&Out, LPoints->x[0], LPoints->y[0], LPoints->z[0], cat, 0.0, table_flag->answer); } else { /* lines */ write_line(&Out, LPoints, cat, vertex_type, inter_flag->answer, dmax, table_flag->answer); } G_percent(line, nlines, 2); } } if (type == GV_AREA) { int area, nareas, centroid, cat; nareas = Vect_get_num_areas(&In); for (area = 1; area <= nareas; area++) { int i, isle, nisles; centroid = Vect_get_area_centroid(&In, area); cat = -1; if (centroid > 0) { Vect_read_line(&In, NULL, LCats, centroid); Vect_cat_get(LCats, field, &cat); } Vect_get_area_points(&In, area, LPoints); write_line(&Out, LPoints, cat, vertex_type, inter_flag->answer, dmax, table_flag->answer); nisles = Vect_get_area_num_isles(&In, area); for (i = 0; i < nisles; i++) { isle = Vect_get_area_isle(&In, area, i); Vect_get_isle_points(&In, isle, LPoints); write_line(&Out, LPoints, cat, vertex_type, inter_flag->answer, dmax, table_flag->answer); } G_percent(area, nareas, 2); } } if (!table_flag->answer) { db_commit_transaction(driver); db_close_database_shutdown_driver(driver); } Vect_build(&Out); /* Free, close ... */ Vect_close(&In); Vect_close(&Out); G_done_msg(_("%d points written to output vector map"), point_cat - 1); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct GModule *module; struct Option *out_opt, *in_opt; struct Flag *z_flag, *circle_flag, *l_flag, *int_flag; char buf[2000]; /* DWG */ char path[2000]; short initerror, entset, retval; AD_OBJHANDLE pspace, mspace; PAD_ENT_HDR adenhd; PAD_ENT aden; AD_VMADDR entlist; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("import")); module->description = _("Converts DWG/DXF to GRASS vector map"); in_opt = G_define_standard_option(G_OPT_F_INPUT); in_opt->description = _("Name of DWG or DXF file"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->required = YES; layers_opt = G_define_option(); layers_opt->key = "layers"; layers_opt->type = TYPE_STRING; layers_opt->required = NO; layers_opt->multiple = YES; layers_opt->description = _("List of layers to import"); invert_flag = G_define_flag(); invert_flag->key = 'i'; invert_flag->description = _("Invert selection by layers (don't import layers in list)"); z_flag = G_define_flag(); z_flag->key = 'z'; z_flag->description = _("Create 3D vector map"); circle_flag = G_define_flag(); circle_flag->key = 'c'; circle_flag->description = _("Write circles as points (centre)"); l_flag = G_define_flag(); l_flag->key = 'l'; l_flag->description = _("List available layers and exit"); int_flag = G_define_flag(); int_flag->key = 'n'; int_flag->description = _("Use numeric type for attribute \"layer\""); if (G_parser(argc, argv)) exit(EXIT_FAILURE); db_init_string(&sql); db_init_string(&str); adenhd = (PAD_ENT_HDR) G_malloc(sizeof(AD_ENT_HDR)); aden = (PAD_ENT) G_malloc(sizeof(AD_ENT)); Layer = (PAD_LAY) G_malloc(sizeof(AD_LAY)); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Block = NULL; atrans = 20; /* nested, recursive levels */ Trans = (TRANS *) G_malloc(atrans * sizeof(TRANS)); /* Init OpenDWG */ sprintf(path, "%s/etc/adinit.dat", G_gisbase()); if (!adInitAd2(path, &initerror)) { sprintf(buf, _("Unable to initialize OpenDWG Toolkit, error: %d: %s."), initerror, adErrorStr(initerror)); if (initerror == AD_UNABLE_TO_OPEN_INIT_FILE) sprintf(buf, _("%s Cannot open %s"), buf, path); G_fatal_error(buf); } adSetupDwgRead(); adSetupDxfRead(); /* Open input file */ if ((dwghandle = adLoadFile(in_opt->answer, AD_PRELOAD_ALL, 1)) == NULL) { G_fatal_error(_("Unable to open input file <%s>. Error %d: %s"), in_opt->answer, adError(), adErrorStr(adError())); } if (l_flag->answer) { /* List layers */ PAD_TB adtb; AD_DWGHDR adhd; int i; char on, frozen, vpfrozen, locked; adtb = (PAD_TB) G_malloc(sizeof(AD_TB)); G_debug(2, "%d layers", (int)adNumLayers(dwghandle)); adReadHeaderBlock(dwghandle, &adhd); adStartLayerGet(dwghandle); fprintf(stdout, "%d layers:\n", (int)adNumLayers(dwghandle)); for (i = 0; i < (int)adNumLayers(dwghandle); i++) { adGetLayer(dwghandle, &(adtb->lay)); if (!adtb->lay.purgedflag) { fprintf(stdout, "%s COLOR %d, ", adtb->lay.name, adtb->lay.color); } adGetLayerState(dwghandle, adtb->lay.objhandle, &on, &frozen, &vpfrozen, &locked); if (on) fprintf(stdout, "ON, "); else fprintf(stdout, "OFF, "); if (frozen) fprintf(stdout, "FROZEN, "); else fprintf(stdout, "THAWED, "); if (vpfrozen) fprintf(stdout, "VPFROZEN, "); else fprintf(stdout, "VPTHAWED, "); if (locked) fprintf(stdout, "LOCKED\n"); else fprintf(stdout, "UNLOCKED\n"); } adCloseFile(dwghandle); adCloseAd2(); exit(EXIT_SUCCESS); } /* open output vector */ if (Vect_open_new(&Map, out_opt->answer, z_flag->answer) < 0) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); Vect_hist_command(&Map); /* Add DB link */ 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>"), Vect_subst_var(Fi->database, &Map), Fi->driver); } db_set_error_handler_driver(driver); db_begin_transaction(driver); /* Create table */ if (int_flag->answer) { /* List layers */ sprintf(buf, "create table %s ( cat integer, entity_name varchar(20), color int, weight int, " "layer real, block varchar(100), txt varchar(100) )", Fi->table); } else { sprintf(buf, "create table %s ( cat integer, entity_name varchar(20), color int, weight int, " "layer varchar(100), block varchar(100), txt varchar(100) )", Fi->table); } db_set_string(&sql, buf); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); 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 for table <%s>, key <%s>"), Fi->table, GV_KEY_COLUMN); 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); cat = 1; n_elements = n_skipped = 0; /* Write each entity. Some entities may be composed by other entities (like INSERT or BLOCK) */ /* Set transformation for first (index 0) level */ Trans[0].dx = Trans[0].dy = Trans[0].dz = 0; Trans[0].xscale = Trans[0].yscale = Trans[0].zscale = 1; Trans[0].rotang = 0; if (adGetBlockHandle(dwghandle, pspace, AD_PAPERSPACE_HANDLE)) { entlist = adEntityList(dwghandle, pspace); adStartEntityGet(entlist); for (entset = 0; entset < 2; entset++) { do { if (!(retval = adGetEntity(entlist, adenhd, aden))) continue; wrentity(adenhd, aden, 0, entlist, circle_flag->answer); } while (retval == 1); if (entset == 0) { if (adGetBlockHandle(dwghandle, mspace, AD_MODELSPACE_HANDLE)) { entlist = adEntityList(dwghandle, mspace); adStartEntityGet(entlist); } } } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); adCloseFile(dwghandle); adCloseAd2(); Vect_build(&Map, stderr); Vect_close(&Map); if (n_skipped > 0) G_message(_("%d elements skipped (layer name was not in list)"), n_skipped); G_done_msg(_("%d elements processed"), n_elements); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int field, type, vertex_type; double dmax; char buf[DB_SQL_MAX]; struct { struct Option *input, *output, *type, *dmax, *lfield, *use; } opt; struct { struct Flag *table, *inter; } flag; struct GModule *module; struct Map_info In, Out; struct line_cats *LCats; struct line_pnts *LPoints; dbDriver *driver; struct field_info *Fi; dbString stmt; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); G_add_keyword("3D"); G_add_keyword(_("node")); G_add_keyword(_("vertex")); module->description = _("Creates points along input lines in new vector map with 2 layers."); opt.input = G_define_standard_option(G_OPT_V_INPUT); opt.lfield = G_define_standard_option(G_OPT_V_FIELD); opt.lfield->key = "llayer"; opt.lfield->answer = "1"; opt.lfield->label = "Line layer number or name"; opt.lfield->guisection = _("Selection"); opt.type = G_define_standard_option(G_OPT_V3_TYPE); opt.type->answer = "point,line,boundary,centroid,face"; opt.type->guisection = _("Selection"); opt.output = G_define_standard_option(G_OPT_V_OUTPUT); opt.use = G_define_option(); opt.use->key = "use"; opt.use->type = TYPE_STRING; opt.use->required = NO; opt.use->description = _("Use line nodes or vertices only"); opt.use->options = "node,vertex"; opt.dmax = G_define_option(); opt.dmax->key = "dmax"; opt.dmax->type = TYPE_DOUBLE; opt.dmax->required = NO; opt.dmax->answer = "100"; opt.dmax->description = _("Maximum distance between points in map units"); flag.inter = G_define_flag(); flag.inter->key = 'i'; flag.inter->description = _("Interpolate points between line vertices (only for use=vertex)"); flag.table = G_define_standard_flag(G_FLG_V_TABLE); if (G_parser(argc, argv)) exit(EXIT_FAILURE); LCats = Vect_new_cats_struct(); LPoints = Vect_new_line_struct(); db_init_string(&stmt); type = Vect_option_to_types(opt.type); dmax = atof(opt.dmax->answer); vertex_type = 0; if (opt.use->answer) { if (opt.use->answer[0] == 'n') vertex_type = GV_NODE; else vertex_type = GV_VERTEX; } Vect_check_input_output_name(opt.input->answer, opt.output->answer, G_FATAL_EXIT); /* Open input lines */ Vect_set_open_level(2); if (Vect_open_old2(&In, opt.input->answer, "", opt.lfield->answer) < 0) G_fatal_error(_("Unable to open vector map <%s>"), opt.input->answer); Vect_set_error_handler_io(&In, &Out); field = Vect_get_field_number(&In, opt.lfield->answer); /* Open output segments */ if (Vect_open_new(&Out, opt.output->answer, Vect_is_3d(&In)) < 0) G_fatal_error(_("Unable to create vector map <%s>"), opt.output->answer); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); /* Table */ Fi = NULL; if (!flag.table->answer) { struct field_info *Fin; /* copy input table */ Fin = Vect_get_field(&In, field); if (Fin) { /* table defined */ int ret; Fi = Vect_default_field_info(&Out, 1, NULL, GV_MTABLE); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, Fin->key, Fi->database, Fi->driver); ret = db_copy_table(Fin->driver, Fin->database, Fin->table, Fi->driver, Vect_subst_var(Fi->database, &Out), Fi->table); if (ret == DB_FAILED) { G_fatal_error(_("Unable to copy table <%s>"), Fin->table); } } Fi = Vect_default_field_info(&Out, 2, NULL, GV_MTABLE); Vect_map_add_dblink(&Out, 2, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); /* Open driver */ driver = db_start_driver_open_database(Fi->driver, Fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_set_error_handler_driver(driver); if (field == -1) sprintf(buf, "create table %s ( cat int, along double precision )", Fi->table); else sprintf(buf, "create table %s ( cat int, lcat int, along double precision )", Fi->table); db_append_string(&stmt, buf); if (db_execute_immediate(driver, &stmt) != DB_OK) { G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&stmt)); } if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK) G_warning(_("Unable to create index for table <%s>, key <%s>"), Fi->table, GV_KEY_COLUMN); 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); } if (type & (GV_POINTS | GV_LINES | GV_FACE)) { int line, nlines, nskipped; nskipped = 0; nlines = Vect_get_num_lines(&In); for (line = 1; line <= nlines; line++) { int ltype, cat; G_debug(3, "line = %d", line); G_percent(line, nlines, 2); ltype = Vect_read_line(&In, LPoints, LCats, line); if (!(ltype & type)) continue; if (!Vect_cat_get(LCats, field, &cat) && field != -1) { nskipped++; continue; } /* Assign CAT for layer 0 objects (i.e. boundaries) */ if (field == -1) cat = -1; if (LPoints->n_points <= 1) { write_point(&Out, LPoints->x[0], LPoints->y[0], LPoints->z[0], cat, 0.0, driver, Fi); } else { /* lines */ write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer, dmax, driver, Fi); } } if (nskipped > 0) G_warning(_("%d features without category in layer <%d> skipped. " "Note that features without category (usually boundaries) are not " "skipped when '%s=-1' is given."), nskipped, field, opt.lfield->key); } if (type == GV_AREA) { int area, nareas, centroid, cat; nareas = Vect_get_num_areas(&In); for (area = 1; area <= nareas; area++) { int i, isle, nisles; G_percent(area, nareas, 2); centroid = Vect_get_area_centroid(&In, area); cat = -1; if (centroid > 0) { Vect_read_line(&In, NULL, LCats, centroid); if (!Vect_cat_get(LCats, field, &cat)) continue; } Vect_get_area_points(&In, area, LPoints); write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer, dmax, driver, Fi); nisles = Vect_get_area_num_isles(&In, area); for (i = 0; i < nisles; i++) { isle = Vect_get_area_isle(&In, area, i); Vect_get_isle_points(&In, isle, LPoints); write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer, dmax, driver, Fi); } } } if (!flag.table->answer) { db_commit_transaction(driver); db_close_database_shutdown_driver(driver); } Vect_build(&Out); /* Free, close ... */ Vect_close(&In); G_done_msg(_("%d points written to output vector map."), Vect_get_num_primitives(&Out, GV_POINT)); Vect_close(&Out); exit(EXIT_SUCCESS); }
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; int feature; 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->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"); 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; 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) { G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be written to the table.")); value_flag = 0; } if (z_flg->answer) Vect_open_new(&Map, out_opt->answer, 1); else Vect_open_new(&Map, out_opt->answer, 0); 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)) { 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, 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); if (!no_topol->answer) Vect_build(&Map); /* insert cats and optionally labels if raster cats were used */ if (driver && value_flag) { char buf[1000]; int c, i, cat, fidx, ncats, lastcat, tp, id; fidx = Vect_cidx_get_field_index(&Map, 1); if (fidx >= 0) { ncats = Vect_cidx_get_num_cats_by_index(&Map, fidx); lastcat = -1; for (c = 0; c < ncats; c++) { Vect_cidx_get_cat_by_index(&Map, fidx, c, &cat, &tp, &id); if (lastcat == cat) continue; /* 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, 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)); lastcat = cat; } } } if (has_cats) Rast_free_cats(&RastCats); if (driver != NULL) { db_commit_transaction(driver); db_close_database_shutdown_driver(driver); } Vect_close(&Map); G_done_msg(" "); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { /* loop */ int i, j; /* store filename and path */ char *dig_file; char buf[2000]; /* Other local variables */ int attCount, nbreaks; struct grid_description grid_info; struct Cell_head window; struct Map_info Map; struct Option *vectname, *grid, *coord, *box, *angle, *position_opt, *breaks; struct GModule *module; struct Flag *points_fl, *line_fl; int points_p, line_p, output_type; char *desc; struct line_pnts *Points; struct line_cats *Cats; /* Attributes */ struct field_info *Fi; dbDriver *Driver; dbString sql; G_gisinit(argv[0]); /* Set description */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); module->description = _("Creates a vector map of a user-defined grid."); vectname = G_define_standard_option(G_OPT_V_OUTPUT); vectname->key = "map"; grid = G_define_option(); grid->key = "grid"; grid->key_desc = _("rows,columns"); grid->type = TYPE_INTEGER; grid->required = YES; grid->multiple = NO; grid->description = _("Number of rows and columns in grid"); position_opt = G_define_option(); position_opt->key = "position"; position_opt->type = TYPE_STRING; position_opt->required = NO; position_opt->multiple = NO; position_opt->options = "region,coor"; position_opt->answer = "region"; position_opt->description = _("Where to place the grid"); desc = NULL; G_asprintf(&desc, "region;%s;coor;%s", _("current region"), _("use 'coor' and 'box' options")); position_opt->descriptions = desc; coord = G_define_option(); coord->key = "coor"; coord->key_desc = "x,y"; coord->type = TYPE_DOUBLE; coord->required = NO; coord->multiple = NO; coord->description = _("Lower left easting and northing coordinates of map"); box = G_define_option(); box->key = "box"; box->key_desc = _("width,height"); box->type = TYPE_DOUBLE; box->required = NO; box->multiple = NO; box->description = _("Width and height of boxes in grid"); angle = G_define_option(); angle->key = "angle"; angle->type = TYPE_DOUBLE; angle->required = NO; angle->description = _("Angle of rotation (in degrees counter-clockwise)"); angle->answer = "0"; breaks = G_define_option(); breaks->key = "breaks"; breaks->type = TYPE_INTEGER; breaks->required = NO; breaks->description = _("Number of vertex points per grid cell"); breaks->options = "0-60"; breaks->answer = "3"; points_fl = G_define_flag(); points_fl->key = 'p'; points_fl->description = _("Create grid of points instead of areas and centroids"); line_fl = G_define_flag(); line_fl->key = 'l'; line_fl->description = _("Create grid as lines, instead of areas"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); line_p = line_fl->answer; if (line_p) { output_type = GV_LINE; } else { output_type = GV_BOUNDARY; } points_p = points_fl->answer; /* get the current window */ G_get_window(&window); /* * information we need to collect from user: origin point x and y (lower * left), shift in x, shift in y, number of rows, number of cols */ dig_file = G_store(vectname->answer); /* Number of row and cols */ grid_info.num_rows = atoi(grid->answers[0]); grid_info.num_cols = atoi(grid->answers[1]); grid_info.angle = M_PI / 180 * atof(angle->answer); nbreaks = atoi(breaks->answer); /* Position */ if (position_opt->answer[0] == 'r') { /* region */ if (coord->answer) G_fatal_error(_("'coor' and 'position=region' are exclusive options")); if (box->answer) G_fatal_error(_("'box' and 'position=region' are exclusive options")); if (grid_info.angle != 0.0) G_fatal_error(_("'angle' and 'position=region' are exclusive options")); grid_info.origin_x = window.west; grid_info.origin_y = window.south; grid_info.length = (window.east - window.west) / grid_info.num_cols; grid_info.width = (window.north - window.south) / grid_info.num_rows; G_debug(2, "x = %e y = %e l = %e w = %e", grid_info.origin_x, grid_info.origin_y, grid_info.length, grid_info.width); } else { if (!coord->answer) G_fatal_error(_("'coor' option missing")); if (!box->answer) G_fatal_error(_("'box' option missing")); if (!G_scan_easting (coord->answers[0], &(grid_info.origin_x), window.proj)) G_fatal_error(_("Invalid easting"));; if (!G_scan_northing (coord->answers[1], &(grid_info.origin_y), window.proj)) G_fatal_error(_("Invalid northing"));; if (!G_scan_resolution (box->answers[0], &(grid_info.length), window.proj)) G_fatal_error(_("Invalid distance"));; if (!G_scan_resolution (box->answers[1], &(grid_info.width), window.proj)) G_fatal_error(_("Invalid distance"));; } /* * vector rows are the actual number of rows of vectors to make up the * entire grid. ditto for cols. */ grid_info.num_vect_rows = grid_info.num_rows + 1; grid_info.num_vect_cols = grid_info.num_cols + 1; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); db_init_string(&sql); /* Open output map */ if (0 > Vect_open_new(&Map, dig_file, 0)) { G_fatal_error(_("Unable to create vector map <%s>"), dig_file); } Vect_hist_command(&Map); /* Open database, create table */ Fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Map, Fi->number, Fi->name, Fi->table, Fi->key, 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); db_set_error_handler_driver(Driver); if (grid_info.num_rows < 27 && grid_info.num_cols < 27) { sprintf(buf, "create table %s ( cat integer, row integer, col integer, " "rown varchar(1), coln varchar(1))", Fi->table); } else { sprintf(buf, "create table %s ( cat integer, row integer, col integer)", Fi->table); } db_set_string(&sql, buf); G_debug(1, "SQL: %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, Fi->key) != 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); if (!points_p) { /* create areas */ write_grid(&grid_info, &Map, nbreaks, output_type); } /* Create a grid of label points at the centres of the grid cells */ G_verbose_message(_("Creating centroids...")); /* Write out centroids and attributes */ /* If the output id is lines it skips to add centroids and attributes TODO decide what to write in the attribute table */ if (!line_p) { db_begin_transaction(Driver); attCount = 0; for (i = 0; i < grid_info.num_rows; ++i) { for (j = 0; j < grid_info.num_cols; ++j) { double x, y; const int point_type = points_p ? GV_POINT : GV_CENTROID; x = grid_info.origin_x + (0.5 + j) * grid_info.length; y = grid_info.origin_y + (0.5 + i) * grid_info.width; rotate(&x, &y, grid_info.origin_x, grid_info.origin_y, grid_info.angle); Vect_reset_line(Points); Vect_reset_cats(Cats); Vect_append_point(Points, x, y, 0.0); Vect_cat_set(Cats, 1, attCount + 1); Vect_write_line(&Map, point_type, Points, Cats); sprintf(buf, "insert into %s values ", Fi->table); if (db_set_string(&sql, buf) != DB_OK) G_fatal_error(_("Unable to fill attribute table")); if (grid_info.num_rows < 27 && grid_info.num_cols < 27) { sprintf(buf, "( %d, %d, %d, '%c', '%c' )", attCount + 1, grid_info.num_rows - i, j + 1, 'A' + grid_info.num_rows - i - 1, 'A' + j); } else { sprintf(buf, "( %d, %d, %d )", attCount + 1, i + 1, j + 1); } if (db_append_string(&sql, buf) != DB_OK) G_fatal_error(_("Unable to fill attribute table")); G_debug(3, "SQL: %s", db_get_string(&sql)); if (db_execute_immediate(Driver, &sql) != DB_OK) { G_fatal_error(_("Unable to insert new record: %s"), db_get_string(&sql)); } attCount++; } } } db_commit_transaction(Driver); db_close_database_shutdown_driver(Driver); Vect_build(&Map); Vect_close(&Map); exit(EXIT_SUCCESS); }
int execute_random(struct rr_state *theState) { long nt; long nc; struct Cell_head window; int nrows, ncols, row, col; int infd, cinfd, outfd; struct Map_info Out; struct field_info *fi; dbTable *table; dbColumn *column; dbString sql; dbDriver *driver; struct line_pnts *Points; struct line_cats *Cats; int cat; RASTER_MAP_TYPE type; int do_check; G_get_window(&window); nrows = Rast_window_rows(); ncols = Rast_window_cols(); /* open the data files, input raster should be set-up already */ if ((infd = theState->fd_old) < 0) G_fatal_error(_("Unable to open raster map <%s>"), theState->inraster); if (theState->docover == TRUE) { if ((cinfd = theState->fd_cold) < 0) G_fatal_error(_("Unable to open raster map <%s>"), theState->inrcover); } if (theState->outraster != NULL) { if (theState->docover == TRUE) type = theState->cover.type; else type = theState->buf.type; outfd = Rast_open_new(theState->outraster, type); theState->fd_new = outfd; } if (theState->outvector) { if (Vect_open_new(&Out, theState->outvector, theState->z_geometry) < 0) G_fatal_error(_("Unable to create vector map <%s>"), theState->outvector); Vect_hist_command(&Out); fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); driver = db_start_driver_open_database(fi->driver, Vect_subst_var(fi->database, &Out)); if (!driver) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Vect_subst_var(fi->database, &Out), fi->driver); db_set_error_handler_driver(driver); Vect_map_add_dblink(&Out, 1, NULL, fi->table, GV_KEY_COLUMN, fi->database, fi->driver); if (theState->docover == TRUE) table = db_alloc_table(3); else table = db_alloc_table(2); db_set_table_name(table, fi->table); column = db_get_table_column(table, 0); db_set_column_name(column, GV_KEY_COLUMN); db_set_column_sqltype(column, DB_SQL_TYPE_INTEGER); column = db_get_table_column(table, 1); db_set_column_name(column, "value"); db_set_column_sqltype(column, DB_SQL_TYPE_DOUBLE_PRECISION); if (theState->docover == TRUE) { column = db_get_table_column(table, 2); db_set_column_name(column, "covervalue"); db_set_column_sqltype(column, DB_SQL_TYPE_DOUBLE_PRECISION); } if (db_create_table(driver, table) != DB_OK) G_warning(_("Cannot create new table")); db_begin_transaction(driver); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); db_init_string(&sql); } if (theState->outvector && theState->outraster) G_message(_("Writing raster map <%s> and vector map <%s> ..."), theState->outraster, theState->outvector); else if (theState->outraster) G_message(_("Writing raster map <%s> ..."), theState->outraster); else if (theState->outvector) G_message(_("Writing vector map <%s> ..."), theState->outvector); G_percent(0, theState->nRand, 2); init_rand(); nc = (theState->use_nulls) ? theState->nCells : theState->nCells - theState->nNulls; nt = theState->nRand; /* Number of points to generate */ cat = 1; /* Execute for loop for every row if nt>1 */ for (row = 0; row < nrows && nt; row++) { Rast_get_row(infd, theState->buf.data.v, row, theState->buf.type); if (theState->docover == TRUE) { Rast_get_row(cinfd, theState->cover.data.v, row, theState->cover.type); } for (col = 0; col < ncols && nt; col++) { do_check = 0; if (theState->use_nulls || !is_null_value(theState->buf, col)) do_check = 1; if (do_check && theState->docover == TRUE) { /* skip no data cover points */ if (!theState->use_nulls && is_null_value(theState->cover, col)) do_check = 0; } if (do_check && make_rand() % nc < nt) { nt--; if (is_null_value(theState->buf, col)) cpvalue(&theState->nulls, 0, &theState->buf, col); if (theState->docover == TRUE) { if (is_null_value(theState->cover, col)) cpvalue(&theState->cnulls, 0, &theState->cover, col); } if (theState->outvector) { double x, y, val, coverval; char buf[500]; Vect_reset_line(Points); Vect_reset_cats(Cats); x = window.west + (col + .5) * window.ew_res; y = window.north - (row + .5) * window.ns_res; val = cell_as_dbl(&theState->buf, col); if (theState->docover == 1) coverval = cell_as_dbl(&theState->cover, col); if (theState->z_geometry) Vect_append_point(Points, x, y, val); else Vect_append_point(Points, x, y, 0.0); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, GV_POINT, Points, Cats); if (theState->docover == 1) if (is_null_value(theState->cover, col)) sprintf(buf, "insert into %s values ( %d, %f, NULL )", fi->table, cat, val); else sprintf(buf, "insert into %s values ( %d, %f, %f )", fi->table, cat, val, coverval); else sprintf(buf, "insert into %s values ( %d, %f )", fi->table, cat, val); db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) G_fatal_error(_("Cannot insert new record: %s"), db_get_string(&sql)); cat++; } G_percent((theState->nRand - nt), theState->nRand, 2); } else { set_to_null(&theState->buf, col); if (theState->docover == 1) set_to_null(&theState->cover, col); } if (do_check) nc--; } while (col < ncols) { set_to_null(&theState->buf, col); if (theState->docover == 1) set_to_null(&theState->cover, col); col++; } if (theState->outraster) { if (theState->docover == 1) Rast_put_row(outfd, theState->cover.data.v, theState->cover.type); else Rast_put_row(outfd, theState->buf.data.v, theState->buf.type); } } /* Catch any remaining rows in the window */ if (theState->outraster && row < nrows) { for (col = 0; col < ncols; col++) { if (theState->docover == 1) set_to_null(&theState->cover, col); else set_to_null(&theState->buf, col); } for (; row < nrows; row++) { if (theState->docover == 1) Rast_put_row(outfd, theState->cover.data.v, theState->cover.type); else Rast_put_row(outfd, theState->buf.data.v, theState->buf.type); } } if (nt > 0) G_warning(_("Only [%ld] random points created"), theState->nRand - nt); /* close files */ Rast_close(infd); if (theState->docover == TRUE) Rast_close(cinfd); if (theState->outvector) { db_commit_transaction(driver); 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_close_database_shutdown_driver(driver); if (theState->notopol != 1) Vect_build(&Out); Vect_close(&Out); } if (theState->outraster) Rast_close(outfd); return 0; } /* execute_random() */
/*! \brief Copy a map including attribute tables Old vector is deleted \param in input vector map name \param mapset mapset name \param out output vector map name \return -1 error \return 0 success */ int Vect_copy(const char *in, const char *mapset, const char *out) { int i, n, ret, type; struct Map_info In, Out; struct field_info *Fi, *Fin; char old_path[GPATH_MAX], new_path[GPATH_MAX], buf[GPATH_MAX]; const char *files[] = { GV_FRMT_ELEMENT, GV_COOR_ELEMENT, GV_HEAD_ELEMENT, GV_HIST_ELEMENT, GV_TOPO_ELEMENT, GV_SIDX_ELEMENT, GV_CIDX_ELEMENT, NULL }; const char *inmapset; char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; dbDriver *driver; G_debug(2, "Copy vector '%s' in '%s' to '%s'", in, mapset, out); /* check for [A-Za-z][A-Za-z0-9_]* in name */ if (Vect_legal_filename(out) < 0) G_fatal_error(_("Vector map name is not SQL compliant")); inmapset = G_find_vector2(in, mapset); if (!inmapset) { G_warning(_("Unable to find vector map <%s> in <%s>"), in, mapset); return -1; } mapset = inmapset; /* remove mapset from fully qualified name, confuses G_file_name() */ if (G_name_is_fully_qualified(in, xname, xmapset)) { in = xname; } /* Delete old vector if it exists */ if (G_find_vector2(out, G_mapset())) { G_warning(_("Vector map <%s> already exists and will be overwritten"), out); ret = Vect_delete(out); if (ret != 0) { G_warning(_("Unable to delete vector map <%s>"), out); return -1; } } /* Copy the directory */ G__make_mapset_element(GV_DIRECTORY); sprintf(buf, "%s/%s", GV_DIRECTORY, out); G__make_mapset_element(buf); i = 0; while (files[i]) { sprintf(buf, "%s/%s", in, files[i]); G_file_name(old_path, GV_DIRECTORY, buf, mapset); sprintf(buf, "%s/%s", out, files[i]); G_file_name(new_path, GV_DIRECTORY, buf, G_mapset()); if (access(old_path, F_OK) == 0) { /* file exists? */ G_debug(2, "copy %s to %s", old_path, new_path); if (copy_file(old_path, new_path)) { G_warning(_("Unable to copy vector map <%s> to <%s>"), old_path, new_path); } } i++; } G_file_name(old_path, GV_DIRECTORY, in, mapset); G_file_name(new_path, GV_DIRECTORY, out, G_mapset()); /* Open input */ Vect_set_open_level(1); Vect_open_old_head(&In, in, mapset); if (In.format != GV_FORMAT_NATIVE) { /* Done */ Vect_close(&In); return 0; } /* Open output */ Vect_set_open_level(1); Vect_open_update_head(&Out, out, G_mapset()); /* Copy tables */ n = Vect_get_num_dblinks(&In); type = GV_1TABLE; if (n > 1) type = GV_MTABLE; for (i = 0; i < n; i++) { Fi = Vect_get_dblink(&In, i); if (Fi == NULL) { G_warning(_("Database connection not defined for layer %d"), In.dblnk->field[i].number); Vect_close(&In); Vect_close(&Out); return -1; } Fin = Vect_default_field_info(&Out, Fi->number, Fi->name, type); G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table); Vect_map_add_dblink(&Out, Fi->number, Fi->name, Fin->table, Fi->key, Fin->database, Fin->driver); ret = db_copy_table(Fi->driver, Fi->database, Fi->table, Fin->driver, Vect_subst_var(Fin->database, &Out), Fin->table); if (ret == DB_FAILED) { G_warning(_("Unable to copy table <%s>"), Fin->table); Vect_close(&In); Vect_close(&Out); return -1; } driver = db_start_driver_open_database(Fin->driver, Vect_subst_var(Fin->database, &Out)); if (driver == NULL) { G_warning(_("Unable to open database <%s> by driver <%s>"), Fin->database, Fin->driver); } else { if (db_create_index2(driver, Fin->table, Fi->key) != DB_OK) G_warning(_("Unable to create index for table <%s>, key <%s>"), Fi->table, Fi->key); db_close_database_shutdown_driver(driver); } } Vect_close(&In); Vect_close(&Out); return 0; }
int main(int argc, char *argv[]) { struct Map_info In, Out; static struct line_pnts *Points; struct line_cats *Cats; struct GModule *module; /* GRASS module for parsing arguments */ struct Option *map_in, *map_out; struct Option *cat_opt, *field_opt, *where_opt, *abcol, *afcol; struct Option *iter_opt, *error_opt; struct Flag *geo_f, *add_f; int chcat, with_z; int layer, mask_type; struct varray *varray; dglGraph_s *graph; int i, geo, nnodes, nlines, j, max_cat; char buf[2000], *covered; /* initialize GIS environment */ G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */ /* initialize module */ module = G_define_module(); module->keywords = _("vector, network, centrality measures"); module->description = _("Computes degree, centrality, betweeness, closeness and eigenvector " "centrality measures in the network."); /* Define the different options as defined in gis.h */ map_in = G_define_standard_option(G_OPT_V_INPUT); field_opt = G_define_standard_option(G_OPT_V_FIELD); map_out = G_define_standard_option(G_OPT_V_OUTPUT); cat_opt = G_define_standard_option(G_OPT_V_CATS); cat_opt->guisection = _("Selection"); where_opt = G_define_standard_option(G_OPT_WHERE); where_opt->guisection = _("Selection"); afcol = G_define_standard_option(G_OPT_COLUMN); afcol->key = "afcolumn"; afcol->required = NO; afcol->description = _("Name of arc forward/both direction(s) cost column"); afcol->guisection = _("Cost"); abcol = G_define_standard_option(G_OPT_COLUMN); abcol->key = "abcolumn"; abcol->required = NO; abcol->description = _("Name of arc backward direction cost column"); abcol->guisection = _("Cost"); deg_opt = G_define_standard_option(G_OPT_COLUMN); deg_opt->key = "degree"; deg_opt->required = NO; deg_opt->description = _("Name of degree centrality column"); deg_opt->guisection = _("Columns"); close_opt = G_define_standard_option(G_OPT_COLUMN); close_opt->key = "closeness"; close_opt->required = NO; close_opt->description = _("Name of closeness centrality column"); close_opt->guisection = _("Columns"); betw_opt = G_define_standard_option(G_OPT_COLUMN); betw_opt->key = "betweenness"; betw_opt->required = NO; betw_opt->description = _("Name of betweenness centrality column"); betw_opt->guisection = _("Columns"); eigen_opt = G_define_standard_option(G_OPT_COLUMN); eigen_opt->key = "eigenvector"; eigen_opt->required = NO; eigen_opt->description = _("Name of eigenvector centrality column"); eigen_opt->guisection = _("Columns"); iter_opt = G_define_option(); iter_opt->key = "iterations"; iter_opt->answer = "1000"; iter_opt->type = TYPE_INTEGER; iter_opt->required = NO; iter_opt->description = _("Maximum number of iterations to compute eigenvector centrality"); error_opt = G_define_option(); error_opt->key = "error"; error_opt->answer = "0.1"; error_opt->type = TYPE_DOUBLE; error_opt->required = NO; error_opt->description = _("Cummulative error tolerance for eigenvector centrality"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); add_f = G_define_flag(); add_f->key = 'a'; add_f->description = _("Add points on nodes"); /* options and flags parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* TODO: make an option for this */ mask_type = GV_LINE | GV_BOUNDARY; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Vect_check_input_output_name(map_in->answer, map_out->answer, GV_FATAL_EXIT); Vect_set_open_level(2); if (1 > Vect_open_old(&In, map_in->answer, "")) G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer); with_z = Vect_is_3d(&In); if (0 > Vect_open_new(&Out, map_out->answer, with_z)) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer); } if (geo_f->answer) { geo = 1; if (G_projection() != PROJECTION_LL) G_warning(_("The current projection is not longitude-latitude")); } else geo = 0; /* parse filter option and select appropriate lines */ layer = atoi(field_opt->answer); chcat = (NetA_initialise_varray (&In, layer, mask_type, where_opt->answer, cat_opt->answer, &varray) == 1); /* Create table */ Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", Fi->database, Fi->driver); db_init_string(&sql); driver = db_start_driver_open_database(Fi->driver, Fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_init_string(&tmp); if (deg_opt->answer) append_string(&tmp, deg_opt->answer); if (close_opt->answer) append_string(&tmp, close_opt->answer); if (betw_opt->answer) append_string(&tmp, betw_opt->answer); if (eigen_opt->answer) append_string(&tmp, eigen_opt->answer); sprintf(buf, "create table %s(cat integer%s)", Fi->table, db_get_string(&tmp)); db_set_string(&sql, buf); G_debug(2, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql)); } if (db_create_index2(driver, Fi->table, "cat") != DB_OK) G_warning(_("Cannot create index")); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); Vect_net_build_graph(&In, mask_type, atoi(field_opt->answer), 0, afcol->answer, abcol->answer, NULL, geo, 0); graph = &(In.graph); nnodes = dglGet_NodeCount(graph); deg = closeness = betw = eigen = NULL; covered = (char *)G_calloc(nnodes + 1, sizeof(char)); if (!covered) G_fatal_error(_("Out of memory")); if (deg_opt->answer) { deg = (double *)G_calloc(nnodes + 1, sizeof(double)); if (!deg) G_fatal_error(_("Out of memory")); } if (close_opt->answer) { closeness = (double *)G_calloc(nnodes + 1, sizeof(double)); if (!closeness) G_fatal_error(_("Out of memory")); } if (betw_opt->answer) { betw = (double *)G_calloc(nnodes + 1, sizeof(double)); if (!betw) G_fatal_error(_("Out of memory")); } if (eigen_opt->answer) { eigen = (double *)G_calloc(nnodes + 1, sizeof(double)); if (!eigen) G_fatal_error(_("Out of memory")); } if (deg_opt->answer) { G_message(_("Computing degree centrality measure")); NetA_degree_centrality(graph, deg); } if (betw_opt->answer || close_opt->answer) { G_message(_("Computing betweenness and/or closeness centrality measure")); NetA_betweenness_closeness(graph, betw, closeness); if (closeness) for (i = 1; i <= nnodes; i++) closeness[i] /= (double)In.cost_multip; } if (eigen_opt->answer) { G_message(_("Computing eigenvector centrality measure")); NetA_eigenvector_centrality(graph, atoi(iter_opt->answer), atof(error_opt->answer), eigen); } nlines = Vect_get_num_lines(&In); G_message(_("Writing data into the table...")); G_percent_reset(); for (i = 1; i <= nlines; i++) { G_percent(i, nlines, 1); int type = Vect_read_line(&In, Points, Cats, i); if (type == GV_POINT && (!chcat || varray->c[i])) { int cat, node; if (!Vect_cat_get(Cats, layer, &cat)) continue; Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, type, Points, Cats); Vect_get_line_nodes(&In, i, &node, NULL); process_node(node, cat); covered[node] = 1; } } if (add_f->answer && !chcat) { max_cat = 0; for (i = 1; i <= nlines; i++) { Vect_read_line(&In, NULL, Cats, i); for (j = 0; j < Cats->n_cats; j++) if (Cats->cat[j] > max_cat) max_cat = Cats->cat[j]; } max_cat++; for (i = 1; i <= nnodes; i++) if (!covered[i]) { Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, max_cat); NetA_add_point_on_node(&In, &Out, i, Cats); process_node(i, max_cat); max_cat++; } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); G_free(covered); if (deg) G_free(deg); if (closeness) G_free(closeness); if (betw) G_free(betw); if (eigen) G_free(eigen); Vect_build(&Out); Vect_close(&In); Vect_close(&Out); exit(EXIT_SUCCESS); }
/*! \brief Rename a map. Attribute tables are created in the same database where input tables were stored. The original format (native/OGR) is used. Old map ('out') is deleted!!! \param in input vector map name \param out output vector map name \return -1 error \return 0 success */ int Vect_rename(const char *in, const char *out) { int i, n, ret, type; struct Map_info Map; struct field_info *Fin, *Fout; int *fields; dbDriver *driver; char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; G_debug(2, "Rename vector '%s' to '%s'", in, out); /* check for [A-Za-z][A-Za-z0-9_]* in name */ if (Vect_legal_filename(out) < 0) G_fatal_error(_("Vector map name is not SQL compliant")); /* Delete old vector if it exists */ if (G_find_vector2(out, G_mapset())) { G_warning(_("Vector map <%s> already exists and will be overwritten"), out); Vect_delete(out); } /* remove mapset from fully qualified name */ if (G_name_is_fully_qualified(in, xname, xmapset)) { in = xname; } /* Move the directory */ ret = G_rename(GV_DIRECTORY, in, out); if (ret == 0) { G_warning(_("Vector map <%s> not found"), in); return -1; } else if (ret == -1) { G_warning(_("Unable to copy vector map <%s> to <%s>"), in, out); return -1; } /* Rename all tables if the format is native */ Vect_set_open_level(1); Vect_open_update_head(&Map, out, G_mapset()); if (Map.format != GV_FORMAT_NATIVE) { /* Done */ Vect_close(&Map); return 0; } /* Copy tables */ n = Vect_get_num_dblinks(&Map); type = GV_1TABLE; if (n > 1) type = GV_MTABLE; /* Make the list of fields */ fields = (int *)G_malloc(n * sizeof(int)); for (i = 0; i < n; i++) { Fin = Vect_get_dblink(&Map, i); fields[i] = Fin->number; } for (i = 0; i < n; i++) { G_debug(3, "field[%d] = %d", i, fields[i]); Fin = Vect_get_field(&Map, fields[i]); if (Fin == NULL) { G_warning(_("Database connection not defined for layer %d"), fields[i]); Vect_close(&Map); return -1; } Fout = Vect_default_field_info(&Map, Fin->number, Fin->name, type); G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", Fin->driver, Fin->database, Fin->table, Fout->driver, Fout->database, Fout->table); /* TODO: db_rename_table instead of db_copy_table */ ret = db_copy_table(Fin->driver, Fin->database, Fin->table, Fout->driver, Vect_subst_var(Fout->database, &Map), Fout->table); if (ret == DB_FAILED) { G_warning(_("Unable to copy table <%s>"), Fin->table); Vect_close(&Map); return -1; } /* Change the link */ Vect_map_del_dblink(&Map, Fin->number); Vect_map_add_dblink(&Map, Fout->number, Fout->name, Fout->table, Fin->key, Fout->database, Fout->driver); /* Delete old table */ ret = db_delete_table(Fin->driver, Fin->database, Fin->table); if (ret == DB_FAILED) { G_warning(_("Unable to delete table <%s>"), Fin->table); Vect_close(&Map); return -1; } driver = db_start_driver_open_database(Fout->driver, Vect_subst_var(Fout->database, &Map)); if (driver == NULL) { G_warning(_("Unable to open database <%s> by driver <%s>"), Fout->database, Fout->driver); } else { if (db_create_index2(driver, Fout->table, Fin->key) != DB_OK) G_warning(_("Unable to create index for table <%s>, key <%s>"), Fout->table, Fout->key); db_close_database_shutdown_driver(driver); } } Vect_close(&Map); free(fields); return 0; }
int main(int argc, char *argv[]) { int i, cat, with_z, more, ctype, nrows; char buf[DB_SQL_MAX]; int count; double coor[3]; int ncoor; struct Option *driver_opt, *database_opt, *table_opt; struct Option *xcol_opt, *ycol_opt, *zcol_opt, *keycol_opt, *where_opt, *outvect; struct Flag *same_table_flag; struct GModule *module; struct Map_info Map; struct line_pnts *Points; struct line_cats *Cats; dbString sql; dbDriver *driver; dbCursor cursor; dbTable *table; dbColumn *column; dbValue *value; struct field_info *fi; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("import")); G_add_keyword(_("database")); G_add_keyword(_("points")); module->description = _("Creates new vector (points) map from database table containing coordinates."); table_opt = G_define_standard_option(G_OPT_DB_TABLE); table_opt->required = YES; table_opt->description = _("Input table name"); driver_opt = G_define_standard_option(G_OPT_DB_DRIVER); driver_opt->options = db_list_drivers(); driver_opt->answer = (char *)db_get_default_driver_name(); driver_opt->guisection = _("Input DB"); database_opt = G_define_standard_option(G_OPT_DB_DATABASE); database_opt->answer = (char *)db_get_default_database_name(); database_opt->guisection = _("Input DB"); xcol_opt = G_define_standard_option(G_OPT_DB_COLUMN); xcol_opt->key = "x"; xcol_opt->required = YES; xcol_opt->description = _("Name of column containing x coordinate"); ycol_opt = G_define_standard_option(G_OPT_DB_COLUMN); ycol_opt->key = "y"; ycol_opt->required = YES; ycol_opt->description = _("Name of column containing y coordinate"); zcol_opt = G_define_standard_option(G_OPT_DB_COLUMN); zcol_opt->key = "z"; zcol_opt->description = _("Name of column containing z coordinate"); zcol_opt->guisection = _("3D output"); keycol_opt = G_define_standard_option(G_OPT_DB_COLUMN); keycol_opt->key = "key"; keycol_opt->required = NO; keycol_opt->label = _("Name of column containing category number"); keycol_opt->description = _("Must refer to an integer column"); where_opt = G_define_standard_option(G_OPT_DB_WHERE); where_opt->guisection = _("Selection"); outvect = G_define_standard_option(G_OPT_V_OUTPUT); same_table_flag = G_define_flag(); same_table_flag->key = 't'; same_table_flag->description = _("Use imported table as attribute table for new map"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (zcol_opt->answer) { with_z = WITH_Z; ncoor = 3; } else { with_z = WITHOUT_Z; ncoor = 2; } Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); db_init_string(&sql); if (G_get_overwrite()) { /* We don't want to delete the input table when overwriting the output * vector. */ char name[GNAME_MAX], mapset[GMAPSET_MAX]; if (!G_name_is_fully_qualified(outvect->answer, name, mapset)) { strcpy(name, outvect->answer); strcpy(mapset, G_mapset()); } Vect_set_open_level(1); /* no topo needed */ if (strcmp(mapset, G_mapset()) == 0 && G_find_vector2(name, mapset) && Vect_open_old(&Map, name, mapset) >= 0) { int num_dblinks; num_dblinks = Vect_get_num_dblinks(&Map); for (i = 0; i < num_dblinks; i++) { if ((fi = Vect_get_dblink(&Map, i)) != NULL && strcmp(fi->driver, driver_opt->answer) == 0 && strcmp(fi->database, database_opt->answer) == 0 && strcmp(fi->table, table_opt->answer) == 0) G_fatal_error(_("Vector map <%s> cannot be overwritten " "because input table <%s> is linked to " "this map."), outvect->answer, table_opt->answer); } Vect_close(&Map); } } if (Vect_open_new(&Map, outvect->answer, with_z) < 0) G_fatal_error(_("Unable to create vector map <%s>"), outvect->answer); Vect_set_error_handler_io(NULL, &Map); Vect_hist_command(&Map); fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE); /* Open driver */ driver = db_start_driver_open_database(driver_opt->answer, database_opt->answer); if (driver == NULL) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), fi->database, fi->driver); } db_set_error_handler_driver(driver); /* check if target table already exists */ G_debug(3, "Output vector table <%s>, driver: <%s>, database: <%s>", outvect->answer, db_get_default_driver_name(), db_get_default_database_name()); if (!same_table_flag->answer && db_table_exists(db_get_default_driver_name(), db_get_default_database_name(), outvect->answer) == 1) G_fatal_error(_("Output vector map, table <%s> (driver: <%s>, database: <%s>) " "already exists"), outvect->answer, db_get_default_driver_name(), db_get_default_database_name()); if (keycol_opt->answer) { int coltype; coltype = db_column_Ctype(driver, table_opt->answer, keycol_opt->answer); if (coltype == -1) G_fatal_error(_("Column <%s> not found in table <%s>"), keycol_opt->answer, table_opt->answer); if (coltype != DB_C_TYPE_INT) G_fatal_error(_("Data type of key column must be integer")); } else { if (same_table_flag->answer) { G_fatal_error(_("Option <%s> must be specified when -%c flag is given"), keycol_opt->key, same_table_flag->key); } if (strcmp(db_get_default_driver_name(), "sqlite") != 0) G_fatal_error(_("Unable to define key column. This operation is not supported " "by <%s> driver. You need to define <%s> option."), fi->driver, keycol_opt->key); } /* Open select cursor */ sprintf(buf, "SELECT %s, %s", xcol_opt->answer, ycol_opt->answer); db_set_string(&sql, buf); if (with_z) { sprintf(buf, ", %s", zcol_opt->answer); db_append_string(&sql, buf); } if (keycol_opt->answer) { sprintf(buf, ", %s", keycol_opt->answer); db_append_string(&sql, buf); } sprintf(buf, " FROM %s", table_opt->answer); db_append_string(&sql, buf); if (where_opt->answer) { sprintf(buf, " WHERE %s", where_opt->answer); db_append_string(&sql, buf); } G_debug(2, "SQL: %s", db_get_string(&sql)); if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) { G_fatal_error(_("Unable to open select cursor: '%s'"), db_get_string(&sql)); } table = db_get_cursor_table(&cursor); nrows = db_get_num_rows(&cursor); G_debug(2, "%d points selected", nrows); count = cat = 0; G_message(_("Writing features...")); while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) { G_percent(count, nrows, 2); /* key column */ if (keycol_opt->answer) { column = db_get_table_column(table, with_z ? 3 : 2); ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column)); if (ctype != DB_C_TYPE_INT) G_fatal_error(_("Key column must be integer")); value = db_get_column_value(column); cat = db_get_value_int(value); } else { cat++; } /* coordinates */ for (i = 0; i < ncoor; i++) { column = db_get_table_column(table, i); ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column)); if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE) G_fatal_error(_("x/y/z column must be integer or double")); value = db_get_column_value(column); if (ctype == DB_C_TYPE_INT) coor[i] = (double)db_get_value_int(value); else coor[i] = db_get_value_double(value); } Vect_reset_line(Points); Vect_reset_cats(Cats); Vect_append_point(Points, coor[0], coor[1], coor[2]); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Map, GV_POINT, Points, Cats); count++; } G_percent(1, 1, 1); /* close connection to input DB before copying attributes */ db_close_database_shutdown_driver(driver); /* Copy table */ if (!same_table_flag->answer) { G_message(_("Copying attributes...")); if (DB_FAILED == db_copy_table_where(driver_opt->answer, database_opt->answer, table_opt->answer, fi->driver, fi->database, fi->table, where_opt->answer)) { /* where can be NULL */ G_warning(_("Unable to copy table")); } else { Vect_map_add_dblink(&Map, 1, NULL, fi->table, keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN, fi->database, fi->driver); } if (!keycol_opt->answer) { /* TODO: implement for all DB drivers in generic way if * possible */ driver = db_start_driver_open_database(fi->driver, fi->database); if (driver == NULL) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), fi->database, fi->driver); } db_set_error_handler_driver(driver); /* add key column */ sprintf(buf, "ALTER TABLE %s ADD COLUMN %s INTEGER", fi->table, GV_KEY_COLUMN); db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Unable to add key column <%s>: " "SERIAL type is not supported by <%s>"), GV_KEY_COLUMN, fi->driver); } /* update key column */ sprintf(buf, "UPDATE %s SET %s = _ROWID_", fi->table, GV_KEY_COLUMN); db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Failed to update key column <%s>"), GV_KEY_COLUMN); } } } else { /* do not copy attributes, link original table */ Vect_map_add_dblink(&Map, 1, NULL, table_opt->answer, keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN, database_opt->answer, driver_opt->answer); } Vect_build(&Map); Vect_close(&Map); G_done_msg(_n("%d point written to vector map.", "%d points written to vector map.", count), count); return (EXIT_SUCCESS); }
int main(int argc, char *argv[]) { /* Variables' declarations */ int nsplx_adj, nsply_adj; int nsubregion_col, nsubregion_row, subregion = 0, nsubregions = 0; double N_extension, E_extension, edgeE, edgeN; int dim_vect, nparameters, BW, npoints; double lambda_B, lambda_F, grad_H, grad_L, alpha, mean; const char *dvr, *db, *mapset; char table_interpolation[GNAME_MAX], table_name[GNAME_MAX]; char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; int last_row, last_column, flag_auxiliar = FALSE; int *lineVect; double *TN, *Q, *parVect_bilin, *parVect_bicub; /* Interpolating and least-square vectors */ double **N, **obsVect; /* Interpolation and least-square matrix */ /* Structs' declarations */ struct Map_info In, Out; struct Option *in_opt, *out_opt, *stepE_opt, *stepN_opt, *lambdaF_opt, *lambdaB_opt, *gradH_opt, *gradL_opt, *alfa_opt; struct Flag *spline_step_flag; struct GModule *module; struct Cell_head elaboration_reg, original_reg; struct Reg_dimens dims; struct bound_box general_box, overlap_box; struct Point *observ; dbDriver *driver; /*------------------------------------------------------------------------------------------*/ /* Options' declaration */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("LIDAR")); G_add_keyword(_("edges")); module->description = _("Detects the object's edges from a LIDAR data set."); spline_step_flag = G_define_flag(); spline_step_flag->key = 'e'; spline_step_flag->label = _("Estimate point density and distance"); spline_step_flag->description = _("Estimate point density and distance for the input vector points within the current region extends and quit"); in_opt = G_define_standard_option(G_OPT_V_INPUT); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); stepE_opt = G_define_option(); stepE_opt->key = "see"; stepE_opt->type = TYPE_DOUBLE; stepE_opt->required = NO; stepE_opt->answer = "4"; stepE_opt->description = _("Interpolation spline step value in east direction"); stepE_opt->guisection = _("Settings"); stepN_opt = G_define_option(); stepN_opt->key = "sen"; stepN_opt->type = TYPE_DOUBLE; stepN_opt->required = NO; stepN_opt->answer = "4"; stepN_opt->description = _("Interpolation spline step value in north direction"); stepN_opt->guisection = _("Settings"); lambdaB_opt = G_define_option(); lambdaB_opt->key = "lambda_g"; lambdaB_opt->type = TYPE_DOUBLE; lambdaB_opt->required = NO; lambdaB_opt->description = _("Regularization weight in gradient evaluation"); lambdaB_opt->answer = "0.01"; lambdaB_opt->guisection = _("Settings"); gradH_opt = G_define_option(); gradH_opt->key = "tgh"; gradH_opt->type = TYPE_DOUBLE; gradH_opt->required = NO; gradH_opt->description = _("High gradient threshold for edge classification"); gradH_opt->answer = "6"; gradH_opt->guisection = _("Settings"); gradL_opt = G_define_option(); gradL_opt->key = "tgl"; gradL_opt->type = TYPE_DOUBLE; gradL_opt->required = NO; gradL_opt->description = _("Low gradient threshold for edge classification"); gradL_opt->answer = "3"; gradL_opt->guisection = _("Settings"); alfa_opt = G_define_option(); alfa_opt->key = "theta_g"; alfa_opt->type = TYPE_DOUBLE; alfa_opt->required = NO; alfa_opt->description = _("Angle range for same direction detection"); alfa_opt->answer = "0.26"; alfa_opt->guisection = _("Settings"); lambdaF_opt = G_define_option(); lambdaF_opt->key = "lambda_r"; lambdaF_opt->type = TYPE_DOUBLE; lambdaF_opt->required = NO; lambdaF_opt->description = _("Regularization weight in residual evaluation"); lambdaF_opt->answer = "2"; lambdaF_opt->guisection = _("Settings"); /* Parsing */ G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); line_out_counter = 1; stepN = atof(stepN_opt->answer); stepE = atof(stepE_opt->answer); lambda_F = atof(lambdaF_opt->answer); lambda_B = atof(lambdaB_opt->answer); grad_H = atof(gradH_opt->answer); grad_L = atof(gradL_opt->answer); alpha = atof(alfa_opt->answer); grad_L = grad_L * grad_L; grad_H = grad_H * grad_H; if (!(db = G__getenv2("DB_DATABASE", G_VAR_MAPSET))) G_fatal_error(_("Unable to read name of database")); if (!(dvr = G__getenv2("DB_DRIVER", G_VAR_MAPSET))) G_fatal_error(_("Unable to read name of driver")); /* Setting auxiliar table's name */ if (G_name_is_fully_qualified(out_opt->answer, xname, xmapset)) { sprintf(table_name, "%s_aux", xname); sprintf(table_interpolation, "%s_edge_Interpolation", xname); } else { sprintf(table_name, "%s_aux", out_opt->answer); sprintf(table_interpolation, "%s_edge_Interpolation", out_opt->answer); } /* Something went wrong in a previous v.lidar.edgedetection execution */ if (db_table_exists(dvr, db, table_name)) { /* Start driver and open db */ driver = db_start_driver_open_database(dvr, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."), dvr); if (P_Drop_Aux_Table(driver, table_name) != DB_OK) G_fatal_error(_("Old auxiliar table could not be dropped")); db_close_database_shutdown_driver(driver); } /* Something went wrong in a previous v.lidar.edgedetection execution */ if (db_table_exists(dvr, db, table_interpolation)) { /* Start driver and open db */ driver = db_start_driver_open_database(dvr, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."), dvr); if (P_Drop_Aux_Table(driver, table_interpolation) != DB_OK) G_fatal_error(_("Old auxiliar table could not be dropped")); db_close_database_shutdown_driver(driver); } /* Checking vector names */ Vect_check_input_output_name(in_opt->answer, out_opt->answer, G_FATAL_EXIT); if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL) { G_fatal_error(_("Vector map <%s> not found"), in_opt->answer); } Vect_set_open_level(1); /* Open input vector */ if (1 > Vect_open_old(&In, in_opt->answer, mapset)) G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer); /* Input vector must be 3D */ if (!Vect_is_3d(&In)) G_fatal_error(_("Input vector map <%s> is not 3D!"), in_opt->answer); /* Estimate point density and mean distance for current region */ if (spline_step_flag->answer) { double dens, dist; if (P_estimate_splinestep(&In, &dens, &dist) == 0) { G_message("Estimated point density: %.4g", dens); G_message("Estimated mean distance between points: %.4g", dist); } else G_warning(_("No points in current region!")); Vect_close(&In); exit(EXIT_SUCCESS); } /* Open output vector */ if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z)) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); /* Copy vector Head File */ Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); /* Start driver and open db */ driver = db_start_driver_open_database(dvr, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."), dvr); db_set_error_handler_driver(driver); /* Create auxiliar and interpolation table */ if ((flag_auxiliar = P_Create_Aux4_Table(driver, table_name)) == FALSE) G_fatal_error(_("It was impossible to create <%s>."), table_name); if (P_Create_Aux2_Table(driver, table_interpolation) == FALSE) G_fatal_error(_("It was impossible to create <%s> interpolation table in database."), out_opt->answer); db_create_index2(driver, table_name, "ID"); db_create_index2(driver, table_interpolation, "ID"); /* sqlite likes that ??? */ db_close_database_shutdown_driver(driver); driver = db_start_driver_open_database(dvr, db); /* Setting regions and boxes */ G_get_set_window(&original_reg); G_get_set_window(&elaboration_reg); Vect_region_box(&elaboration_reg, &overlap_box); Vect_region_box(&elaboration_reg, &general_box); /*------------------------------------------------------------------ | Subdividing and working with tiles: | Each original region will be divided into several subregions. | Each one will be overlaped by its neighbouring subregions. | The overlapping is calculated as a fixed OVERLAP_SIZE times | the largest spline step plus 2 * edge ----------------------------------------------------------------*/ /* Fixing parameters of the elaboration region */ P_zero_dim(&dims); nsplx_adj = NSPLX_MAX; nsply_adj = NSPLY_MAX; if (stepN > stepE) dims.overlap = OVERLAP_SIZE * stepN; else dims.overlap = OVERLAP_SIZE * stepE; P_get_edge(P_BICUBIC, &dims, stepE, stepN); P_set_dim(&dims, stepE, stepN, &nsplx_adj, &nsply_adj); G_verbose_message(_("adjusted EW splines %d"), nsplx_adj); G_verbose_message(_("adjusted NS splines %d"), nsply_adj); /* calculate number of subregions */ edgeE = dims.ew_size - dims.overlap - 2 * dims.edge_v; edgeN = dims.sn_size - dims.overlap - 2 * dims.edge_h; N_extension = original_reg.north - original_reg.south; E_extension = original_reg.east - original_reg.west; nsubregion_col = ceil(E_extension / edgeE) + 0.5; nsubregion_row = ceil(N_extension / edgeN) + 0.5; if (nsubregion_col < 0) nsubregion_col = 0; if (nsubregion_row < 0) nsubregion_row = 0; nsubregions = nsubregion_row * nsubregion_col; elaboration_reg.south = original_reg.north; last_row = FALSE; while (last_row == FALSE) { /* For each row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, GENERAL_ROW); if (elaboration_reg.north > original_reg.north) { /* First row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, FIRST_ROW); } if (elaboration_reg.south <= original_reg.south) { /* Last row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, LAST_ROW); last_row = TRUE; } nsply = ceil((elaboration_reg.north - elaboration_reg.south) / stepN) + 0.5; /* if (nsply > NSPLY_MAX) { nsply = NSPLY_MAX; } */ G_debug(1, "nsply = %d", nsply); elaboration_reg.east = original_reg.west; last_column = FALSE; while (last_column == FALSE) { /* For each column */ subregion++; if (nsubregions > 1) G_message(_("subregion %d of %d"), subregion, nsubregions); P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, GENERAL_COLUMN); if (elaboration_reg.west < original_reg.west) { /* First column */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, FIRST_COLUMN); } if (elaboration_reg.east >= original_reg.east) { /* Last column */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, LAST_COLUMN); last_column = TRUE; } nsplx = ceil((elaboration_reg.east - elaboration_reg.west) / stepE) + 0.5; /* if (nsplx > NSPLX_MAX) { nsplx = NSPLX_MAX; } */ G_debug(1, "nsplx = %d", nsplx); /*Setting the active region */ dim_vect = nsplx * nsply; G_debug(1, "read vector region map"); observ = P_Read_Vector_Region_Map(&In, &elaboration_reg, &npoints, dim_vect, 1); if (npoints > 0) { /* If there is any point falling into elaboration_reg... */ int i, tn; nparameters = nsplx * nsply; /* Mean's calculation */ mean = P_Mean_Calc(&elaboration_reg, observ, npoints); /* Least Squares system */ G_debug(1, _("Allocating memory for bilinear interpolation")); BW = P_get_BandWidth(P_BILINEAR, nsply); /* Bilinear interpolation */ N = G_alloc_matrix(nparameters, BW); /* Normal matrix */ TN = G_alloc_vector(nparameters); /* vector */ parVect_bilin = G_alloc_vector(nparameters); /* Bilinear parameters vector */ obsVect = G_alloc_matrix(npoints + 1, 3); /* Observation vector */ Q = G_alloc_vector(npoints + 1); /* "a priori" var-cov matrix */ lineVect = G_alloc_ivector(npoints + 1); /* Setting obsVect vector & Q matrix */ for (i = 0; i < npoints; i++) { obsVect[i][0] = observ[i].coordX; obsVect[i][1] = observ[i].coordY; obsVect[i][2] = observ[i].coordZ - mean; lineVect[i] = observ[i].lineID; Q[i] = 1; /* Q=I */ } G_free(observ); G_verbose_message(_("Bilinear interpolation")); normalDefBilin(N, TN, Q, obsVect, stepE, stepN, nsplx, nsply, elaboration_reg.west, elaboration_reg.south, npoints, nparameters, BW); nCorrectGrad(N, lambda_B, nsplx, nsply, stepE, stepN); G_math_solver_cholesky_sband(N, parVect_bilin, TN, nparameters, BW); G_free_matrix(N); for (tn = 0; tn < nparameters; tn++) TN[tn] = 0; G_debug(1, _("Allocating memory for bicubic interpolation")); BW = P_get_BandWidth(P_BICUBIC, nsply); N = G_alloc_matrix(nparameters, BW); /* Normal matrix */ parVect_bicub = G_alloc_vector(nparameters); /* Bicubic parameters vector */ G_verbose_message(_("Bicubic interpolation")); normalDefBicubic(N, TN, Q, obsVect, stepE, stepN, nsplx, nsply, elaboration_reg.west, elaboration_reg.south, npoints, nparameters, BW); nCorrectLapl(N, lambda_F, nsplx, nsply, stepE, stepN); G_math_solver_cholesky_sband(N, parVect_bicub, TN, nparameters, BW); G_free_matrix(N); G_free_vector(TN); G_free_vector(Q); G_verbose_message(_("Point classification")); classification(&Out, elaboration_reg, general_box, overlap_box, obsVect, parVect_bilin, parVect_bicub, mean, alpha, grad_H, grad_L, dims.overlap, lineVect, npoints, driver, table_interpolation, table_name); G_free_vector(parVect_bilin); G_free_vector(parVect_bicub); G_free_matrix(obsVect); G_free_ivector(lineVect); } /* IF */ else { G_free(observ); G_warning(_("No data within this subregion. " "Consider changing the spline step.")); } } /*! END WHILE; last_column = TRUE */ } /*! END WHILE; last_row = TRUE */ /* Dropping auxiliar table */ if (npoints > 0) { G_debug(1, _("Dropping <%s>"), table_name); if (P_Drop_Aux_Table(driver, table_name) != DB_OK) G_warning(_("Auxiliar table could not be dropped")); } db_close_database_shutdown_driver(driver); Vect_close(&In); Vect_map_add_dblink(&Out, F_INTERPOLATION, NULL, table_interpolation, "id", db, dvr); Vect_close(&Out); G_done_msg(" "); exit(EXIT_SUCCESS); } /*!END MAIN */