/* 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 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; struct line_cats *Cats; struct GModule *module; /* GRASS module for parsing arguments */ struct Option *map_in, *map_out; struct Option *afield_opt, *nfield_opt, *afcol, *ncol; struct Flag *geo_f; int with_z; int afield, nfield, mask_type; dglGraph_s *graph; int i, edges, geo; struct ilist *tree_list; /* 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(_("spanning tree")); module->description = _("Computes minimum spanning tree for the network."); /* 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 = "alayer"; 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 = "nlayer"; nfield_opt->answer = "2"; nfield_opt->label = _("Node layer"); nfield_opt->guisection = _("Cost"); afcol = G_define_standard_option(G_OPT_DB_COLUMN); afcol->key = "afcolumn"; afcol->required = NO; afcol->description = _("Arc forward/both direction(s) cost column (number)"); afcol->guisection = _("Cost"); ncol = G_define_standard_option(G_OPT_DB_COLUMN); ncol->key = "ncolumn"; 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"); /* 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); } 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 */ 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, NULL, ncol->answer, geo, 0)) G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In)); graph = Vect_net_get_graph(&In); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); tree_list = Vect_new_list(); edges = NetA_spanning_tree(graph, tree_list); G_debug(3, "Edges: %d", edges); for (i = 0; i < edges; i++) { int type = Vect_read_line(&In, Points, Cats, abs(tree_list->value[i])); Vect_write_line(&Out, type, Points, Cats); } Vect_destroy_list(tree_list); Vect_build(&Out); Vect_close(&In); Vect_close(&Out); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int line; struct line_pnts *points; struct line_cats *Cats; struct Map_info map, Out; struct GModule *module; struct Option *input; struct Option *output; struct Option *cats; struct Option *type_opt; char *desc; int polyline; int *lines_visited; int points_in_polyline; int start_line; int nlines; int write_cats, copy_tables; int type, ltype; /* Initialize the GIS calls */ G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("topology")); G_add_keyword(_("geometry")); G_add_keyword(_("line")); G_add_keyword(_("node")); G_add_keyword(_("vertex")); module->description = _("Builds polylines from lines or boundaries."); /* Define the options */ input = G_define_standard_option(G_OPT_V_INPUT); output = G_define_standard_option(G_OPT_V_OUTPUT); cats = G_define_option(); cats->key = "cats"; cats->type = TYPE_STRING; cats->description = _("Category number mode"); cats->options = "no,first,multi,same"; desc = NULL; G_asprintf(&desc, "no;%s;first;%s;multi;%s;same;%s", _("Do not assign any category number to polyline"), _("Assign category number of first line to polyline"), _("Assign multiple category numbers to polyline"), _("Create polyline from lines with same categories")); cats->descriptions = desc; cats->answer = "no"; type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "line,boundary"; type_opt->answer = "line,boundary"; if (G_parser(argc, argv)) exit(EXIT_FAILURE); Vect_check_input_output_name(input->answer, output->answer, G_FATAL_EXIT); /* Open binary vector map at level 2 */ Vect_set_open_level(2); if (Vect_open_old(&map, input->answer, "") < 0) G_fatal_error(_("Unable to open vector map <%s>"), input->answer); /* Open new vector */ G_find_vector2(output->answer, ""); if (Vect_open_new(&Out, output->answer, Vect_is_3d(&map)) < 0) G_fatal_error(_("Unable to create vector map <%s>"), output->answer); /* Copy header info. */ Vect_copy_head_data(&map, &Out); /* History */ Vect_hist_copy(&map, &Out); Vect_hist_command(&Out); /* Get the number of lines in the binary map and set up record of lines visited */ lines_visited = (int *)G_calloc(Vect_get_num_lines(&map) + 1, sizeof(int)); /* Set up points structure and coordinate arrays */ points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); /* Write cats */ if (strcmp(cats->answer, "no") == 0) write_cats = NO_CATS; else if (strcmp(cats->answer, "first") == 0) write_cats = ONE_CAT; else write_cats = MULTI_CATS; if (type_opt->answer) type = Vect_option_to_types(type_opt); else type = GV_LINES; /* Step over all lines in binary map */ polyline = 0; nlines = 0; copy_tables = (write_cats != NO_CATS); for (line = 1; line <= Vect_get_num_lines(&map); line++) { Vect_reset_cats(Cats); ltype = Vect_read_line(&map, NULL, NULL, line); if ((ltype & GV_LINES) && (ltype & type)) nlines++; else { /* copy points to output as they are, with cats */ Vect_read_line(&map, points, Cats, line); Vect_write_line(&Out, ltype, points, Cats); if (Cats->n_cats > 0) copy_tables = 1; continue; } /* Skip line if already visited from another */ if (lines_visited[line]) continue; /* Only get here if line is not previously visited */ /* Find start of this polyline */ start_line = walk_back(&map, line, ltype); G_debug(1, "Polyline %d: start line = %d", polyline, start_line); /* Walk forward and pick up coordinates */ points_in_polyline = walk_forward_and_pick_up_coords(&map, start_line, ltype, points, lines_visited, Cats, write_cats); /* Write the line (type of the first line is used) */ Vect_write_line(&Out, ltype, points, Cats); polyline++; } G_verbose_message(n_("%d line or boundaries found in input vector map", "%d lines or boundaries found in input vector map", nlines), nlines, Vect_get_name(&map), Vect_get_mapset(&map)); G_verbose_message(n_("%d polyline stored in output vector map", "%d polylines stored in output vector map", polyline), polyline, Vect_get_name(&Out), Vect_get_mapset(&Out)); /* Copy (all linked) tables if needed */ if (copy_tables) { if (Vect_copy_tables(&map, &Out, 0)) G_warning(_("Failed to copy attribute table to output map")); } /* Tidy up */ Vect_destroy_line_struct(points); Vect_destroy_cats_struct(Cats); G_free(lines_visited); Vect_close(&map); Vect_build(&Out); Vect_close(&Out); 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, *notab_flg; int feature, notab_flag; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("conversion")); G_add_keyword(_("geometry")); G_add_keyword(_("vectorization")); module->description = _("Converts a raster map into a vector map."); in_opt = G_define_standard_option(G_OPT_R_INPUT); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); feature_opt = G_define_standard_option(G_OPT_V_TYPE); feature_opt->required = YES; feature_opt->multiple = NO; feature_opt->options = "point,line,area"; feature_opt->answer = NULL; column_name = G_define_standard_option(G_OPT_DB_COLUMN); column_name->label = _("Name of attribute column to store value"); column_name->description = _("Name must be SQL compliant"); column_name->answer = "value"; smooth_flg = G_define_flag(); smooth_flg->key = 's'; smooth_flg->description = _("Smooth corners of area features"); value_flg = G_define_flag(); value_flg->key = 'v'; value_flg->description = _("Use raster values as categories instead of unique sequence (CELL only)"); value_flg->guisection = _("Attributes"); z_flg = G_define_flag(); z_flg->key = 'z'; z_flg->label = _("Write raster values as z coordinate"); z_flg->description = _("Table is not created. " "Currently supported only for points."); z_flg->guisection = _("Attributes"); no_topol = G_define_flag(); no_topol->key = 'b'; no_topol->label = _("Do not build vector topology"); no_topol->description = _("Recommended for massive point conversion"); notab_flg = G_define_standard_flag(G_FLG_V_TABLE); if (G_parser(argc, argv)) exit(EXIT_FAILURE); feature = Vect_option_to_types(feature_opt); smooth_flag = (smooth_flg->answer) ? SMOOTH : NO_SMOOTH; value_flag = value_flg->answer; notab_flag = notab_flg->answer; if (z_flg->answer && (feature != GV_POINT)) G_fatal_error(_("z flag is supported only for points")); /* Open files */ input_fd = Rast_open_old(in_opt->answer, ""); data_type = Rast_get_map_type(input_fd); data_size = Rast_cell_size(data_type); G_get_window(&cell_head); if (value_flag && data_type != CELL_TYPE) { if (!notab_flag) G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be written to the table.")); else if (z_flg->answer) G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be z coordinate.")); else G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be lost.")); value_flag = 0; } if (!value_flag && notab_flag) { G_warning(_("Categories will be unique sequence, raster values will be lost.")); } if (Vect_open_new(&Map, out_opt->answer, z_flg->answer) < 0) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); Vect_hist_command(&Map); Cats = Vect_new_cats_struct(); /* Open category labels */ if (data_type == CELL_TYPE) { if (0 == Rast_read_cats(in_opt->answer, "", &RastCats)) has_cats = 1; } else has_cats = 0; db_init_string(&sql); db_init_string(&label); /* Create table */ if ((feature & (GV_AREA | GV_POINT | GV_LINE)) && (!value_flag || (value_flag && has_cats)) && !(z_flg->answer) && !notab_flag) { char buf[1000]; Fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Map, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Map)); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_set_error_handler_driver(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; G_important_message(_("Updating attributes...")); 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[]) { struct GModule *module; struct Option *in_opt, *layer_opt, *out_opt, *length_opt, *units_opt, *vertices_opt; struct Flag *nosplit_flag, *fixedlength_flag; struct Map_info In, Out; struct line_pnts *Points, *Points2, *Points3; struct line_cats *Cats; int line, nlines, layer, nosplit, fixedlength; double length = -1; int vertices = 0; double (*line_length) (); int geodesic = 0; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); G_add_keyword(_("densification")); G_add_keyword(_("node")); G_add_keyword(_("segment")); G_add_keyword(_("vertex")); module->description = _("Splits vector lines to shorter segments."); in_opt = G_define_standard_option(G_OPT_V_INPUT); layer_opt = G_define_standard_option(G_OPT_V_FIELD_ALL); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); length_opt = G_define_option(); length_opt->key = "length"; length_opt->type = TYPE_DOUBLE; length_opt->required = NO; length_opt->multiple = NO; length_opt->description = _("Maximum segment length"); units_opt = G_define_option(); units_opt->key = "units"; units_opt->type = TYPE_STRING; units_opt->required = NO; units_opt->multiple = NO; units_opt->options = "map,meters,kilometers,feet,surveyfeet,miles,nautmiles"; units_opt->answer = "map"; units_opt->description = _("Length units"); vertices_opt = G_define_option(); vertices_opt->key = "vertices"; vertices_opt->type = TYPE_INTEGER; vertices_opt->required = NO; vertices_opt->multiple = NO; vertices_opt->description = _("Maximum number of vertices in segment"); nosplit_flag = G_define_flag(); nosplit_flag->key = 'n'; nosplit_flag->label = _("Add new vertices, but do not split"); nosplit_flag->description = _("Applies only to 'length' option"); fixedlength_flag = G_define_flag(); fixedlength_flag->key = 'f'; fixedlength_flag->label = _("Force segments to be exactly of given length, except for last one"); fixedlength_flag->description = _("Applies only to 'length' option"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if ((length_opt->answer && vertices_opt->answer) || !(length_opt->answer || vertices_opt->answer)) G_fatal_error(_("Use either length or vertices")); line_length = NULL; if (length_opt->answer) { length = atof(length_opt->answer); if (length <= 0) G_fatal_error(_("Length must be positive but is %g"), length); /* convert length to meters */ if (strcmp(units_opt->answer, "meters") == 0) /* do nothing */ ; else if (strcmp(units_opt->answer, "kilometers") == 0) length *= FROM_KILOMETERS; else if (strcmp(units_opt->answer, "feet") == 0) length *= FROM_FEET; else if (strcmp(units_opt->answer, "surveyfeet") == 0) length *= FROM_SFEET; else if (strcmp(units_opt->answer, "miles") == 0) length *= FROM_MILES; else if (strcmp(units_opt->answer, "nautmiles") == 0) length *= FROM_NAUTMILES; else if (strcmp(units_opt->answer, "map") != 0) G_fatal_error(_("Unknown unit %s"), units_opt->answer); /* set line length function */ if (G_projection() == PROJECTION_LL) { if (strcmp(units_opt->answer, "map") == 0) line_length = Vect_line_length; else { line_length = Vect_line_geodesic_length; geodesic = 1; } } else { double factor; line_length = Vect_line_length; /* convert length to map units */ if ((factor = G_database_units_to_meters_factor()) == 0) G_fatal_error(_("Can not get projection units")); else if (strcmp(units_opt->answer, "map") != 0) { /* meters to units */ length = length / factor; } } if (strcmp(units_opt->answer, "map") == 0) G_verbose_message(_("Length in map units: %g"), length); else G_verbose_message(_("Length in meters: %g"), length); } if (vertices_opt->answer) { vertices = atoi(vertices_opt->answer); if (vertices < 2) G_fatal_error(_("Number of vertices must be at least 2")); } nosplit = nosplit_flag->answer; fixedlength = fixedlength_flag->answer; Vect_set_open_level(2); if (Vect_open_old2(&In, in_opt->answer, "", layer_opt->answer) < 0) G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer); layer = Vect_get_field_number(&In, layer_opt->answer); if (Vect_open_new(&Out, out_opt->answer, Vect_is_3d(&In)) < 0) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); Vect_copy_tables(&In, &Out, layer); Points = Vect_new_line_struct(); Points2 = Vect_new_line_struct(); Points3 = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); nlines = Vect_get_num_lines(&In); for (line = 1; line <= nlines; line++) { int ltype; G_percent(line, nlines, 1); if (!Vect_line_alive(&In, line)) continue; ltype = Vect_read_line(&In, Points, Cats, line); if (layer != -1 && !Vect_cat_get(Cats, layer, NULL)) continue; if (ltype & GV_LINES) { if (length > 0) { double l, from, to, step; l = line_length(Points); if (l <= length) { Vect_write_line(&Out, ltype, Points, Cats); } else { long n, i; G_debug(3, "l: %f, length: %f", l, length); n = ceil(l / length); if (geodesic) l = Vect_line_length(Points); if (fixedlength) { step = length; } else { step = l / n; } from = 0.; G_debug(3, "n: %ld, step: %f", n, step); if (nosplit) Vect_reset_line(Points3); for (i = 0; i < n; i++) { int ret; double x, y, z; if (i == n - 1) { to = l; /* to be sure that it goes to end */ } else { to = from + step; } ret = Vect_line_segment(Points, from, to, Points2); if (ret == 0) { G_warning(_("Unable to make line segment: %f - %f (line length = %f)"), from, to, l); continue; } /* To be sure that the coordinates are identical */ if (i > 0) { Points2->x[0] = x; Points2->y[0] = y; Points2->z[0] = z; } if (i == n - 1) { Points2->x[Points2->n_points - 1] = Points->x[Points->n_points - 1]; Points2->y[Points2->n_points - 1] = Points->y[Points->n_points - 1]; Points2->z[Points2->n_points - 1] = Points->z[Points->n_points - 1]; } if (nosplit) { if (Points3->n_points > 0) Points3->n_points--; Vect_append_points(Points3, Points2, GV_FORWARD); } else Vect_write_line(&Out, ltype, Points2, Cats); /* last point */ x = Points2->x[Points2->n_points - 1]; y = Points2->y[Points2->n_points - 1]; z = Points2->z[Points2->n_points - 1]; from += step; } if (nosplit) Vect_write_line(&Out, ltype, Points3, Cats); } } else { int start = 0; /* number of coordinates written */ while (start < Points->n_points - 1) { int i, v = 0; Vect_reset_line(Points2); for (i = 0; i < vertices; i++) { v = start + i; if (v == Points->n_points) break; Vect_append_point(Points2, Points->x[v], Points->y[v], Points->z[v]); } Vect_write_line(&Out, ltype, Points2, Cats); start = v; } } } else { Vect_write_line(&Out, ltype, Points, Cats); } } Vect_close(&In); Vect_build(&Out); Vect_close(&Out); 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; 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 (theState->z_geometry) Vect_open_new(&Out, theState->outvector, 1); else Vect_open_new(&Out, theState->outvector, 0); 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); 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++) { if ((theState->use_nulls || !is_null_value(theState->buf, col)) && (!theState->docover || theState->use_nulls || !is_null_value(theState->cover, col)) && (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); nc--; } else { set_to_null(&theState->buf, col); if (theState->docover == 1) set_to_null(&theState->cover, col); } } 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); 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() */
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 *afield_opt, *nfield_opt, *abcol, *afcol, *ncol, *method_opt; int with_z; int afield, nfield, mask_type; dglGraph_s *graph; int i, bridges, articulations; struct ilist *bridge_list, *articulation_list; /* 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(_("articulation points")); module->description = _("Computes bridges and articulation points in the network."); /* 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 = "alayer"; afield_opt->answer = "1"; afield_opt->description = _("Arc layer"); afield_opt->guisection = _("Cost"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "nlayer"; nfield_opt->answer = "2"; nfield_opt->description = _("Node layer"); nfield_opt->guisection = _("Cost"); afcol = G_define_standard_option(G_OPT_DB_COLUMN); afcol->key = "afcolumn"; 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 = "abcolumn"; abcol->required = NO; abcol->description = _("Arc backward direction cost column (number)"); abcol->guisection = _("Cost"); ncol = G_define_option(); ncol->key = "ncolumn"; ncol->type = TYPE_STRING; ncol->required = NO; ncol->description = _("Node cost column (number)"); ncol->guisection = _("Cost"); 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 = "bridge,articulation"; method_opt->descriptions = _("bridge;Finds bridges;" "articulation;Finds articulation points;"); method_opt->description = _("Feature type"); /* 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); } /* 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); Vect_net_build_graph(&In, mask_type, afield, nfield, afcol->answer, abcol->answer, ncol->answer, 0, 0); graph = &(In.graph); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); if (method_opt->answer[0] == 'b') { bridge_list = Vect_new_list(); bridges = NetA_compute_bridges(graph, bridge_list); G_debug(3, "Bridges: %d", bridges); for (i = 0; i < bridges; i++) { int type = Vect_read_line(&In, Points, Cats, abs(bridge_list->value[i])); Vect_write_line(&Out, type, Points, Cats); } Vect_destroy_list(bridge_list); } else { articulation_list = Vect_new_list(); articulations = NetA_articulation_points(graph, articulation_list); G_debug(3, "Articulation points: %d", articulations); for (i = 0; i < articulations; i++) { double x, y, z; Vect_get_node_coor(&In, articulation_list->value[i], &x, &y, &z); Vect_reset_line(Points); Vect_append_point(Points, x, y, z); Vect_write_line(&Out, GV_POINT, Points, Cats); } Vect_destroy_list(articulation_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, ret, centre, line, centre1, centre2; int nlines, nnodes, type, ltype, afield, nfield, geo, cat; int node, node1, node2; double cost, e1cost, e2cost, n1cost, n2cost, s1cost, s2cost, l, l1; struct Option *map, *output; struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt, *term_opt, *cost_opt; struct Flag *geo_f; struct GModule *module; struct Map_info Map, Out; struct cat_list *catlist; CENTER *Centers = NULL; int acentres = 0, ncentres = 0; NODE *Nodes; struct line_cats *Cats; struct line_pnts *Points, *SPoints; int niso, aiso; double *iso; int npnts1, apnts1 = 0, npnts2, apnts2 = 0; ISOPOINT *pnts1 = NULL, *pnts2 = NULL; int next_iso; G_gisinit(argv[0]); module = G_define_module(); module->label = _("Splits net by cost isolines."); G_add_keyword(_("vector")); G_add_keyword(_("network")); G_add_keyword(_("isolines")); module->description = _("Splits net to bands between cost isolines (direction from centre). " "Centre node must be opened (costs >= 0). " "Costs of centre node are used in calculation."); map = G_define_standard_option(G_OPT_V_INPUT); output = G_define_standard_option(G_OPT_V_OUTPUT); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "line,boundary"; type_opt->answer = "line,boundary"; type_opt->description = _("Arc type"); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "alayer"; afield_opt->label = _("Arc layer"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "nlayer"; nfield_opt->answer = "2"; nfield_opt->label = _("Node layer"); afcol = G_define_standard_option(G_OPT_DB_COLUMN); afcol->key = "afcolumn"; afcol->description = _("Arc forward/both direction(s) cost column (number)"); abcol = G_define_standard_option(G_OPT_DB_COLUMN); abcol->key = "abcolumn"; abcol->description = _("Arc backward direction cost column (number)"); ncol = G_define_standard_option(G_OPT_DB_COLUMN); ncol->key = "ncolumn"; ncol->description = _("Node cost column (number)"); term_opt = G_define_standard_option(G_OPT_V_CATS); term_opt->key = "ccats"; term_opt->required = YES; term_opt->description = _("Categories of centres (points on nodes) to which net " "will be allocated. " "Layer for this categories is given by nlayer option."); cost_opt = G_define_option(); cost_opt->key = "costs"; cost_opt->type = TYPE_INTEGER; cost_opt->multiple = YES; cost_opt->required = YES; cost_opt->description = _("Costs for isolines"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); Cats = Vect_new_cats_struct(); Points = Vect_new_line_struct(); SPoints = Vect_new_line_struct(); type = Vect_option_to_types(type_opt); afield = atoi(afield_opt->answer); nfield = atoi(nfield_opt->answer); catlist = Vect_new_cat_list(); Vect_str_to_cat_list(term_opt->answer, catlist); Vect_check_input_output_name(map->answer, output->answer, GV_FATAL_EXIT); /* Iso costs */ aiso = 1; iso = (double *)G_malloc(aiso * sizeof(double)); /* Set first iso to 0 */ iso[0] = 0; niso = 1; i = 0; while (cost_opt->answers[i]) { if (niso == aiso) { aiso += 1; iso = (double *)G_realloc(iso, aiso * sizeof(double)); } iso[niso] = atof(cost_opt->answers[i]); if (iso[niso] <= 0) G_fatal_error(_("Wrong iso cost: %f"), iso[niso]); if (iso[niso] <= iso[niso - 1]) G_fatal_error(_("Iso cost: %f less than previous"), iso[niso]); G_verbose_message(_("Iso cost %d: %f"), niso, iso[niso]); niso++; i++; } /* Should not happen: */ if (niso < 2) G_warning(_("Not enough costs, everything reachable falls to first band")); if (geo_f->answer) geo = 1; else geo = 0; Vect_set_open_level(2); Vect_open_old(&Map, map->answer, ""); /* Build graph */ Vect_net_build_graph(&Map, type, afield, nfield, afcol->answer, abcol->answer, ncol->answer, geo, 0); nnodes = Vect_get_num_nodes(&Map); nlines = Vect_get_num_lines(&Map); /* Create list of centres based on list of categories */ for (i = 1; i <= nlines; i++) { ltype = Vect_get_line_type(&Map, i); if (!(ltype & GV_POINT)) continue; Vect_read_line(&Map, Points, Cats, i); node = Vect_find_node(&Map, Points->x[0], Points->y[0], Points->z[0], 0, 0); if (!node) { G_warning(_("Point is not connected to the network")); continue; } if (!(Vect_cat_get(Cats, nfield, &cat))) continue; if (Vect_cat_in_cat_list(cat, catlist)) { Vect_net_get_node_cost(&Map, node, &n1cost); if (n1cost == -1) { /* closed */ G_warning(_("Centre at closed node (costs = -1) ignored")); } else { if (acentres == ncentres) { acentres += 1; Centers = (CENTER *) G_realloc(Centers, acentres * sizeof(CENTER)); } Centers[ncentres].cat = cat; Centers[ncentres].node = node; G_debug(2, "centre = %d node = %d cat = %d", ncentres, node, cat); ncentres++; } } } G_message(_("Number of centres: %d (nlayer %d)"), ncentres, nfield); if (ncentres == 0) G_warning(_("Not enough centres for selected nlayer. Nothing will be allocated.")); /* alloc and reset space for all nodes */ Nodes = (NODE *) G_calloc((nnodes + 1), sizeof(NODE)); for (i = 1; i <= nnodes; i++) { Nodes[i].centre = -1; } apnts1 = 1; pnts1 = (ISOPOINT *) G_malloc(apnts1 * sizeof(ISOPOINT)); apnts2 = 1; pnts2 = (ISOPOINT *) G_malloc(apnts2 * sizeof(ISOPOINT)); /* Fill Nodes by neares centre and costs from that centre */ for (centre = 0; centre < ncentres; centre++) { node1 = Centers[centre].node; Vect_net_get_node_cost(&Map, node1, &n1cost); G_debug(2, "centre = %d node = %d cat = %d", centre, node1, Centers[centre].cat); G_message(_("Calculating costs from centre %d..."), centre + 1); for (node2 = 1; node2 <= nnodes; node2++) { G_percent(node2, nnodes, 1); G_debug(5, " node1 = %d node2 = %d", node1, node2); Vect_net_get_node_cost(&Map, node2, &n2cost); if (n2cost == -1) { continue; } /* closed, left it as not attached */ ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &cost); if (ret == -1) { continue; } /* node unreachable */ /* We must add centre node costs (not calculated by Vect_net_shortest_path() ), but * only if centre and node are not identical, because at the end node cost is add later */ if (node1 != node2) cost += n1cost; G_debug(5, "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f", node1, node2, cost, Nodes[node2].centre, Nodes[node2].cost); if (Nodes[node2].centre == -1 || cost < Nodes[node2].cost) { Nodes[node2].cost = cost; Nodes[node2].centre = centre; } } } /* Write arcs to new map */ Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)); Vect_hist_command(&Out); G_message("Generating isolines..."); nlines = Vect_get_num_lines(&Map); for (line = 1; line <= nlines; line++) { G_percent(line, nlines, 2); ltype = Vect_read_line(&Map, Points, NULL, line); if (!(ltype & type)) { continue; } Vect_get_line_nodes(&Map, line, &node1, &node2); centre1 = Nodes[node1].centre; centre2 = Nodes[node2].centre; s1cost = Nodes[node1].cost; s2cost = Nodes[node2].cost; l = Vect_line_length(Points); if (l == 0) continue; G_debug(3, "Line %d : length = %f", line, l); G_debug(3, "Arc centres: %d %d (nodes: %d %d)", centre1, centre2, node1, node2); Vect_net_get_node_cost(&Map, node1, &n1cost); Vect_net_get_node_cost(&Map, node2, &n2cost); Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e1cost); Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e2cost); G_debug(3, " s1cost = %f n1cost = %f e1cost = %f", s1cost, n1cost, e1cost); G_debug(3, " s2cost = %f n2cost = %f e2cost = %f", s2cost, n2cost, e2cost); /* First check if arc is reachable from at least one side */ if ((centre1 != -1 && n1cost != -1 && e1cost != -1) || (centre2 != -1 && n2cost != -1 && e2cost != -1)) { /* Line is reachable at least from one side */ G_debug(3, " -> arc is reachable"); /* Add costs of node to starting costs */ s1cost += n1cost; s2cost += n2cost; e1cost /= l; e2cost /= l; /* Find points on isolines along the line in both directions, add them to array, * first point is placed at the beginning/end of line */ /* Forward */ npnts1 = 0; /* in case this direction is closed */ if (centre1 != -1 && n1cost != -1 && e1cost != -1) { /* Find iso for beginning of the line */ next_iso = 0; for (i = niso - 1; i >= 0; i--) { if (iso[i] <= s1cost) { next_iso = i; break; } } /* Add first */ pnts1[0].iso = next_iso; pnts1[0].distance = 0; npnts1++; next_iso++; /* Calculate distances for points along line */ while (next_iso < niso) { if (e1cost == 0) break; /* Outside line */ l1 = (iso[next_iso] - s1cost) / e1cost; if (l1 >= l) break; /* Outside line */ if (npnts1 == apnts1) { apnts1 += 1; pnts1 = (ISOPOINT *) G_realloc(pnts1, apnts1 * sizeof(ISOPOINT)); } pnts1[npnts1].iso = next_iso; pnts1[npnts1].distance = l1; G_debug(3, " forward %d : iso %d : distance %f : cost %f", npnts1, next_iso, l1, iso[next_iso]); npnts1++; next_iso++; } } G_debug(3, " npnts1 = %d", npnts1); /* Backward */ npnts2 = 0; if (centre2 != -1 && n2cost != -1 && e2cost != -1) { /* Find iso for beginning of the line */ next_iso = 0; for (i = niso - 1; i >= 0; i--) { if (iso[i] <= s2cost) { next_iso = i; break; } } /* Add first */ pnts2[0].iso = next_iso; pnts2[0].distance = l; npnts2++; next_iso++; /* Calculate distances for points along line */ while (next_iso < niso) { if (e2cost == 0) break; /* Outside line */ l1 = (iso[next_iso] - s2cost) / e2cost; if (l1 >= l) break; /* Outside line */ if (npnts2 == apnts2) { apnts2 += 1; pnts2 = (ISOPOINT *) G_realloc(pnts2, apnts2 * sizeof(ISOPOINT)); } pnts2[npnts2].iso = next_iso; pnts2[npnts2].distance = l - l1; G_debug(3, " backward %d : iso %d : distance %f : cost %f", npnts2, next_iso, l - l1, iso[next_iso]); npnts2++; next_iso++; } } G_debug(3, " npnts2 = %d", npnts2); /* Limit number of points by maximum costs in reverse direction, this may remove * also the first point in one direction, but not in both */ /* Forward */ if (npnts2 > 0) { for (i = 0; i < npnts1; i++) { G_debug(3, " pnt1 = %d dist1 = %f iso1 = %d max iso2 = %d", i, pnts1[i].distance, pnts1[i].iso, pnts2[npnts2 - 1].iso); if (pnts2[npnts2 - 1].iso < pnts1[i].iso) { G_debug(3, " -> cut here"); npnts1 = i; break; } } } G_debug(3, " npnts1 cut = %d", npnts1); /* Backward */ if (npnts1 > 0) { for (i = 0; i < npnts2; i++) { G_debug(3, " pnt2 = %d dist2 = %f iso2 = %d max iso1 = %d", i, pnts2[i].distance, pnts2[i].iso, pnts1[npnts1 - 1].iso); if (pnts1[npnts1 - 1].iso < pnts2[i].iso) { G_debug(3, " -> cut here"); npnts2 = i; break; } } } G_debug(3, " npnts2 cut = %d", npnts2); /* Biggest cost shoud be equal if exist (npnts > 0). Cut out overlapping segments, * this can cut only points on line but not first points */ if (npnts1 > 1 && npnts2 > 1) { while (npnts1 > 1 && npnts2 > 1) { if (pnts1[npnts1 - 1].distance >= pnts2[npnts2 - 1].distance) { /* overlap */ npnts1--; npnts2--; } else { break; } } } G_debug(3, " npnts1 2. cut = %d", npnts1); G_debug(3, " npnts2 2. cut = %d", npnts2); /* Now we have points in both directions which may not overlap, npoints in one * direction may be 0 but not both */ /* Join both arrays, iso of point is for next segment (point is at the beginning) */ /* In case npnts1 == 0 add point at distance 0 */ if (npnts1 == 0) { G_debug(3, " npnts1 = 0 -> add first at distance 0, cat = %d", pnts2[npnts2 - 1].iso); pnts1[0].iso = pnts2[npnts2 - 1].iso; /* use last point iso in reverse direction */ pnts1[0].distance = 0; npnts1++; } for (i = npnts2 - 1; i >= 0; i--) { /* Check if identical */ if (pnts1[npnts1 - 1].distance == pnts2[i].distance) continue; if (npnts1 == apnts1) { apnts1 += 1; pnts1 = (ISOPOINT *) G_realloc(pnts1, apnts1 * sizeof(ISOPOINT)); } pnts1[npnts1].iso = pnts2[i].iso - 1; /* last may be -1, but it is not used */ pnts1[npnts1].distance = pnts2[i].distance; npnts1++; } /* In case npnts2 == 0 add point at the end */ if (npnts2 == 0) { pnts1[npnts1].iso = 0; /* not used */ pnts1[npnts1].distance = l; npnts1++; } /* Create line segments. */ for (i = 1; i < npnts1; i++) { cat = pnts1[i - 1].iso + 1; G_debug(3, " segment %f - %f cat %d", pnts1[i - 1].distance, pnts1[i].distance, cat); ret = Vect_line_segment(Points, pnts1[i - 1].distance, pnts1[i].distance, SPoints); if (ret == 0) { G_warning(_("Cannot get line segment, segment out of line")); } else { Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, SPoints, Cats); } } } else { /* arc is not reachable */ G_debug(3, " -> arc is not reachable"); Vect_reset_cats(Cats); Vect_write_line(&Out, ltype, Points, Cats); } } Vect_build(&Out); /* Free, ... */ G_free(Nodes); G_free(Centers); Vect_close(&Map); Vect_close(&Out); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int i, j, ret, centre, line, centre1, centre2; int nlines, nnodes, type, ltype, afield, nfield, geo, cat; int node, node1, node2; double cost, e1cost, e2cost, n1cost, n2cost, s1cost, s2cost, l, l1, l2; struct Option *map, *output; struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt, *term_opt; struct Flag *geo_f; struct GModule *module; char *mapset; struct Map_info Map, Out; struct cat_list *catlist; CENTER *Centers = NULL; int acentres = 0, ncentres = 0; NODE *Nodes; struct line_cats *Cats; struct line_pnts *Points, *SPoints; G_gisinit(argv[0]); module = G_define_module(); module->keywords = _("vector, network, allocation"); module->label = _("Allocate subnets for nearest centres (direction from centre)."); module->description = _("Centre node must be opened (costs >= 0). " "Costs of centre node are used in calculation"); map = G_define_standard_option(G_OPT_V_INPUT); output = G_define_standard_option(G_OPT_V_OUTPUT); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "line,boundary"; type_opt->answer = "line,boundary"; type_opt->description = _("Arc type"); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "alayer"; afield_opt->answer = "1"; afield_opt->description = _("Arc layer"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "nlayer"; nfield_opt->answer = "2"; nfield_opt->description = _("Node layer"); afcol = G_define_option(); afcol->key = "afcolumn"; afcol->type = TYPE_STRING; afcol->required = NO; afcol->description = _("Arc forward/both direction(s) cost column (number)"); abcol = G_define_option(); abcol->key = "abcolumn"; abcol->type = TYPE_STRING; abcol->required = NO; abcol->description = _("Arc backward direction cost column (number)"); ncol = G_define_option(); ncol->key = "ncolumn"; ncol->type = TYPE_STRING; ncol->required = NO; ncol->description = _("Node cost column (number)"); term_opt = G_define_standard_option(G_OPT_V_CATS); term_opt->key = "ccats"; term_opt->required = YES; term_opt->description = _("Categories of centres (points on nodes) to which net " "will be allocated, " "layer for this categories is given by nlayer option"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); Vect_check_input_output_name(map->answer, output->answer, GV_FATAL_EXIT); Cats = Vect_new_cats_struct(); Points = Vect_new_line_struct(); SPoints = Vect_new_line_struct(); type = Vect_option_to_types(type_opt); afield = atoi(afield_opt->answer); nfield = atoi(nfield_opt->answer); catlist = Vect_new_cat_list(); Vect_str_to_cat_list(term_opt->answer, catlist); if (geo_f->answer) geo = 1; else geo = 0; mapset = G_find_vector2(map->answer, NULL); if (mapset == NULL) G_fatal_error(_("Vector map <%s> not found"), map->answer); Vect_set_open_level(2); Vect_open_old(&Map, map->answer, mapset); /* Build graph */ Vect_net_build_graph(&Map, type, afield, nfield, afcol->answer, abcol->answer, ncol->answer, geo, 0); nnodes = Vect_get_num_nodes(&Map); /* Create list of centres based on list of categories */ for (node = 1; node <= nnodes; node++) { nlines = Vect_get_node_n_lines(&Map, node); for (j = 0; j < nlines; j++) { line = abs(Vect_get_node_line(&Map, node, j)); ltype = Vect_read_line(&Map, NULL, Cats, line); if (!(ltype & GV_POINT)) continue; if (!(Vect_cat_get(Cats, nfield, &cat))) continue; if (Vect_cat_in_cat_list(cat, catlist)) { Vect_net_get_node_cost(&Map, node, &n1cost); if (n1cost == -1) { /* closed */ G_warning("Centre at closed node (costs = -1) ignored"); } else { if (acentres == ncentres) { acentres += 1; Centers = (CENTER *) G_realloc(Centers, acentres * sizeof(CENTER)); } Centers[ncentres].cat = cat; Centers[ncentres].node = node; G_debug(2, "centre = %d node = %d cat = %d", ncentres, node, cat); ncentres++; } } } } G_message(_("Number of centres: [%d] (nlayer: [%d])"), ncentres, nfield); if (ncentres == 0) G_warning(_("Not enough centres for selected nlayer. " "Nothing will be allocated.")); /* alloc and reset space for all nodes */ Nodes = (NODE *) G_calloc((nnodes + 1), sizeof(NODE)); for (i = 1; i <= nnodes; i++) { Nodes[i].centre = -1; } /* Fill Nodes by neares centre and costs from that centre */ G_message(_("Calculating costs from centres ...")); for (centre = 0; centre < ncentres; centre++) { G_percent(centre, ncentres, 1); node1 = Centers[centre].node; Vect_net_get_node_cost(&Map, node1, &n1cost); G_debug(2, "centre = %d node = %d cat = %d", centre, node1, Centers[centre].cat); for (node2 = 1; node2 <= nnodes; node2++) { G_debug(5, " node1 = %d node2 = %d", node1, node2); Vect_net_get_node_cost(&Map, node2, &n2cost); if (n2cost == -1) { continue; } /* closed, left it as not attached */ ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &cost); if (ret == -1) { continue; } /* node unreachable */ /* We must add centre node costs (not calculated by Vect_net_shortest_path() ), but * only if centre and node are not identical, because at the end node cost is add later */ if (node1 != node2) cost += n1cost; G_debug(5, "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f", node1, node2, cost, Nodes[node2].centre, Nodes[node2].cost); if (Nodes[node2].centre == -1 || cost < Nodes[node2].cost) { Nodes[node2].cost = cost; Nodes[node2].centre = centre; } } } G_percent(1, 1, 1); /* Write arcs to new map */ Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)); Vect_hist_command(&Out); nlines = Vect_get_num_lines(&Map); for (line = 1; line <= nlines; line++) { ltype = Vect_read_line(&Map, Points, NULL, line); if (!(ltype & type)) { continue; } Vect_get_line_nodes(&Map, line, &node1, &node2); centre1 = Nodes[node1].centre; centre2 = Nodes[node2].centre; s1cost = Nodes[node1].cost; s2cost = Nodes[node2].cost; G_debug(3, "Line %d:", line); G_debug(3, "Arc centres: %d %d (nodes: %d %d)", centre1, centre2, node1, node2); Vect_net_get_node_cost(&Map, node1, &n1cost); Vect_net_get_node_cost(&Map, node2, &n2cost); Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e1cost); Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e2cost); G_debug(3, " s1cost = %f n1cost = %f e1cost = %f", s1cost, n1cost, e1cost); G_debug(3, " s2cost = %f n2cost = %f e2cost = %f", s2cost, n2cost, e2cost); Vect_reset_cats(Cats); /* First check if arc is reachable from at least one side */ if ((centre1 != -1 && n1cost != -1 && e1cost != -1) || (centre2 != -1 && n2cost != -1 && e2cost != -1)) { /* Line is reachable at least from one side */ G_debug(3, " -> arc is reachable"); if (centre1 == centre2) { /* both nodes in one area -> whole arc in one area */ if (centre1 != -1) cat = Centers[centre1].cat; /* line reachable */ else cat = Centers[centre2].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, Points, Cats); } else { /* each node in different area */ /* Check if direction is reachable */ if (centre1 == -1 || n1cost == -1 || e1cost == -1) { /* closed from first node */ G_debug(3, " -> arc is not reachable from 1. node -> alloc to 2. node"); cat = Centers[centre2].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, Points, Cats); continue; } else if (centre2 == -1 || n2cost == -1 || e2cost == -1) { /* closed from second node */ G_debug(3, " -> arc is not reachable from 2. node -> alloc to 1. node"); cat = Centers[centre1].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, Points, Cats); continue; } /* Now we know that arc is reachable from both sides */ /* Add costs of node to starting costs */ s1cost += n1cost; s2cost += n2cost; /* Check if s1cost + e1cost <= s2cost or s2cost + e2cost <= s1cost ! * Note this check also possibility of (e1cost + e2cost) = 0 */ if (s1cost + e1cost <= s2cost) { /* whole arc reachable from node1 */ cat = Centers[centre1].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, Points, Cats); } else if (s2cost + e2cost <= s1cost) { /* whole arc reachable from node2 */ cat = Centers[centre2].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, Points, Cats); } else { /* split */ /* Calculate relative costs - we expect that costs along the line do not change */ l = Vect_line_length(Points); e1cost /= l; e2cost /= l; G_debug(3, " -> s1cost = %f e1cost = %f", s1cost, e1cost); G_debug(3, " -> s2cost = %f e2cost = %f", s2cost, e2cost); /* Costs from both centres to the splitting point must be equal: * s1cost + l1 * e1cost = s2cost + l2 * e2cost */ l1 = (l * e2cost - s1cost + s2cost) / (e1cost + e2cost); l2 = l - l1; G_debug(3, "l = %f l1 = %f l2 = %f", l, l1, l2); /* First segment */ ret = Vect_line_segment(Points, 0, l1, SPoints); if (ret == 0) { G_warning(_("Cannot get line segment, segment out of line")); } else { cat = Centers[centre1].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, SPoints, Cats); } /* Second segment */ ret = Vect_line_segment(Points, l1, l, SPoints); if (ret == 0) { G_warning(_("Cannot get line segment, segment out of line")); } else { Vect_reset_cats(Cats); cat = Centers[centre2].cat; Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, ltype, SPoints, Cats); } } } } else { /* arc is not reachable */ G_debug(3, " -> arc is not reachable"); Vect_write_line(&Out, ltype, Points, Cats); } } Vect_build(&Out); /* Free, ... */ G_free(Nodes); G_free(Centers); Vect_close(&Map); Vect_close(&Out); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int i, j, k, ret, city, city1; int nlines, type, ltype, afield, tfield, geo, cat; int node, node1, node2, line; struct Option *map, *output, *afield_opt, *tfield_opt, *afcol, *type_opt, *term_opt; struct Flag *geo_f; struct GModule *module; char *mapset; struct Map_info Map, Out; struct ilist *TList; /* list of terminal nodes */ struct ilist *List; struct ilist *StArcs; /* list of arcs on Steiner tree */ struct ilist *StNodes; /* list of nodes on Steiner tree */ double cost, tmpcost, tcost; struct cat_list *Clist; struct line_cats *Cats; struct line_pnts *Points; /* Initialize the GIS calls */ G_gisinit(argv[0]); module = G_define_module(); module->keywords = _("vector, network, salesman"); module->label = _("Creates a cycle connecting given nodes (Traveling salesman problem)."); module->description = _("Note that TSP is NP-hard, heuristic algorithm is used by " "this module and created cycle may be sub optimal"); map = G_define_standard_option(G_OPT_V_INPUT); output = G_define_standard_option(G_OPT_V_OUTPUT); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "line,boundary"; type_opt->answer = "line,boundary"; type_opt->description = _("Arc type"); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "alayer"; afield_opt->description = _("Arc layer"); tfield_opt = G_define_standard_option(G_OPT_V_FIELD); tfield_opt->key = "nlayer"; tfield_opt->answer = "2"; tfield_opt->description = _("Node layer (used for cities)"); afcol = G_define_option(); afcol->key = "acolumn"; afcol->type = TYPE_STRING; afcol->required = NO; afcol->description = _("Arcs' cost column (for both directions)"); term_opt = G_define_standard_option(G_OPT_V_CATS); term_opt->key = "ccats"; term_opt->required = YES; term_opt->description = _("Categories of points ('cities') on nodes " "(layer is specified by nlayer)"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); Cats = Vect_new_cats_struct(); Points = Vect_new_line_struct(); type = Vect_option_to_types(type_opt); afield = atoi(afield_opt->answer); TList = Vect_new_list(); List = Vect_new_list(); StArcs = Vect_new_list(); StNodes = Vect_new_list(); Clist = Vect_new_cat_list(); tfield = atoi(tfield_opt->answer); Vect_str_to_cat_list(term_opt->answer, Clist); G_debug(1, "Imput categories:\n"); for (i = 0; i < Clist->n_ranges; i++) { G_debug(1, "%d - %d\n", Clist->min[i], Clist->max[i]); } if (geo_f->answer) geo = 1; else geo = 0; Vect_check_input_output_name(map->answer, output->answer, GV_FATAL_EXIT); mapset = G_find_vector2(map->answer, NULL); if (mapset == NULL) G_fatal_error(_("Vector map <%s> not found"), map->answer); Vect_set_open_level(2); Vect_open_old(&Map, map->answer, mapset); nnodes = Vect_get_num_nodes(&Map); /* Create list of terminals based on list of categories */ for (i = 1; i <= nnodes; i++) { nlines = Vect_get_node_n_lines(&Map, i); for (j = 0; j < nlines; j++) { line = abs(Vect_get_node_line(&Map, i, j)); ltype = Vect_read_line(&Map, NULL, Cats, line); if (!(ltype & GV_POINT)) continue; if (!(Vect_cat_get(Cats, tfield, &cat))) continue; if (Vect_cat_in_cat_list(cat, Clist)) { Vect_list_append(TList, i); } } } ncities = TList->n_values; G_message(_("Number of cities: [%d]"), ncities); if (ncities < 2) G_fatal_error(_("Not enough cities (< 2)")); /* Alloc memory */ cities = (int *)G_malloc(ncities * sizeof(int)); cused = (int *)G_malloc(ncities * sizeof(int)); for (i = 0; i < ncities; i++) { G_debug(1, "%d\n", TList->value[i]); cities[i] = TList->value[i]; cused[i] = 0; /* not in cycle */ } costs = (COST **) G_malloc(ncities * sizeof(COST *)); for (i = 0; i < ncities; i++) { costs[i] = (COST *) G_malloc(ncities * sizeof(COST)); } cycle = (int *)G_malloc((ncities + 1) * sizeof(int)); /* + 1 is for output cycle */ /* Build graph */ Vect_net_build_graph(&Map, type, afield, 0, afcol->answer, NULL, NULL, geo, 0); /* Create sorted lists of costs */ for (i = 0; i < ncities; i++) { k = 0; for (j = 0; j < ncities; j++) { if (i == j) continue; ret = Vect_net_shortest_path(&Map, cities[i], cities[j], NULL, &cost); if (ret == -1) G_fatal_error(_("Destination node [%d] is unreachable " "from node [%d]"), cities[i], cities[j]); costs[i][k].city = j; costs[i][k].cost = cost; k++; } qsort((void *)costs[i], k, sizeof(COST), cmp); } /* debug: print sorted */ for (i = 0; i < ncities; i++) { for (j = 0; j < ncities - 1; j++) { city = costs[i][j].city; G_debug(2, "%d -> %d = %f\n", cities[i], cities[city], costs[i][j].cost); } } /* find 2 cities with largest distance */ cost = -1; for (i = 0; i < ncities; i++) { tmpcost = costs[i][ncities - 2].cost; if (tmpcost > cost) { cost = tmpcost; city = i; } } G_debug(2, "biggest costs %d - %d\n", city, costs[city][ncities - 2].city); /* add this 2 cities to array */ add_city(city, -1); add_city(costs[city][ncities - 2].city, 0); /* In each step, find not used city, with biggest cost to any used city, and insert * into cycle between 2 nearest nodes */ for (i = 0; i < ncities - 2; i++) { cost = -1; G_debug(2, "---- %d ----\n", i); for (j = 0; j < ncities; j++) { if (cused[j] == 1) continue; tmpcost = 0; for (k = 0; k < ncities - 1; k++) { G_debug(2, "? %d (%d) - %d (%d) \n", j, cnode(j), costs[j][k].city, cnode(costs[j][k].city)); if (!cused[costs[j][k].city]) continue; /* only used */ tmpcost += costs[j][k].cost; break; /* first nearest */ } G_debug(2, " cost = %f x %f\n", tmpcost, cost); if (tmpcost > cost) { cost = tmpcost; city = j; } } G_debug(2, "add %d\n", city); /* add to cycle on lovest costs */ cycle[ncyc] = cycle[0]; /* tmp for cycle */ cost = PORT_DOUBLE_MAX; for (j = 0; j < ncyc; j++) { node1 = cities[cycle[j]]; node2 = cities[cycle[j + 1]]; ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost); tmpcost = -tcost; node1 = cities[cycle[j]]; node2 = cities[city]; ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost); tmpcost += tcost; node1 = cities[cycle[j + 1]]; node2 = cities[city]; ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &tcost); tmpcost += tcost; G_debug(2, "? %d - %d cost = %f x %f\n", node1, node2, tmpcost, cost); if (tmpcost < cost) { city1 = j; cost = tmpcost; } } add_city(city, city1); } /* Print */ G_debug(2, "Cycle:\n"); for (i = 0; i < ncities; i++) { G_debug(2, "%d: %d: %d\n", i, cycle[i], cities[cycle[i]]); } /* Create list of arcs */ cycle[ncities] = cycle[0]; for (i = 0; i < ncities; i++) { node1 = cities[cycle[i]]; node2 = cities[cycle[i + 1]]; G_debug(2, " %d -> %d\n", node1, node2); ret = Vect_net_shortest_path(&Map, node1, node2, List, NULL); for (j = 0; j < List->n_values; j++) { line = abs(List->value[j]); Vect_list_append(StArcs, line); Vect_get_line_nodes(&Map, line, &node1, &node2); Vect_list_append(StNodes, node1); Vect_list_append(StNodes, node2); } } /* Write arcs to new map */ Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)); Vect_hist_command(&Out); fprintf(stdout, "\nCycle:\n"); fprintf(stdout, "Arcs' categories (layer %d, %d arcs):\n", afield, StArcs->n_values); for (i = 0; i < StArcs->n_values; i++) { line = StArcs->value[i]; ltype = Vect_read_line(&Map, Points, Cats, line); Vect_write_line(&Out, ltype, Points, Cats); Vect_cat_get(Cats, afield, &cat); if (i > 0) printf(","); fprintf(stdout, "%d", cat); } fprintf(stdout, "\n\n"); fprintf(stdout, "Nodes' categories (layer %d, %d nodes):\n", tfield, StNodes->n_values); k = 0; for (i = 0; i < StNodes->n_values; i++) { node = StNodes->value[i]; nlines = Vect_get_node_n_lines(&Map, node); for (j = 0; j < nlines; j++) { line = abs(Vect_get_node_line(&Map, node, j)); ltype = Vect_read_line(&Map, Points, Cats, line); if (!(ltype & GV_POINT)) continue; if (!(Vect_cat_get(Cats, tfield, &cat))) continue; Vect_write_line(&Out, ltype, Points, Cats); if (k > 0) fprintf(stdout, ","); fprintf(stdout, "%d", cat); k++; } } fprintf(stdout, "\n\n"); Vect_build(&Out); /* Free, ... */ Vect_destroy_list(StArcs); Vect_destroy_list(StNodes); Vect_close(&Map); Vect_close(&Out); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct GModule *module; struct { struct Option *input, *output, *zshift, *height, *elevation, *hcolumn, *type, *field, *cats, *where, *interp, *scale, *null; } opt; struct { struct Flag *trace; } flag; struct Map_info In, Out; struct line_pnts *Points; struct line_cats *Cats; struct bound_box map_box; struct cat_list *cat_list; struct Cell_head window; int field; int only_type, cat; int fdrast, interp_method, trace; double objheight, objheight_default, voffset; double scale, null_val; struct field_info *Fi; dbDriver *driver = NULL; char *comment; module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); G_add_keyword(_("sampling")); G_add_keyword(_("3D")); module->label = _("Extrudes flat vector features to 3D vector features with defined height."); module->description = _("Optionally the height can be derived from sampling of elevation raster map."); flag.trace = G_define_flag(); flag.trace->key = 't'; flag.trace->description = _("Trace elevation"); flag.trace->guisection = _("Elevation"); opt.input = G_define_standard_option(G_OPT_V_INPUT); opt.field = G_define_standard_option(G_OPT_V_FIELD_ALL); opt.field->guisection = _("Selection"); opt.cats = G_define_standard_option(G_OPT_V_CATS); opt.cats->guisection = _("Selection"); opt.where = G_define_standard_option(G_OPT_DB_WHERE); opt.where->guisection = _("Selection"); opt.type = G_define_standard_option(G_OPT_V_TYPE); opt.type->answer = "point,line,area"; opt.type->options = "point,line,area"; opt.type->guisection = _("Selection"); opt.output = G_define_standard_option(G_OPT_V_OUTPUT); opt.zshift = G_define_option(); opt.zshift->key = "zshift"; opt.zshift->description = _("Shifting value for z coordinates"); opt.zshift->type = TYPE_DOUBLE; opt.zshift->required = NO; opt.zshift->answer = "0"; opt.zshift->guisection = _("Height"); opt.height = G_define_option(); opt.height->key = "height"; opt.height->type = TYPE_DOUBLE; opt.height->required = NO; opt.height->multiple = NO; opt.height->description = _("Fixed height for 3D vector features"); opt.height->guisection = _("Height"); opt.hcolumn = G_define_standard_option(G_OPT_DB_COLUMN); opt.hcolumn->key = "height_column"; opt.hcolumn->multiple = NO; opt.hcolumn->description = _("Name of attribute column with feature height"); opt.hcolumn->guisection = _("Height"); /* raster sampling */ opt.elevation = G_define_standard_option(G_OPT_R_ELEV); opt.elevation->required = NO; opt.elevation->description = _("Elevation raster map for height extraction"); opt.elevation->guisection = _("Elevation"); opt.interp = G_define_standard_option(G_OPT_R_INTERP_TYPE); opt.interp->answer = "nearest"; opt.interp->guisection = _("Elevation"); opt.scale = G_define_option(); opt.scale->key = "scale"; opt.scale->type = TYPE_DOUBLE; opt.scale->description = _("Scale factor sampled raster values"); opt.scale->answer = "1.0"; opt.scale->guisection = _("Elevation"); opt.null = G_define_option(); opt.null->key = "null_value"; opt.null->type = TYPE_DOUBLE; opt.null->description = _("Height for sampled raster NULL values"); opt.null->guisection = _("Elevation"); G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (!opt.height->answer && !opt.hcolumn->answer) { G_fatal_error(_("One of '%s' or '%s' parameters must be set"), opt.height->key, opt.hcolumn->key); } sscanf(opt.zshift->answer, "%lf", &voffset); G_debug(1, "voffset = %f", voffset); if (opt.height->answer) sscanf(opt.height->answer, "%lf", &objheight); else objheight = 0.; G_debug(1, "objheight = %f", objheight); objheight_default = objheight; only_type = Vect_option_to_types(opt.type); /* sampling method */ interp_method = Rast_option_to_interp_type(opt.interp); /* used to scale sampled raster values */ scale = atof(opt.scale->answer); /* is null value defined */ if (opt.null->answer) null_val = atof(opt.null->answer); /* trace elevation */ trace = flag.trace->answer ? TRUE : FALSE; /* set input vector map name and mapset */ Vect_check_input_output_name(opt.input->answer, opt.output->answer, G_FATAL_EXIT); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Vect_set_open_level(2); /* topology required for input */ /* opening input vector map */ if (Vect_open_old2(&In, opt.input->answer, "", opt.field->answer) < 0) G_fatal_error(_("Unable to open vector map <%s>"), opt.input->answer); Vect_set_error_handler_io(&In, &Out); /* creating output vector map */ if (Vect_open_new(&Out, opt.output->answer, WITH_Z) < 0) G_fatal_error(_("Unable to create vector map <%s>"), opt.output->answer); field = Vect_get_field_number(&In, opt.field->answer); if ((opt.hcolumn->answer || opt.cats->answer || opt.where->answer) && field == -1) { G_warning(_("Invalid layer number (%d). " "Parameter '%s', '%s' or '%s' specified, assuming layer '1'."), field, opt.hcolumn->key, opt.cats->key, opt.where->key); field = 1; } /* set constraint for cats or where */ cat_list = NULL; if (field > 0) cat_list = Vect_cats_set_constraint(&In, field, opt.where->answer, opt.cats->answer); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); /* opening database connection, if required */ if (opt.hcolumn->answer) { int ctype; dbColumn *column; if ((Fi = Vect_get_field(&In, field)) == NULL) G_fatal_error(_("Database connection not defined for layer %d"), field); if ((driver = db_start_driver_open_database(Fi->driver, Fi->database)) == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_set_error_handler_driver(driver); if (db_get_column(driver, Fi->table, opt.hcolumn->answer, &column) != DB_OK) G_fatal_error(_("Column <%s> does not exist"), opt.hcolumn->answer); else db_free_column(column); ctype = db_column_Ctype(driver, Fi->table, opt.hcolumn->answer); if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_STRING && ctype != DB_C_TYPE_DOUBLE) { G_fatal_error(_("Column <%s>: invalid data type"), opt.hcolumn->answer); } } /* do we work with elevation raster? */ fdrast = -1; if (opt.elevation->answer) { /* raster setup */ G_get_window(&window); /* open the elev raster, and check for error condition */ fdrast = Rast_open_old(opt.elevation->answer, ""); } /* if area */ if (only_type & GV_AREA) { int area, nareas, centroid; nareas = Vect_get_num_areas(&In); G_debug(2, "n_areas = %d", nareas); if (nareas > 0) G_message(_("Extruding areas...")); for (area = 1; area <= nareas; area++) { G_debug(3, "area = %d", area); G_percent(area, nareas, 2); if (!Vect_area_alive(&In, area)) continue; centroid = Vect_get_area_centroid(&In, area); if (!centroid) { G_warning(_("Skipping area %d without centroid"), area); continue; } Vect_read_line(&In, NULL, Cats, centroid); if (field > 0 && !Vect_cats_in_constraint(Cats, field, cat_list)) continue; /* height attribute */ if (opt.hcolumn->answer) { cat = Vect_get_area_cat(&In, area, field); if (cat == -1) { G_warning(_("No category defined for area %d. Using default fixed height %f."), area, objheight_default); objheight = objheight_default; } if (get_height(Fi, opt.hcolumn->answer, driver, cat, &objheight) != 0) { G_warning(_("Unable to fetch height from DB for area %d. Using default fixed height %f."), area, objheight_default); objheight = objheight_default; } } /* if opt.hcolumn->answer */ Vect_get_area_points(&In, area, Points); G_debug(3, "area: %d height: %f", area, objheight); extrude(&In, &Out, Cats, Points, fdrast, trace, interp_method, scale, opt.null->answer ? TRUE : FALSE, null_val, objheight, voffset, &window, GV_AREA, centroid); } /* foreach area */ } if (only_type > 0) { int line, nlines; int type; G_debug(1, "other than areas"); /* loop through each line in the dataset */ nlines = Vect_get_num_lines(&In); G_message(_("Extruding features...")); for (line = 1; line <= nlines; line++) { /* progress feedback */ G_percent(line, nlines, 2); if (!Vect_line_alive(&In, line)) continue; /* read line */ type = Vect_read_line(&In, Points, Cats, line); if (!(type & only_type)) continue; if (field > 0 && !Vect_cats_in_constraint(Cats, field, cat_list)) continue; /* height attribute */ if (opt.hcolumn->answer) { cat = Vect_get_line_cat(&In, line, field); if (cat == -1) { G_warning(_("No category defined for feature %d. Using default fixed height %f."), line, objheight_default); objheight = objheight_default; } if (get_height(Fi, opt.hcolumn->answer, driver, cat, &objheight) != 0) { G_warning(_("Unable to fetch height from DB for line %d. Using default fixed height %f."), line, objheight_default); objheight = objheight_default; } } /* if opt.hcolumn->answer */ extrude(&In, &Out, Cats, Points, fdrast, trace, interp_method, scale, opt.null->answer ? TRUE : FALSE, null_val, objheight, voffset, &window, type, -1); } /* for each line */ } /* else if area */ if (driver) { db_close_database(driver); db_shutdown_driver(driver); } G_important_message(_("Copying attribute table...")); if (field < 0) Vect_copy_tables(&In, &Out, 0); else Vect_copy_table_by_cat_list(&In, &Out, field, field, NULL, GV_1TABLE, cat_list); Vect_build(&Out); /* header */ G_asprintf(&comment, "Generated by %s from vector map <%s>", G_program_name(), Vect_get_full_name(&In)); Vect_set_comment(&Out, comment); G_free(comment); Vect_get_map_box(&Out, &map_box); Vect_close(&In); Vect_close(&Out); Vect_destroy_line_struct(Points); Vect_destroy_cats_struct(Cats); G_done_msg("T: %f B: %f.", map_box.T, map_box.B); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct GModule *module; struct GParams params; struct Map_info Map; struct Map_info **BgMap; /* background vector maps */ int nbgmaps; /* number of registrated background maps */ enum mode action_mode; FILE *ascii; int i; int move_first, snap; int ret, layer; double move_x, move_y, move_z, thresh[3]; struct line_pnts *coord; struct ilist *List; struct cat_list *Clist; ascii = NULL; List = NULL; BgMap = NULL; nbgmaps = 0; coord = NULL; Clist = NULL; G_gisinit(argv[0]); module = G_define_module(); module->overwrite = TRUE; G_add_keyword(_("vector")); G_add_keyword(_("geometry")); G_add_keyword(_("editing")); G_add_keyword(_("line")); G_add_keyword(_("node")); G_add_keyword(_("point")); G_add_keyword(_("vertex")); module->description = _("Edits a vector map, allows adding, deleting " "and modifying selected vector features."); if (!parser(argc, argv, ¶ms, &action_mode)) exit(EXIT_FAILURE); /* get list of categories */ Clist = Vect_new_cat_list(); if (params.cat->answer && Vect_str_to_cat_list(params.cat->answer, Clist)) { G_fatal_error(_("Unable to get category list <%s>"), params.cat->answer); } /* open input file */ if (params.in->answer) { if (strcmp(params.in->answer, "-") != 0) { ascii = fopen(params.in->answer, "r"); if (ascii == NULL) G_fatal_error(_("Unable to open file <%s>"), params.in->answer); } else { ascii = stdin; } } if (!ascii && action_mode == MODE_ADD) G_fatal_error(_("Required parameter <%s> not set"), params.in->key); if (action_mode == MODE_CREATE) { int overwrite, map_type; overwrite = G_check_overwrite(argc, argv); if (G_find_vector2(params.map->answer, G_mapset()) && (!G_find_file("", "OGR", G_mapset()) && !G_find_file("", "PG", G_mapset()))) { if (!overwrite) G_fatal_error(_("Vector map <%s> already exists"), params.map->answer); } /* 3D vector maps? */ putenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE=1"); ret = Vect_open_new(&Map, params.map->answer, WITHOUT_Z); if (ret == -1) { G_fatal_error(_("Unable to create vector map <%s>"), params.map->answer); } Vect_set_error_handler_io(NULL, &Map); /* native or external data source ? */ map_type = Vect_maptype(&Map); if (map_type != GV_FORMAT_NATIVE) { int type; type = Vect_option_to_types(params.type); if (type != GV_POINT && !(type & GV_LINES)) G_fatal_error("%s: point,line,boundary", _("Supported feature types for non-native formats:")); /* create OGR or PostGIS layer */ if (Vect_write_line(&Map, type, NULL, NULL) < 0) G_fatal_error(_("Unable to create vector map <%s>"), params.map->answer); } G_debug(1, "Map created"); if (ascii) { /* also add new vector features */ action_mode = MODE_ADD; } } else { /* open selected vector file */ if (action_mode == MODE_ADD) /* write */ ret = Vect_open_update2(&Map, params.map->answer, G_mapset(), params.fld->answer); else /* read-only -- select features */ ret = Vect_open_old2(&Map, params.map->answer, G_mapset(), params.fld->answer); if (ret < 2) G_fatal_error(_("Unable to open vector map <%s> on topological level. " "Try to rebuild vector topology by v.build."), params.map->answer); } G_debug(1, "Map opened"); /* open background maps */ if (params.bmaps->answer) { i = 0; while (params.bmaps->answers[i]) { const char *bmap = params.bmaps->answers[i]; const char *mapset = G_find_vector2(bmap, ""); if (!mapset) G_fatal_error(_("Vector map <%s> not found"), bmap); if (strcmp( G_fully_qualified_name(params.map->answer, G_mapset()), G_fully_qualified_name(bmap, mapset)) == 0) { G_fatal_error(_("Unable to open vector map <%s> as the background map. " "It is given as vector map to be edited."), bmap); } nbgmaps++; BgMap = (struct Map_info **)G_realloc( BgMap, nbgmaps * sizeof(struct Map_info *)); BgMap[nbgmaps - 1] = (struct Map_info *)G_malloc(sizeof(struct Map_info)); if (Vect_open_old(BgMap[nbgmaps - 1], bmap, "") == -1) G_fatal_error(_("Unable to open vector map <%s>"), bmap); G_verbose_message(_("Background vector map <%s> registered"), bmap); i++; } } layer = Vect_get_field_number(&Map, params.fld->answer); i = 0; while (params.maxdist->answers[i]) { switch (i) { case THRESH_COORDS: thresh[THRESH_COORDS] = max_distance(atof(params.maxdist->answers[THRESH_COORDS])); thresh[THRESH_SNAP] = thresh[THRESH_QUERY] = thresh[THRESH_COORDS]; break; case THRESH_SNAP: thresh[THRESH_SNAP] = max_distance(atof(params.maxdist->answers[THRESH_SNAP])); break; case THRESH_QUERY: thresh[THRESH_QUERY] = atof(params.maxdist->answers[THRESH_QUERY]); break; default: break; } i++; } move_first = params.move_first->answer ? 1 : 0; snap = NO_SNAP; if (strcmp(params.snap->answer, "node") == 0) snap = SNAP; else if (strcmp(params.snap->answer, "vertex") == 0) snap = SNAPVERTEX; if (snap != NO_SNAP && thresh[THRESH_SNAP] <= 0) { G_warning(_("Threshold for snapping must be > 0. No snapping applied.")); snap = NO_SNAP; } if (action_mode != MODE_CREATE && action_mode != MODE_ADD) { /* select lines */ List = Vect_new_list(); G_message(_("Selecting features...")); if (action_mode == MODE_COPY && BgMap && BgMap[0]) { List = select_lines(BgMap[0], action_mode, ¶ms, thresh, List); } else { List = select_lines(&Map, action_mode, ¶ms, thresh, List); } } if ((action_mode != MODE_CREATE && action_mode != MODE_ADD && action_mode != MODE_SELECT)) { if (List->n_values < 1) { G_warning(_("No features selected, nothing to edit")); action_mode = MODE_NONE; ret = 0; } else { /* reopen the map for updating */ if (action_mode == MODE_ZBULK && !Vect_is_3d(&Map)) { Vect_close(&Map); G_fatal_error(_("Vector map <%s> is not 3D. Tool '%s' requires 3D vector map. " "Please convert the vector map " "to 3D using e.g. %s."), params.map->answer, params.tool->answer, "v.extrude"); } Vect_close(&Map); if (Vect_open_update2(&Map, params.map->answer, G_mapset(), params.fld->answer) < 0) G_fatal_error(_("Unable to open vector map <%s>"), params.map->answer); } } /* coords option -> array */ if (params.coord->answers) { coord = Vect_new_line_struct(); int i = 0; double east, north; while (params.coord->answers[i]) { east = atof(params.coord->answers[i]); north = atof(params.coord->answers[i + 1]); Vect_append_point(coord, east, north, 0.0); i += 2; } } /* perform requested editation */ switch (action_mode) { case MODE_CREATE: break; case MODE_ADD: if (!params.header->answer) Vect_read_ascii_head(ascii, &Map); int num_lines; num_lines = Vect_get_num_lines(&Map); ret = Vect_read_ascii(ascii, &Map); if (ret > 0) { int iline; struct ilist *List_added; G_message(n_("%d feature added", "%d features added", ret), ret); List_added = Vect_new_list(); for (iline = num_lines + 1; iline <= Vect_get_num_lines(&Map); iline++) Vect_list_append(List_added, iline); G_verbose_message(_("Threshold value for snapping is %.2f"), thresh[THRESH_SNAP]); if (snap != NO_SNAP) { /* apply snapping */ /* snap to vertex ? */ Vedit_snap_lines(&Map, BgMap, nbgmaps, List_added, thresh[THRESH_SNAP], snap == SNAP ? FALSE : TRUE); } if (params.close->answer) { /* close boundaries */ int nclosed; nclosed = close_lines(&Map, GV_BOUNDARY, thresh[THRESH_SNAP]); G_message(n_("%d boundary closed", "%d boundaries closed", nclosed), nclosed); } Vect_destroy_list(List_added); } break; case MODE_DEL: ret = Vedit_delete_lines(&Map, List); G_message(n_("%d feature deleted", "%d features deleted", ret), ret); break; case MODE_MOVE: move_x = atof(params.move->answers[0]); move_y = atof(params.move->answers[1]); move_z = atof(params.move->answers[2]); G_verbose_message(_("Threshold value for snapping is %.2f"), thresh[THRESH_SNAP]); ret = Vedit_move_lines(&Map, BgMap, nbgmaps, List, move_x, move_y, move_z, snap, thresh[THRESH_SNAP]); G_message(n_("%d feature moved", "%d features moved", ret), ret); break; case MODE_VERTEX_MOVE: move_x = atof(params.move->answers[0]); move_y = atof(params.move->answers[1]); move_z = atof(params.move->answers[2]); G_verbose_message(_("Threshold value for snapping is %.2f"), thresh[THRESH_SNAP]); ret = Vedit_move_vertex(&Map, BgMap, nbgmaps, List, coord, thresh[THRESH_COORDS], thresh[THRESH_SNAP], move_x, move_y, move_z, move_first, snap); G_message(n_("%d vertex moved", "%d vertices moved", ret), ret); break; case MODE_VERTEX_ADD: ret = Vedit_add_vertex(&Map, List, coord, thresh[THRESH_COORDS]); G_message(n_("%d vertex added", "%d vertices added", ret), ret); break; case MODE_VERTEX_DELETE: ret = Vedit_remove_vertex(&Map, List, coord, thresh[THRESH_COORDS]); G_message(n_("%d vertex removed", "%d vertices removed", ret), ret); break; case MODE_BREAK: if (params.coord->answer) { ret = Vedit_split_lines(&Map, List, coord, thresh[THRESH_COORDS], NULL); } else { ret = Vect_break_lines_list(&Map, List, NULL, GV_LINES, NULL); } G_message(n_("%d line broken", "%d lines broken", ret), ret); break; case MODE_CONNECT: G_verbose_message(_("Threshold value for snapping is %.2f"), thresh[THRESH_SNAP]); ret = Vedit_connect_lines(&Map, List, thresh[THRESH_SNAP]); G_message(n_("%d line connected", "%d lines connected", ret), ret); break; case MODE_MERGE: ret = Vedit_merge_lines(&Map, List); G_message(n_("%d line merged", "%d lines merged", ret), ret); break; case MODE_SELECT: ret = print_selected(List); break; case MODE_CATADD: ret = Vedit_modify_cats(&Map, List, layer, 0, Clist); G_message(n_("%d feature modified", "%d features modified", ret), ret); break; case MODE_CATDEL: ret = Vedit_modify_cats(&Map, List, layer, 1, Clist); G_message(n_("%d feature modified", "%d features modified", ret), ret); break; case MODE_COPY: if (BgMap && BgMap[0]) { if (nbgmaps > 1) G_warning(_("Multiple background maps were given. " "Selected features will be copied only from " "vector map <%s>."), Vect_get_full_name(BgMap[0])); ret = Vedit_copy_lines(&Map, BgMap[0], List); } else { ret = Vedit_copy_lines(&Map, NULL, List); } G_message(n_("%d feature copied", "%d features copied", ret), ret); break; case MODE_SNAP: G_verbose_message(_("Threshold value for snapping is %.2f"), thresh[THRESH_SNAP]); ret = snap_lines(&Map, List, thresh[THRESH_SNAP]); break; case MODE_FLIP: ret = Vedit_flip_lines(&Map, List); G_message(n_("%d line flipped", "%d lines flipped", ret), ret); break; case MODE_NONE: break; case MODE_ZBULK: { double start, step; double x1, y1, x2, y2; start = atof(params.zbulk->answers[0]); step = atof(params.zbulk->answers[1]); x1 = atof(params.bbox->answers[0]); y1 = atof(params.bbox->answers[1]); x2 = atof(params.bbox->answers[2]); y2 = atof(params.bbox->answers[3]); ret = Vedit_bulk_labeling(&Map, List, x1, y1, x2, y2, start, step); G_message(n_("%d line labeled", "%d lines labeled", ret), ret); break; } case MODE_CHTYPE: ret = Vedit_chtype_lines(&Map, List); if (ret > 0) { G_message(n_("%d feature converted", "%d features converted", ret), ret); } else { G_message(_("No feature modified")); } break; case MODE_AREA_DEL: { ret = 0; for (i = 0; i < List->n_values; i++) { if (Vect_get_line_type(&Map, List->value[i]) != GV_CENTROID) { G_warning(_("Select feature %d is not centroid, ignoring..."), List->value[i]); continue; } ret += Vedit_delete_area_centroid(&Map, List->value[i]); } G_message(n_("%d area removed", "%d areas removed", ret), ret); break; } default: G_warning(_("Operation not implemented")); ret = -1; break; } Vect_hist_command(&Map); /* build topology only if requested or if tool!=select */ if (action_mode != MODE_SELECT && action_mode != MODE_NONE && params.topo->answer != 1) { Vect_build_partial(&Map, GV_BUILD_NONE); Vect_build(&Map); } if (List) Vect_destroy_list(List); Vect_close(&Map); G_debug(1, "Map closed"); /* close background maps */ for (i = 0; i < nbgmaps; i++) { Vect_close(BgMap[i]); G_free((void *)BgMap[i]); } G_free((void *)BgMap); if (coord) Vect_destroy_line_struct(coord); if (Clist) Vect_destroy_cat_list(Clist); G_done_msg(" "); if (ret > -1) { exit(EXIT_SUCCESS); } else { exit(EXIT_FAILURE); } }
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); }
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) { 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) { int i, j, k, ret; int nlines, type, ltype, afield, tfield, geo, cat; int sp, nsp, nspused, node, line; struct Option *map, *output, *afield_opt, *tfield_opt, *afcol, *type_opt, *term_opt, *nsp_opt; struct Flag *geo_f; struct GModule *module; struct Map_info Map, Out; int *testnode; /* array all nodes: 1 - should be tested as Steiner, * 0 - no need to test (unreachable or terminal) */ struct ilist *TList; /* list of terminal nodes */ struct ilist *StArcs; /* list of arcs on Steiner tree */ struct ilist *StNodes; /* list of nodes on Steiner tree */ struct boxlist *pointlist; double cost, tmpcost; struct cat_list *Clist; struct line_cats *Cats; struct line_pnts *Points; /* Initialize the GIS calls */ G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("network")); G_add_keyword(_("steiner tree")); module->label = _("Creates Steiner tree for the network and given terminals."); module->description = _("Note that 'Minimum Steiner Tree' problem is NP-hard " "and heuristic algorithm is used in this module so " "the result may be sub optimal."); map = G_define_standard_option(G_OPT_V_INPUT); output = G_define_standard_option(G_OPT_V_OUTPUT); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->key = "arc_type"; type_opt->options = "line,boundary"; type_opt->answer = "line,boundary"; type_opt->label = _("Arc type"); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "arc_layer"; afield_opt->answer = "1"; afield_opt->label = _("Arc layer"); tfield_opt = G_define_standard_option(G_OPT_V_FIELD); tfield_opt->key = "node_layer"; tfield_opt->answer = "2"; tfield_opt->label = _("Node layer (used for terminals)"); afcol = G_define_option(); afcol->key = "acolumn"; afcol->type = TYPE_STRING; afcol->required = NO; afcol->description = _("Arcs' cost column (for both directions)"); term_opt = G_define_standard_option(G_OPT_V_CATS); term_opt->key = "terminal_cats"; term_opt->required = YES; term_opt->description = _("Categories of points on terminals (layer is specified by nlayer)"); nsp_opt = G_define_option(); nsp_opt->key = "npoints"; nsp_opt->type = TYPE_INTEGER; nsp_opt->required = NO; nsp_opt->multiple = NO; nsp_opt->answer = "-1"; nsp_opt->description = _("Number of Steiner points (-1 for all possible)"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); Cats = Vect_new_cats_struct(); Points = Vect_new_line_struct(); type = Vect_option_to_types(type_opt); afield = atoi(afield_opt->answer); TList = Vect_new_list(); StArcs = Vect_new_list(); StNodes = Vect_new_list(); Clist = Vect_new_cat_list(); tfield = atoi(tfield_opt->answer); Vect_str_to_cat_list(term_opt->answer, Clist); G_debug(1, "Imput categories:\n"); for (i = 0; i < Clist->n_ranges; i++) { G_debug(1, "%d - %d\n", Clist->min[i], Clist->max[i]); } if (geo_f->answer) geo = 1; else geo = 0; Vect_check_input_output_name(map->answer, output->answer, G_FATAL_EXIT); Vect_set_open_level(2); if (Vect_open_old(&Map, map->answer, "") < 0) G_fatal_error(_("Unable to open vector map <%s>"), map->answer); nnodes = Vect_get_num_nodes(&Map); nlines = Vect_get_num_lines(&Map); /* Create list of terminals based on list of categories */ for (i = 1; i <= nlines; i++) { ltype = Vect_get_line_type(&Map, i); if (!(ltype & GV_POINT)) continue; Vect_read_line(&Map, Points, Cats, i); if (!(Vect_cat_get(Cats, tfield, &cat))) continue; node = Vect_find_node(&Map, Points->x[0], Points->y[0], Points->z[0], 0, 0); if (!node) { G_warning(_("Point is not connected to the network (cat=%d)"), cat); continue; } if (Vect_cat_in_cat_list(cat, Clist)) { Vect_list_append(TList, node); } } nterms = TList->n_values; /* GTC Terminal refers to an Steiner tree endpoint */ G_message(_("Number of terminals: %d\n"), nterms); if (nterms < 2) { /* GTC Terminal refers to an Steiner tree endpoint */ G_fatal_error(_("Not enough terminals (< 2)")); } /* Number of steiner points */ nsp = atoi(nsp_opt->answer); if (nsp > nterms - 2) { nsp = nterms - 2; G_warning(_("Requested number of Steiner points > than possible")); } else if (nsp == -1) { nsp = nterms - 2; } G_message(_("Number of Steiner points set to %d\n"), nsp); testnode = (int *)G_malloc((nnodes + 1) * sizeof(int)); for (i = 1; i <= nnodes; i++) testnode[i] = 1; /* Alloc arrays of costs for nodes, first node at 1 (0 not used) */ nodes_costs = (double **)G_malloc((nnodes) * sizeof(double *)); for (i = 0; i < nnodes; i++) { nodes_costs[i] = (double *)G_malloc((nnodes - i) * sizeof(double)); for (j = 0; j < nnodes - i; j++) nodes_costs[i][j] = -1; /* init, i.e. cost was not calculated yet */ } /* alloc memory from each to each other (not directed) terminal */ i = nterms + nterms - 2; /* max number of terms + Steiner points */ comps = (int *)G_malloc(i * sizeof(int)); i = i * (i - 1) / 2; /* number of combinations */ term_costs = (COST *) G_malloc(i * sizeof(COST)); /* alloc memory for costs from Stp to each other terminal */ i = nterms + nterms - 2 - 1; /* max number of terms + Steiner points - 1 */ sp_costs = (COST *) G_malloc(i * sizeof(COST)); terms = (int *)G_malloc((nterms + nterms - 2) * sizeof(int)); /* i.e. +(nterms - 2) St Points */ /* Create initial parts from list of terminals */ G_debug(1, "List of terminal nodes (%d):\n", nterms); for (i = 0; i < nterms; i++) { G_debug(1, "%d\n", TList->value[i]); terms[i] = TList->value[i]; testnode[terms[i]] = 0; /* do not test as Steiner */ } /* Build graph */ Vect_net_build_graph(&Map, type, afield, 0, afcol->answer, NULL, NULL, geo, 0); /* Init costs for all terminals */ for (i = 0; i < nterms; i++) init_node_costs(&Map, terms[i]); /* Test if all terminal may be connected */ for (i = 1; i < nterms; i++) { ret = get_node_costs(terms[0], terms[i], &cost); if (ret == 0) { /* GTC Terminal refers to an Steiner tree endpoint */ G_fatal_error(_("Terminal at node [%d] cannot be connected " "to terminal at node [%d]"), terms[0], terms[i]); } } /* Remove not reachable from list of SP candidates */ j = 0; for (i = 1; i <= nnodes; i++) { ret = get_node_costs(terms[0], i, &cost); if (ret == 0) { testnode[i] = 0; G_debug(2, "node %d removed from list of Steiner point candidates\n", i ); j++; } } G_message(_("[%d] (not reachable) nodes removed from list " "of Steiner point candidates"), j); /* calc costs for terminals MST */ ret = mst(&Map, terms, nterms, &cost, PORT_DOUBLE_MAX, NULL, NULL, 0, 1); /* no StP, rebuild */ G_message(_("MST costs = %f"), cost); /* Go through all nodes and try to use as steiner points -> find that which saves most costs */ nspused = 0; for (j = 0; j < nsp; j++) { sp = 0; G_verbose_message(_("Search for [%d]. Steiner point"), j + 1); for (i = 1; i <= nnodes; i++) { G_percent(i, nnodes, 1); if (testnode[i] == 0) { G_debug(3, "skip test for %d\n", i); continue; } ret = mst(&Map, terms, nterms + j, &tmpcost, cost, NULL, NULL, i, 0); G_debug(2, "cost = %f x %f\n", tmpcost, cost); if (tmpcost < cost) { /* sp candidate */ G_debug(3, " steiner candidate node = %d mst = %f (x last = %f)\n", i, tmpcost, cost); sp = i; cost = tmpcost; } } if (sp > 0) { G_message(_("Steiner point at node [%d] was added " "to terminals (MST costs = %f)"), sp, cost); terms[nterms + j] = sp; init_node_costs(&Map, sp); testnode[sp] = 0; nspused++; /* rebuild for nex cycle */ ret = mst(&Map, terms, nterms + nspused, &tmpcost, PORT_DOUBLE_MAX, NULL, NULL, 0, 1); } else { /* no steiner found */ G_message(_("No Steiner point found -> leaving cycle")); break; } } G_message(_("Number of added Steiner points: %d " "(theoretic max is %d).\n"), nspused, nterms - 2); /* Build lists of arcs and nodes for final version */ ret = mst(&Map, terms, nterms + nspused, &cost, PORT_DOUBLE_MAX, StArcs, StNodes, 0, 0); /* Calculate true costs, which may be lower than MST if steiner points were not used */ if (nsp < nterms - 2) { G_message(_("Spanning tree costs on complet graph = %f\n" "(may be higher than resulting Steiner tree costs!!!)"), cost); } else G_message(_("Steiner tree costs = %f"), cost); /* Write arcs to new map */ if (Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)) < 0) G_fatal_error(_("Unable to create vector map <%s>"), output->answer); Vect_hist_command(&Out); G_debug(1, "Steiner tree:"); G_debug(1, "Arcs' categories (layer %d, %d arcs):", afield, StArcs->n_values); for (i = 0; i < StArcs->n_values; i++) { line = StArcs->value[i]; ltype = Vect_read_line(&Map, Points, Cats, line); Vect_write_line(&Out, ltype, Points, Cats); Vect_cat_get(Cats, afield, &cat); G_debug(1, "arc cat = %d", cat); } G_debug(1, "Nodes' categories (layer %d, %d nodes):", tfield, StNodes->n_values); k = 0; pointlist = Vect_new_boxlist(0); for (i = 0; i < StNodes->n_values; i++) { double x, y, z; struct bound_box box; node = StNodes->value[i]; Vect_get_node_coor(&Map, node, &x, &y, &z); box.E = box.W = x; box.N = box.S = y; box.T = box.B = z; Vect_select_lines_by_box(&Map, &box, GV_POINT, pointlist); nlines = Vect_get_node_n_lines(&Map, node); for (j = 0; j < pointlist->n_values; j++) { line = pointlist->id[j]; ltype = Vect_read_line(&Map, Points, Cats, line); if (!(ltype & GV_POINT)) continue; if (!(Vect_cat_get(Cats, tfield, &cat))) continue; Vect_write_line(&Out, ltype, Points, Cats); G_debug(1, "node cat = %d", cat); k++; } } Vect_build(&Out); G_message(n_("A Steiner tree with %d arc has been built", "A Steiner tree with %d arcs has been built", StArcs->n_values), StArcs->n_values); /* Free, ... */ Vect_destroy_list(StArcs); Vect_destroy_list(StNodes); Vect_close(&Map); Vect_close(&Out); 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 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); }
int main(int argc, char **argv) { struct GModule *module; struct Option *input, *output, *field; struct Flag *all, *flat; struct Cell_head window; char *sitefile; struct Map_info Map; struct Point *points; /* point loaded from site file */ int *hull; /* index of points located on the convex hull */ int numSitePoints, numHullPoints; int MODE2D; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); module->description = _("Produces a convex hull for a given vector map."); input = G_define_standard_option(G_OPT_V_INPUT); field = G_define_standard_option(G_OPT_V_FIELD_ALL); output = G_define_standard_option(G_OPT_V_OUTPUT); all = G_define_flag(); all->key = 'a'; all->description = _("Use all vector points (do not limit to current region)"); flat = G_define_flag(); flat->key = 'f'; flat->description = _("Create a 'flat' 2D hull even if the input is 3D points"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); sitefile = input->answer; Vect_check_input_output_name(input->answer, output->answer, GV_FATAL_EXIT); Vect_set_open_level(1); if (Vect_open_old2(&Map, sitefile, "", field->answer) < 0) G_fatal_error(_("Unable to open vector map <%s>"), sitefile); /* load site coordinates */ G_get_window(&window); numSitePoints = loadSiteCoordinates(&Map, &points, all->answer, &window, Vect_get_field_number(&Map, field->answer)); if (numSitePoints < 0) G_fatal_error(_("Error loading vector points from <%s>"), sitefile); if (numSitePoints < 3) G_fatal_error(_("Convex hull calculation requires at least three points (%d found)"), numSitePoints); G_verbose_message(_("%d points read from vector map <%s>"), sitefile); /* create a 2D or a 3D hull? */ MODE2D = 1; if (Vect_is_3d(&Map)) { MODE2D = 0; } if (flat->answer) { MODE2D = 1; } /* create vector map */ if (0 > Vect_open_new(&Map, output->answer, MODE2D ? WITHOUT_Z : WITH_Z)) { G_fatal_error(_("Unable to create vector map <%s>"), output->answer); } Vect_hist_command(&Map); if (MODE2D) { /* compute convex hull */ numHullPoints = convexHull(points, numSitePoints, &hull); /* output vector map */ outputHull(&Map, points, hull, numHullPoints); } else { /* this does everything for the 3D hull including vector map creation */ convexHull3d(points, numSitePoints, &Map); } /* clean up and bye bye */ Vect_build(&Map); Vect_close(&Map); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct Map_info in, out, vis; struct GModule *module; /* GRASS module for parsing arguments */ struct Option *input, *output; /* The input map */ struct Option *coor, *ovis; struct Point *points; struct Line *lines; int num_points, num_lines; int n = 0; /* 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")); G_add_keyword(_("visibility")); module->description = _("Performs visibility graph construction."); /* define the arguments needed */ input = G_define_standard_option(G_OPT_V_INPUT); output = G_define_standard_option(G_OPT_V_OUTPUT); coor = G_define_standard_option(G_OPT_M_COORDS); ovis = G_define_standard_option(G_OPT_V_MAP); ovis->key = "visibility"; ovis->required = NO; ovis->label = _("Name of input vector map containing visible points"); ovis->description = _("Add points after computing the visibility graph"); /* options and flags parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); Vect_check_input_output_name(input->answer, output->answer, G_FATAL_EXIT); Vect_set_open_level(2); if (Vect_open_old(&in, input->answer, "") < 1) /* opens the map */ G_fatal_error(_("Unable to open vector map <%s>"), input->answer); if (Vect_open_new(&out, output->answer, WITHOUT_Z) < 0) { Vect_close(&in); G_fatal_error(_("Unable to create vector map <%s>"), output->answer); } if (ovis->answer != NULL) { if (Vect_open_old(&vis, ovis->answer, "") < 1) G_fatal_error(_("Unable to open vector map <%s>"), ovis->answer); if (Vect_copy_map_lines(&vis, &out) > 0) G_fatal_error(_("Unable to copy elements from vector map <%s>"), ovis->answer); } if (G_projection() == PROJECTION_LL) G_warning(_("Lat-long projection")); /* counting how many points and lines we have to allocate */ count(&in, &num_points, &num_lines); /* modify the number if we have new points to add */ if (coor->answers != NULL) num_points += count_new(coor->answers); /* and allocate */ points = G_malloc(num_points * sizeof(struct Point)); lines = G_malloc(num_lines * sizeof(struct Line)); /* and finally set the lines */ load_lines(&in, &points, &num_points, &lines, &num_lines); if (coor->answers != NULL) add_points(coor->answers, &points, &num_points); if (ovis->answer == NULL) construct_visibility(points, num_points, lines, num_lines, &out); else visibility_points(points, num_points, lines, num_lines, &out, n); G_free(points); G_free(lines); Vect_copy_head_data(&in, &out); Vect_hist_copy(&in, &out); Vect_hist_command(&out); Vect_build(&out); Vect_close(&out); Vect_close(&in); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct Map_info In, Out; static struct line_pnts *Points; struct line_cats *Cats; struct field_info *Fi; struct cat_list *Clist; int i, j, ret, option, otype, type, with_z, step, id; int n_areas, centr, new_centr, nmodified; int open_level; double x, y; int cat, ocat, scat, *fields, nfields, field; struct GModule *module; struct Option *in_opt, *out_opt, *option_opt, *type_opt; struct Option *cat_opt, *field_opt, *step_opt, *id_opt; struct Flag *shell, *notab; FREPORT **freps; int nfreps, rtype, fld; char *desc; module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("category")); G_add_keyword(_("layer")); module->description = _("Attaches, deletes or reports vector categories to map geometry."); in_opt = G_define_standard_option(G_OPT_V_INPUT); field_opt = G_define_standard_option(G_OPT_V_FIELD); field_opt->multiple = YES; field_opt->guisection = _("Selection"); type_opt = G_define_standard_option(G_OPT_V3_TYPE); type_opt->answer = "point,line,centroid,face"; type_opt->guisection = _("Selection"); id_opt = G_define_standard_option(G_OPT_V_IDS); id_opt->label = _("Feature ids (by default all features are processed)"); id_opt->guisection = _("Selection"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->required = NO; option_opt = G_define_option(); option_opt->key = "option"; option_opt->type = TYPE_STRING; option_opt->required = YES; option_opt->multiple = NO; option_opt->options = "add,del,chlayer,sum,report,print,layers,transfer"; option_opt->description = _("Action to be done"); desc = NULL; G_asprintf(&desc, "add;%s;" "del;%s;" "chlayer;%s;" "sum;%s;" "transfer;%s;" "report;%s;" "print;%s;" "layers;%s", _("add a category to features without category in the given layer"), _("delete category (cat=-1 to delete all categories of given layer)"), _("change layer number (e.g. layer=3,1 changes layer 3 to layer 1)"), _("add the value specified by cat option to the current category value"), _("copy values from one layer to another (e.g. layer=1,2,3 copies values from layer 1 to layer 2 and 3)"), _("print report (statistics), in shell style: layer type count min max"), _("print category values, layers are separated by '|', more cats in the same layer are separated by '/'"), _("print only layer numbers")); option_opt->descriptions = desc; cat_opt = G_define_standard_option(G_OPT_V_CAT); cat_opt->answer = "1"; step_opt = G_define_option(); step_opt->key = "step"; step_opt->type = TYPE_INTEGER; step_opt->required = NO; step_opt->multiple = NO; step_opt->answer = "1"; step_opt->description = _("Category increment"); shell = G_define_flag(); shell->key = 'g'; shell->label = _("Shell script style, currently only for report"); shell->description = _("Format: layer type count min max"); notab = G_define_standard_flag(G_FLG_V_TABLE); notab->description = _("Do not copy attribute table(s)"); G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* read options */ option = 0; switch (option_opt->answer[0]) { case ('a'): option = O_ADD; break; case ('d'): option = O_DEL; break; case ('c'): option = O_CHFIELD; G_warning(_("Database connection and attribute tables for concerned layers are not changed")); break; case ('s'): option = O_SUM; break; case ('t'): option = O_TRANS; break; case ('r'): option = O_REP; break; case ('p'): option = O_PRN; break; case ('l'): option = O_LYR; break; } if (option == O_LYR) { /* print vector layer numbers */ /* open vector on level 2 head only, this is why this option * is processed here, all other options need (?) to fully open * the input vector */ Vect_set_open_level(2); if (Vect_open_old_head2(&In, in_opt->answer, "", field_opt->answer) < 2) { G_fatal_error(_("Unable to open vector map <%s> at topological level %d"), Vect_get_full_name(&In), 2); } if (In.format == GV_FORMAT_NATIVE) { nfields = Vect_cidx_get_num_fields(&In); for (i = 0; i < nfields; i++) { if ((field = Vect_cidx_get_field_number(&In, i)) > 0) fprintf(stdout, "%d\n", field); } } else fprintf(stdout, "%s\n", field_opt->answer); Vect_close(&In); exit(EXIT_SUCCESS); } cat = atoi(cat_opt->answer); step = atoi(step_opt->answer); otype = Vect_option_to_types(type_opt); if (cat < 0 && option == O_ADD) G_fatal_error(_("Invalid category number (must be equal to or greater than 0). " "Normally category number starts at 1.")); /* collect ids */ if (id_opt->answer) { Clist = Vect_new_cat_list(); Clist->field = atoi(field_opt->answer); ret = Vect_str_to_cat_list(id_opt->answer, Clist); if (ret > 0) { G_warning(n_("%d error in id option", "%d errors in id option", ret), ret); } } else { Clist = NULL; } if ((option != O_REP) && (option != O_PRN) && (option != O_LYR)) { if (out_opt->answer == NULL) G_fatal_error(_("Output vector wasn't entered")); Vect_check_input_output_name(in_opt->answer, out_opt->answer, G_FATAL_EXIT); } Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); /* do we need topology ? */ if ((option == O_ADD && (otype & GV_AREA)) || (option == O_REP && (otype & GV_AREA)) || (option == O_TRANS) || /* topo for cidx check */ (option == O_LYR)) /* topo for cidx check */ open_level = 2; else open_level = 1; /* open input vector */ if (open_level > 1) { Vect_set_open_level(open_level); if (Vect_open_old2(&In, in_opt->answer, "", field_opt->answer) < open_level) { G_warning(_("Unable to open vector map <%s> at topological level %d"), Vect_get_full_name(&In), open_level); open_level = 1; } } if (open_level == 1) { Vect_set_open_level(open_level); if (Vect_open_old2(&In, in_opt->answer, "", field_opt->answer) < open_level) { G_fatal_error(_("Unable to open vector map <%s> at topological level %d"), Vect_get_full_name(&In), open_level); } } /* read fields */ i = nfields = 0; while (field_opt->answers[i++]) nfields++; fields = (int *)G_malloc(nfields * sizeof(int)); i = 0; while (field_opt->answers[i]) { fields[i] = Vect_get_field_number(&In, field_opt->answers[i]); i++; } if (nfields > 1 && option != O_PRN && option != O_CHFIELD && option != O_TRANS) G_fatal_error(_("Too many layers for this operation")); if (nfields != 2 && option == O_CHFIELD) G_fatal_error(_("2 layers must be specified")); if (option == O_TRANS && open_level == 1 && nfields < 2) { G_fatal_error(_("2 layers must be specified")); } if (option == O_TRANS && open_level > 1) { /* check if field[>0] already exists */ if (nfields > 1) { for(i = 1; i < nfields; i++) { if (Vect_cidx_get_field_index(&In, fields[i]) != -1) G_warning(_("Categories already exist in layer %d"), fields[i]); } } /* find next free layer number */ else if (nfields == 1) { int max = -1; for (i = 0; i < Vect_cidx_get_num_fields(&In); i++) { if (max < Vect_cidx_get_field_number(&In, i)) max = Vect_cidx_get_field_number(&In, i); } max++; nfields++; fields = (int *)G_realloc(fields, nfields * sizeof(int)); fields[nfields - 1] = max; } } if (otype & GV_AREA && option == O_TRANS && !(otype & GV_CENTROID)) otype |= GV_CENTROID; /* open output vector if needed */ if (option == O_ADD || option == O_DEL || option == O_CHFIELD || option == O_SUM || option == O_TRANS) { with_z = Vect_is_3d(&In); if (0 > Vect_open_new(&Out, out_opt->answer, with_z)) { Vect_close(&In); exit(EXIT_FAILURE); } Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); } id = 0; nmodified = 0; if (option == O_ADD || option == O_DEL || option == O_CHFIELD || option == O_SUM || option == O_TRANS) { G_message(_("Processing features...")); } switch (option) { case (O_ADD): /* Lines */ while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (type & otype && (!Clist || (Clist && Vect_cat_in_cat_list(id, Clist) == TRUE))) { if ((Vect_cat_get(Cats, fields[0], &ocat)) == 0) { if (ocat < 0) { if (Vect_cat_set(Cats, fields[0], cat) > 0) { nmodified++; } cat += step; } } } Vect_write_line(&Out, type, Points, Cats); } /* Areas */ if ((otype & GV_AREA) && open_level > 1) { n_areas = Vect_get_num_areas(&In); new_centr = 0; for (i = 1; i <= n_areas; i++) { centr = Vect_get_area_centroid(&In, i); if (centr > 0) continue; /* Centroid exists and may be processed as line */ ret = Vect_get_point_in_area(&In, i, &x, &y); if (ret < 0) { G_warning(_("Unable to calculate area centroid")); continue; } Vect_reset_line(Points); Vect_reset_cats(Cats); Vect_append_point(Points, x, y, 0.0); if (Vect_cat_set(Cats, fields[0], cat) > 0) { nmodified++; } cat += step; Vect_write_line(&Out, GV_CENTROID, Points, Cats); new_centr++; } if (new_centr > 0) G_message(n_("%d new centroid placed in output map", "%d new centroids placed in output map", new_centr), new_centr); } break; case (O_TRANS): /* Lines */ while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (type & otype && (!Clist || (Clist && Vect_cat_in_cat_list(id, Clist) == TRUE))) { int n = Cats->n_cats; scat = -1; for (i = 0; i < n; i++) { if (Cats->field[i] == fields[0]) { scat = Cats->cat[i]; for (j = 1; j < nfields; j++) { if (Vect_cat_set(Cats, fields[j], scat) > 0) { G_debug(4, "Copy cat %i of field %i to field %i", scat, fields[0], fields[j]); } } } } if (scat != -1) nmodified++; } Vect_write_line(&Out, type, Points, Cats); } break; case (O_DEL): while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (type & otype && (!Clist || (Clist && Vect_cat_in_cat_list(id, Clist) == TRUE))) { ret = Vect_field_cat_del(Cats, fields[0], cat); if (ret > 0) { nmodified++; } } Vect_write_line(&Out, type, Points, Cats); } break; case (O_CHFIELD): while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (type & otype && (!Clist || (Clist && Vect_cat_in_cat_list(id, Clist) == TRUE))) { i = 0; while (i < Cats->n_cats) { if (Cats->field[i] == fields[0]) { int found = -1; /* check if cat already exists in layer fields[1] */ for (j = 0; j < Cats->n_cats; j++) { if (Cats->field[j] == fields[1] && Cats->cat[j] == Cats->cat[i]) { found = j; break; } } /* does not exist, change layer */ if (found < 0) { Cats->field[i] = fields[1]; i++; } /* exists already in fields[1], delete from fields[0] */ else Vect_field_cat_del(Cats, fields[0], Cats->cat[found]); nmodified++; } } } Vect_write_line(&Out, type, Points, Cats); } break; case (O_SUM): while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (type & otype && (!Clist || (Clist && Vect_cat_in_cat_list(id, Clist) == TRUE))) { for (i = 0; i < Cats->n_cats; i++) { if (Cats->field[i] == fields[0]) { Cats->cat[i] += cat; } } nmodified++; } Vect_write_line(&Out, type, Points, Cats); } break; case (O_REP): nfreps = 0; freps = NULL; while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (Clist && Vect_cat_in_cat_list(id, Clist) == FALSE) continue; switch (type) { case (GV_POINT): rtype = FR_POINT; break; case (GV_LINE): rtype = FR_LINE; break; case (GV_BOUNDARY): rtype = FR_BOUNDARY; break; case (GV_CENTROID): rtype = FR_CENTROID; break; case (GV_FACE): rtype = FR_FACE; break; case (GV_KERNEL): rtype = FR_KERNEL; break; default: rtype = FR_UNKNOWN; } for (i = 0; i < Cats->n_cats; i++) { field = Cats->field[i]; cat = Cats->cat[i]; ret = FALSE; for (j = 0; j < nfreps; j++) { if (freps[j]->field == field) { fld = j; ret = TRUE; break; } } if (!ret) { /* field report doesn't exist */ nfreps++; freps = (FREPORT **) G_realloc(freps, nfreps * sizeof(FREPORT *)); fld = nfreps - 1; freps[fld] = (FREPORT *) G_calloc(1, sizeof(FREPORT)); freps[fld]->field = field; for (j = 0; j < FRTYPES; j++) { /* cat '0' is valid category number */ freps[fld]->min[j] = -1; } if ((Fi = Vect_get_field(&In, field)) != NULL) { freps[fld]->table = G_store(Fi->table); } else { freps[fld]->table = '\0'; } } freps[fld]->count[rtype]++; freps[fld]->count[FR_ALL]++; if (freps[fld]->min[rtype] == -1 || freps[fld]->min[rtype] > cat) freps[fld]->min[rtype] = cat; if ((freps[fld]->max[rtype] == 0) || freps[fld]->max[rtype] < cat) freps[fld]->max[rtype] = cat; if (freps[fld]->min[FR_ALL] == -1 || freps[fld]->min[FR_ALL] > cat) freps[fld]->min[FR_ALL] = cat; if ((freps[fld]->max[FR_ALL] == 0) || freps[fld]->max[FR_ALL] < cat) freps[fld]->max[FR_ALL] = cat; } } /* Areas */ if ((otype & GV_AREA) && open_level > 1 && !Clist) { n_areas = Vect_get_num_areas(&In); for (i = 1; i <= n_areas; i++) { int k; centr = Vect_get_area_centroid(&In, i); if (centr <= 0) continue; /* Area without centroid */ Vect_read_line(&In, NULL, Cats, centr); for (j = 0; j < Cats->n_cats; j++) { field = Cats->field[j]; cat = Cats->cat[j]; ret = FALSE; for (k = 0; k < nfreps; k++) { if (freps[k]->field == field) { fld = k; ret = TRUE; break; } } if (!ret) { /* field report doesn't exist */ nfreps++; freps = (FREPORT **) G_realloc(freps, nfreps * sizeof(FREPORT *)); fld = nfreps - 1; freps[fld] = (FREPORT *) G_calloc(1, sizeof(FREPORT)); freps[fld]->field = field; for (j = 0; j < FRTYPES; j++) { /* cat '0' is valid category number */ freps[fld]->min[k] = -1; } if ((Fi = Vect_get_field(&In, field)) != NULL) { freps[fld]->table = G_store(Fi->table); } else { freps[fld]->table = '\0'; } } freps[fld]->count[FR_AREA]++; if (freps[fld]->min[FR_AREA] == -1 || freps[fld]->min[FR_AREA] > cat) freps[fld]->min[FR_AREA] = cat; if ((freps[fld]->max[FR_AREA] == 0) || freps[fld]->max[FR_AREA] < cat) freps[fld]->max[FR_AREA] = cat; } } } for (i = 0; i < nfreps; i++) { if (shell->answer) { if (freps[i]->count[FR_POINT] > 0) fprintf(stdout, "%d point %d %d %d\n", freps[i]->field, freps[i]->count[FR_POINT], (freps[i]->min[FR_POINT] < 0 ? 0 : freps[i]->min[FR_POINT]), freps[i]->max[FR_POINT]); if (freps[i]->count[FR_LINE] > 0) fprintf(stdout, "%d line %d %d %d\n", freps[i]->field, freps[i]->count[FR_LINE], (freps[i]->min[FR_LINE] < 0 ? 0 : freps[i]->min[FR_LINE]), freps[i]->max[FR_LINE]); if (freps[i]->count[FR_BOUNDARY] > 0) fprintf(stdout, "%d boundary %d %d %d\n", freps[i]->field, freps[i]->count[FR_BOUNDARY], (freps[i]->min[FR_BOUNDARY] < 0 ? 0 : freps[i]->min[FR_BOUNDARY]), freps[i]->max[FR_BOUNDARY]); if (freps[i]->count[FR_CENTROID] > 0) fprintf(stdout, "%d centroid %d %d %d\n", freps[i]->field, freps[i]->count[FR_CENTROID], (freps[i]->min[FR_BOUNDARY] < 0 ? 0 : freps[i]->min[FR_BOUNDARY]), freps[i]->max[FR_CENTROID]); if (freps[i]->count[FR_AREA] > 0) fprintf(stdout, "%d area %d %d %d\n", freps[i]->field, freps[i]->count[FR_AREA], (freps[i]->min[FR_AREA] < 0 ? 0 : freps[i]->min[FR_AREA]), freps[i]->max[FR_AREA]); if (freps[i]->count[FR_FACE] > 0) fprintf(stdout, "%d face %d %d %d\n", freps[i]->field, freps[i]->count[FR_FACE], (freps[i]->min[FR_FACE] < 0 ? 0 : freps[i]->min[FR_FACE]), freps[i]->max[FR_FACE]); if (freps[i]->count[FR_KERNEL] > 0) fprintf(stdout, "%d kernel %d %d %d\n", freps[i]->field, freps[i]->count[FR_KERNEL], (freps[i]->min[FR_KERNEL] < 0 ? 0 : freps[i]->min[FR_KERNEL]), freps[i]->max[FR_KERNEL]); if (freps[i]->count[FR_ALL] > 0) fprintf(stdout, "%d all %d %d %d\n", freps[i]->field, freps[i]->count[FR_ALL], (freps[i]->min[FR_ALL] < 0 ? 0 : freps[i]->min[FR_ALL]), freps[i]->max[FR_ALL]); } else { if (freps[i]->table != '\0') { fprintf(stdout, "%s: %d/%s\n", _("Layer/table"), freps[i]->field, freps[i]->table); } else { fprintf(stdout, "%s: %d\n", _("Layer"), freps[i]->field); } fprintf(stdout, _("type count min max\n")); fprintf(stdout, "%s %7d %10d %10d\n", _("point"), freps[i]->count[FR_POINT], (freps[i]->min[FR_POINT] < 0) ? 0 : freps[i]->min[FR_POINT], freps[i]->max[FR_POINT]); fprintf(stdout, "%s %7d %10d %10d\n", _("line"), freps[i]->count[FR_LINE], (freps[i]->min[FR_LINE] < 0) ? 0 : freps[i]->min[FR_LINE], freps[i]->max[FR_LINE]); fprintf(stdout, "%s %7d %10d %10d\n", _("boundary"), freps[i]->count[FR_BOUNDARY], (freps[i]->min[FR_BOUNDARY] < 0) ? 0 : freps[i]->min[FR_BOUNDARY], freps[i]->max[FR_BOUNDARY]); fprintf(stdout, "%s %7d %10d %10d\n", _("centroid"), freps[i]->count[FR_CENTROID], (freps[i]->min[FR_CENTROID] < 0) ? 0 : freps[i]->min[FR_CENTROID], freps[i]->max[FR_CENTROID]); fprintf(stdout, "%s %7d %10d %10d\n", _("area"), freps[i]->count[FR_AREA], (freps[i]->min[FR_AREA] < 0) ? 0 : freps[i]->min[FR_AREA], freps[i]->max[FR_AREA]); fprintf(stdout, "%s %7d %10d %10d\n", _("face"), freps[i]->count[FR_FACE], (freps[i]->min[FR_FACE] < 0) ? 0 : freps[i]->min[FR_FACE], freps[i]->max[FR_FACE]); fprintf(stdout, "%s %7d %10d %10d\n", _("kernel"), freps[i]->count[FR_KERNEL], (freps[i]->min[FR_KERNEL] < 0) ? 0 : freps[i]->min[FR_KERNEL], freps[i]->max[FR_KERNEL]); fprintf(stdout, "%s %7d %10d %10d\n", _("all"), freps[i]->count[FR_ALL], (freps[i]->min[FR_ALL] < 0) ? 0 : freps[i]->min[FR_ALL], freps[i]->max[FR_ALL]); } } break; case (O_PRN): while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; int has = 0; if (!(type & otype)) continue; if (Clist && Vect_cat_in_cat_list(id, Clist) == FALSE) continue; /* Check if the line has at least one cat */ for (i = 0; i < nfields; i++) { for (j = 0; j < Cats->n_cats; j++) { if (Cats->field[j] == fields[i]) { has = 1; break; } } } if (!has) continue; for (i = 0; i < nfields; i++) { int first = 1; if (i > 0) fprintf(stdout, "|"); for (j = 0; j < Cats->n_cats; j++) { if (Cats->field[j] == fields[i]) { if (!first) fprintf(stdout, "/"); fprintf(stdout, "%d", Cats->cat[j]); first = 0; } } } fprintf(stdout, "\n"); } break; } if (option == O_ADD || option == O_DEL || option == O_CHFIELD || option == O_SUM || option == O_TRANS){ if (!notab->answer){ G_message(_("Copying attribute table(s)...")); if (Vect_copy_tables(&In, &Out, 0)) G_warning(_("Failed to copy attribute table to output map")); } Vect_build(&Out); Vect_close(&Out); } if (option == O_TRANS && nmodified > 0) for(i = 1; i < nfields; i++) G_important_message(_("Categories copied from layer %d to layer %d"), fields[0], fields[i]); if (option != O_REP && option != O_PRN) G_done_msg(n_("%d feature modified.", "%d features modified.", nmodified), nmodified); Vect_close(&In); 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) { struct GModule *module; struct opts opt; struct Map_info In, Out; BOUND_BOX box; int field, type; int ret; G_gisinit(argv[0]); module = G_define_module(); module->keywords = _("vector, transformation, 3D"); module->description = _("Performs transformation of 2D vector features to 3D."); parse_args(&opt); if (G_parser(argc, argv)) exit(EXIT_FAILURE); field = atoi(opt.field->answer); type = Vect_option_to_types(opt.type); if (!opt.reverse->answer) { if ((!opt.height->answer && !opt.column->answer) || (opt.height->answer && opt.column->answer)) { G_fatal_error(_("Either '%s' or '%s' parameter have to be used"), opt.height->key, opt.column->key); } } else { if (opt.height->answer) { G_warning(_("Parameters '%s' ignored"), opt.height->key); } } if (opt.reverse->answer && opt.table->answer) { G_fatal_error(_("Attribute table required")); } Vect_check_input_output_name(opt.input->answer, opt.output->answer, GV_FATAL_EXIT); /* open input vector, topology not needed */ Vect_set_open_level(1); if (Vect_open_old(&In, opt.input->answer, "") < 1) G_fatal_error(_("Unable to open vector map <%s>"), opt.input->answer); if (opt.reverse->answer && !Vect_is_3d(&In)) { Vect_close(&In); G_fatal_error(_("Vector map <%s> is 2D"), opt.input->answer); } if (!opt.reverse->answer && Vect_is_3d(&In)) { Vect_close(&In); G_fatal_error(_("Vector map <%s> is 3D"), opt.input->answer); } /* create output vector */ Vect_set_open_level(2); if (Vect_open_new(&Out, opt.output->answer, opt.reverse->answer ? WITHOUT_Z : WITH_Z) == -1) G_fatal_error(_("Unable to create vector map <%s>"), opt.output->answer); /* copy history & header */ Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); Vect_copy_head_data(&In, &Out); if (opt.reverse->answer && !opt.table->answer) { G_message(_("Copying attributes...")); if (Vect_copy_tables(&In, &Out, 0) == -1) { G_warning(_("Unable to copy attributes")); } } G_message(_("Transforming features...")); ret = 0; if (opt.reverse->answer) { /* 3d -> 2d */ ret = trans3d(&In, &Out, type, field, opt.column->answer); } else { /* 2d -> 3d */ double height = 0.; if (opt.height->answer) { height = atof(opt.height->answer); } ret = trans2d(&In, &Out, type, height, field, opt.column->answer); } if (ret < 0) { Vect_close(&In); Vect_close(&Out); Vect_delete(opt.output->answer); G_fatal_error(_("%s failed"), G_program_name()); } if (!opt.reverse->answer && !opt.table->answer) { G_message(_("Copying attributes...")); if (Vect_copy_tables(&In, &Out, 0) == -1) { G_warning(_("Unable to copy attributes")); } } Vect_close(&In); Vect_build(&Out); if (!opt.reverse->answer) { Vect_get_map_box(&Out, &box); G_message(_("Vertical extent of vector map <%s>: B: %f T: %f"), opt.output->answer, box.B, box.T); } Vect_close(&Out); exit(EXIT_SUCCESS); }
void QgsGrassPlugin::newVector() { // QgsDebugMsg("entered."); if ( QgsGrassEdit::isRunning() ) { QMessageBox::warning( 0, tr( "Warning" ), tr( "GRASS Edit is already running." ) ); return; } bool ok; QString name; QgsGrassElementDialog dialog; name = dialog.getItem( "vector", tr( "New vector name" ), tr( "New vector name" ), "", "", &ok ); if ( !ok ) return; // Create new map QgsGrass::setMapset( QgsGrass::getDefaultGisdbase(), QgsGrass::getDefaultLocation(), QgsGrass::getDefaultMapset() ); try { struct Map_info Map; Vect_open_new( &Map, name.toUtf8().data(), 0 ); #if defined(GRASS_VERSION_MAJOR) && defined(GRASS_VERSION_MINOR) && \ ( ( GRASS_VERSION_MAJOR == 6 && GRASS_VERSION_MINOR >= 4 ) || GRASS_VERSION_MAJOR > 6 ) Vect_build( &Map ); #else Vect_build( &Map, stderr ); #endif Vect_set_release_support( &Map ); Vect_close( &Map ); } catch ( QgsGrass::Exception &e ) { QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot create new vector: %1" ).arg( e.what() ) ); return; } // Open in GRASS vector provider QString uri = QgsGrass::getDefaultGisdbase() + "/" + QgsGrass::getDefaultLocation() + "/" + QgsGrass::getDefaultMapset() + "/" + name + "/0_point"; QgsVectorLayer* layer = new QgsVectorLayer( uri, name, "grass" ); if ( !layer ) { QMessageBox::warning( 0, tr( "Warning" ), tr( "New vector created but cannot be opened by data provider." ) ); return; } QgsGrassEdit *ed = new QgsGrassEdit( qGisInterface, layer, true, qGisInterface->mainWindow(), Qt::Dialog ); if ( ed->isValid() ) { ed->show(); mCanvas->refresh(); } else { QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot start editing." ) ); delete ed; } #if 0 if ( !( mProvider->startEdit() ) ) { QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot open vector for update." ) ); return; } #endif }
/*--------------------------------------------------------------------*/ int main(int argc, char *argv[]) { /* Variables declarations */ int nsplx_adj, nsply_adj; int nsubregion_col, nsubregion_row; int subregion = 0, nsubregions = 0; double N_extension, E_extension, edgeE, edgeN; int dim_vect, nparameters, BW, npoints; double mean, lambda; const char *dvr, *db, *mapset; char table_name[GNAME_MAX]; char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; int last_row, last_column, flag_auxiliar = FALSE; int filter_mode; int *lineVect; double *TN, *Q, *parVect; /* Interpolating and least-square vectors */ double **N, **obsVect; /* Interpolation and least-square matrix */ /* Structs declarations */ struct Map_info In, Out, Outlier, Qgis; struct Option *in_opt, *out_opt, *outlier_opt, *qgis_opt, *stepE_opt, *stepN_opt, *lambda_f_opt, *Thres_O_opt, *filter_opt; struct Flag *spline_step_flag; struct GModule *module; struct Reg_dimens dims; struct Cell_head elaboration_reg, original_reg; 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(_("statistics")); G_add_keyword(_("extract")); G_add_keyword(_("select")); G_add_keyword(_("filter")); G_add_keyword(_("LIDAR")); module->description = _("Removes outliers from vector point data."); 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"); spline_step_flag->suppress_required = YES; in_opt = G_define_standard_option(G_OPT_V_INPUT); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); outlier_opt = G_define_standard_option(G_OPT_V_OUTPUT); outlier_opt->key = "outlier"; outlier_opt->description = _("Name for output outlier vector map"); qgis_opt = G_define_standard_option(G_OPT_V_OUTPUT); qgis_opt->key = "qgis"; qgis_opt->required = NO; qgis_opt->description = _("Name for vector map for visualization in QGIS"); stepE_opt = G_define_option(); stepE_opt->key = "ew_step"; stepE_opt->type = TYPE_DOUBLE; stepE_opt->required = NO; stepE_opt->answer = "10"; stepE_opt->description = _("Length of each spline step in the east-west direction"); stepE_opt->guisection = _("Settings"); stepN_opt = G_define_option(); stepN_opt->key = "ns_step"; stepN_opt->type = TYPE_DOUBLE; stepN_opt->required = NO; stepN_opt->answer = "10"; stepN_opt->description = _("Length of each spline step in the north-south direction"); stepN_opt->guisection = _("Settings"); lambda_f_opt = G_define_option(); lambda_f_opt->key = "lambda"; lambda_f_opt->type = TYPE_DOUBLE; lambda_f_opt->required = NO; lambda_f_opt->description = _("Tykhonov regularization weight"); lambda_f_opt->answer = "0.1"; lambda_f_opt->guisection = _("Settings"); Thres_O_opt = G_define_option(); Thres_O_opt->key = "threshold"; Thres_O_opt->type = TYPE_DOUBLE; Thres_O_opt->required = NO; Thres_O_opt->description = _("Threshold for the outliers"); Thres_O_opt->answer = "50"; filter_opt = G_define_option(); filter_opt->key = "filter"; filter_opt->type = TYPE_STRING; filter_opt->required = NO; filter_opt->description = _("Filtering option"); filter_opt->options = "both,positive,negative"; filter_opt->answer = "both"; G_gisinit(argv[0]); G_option_requires(spline_step_flag, in_opt, NULL); /* Parsing */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (!(db = G_getenv_nofatal2("DB_DATABASE", G_VAR_MAPSET))) G_fatal_error(_("Unable to read name of database")); if (!(dvr = G_getenv_nofatal2("DB_DRIVER", G_VAR_MAPSET))) G_fatal_error(_("Unable to read name of driver")); stepN = atof(stepN_opt->answer); stepE = atof(stepE_opt->answer); lambda = atof(lambda_f_opt->answer); Thres_Outlier = atof(Thres_O_opt->answer); filter_mode = 0; if (strcmp(filter_opt->answer, "positive") == 0) filter_mode = 1; else if (strcmp(filter_opt->answer, "negative") == 0) filter_mode = -1; P_set_outlier_fn(filter_mode); flag_auxiliar = FALSE; /* Checking vector names */ if (out_opt->answer) 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); } /* Setting auxiliary table's name */ if (out_opt->answer) { if (G_name_is_fully_qualified(out_opt->answer, xname, xmapset)) { sprintf(table_name, "%s_aux", xname); } else sprintf(table_name, "%s_aux", out_opt->answer); } /* Something went wrong in a previous v.outlier 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); db_set_error_handler_driver(driver); if (P_Drop_Aux_Table(driver, table_name) != DB_OK) G_fatal_error(_("Old auxiliary table could not be dropped")); db_close_database_shutdown_driver(driver); } /* Open input vector */ Vect_set_open_level(1); /* WITHOUT TOPOLOGY */ if (1 > Vect_open_old(&In, in_opt->answer, mapset)) G_fatal_error(_("Unable to open vector map <%s> at the topological level"), in_opt->answer); /* 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 (qgis_opt->answer) if (0 > Vect_open_new(&Qgis, qgis_opt->answer, WITHOUT_Z)) G_fatal_error(_("Unable to create vector map <%s>"), qgis_opt->answer); if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z)) { Vect_close(&Qgis); G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); } if (0 > Vect_open_new(&Outlier, outlier_opt->answer, WITH_Z)) { Vect_close(&Out); Vect_close(&Qgis); 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); Vect_copy_head_data(&In, &Outlier); Vect_hist_copy(&In, &Outlier); Vect_hist_command(&Outlier); if (qgis_opt->answer) { Vect_copy_head_data(&In, &Qgis); Vect_hist_copy(&In, &Qgis); Vect_hist_command(&Qgis); } /* Open driver and database */ 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 auxiliary table */ if ((flag_auxiliar = P_Create_Aux2_Table(driver, table_name)) == FALSE) G_fatal_error(_("It was impossible to create <%s> table."), table_name); db_create_index2(driver, table_name, "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 overlapped by its neighbouring subregions. | The overlapping is calculated as a fixed OVERLAP_SIZE times | the largest spline step plus 2 * edge ----------------------------------------------------------------*/ /* Fixing parameters of the elaboration region */ P_zero_dim(&dims); /* Set dim struct to zero */ nsplx_adj = NSPLX_MAX; nsply_adj = NSPLY_MAX; if (stepN > stepE) dims.overlap = OVERLAP_SIZE * stepN; else dims.overlap = OVERLAP_SIZE * stepE; P_get_edge(P_BILINEAR, &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(_("Processing subregion %d of %d..."), subregion, nsubregions); else /* v.outlier -e will report mean point distance: */ G_warning(_("No subregions found! Check values for 'ew_step' and 'ns_step' parameters")); 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; 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; nparameters = nsplx * nsply; /* Mean calculation */ mean = P_Mean_Calc(&elaboration_reg, observ, npoints); /* Least Squares system */ G_debug(1, "Allocation 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 = G_alloc_vector(nparameters); /* Bicubic parameters vector */ obsVect = G_alloc_matrix(npoints, 3); /* Observation vector */ Q = G_alloc_vector(npoints); /* "a priori" var-cov matrix */ lineVect = G_alloc_ivector(npoints); /* 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, nsplx, nsply, stepE, stepN); G_math_solver_cholesky_sband(N, parVect, TN, nparameters, BW); G_free_matrix(N); G_free_vector(TN); G_free_vector(Q); G_verbose_message(_("Outlier detection")); if (qgis_opt->answer) P_Outlier(&Out, &Outlier, &Qgis, elaboration_reg, general_box, overlap_box, obsVect, parVect, mean, dims.overlap, lineVect, npoints, driver, table_name); else P_Outlier(&Out, &Outlier, NULL, elaboration_reg, general_box, overlap_box, obsVect, parVect, mean, dims.overlap, lineVect, npoints, driver, table_name); G_free_vector(parVect); G_free_matrix(obsVect); G_free_ivector(lineVect); } /*! END IF; npoints > 0 */ else { G_free(observ); G_warning(_("No data within this subregion. " "Consider increasing spline step values.")); } } /*! END WHILE; last_column = TRUE */ } /*! END WHILE; last_row = TRUE */ /* Drop auxiliary table */ if (npoints > 0) { G_debug(1, "%s: Dropping <%s>", argv[0], table_name); if (P_Drop_Aux_Table(driver, table_name) != DB_OK) G_fatal_error(_("Auxiliary table could not be dropped")); } db_close_database_shutdown_driver(driver); Vect_close(&In); Vect_close(&Out); Vect_close(&Outlier); if (qgis_opt->answer) { Vect_build(&Qgis); Vect_close(&Qgis); } G_done_msg(" "); exit(EXIT_SUCCESS); } /*END MAIN */
int main(int argc, char *argv[]) { int i, j, k; int print_as_matrix; /* only for all */ int all; /* calculate from each to each within the threshold */ struct GModule *module; struct Option *from_opt, *to_opt, *from_type_opt, *to_type_opt, *from_field_opt, *to_field_opt; struct Option *out_opt, *max_opt, *min_opt, *table_opt; struct Option *upload_opt, *column_opt, *to_column_opt; struct Flag *print_flag, *all_flag; struct Map_info From, To, Out, *Outp; int from_type, to_type, from_field, to_field; double max, min; double *max_step; int n_max_steps, curr_step; struct line_pnts *FPoints, *TPoints; struct line_cats *FCats, *TCats; NEAR *Near, *near; int anear; /* allocated space, used only for all */ UPLOAD *Upload; /* zero terminated */ int ftype, fcat, tcat, count; int nfrom, nto, nfcats, fline, tline, tseg, tarea, area, isle, nisles; double tx, ty, tz, dist, talong, tmp_tx, tmp_ty, tmp_tz, tmp_dist, tmp_talong; struct field_info *Fi, *toFi; dbString stmt, dbstr; dbDriver *driver, *to_driver; int *catexist, ncatexist, *cex; char buf1[2000], buf2[2000]; int update_ok, update_err, update_exist, update_notexist, update_dupl, update_notfound; struct boxlist *List; struct bound_box box; dbCatValArray cvarr; dbColumn *column; all = 0; print_as_matrix = 0; column = NULL; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("database")); G_add_keyword(_("attribute table")); module->description = _("Finds the nearest element in vector map 'to' for elements in vector map 'from'."); from_opt = G_define_standard_option(G_OPT_V_INPUT); from_opt->key = "from"; from_opt->description = _("Name of existing vector map (from)"); from_opt->guisection = _("From"); from_field_opt = G_define_standard_option(G_OPT_V_FIELD); from_field_opt->key = "from_layer"; from_field_opt->label = _("Layer number or name (from)"); from_field_opt->guisection = _("From"); from_type_opt = G_define_standard_option(G_OPT_V_TYPE); from_type_opt->key = "from_type"; from_type_opt->options = "point,centroid"; from_type_opt->answer = "point"; from_type_opt->label = _("Feature type (from)"); from_type_opt->guisection = _("From"); to_opt = G_define_standard_option(G_OPT_V_INPUT); to_opt->key = "to"; to_opt->description = _("Name of existing vector map (to)"); to_opt->guisection = _("To"); to_field_opt = G_define_standard_option(G_OPT_V_FIELD); to_field_opt->key = "to_layer"; to_field_opt->label = _("Layer number or name (to)"); to_field_opt->guisection = _("To"); to_type_opt = G_define_standard_option(G_OPT_V_TYPE); to_type_opt->key = "to_type"; to_type_opt->options = "point,line,boundary,centroid,area"; to_type_opt->answer = "point,line,area"; to_type_opt->label = _("Feature type (to)"); to_type_opt->guisection = _("To"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->key = "output"; out_opt->required = NO; out_opt->description = _("Name for output vector map containing lines " "connecting nearest elements"); max_opt = G_define_option(); max_opt->key = "dmax"; max_opt->type = TYPE_DOUBLE; max_opt->required = NO; max_opt->answer = "-1"; max_opt->description = _("Maximum distance or -1 for no limit"); min_opt = G_define_option(); min_opt->key = "dmin"; min_opt->type = TYPE_DOUBLE; min_opt->required = NO; min_opt->answer = "-1"; min_opt->description = _("Minimum distance or -1 for no limit"); upload_opt = G_define_option(); upload_opt->key = "upload"; upload_opt->type = TYPE_STRING; upload_opt->required = YES; upload_opt->multiple = YES; upload_opt->options = "cat,dist,to_x,to_y,to_along,to_angle,to_attr"; upload_opt->description = _("Values describing the relation between two nearest features"); upload_opt->descriptions = _("cat;category of the nearest feature;" "dist;minimum distance to nearest feature;" "to_x;x coordinate of the nearest point on 'to' feature;" "to_y;y coordinate of the nearest point on 'to' feature;" "to_along;distance between points/centroids in 'from' map and the linear feature's " "start point in 'to' map, along this linear feature;" "to_angle;angle between the linear feature in 'to' map and the positive x axis, at " "the location of point/centroid in 'from' map, counterclockwise, in radians, which " "is between -PI and PI inclusive;" "to_attr;attribute of nearest feature given by to_column option"); /* "from_x - x coordinate of the nearest point on 'from' feature;" */ /* "from_y - y coordinate of the nearest point on 'from' feature;" */ /* "from_along - distance to the nearest point on 'from' feature along linear feature;" */ column_opt = G_define_standard_option(G_OPT_DB_COLUMN); column_opt->required = YES; column_opt->multiple = YES; column_opt->description = _("Column name(s) where values specified by 'upload' option will be uploaded"); column_opt->guisection = _("From_map"); to_column_opt = G_define_standard_option(G_OPT_DB_COLUMN); to_column_opt->key = "to_column"; to_column_opt->description = _("Column name of nearest feature (used with upload=to_attr)"); to_column_opt->guisection = _("To"); table_opt = G_define_standard_option(G_OPT_DB_TABLE); table_opt->gisprompt = "new_dbtable,dbtable,dbtable"; table_opt->description = _("Name of table created for output when the distance to all flag is used"); print_flag = G_define_flag(); print_flag->key = 'p'; print_flag->label = _("Print output to stdout, don't update attribute table"); print_flag->description = _("First column is always category of 'from' feature called from_cat"); all_flag = G_define_flag(); all_flag->key = 'a'; all_flag->label = _("Calculate distances to all features within the threshold"); all_flag->description = _("The output is written to stdout but may be uploaded " "to a new table created by this module. " "From categories are may be multiple."); /* huh? */ /* GUI dependency */ from_opt->guidependency = G_store(from_field_opt->key); sprintf(buf1, "%s,%s", to_field_opt->key, to_column_opt->key); to_opt->guidependency = G_store(buf1); to_field_opt->guidependency = G_store(to_column_opt->key); if (G_parser(argc, argv)) exit(EXIT_FAILURE); from_type = Vect_option_to_types(from_type_opt); to_type = Vect_option_to_types(to_type_opt); from_field = atoi(from_field_opt->answer); max = atof(max_opt->answer); min = atof(min_opt->answer); if (all_flag->answer) all = 1; /* Read upload and column options */ /* count */ i = 0; while (upload_opt->answers[i]) i++; if (strcmp(from_opt->answer, to_opt->answer) == 0 && all && !table_opt->answer && i == 1) print_as_matrix = 1; /* alloc */ Upload = (UPLOAD *) G_calloc(i + 1, sizeof(UPLOAD)); /* read upload */ i = 0; while (upload_opt->answers[i]) { if (strcmp(upload_opt->answers[i], "cat") == 0) Upload[i].upload = CAT; else if (strcmp(upload_opt->answers[i], "from_x") == 0) Upload[i].upload = FROM_X; else if (strcmp(upload_opt->answers[i], "from_y") == 0) Upload[i].upload = FROM_Y; else if (strcmp(upload_opt->answers[i], "to_x") == 0) Upload[i].upload = TO_X; else if (strcmp(upload_opt->answers[i], "to_y") == 0) Upload[i].upload = TO_Y; else if (strcmp(upload_opt->answers[i], "from_along") == 0) Upload[i].upload = FROM_ALONG; else if (strcmp(upload_opt->answers[i], "to_along") == 0) Upload[i].upload = TO_ALONG; else if (strcmp(upload_opt->answers[i], "dist") == 0) Upload[i].upload = DIST; else if (strcmp(upload_opt->answers[i], "to_angle") == 0) Upload[i].upload = TO_ANGLE; else if (strcmp(upload_opt->answers[i], "to_attr") == 0) { if (!(to_column_opt->answer)) { G_fatal_error(_("to_column option missing")); } Upload[i].upload = TO_ATTR; } i++; } Upload[i].upload = END; /* read columns */ i = 0; while (column_opt->answers[i]) { if (Upload[i].upload == END) { G_warning(_("Too many column names")); break; } Upload[i].column = G_store(column_opt->answers[i]); i++; } if (Upload[i].upload != END) G_fatal_error(_("Not enough column names")); /* Open 'from' vector */ Vect_set_open_level(2); Vect_open_old(&From, from_opt->answer, G_mapset()); /* Open 'to' vector */ Vect_set_open_level(2); Vect_open_old2(&To, to_opt->answer, "", to_field_opt->answer); to_field = Vect_get_field_number(&To, to_field_opt->answer); /* Open output vector */ if (out_opt->answer) { Vect_open_new(&Out, out_opt->answer, WITHOUT_Z); Vect_hist_command(&Out); Outp = &Out; } else { Outp = NULL; } /* TODO: add maxdist = -1 to Vect_select_ !!! */ /* Calc maxdist */ n_max_steps = 1; if (max != 0) { struct bound_box fbox, tbox; double dx, dy, dz, tmp_max; int n_features = 0; Vect_get_map_box(&From, &fbox); Vect_get_map_box(&To, &tbox); Vect_box_extend(&fbox, &tbox); dx = fbox.E - fbox.W; dy = fbox.N - fbox.S; if (Vect_is_3d(&From)) dz = fbox.T - fbox.B; else dz = 0.0; tmp_max = sqrt(dx * dx + dy * dy + dz * dz); if (max < 0) max = tmp_max; /* how to determine a reasonable number of steps to increase the search box? */ /* with max > 0 but max <<< tmp_max, 2 steps are sufficient, first 0 then max * a reasonable number of steps also depends on the number of features in To * e.g. only one area in To, no need to step */ nto = Vect_get_num_lines(&To); for (tline = 1; tline <= nto; tline++) { /* TODO: Vect_get_line_type() */ n_features += ((to_type & To.plus.Line[tline]->type) != 0); } if (to_type & GV_AREA) { if (Vect_get_num_areas(&To) > n_features) n_features = Vect_get_num_areas(&To); } if (n_features == 0) G_fatal_error(_("No features of selected type in To vector <%s>"), to_opt->answer); n_max_steps = sqrt(n_features) * max / tmp_max; /* max 9 steps from testing */ if (n_max_steps > 9) n_max_steps = 9; if (n_max_steps < 2) n_max_steps = 2; if (n_max_steps > n_features) n_max_steps = n_features; G_debug(2, "max = %f", max); G_debug(2, "maximum reasonable search distance = %f", tmp_max); G_debug(2, "n_features = %d", n_features); G_debug(2, "n_max_steps = %d", n_max_steps); } if (min > max) G_fatal_error("dmin can not be larger than dmax"); if (n_max_steps > 1) { /* set up steps to increase search box */ max_step = G_malloc(n_max_steps * sizeof(double)); /* first step always 0 */ max_step[0] = 0; for (curr_step = 1; curr_step < n_max_steps - 1; curr_step++) { /* for 9 steps, this would be max / [128, 64, 32, 16, 8, 4, 2] */ max_step[curr_step] = max / (2 << (n_max_steps - 1 - curr_step)); } /* last step always max */ max_step[n_max_steps - 1] = max; } else { max_step = G_malloc(sizeof(double)); max_step[0] = max; } /* Open database driver */ db_init_string(&stmt); db_init_string(&dbstr); driver = NULL; if (!print_flag->answer) { if (!all) { Fi = Vect_get_field(&From, from_field); if (Fi == NULL) G_fatal_error(_("Database connection not defined for layer %d"), from_field); 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); /* check if column exists */ i = 0; while (column_opt->answers[i]) { db_get_column(driver, Fi->table, column_opt->answers[i], &column); if (column) { db_free_column(column); column = NULL; } else { G_fatal_error(_("Column <%s> not found in table <%s>"), column_opt->answers[i], Fi->table); } i++; } } else { driver = db_start_driver_open_database(NULL, NULL); if (driver == NULL) G_fatal_error(_("Unable to open default database")); } } to_driver = NULL; if (to_column_opt->answer) { toFi = Vect_get_field(&To, to_field); if (toFi == NULL) G_fatal_error(_("Database connection not defined for layer %d"), to_field); to_driver = db_start_driver_open_database(toFi->driver, toFi->database); if (to_driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), toFi->database, toFi->driver); /* check if to_column exists */ db_get_column(to_driver, toFi->table, to_column_opt->answer, &column); if (column) { db_free_column(column); column = NULL; } else { G_fatal_error(_("Column <%s> not found in table <%s>"), to_column_opt->answer, toFi->table); } /* Check column types */ if (!print_flag->answer && !all) { char *fcname = NULL; int fctype, tctype; i = 0; while (column_opt->answers[i]) { if (Upload[i].upload == TO_ATTR) { fcname = column_opt->answers[i]; break; } i++; } if (fcname) { fctype = db_column_Ctype(driver, Fi->table, fcname); tctype = db_column_Ctype(to_driver, toFi->table, to_column_opt->answer); if (((tctype == DB_C_TYPE_STRING || tctype == DB_C_TYPE_DATETIME) && (fctype == DB_C_TYPE_INT || fctype == DB_C_TYPE_DOUBLE)) || ((tctype == DB_C_TYPE_INT || tctype == DB_C_TYPE_DOUBLE) && (fctype == DB_C_TYPE_STRING || fctype == DB_C_TYPE_DATETIME)) ) { G_fatal_error(_("Incompatible column types")); } } } } FPoints = Vect_new_line_struct(); TPoints = Vect_new_line_struct(); FCats = Vect_new_cats_struct(); TCats = Vect_new_cats_struct(); List = Vect_new_boxlist(1); /* Allocate space ( may be more than needed (duplicate cats and elements without cats) ) */ nfrom = Vect_get_num_lines(&From); nto = Vect_get_num_lines(&To); if (all) { /* Attention with space for all, it can easily run out of memory */ anear = 2 * nfrom; Near = (NEAR *) G_calloc(anear, sizeof(NEAR)); } else { Near = (NEAR *) G_calloc(nfrom, sizeof(NEAR)); } /* Read all cats from 'from' */ if (!all) { nfcats = 0; for (i = 1; i <= nfrom; i++) { ftype = Vect_read_line(&From, NULL, FCats, i); /* This keeps also categories of areas for future (if area s in from_type) */ if (!(ftype & from_type) && (ftype != GV_CENTROID || !(from_type & GV_AREA))) continue; Vect_cat_get(FCats, from_field, &fcat); if (fcat < 0) continue; Near[nfcats].from_cat = fcat; nfcats++; } G_debug(1, "%d cats loaded from vector (including duplicates)", nfcats); /* Sort by cats and remove duplicates */ qsort((void *)Near, nfcats, sizeof(NEAR), cmp_near); /* remove duplicates */ for (i = 1; i < nfcats; i++) { if (Near[i].from_cat == Near[i - 1].from_cat) { for (j = i; j < nfcats - 1; j++) { Near[j].from_cat = Near[j + 1].from_cat; } nfcats--; } } G_debug(1, "%d cats loaded from vector (unique)", nfcats); } /* Go through all lines in 'from' and find nearest in 'to' for each */ /* Note: as from_type is restricted to GV_POINTS (for now) everything is simple */ count = 0; /* count of distances in 'all' mode */ /* Find nearest lines */ if (to_type & (GV_POINTS | GV_LINES)) { struct line_pnts *LLPoints; if (G_projection() == PROJECTION_LL) { LLPoints = Vect_new_line_struct(); } else { LLPoints = NULL; } G_message(_("Finding nearest feature...")); for (fline = 1; fline <= nfrom; fline++) { int tmp_tcat; double tmp_tangle, tangle; double tmp_min = (min < 0 ? 0 : min); double box_edge = 0; int done = 0; curr_step = 0; G_debug(3, "fline = %d", fline); G_percent(fline, nfrom, 2); ftype = Vect_read_line(&From, FPoints, FCats, fline); if (!(ftype & from_type)) continue; Vect_cat_get(FCats, from_field, &fcat); if (fcat < 0 && !all) continue; while (!done) { done = 1; if (!all) { /* enlarge search box until we get a hit */ /* the objective is to enlarge the search box * in the first iterations just a little bit * to keep the number of hits low */ Vect_reset_boxlist(List); while (curr_step < n_max_steps) { box_edge = max_step[curr_step]; if (box_edge < tmp_min) continue; box.E = FPoints->x[0] + box_edge; box.W = FPoints->x[0] - box_edge; box.N = FPoints->y[0] + box_edge; box.S = FPoints->y[0] - box_edge; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_lines_by_box(&To, &box, to_type, List); curr_step++; if (List->n_values > 0) break; } } else { box.E = FPoints->x[0] + max; box.W = FPoints->x[0] - max; box.N = FPoints->y[0] + max; box.S = FPoints->y[0] - max; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_lines_by_box(&To, &box, to_type, List); } G_debug(3, " %d lines in box", List->n_values); tline = 0; dist = PORT_DOUBLE_MAX; for (i = 0; i < List->n_values; i++) { tmp_tcat = -1; Vect_read_line(&To, TPoints, TCats, List->id[i]); tseg = Vect_line_distance(TPoints, FPoints->x[0], FPoints->y[0], FPoints->z[0], (Vect_is_3d(&From) && Vect_is_3d(&To)) ? WITH_Z : WITHOUT_Z, &tmp_tx, &tmp_ty, &tmp_tz, &tmp_dist, NULL, &tmp_talong); Vect_point_on_line(TPoints, tmp_talong, NULL, NULL, NULL, &tmp_tangle, NULL); if (tmp_dist > max || tmp_dist < min) continue; /* not in threshold */ /* TODO: more cats of the same field */ Vect_cat_get(TCats, to_field, &tmp_tcat); if (G_projection() == PROJECTION_LL) { /* calculate distances in meters not degrees (only 2D) */ Vect_reset_line(LLPoints); Vect_append_point(LLPoints, FPoints->x[0], FPoints->y[0], FPoints->z[0]); Vect_append_point(LLPoints, tmp_tx, tmp_ty, tmp_tz); tmp_dist = Vect_line_geodesic_length(LLPoints); Vect_reset_line(LLPoints); for (k = 0; k < tseg; k++) Vect_append_point(LLPoints, TPoints->x[k], TPoints->y[k], TPoints->z[k]); Vect_append_point(LLPoints, tmp_tx, tmp_ty, tmp_tz); tmp_talong = Vect_line_geodesic_length(LLPoints); } G_debug(4, " tmp_dist = %f tmp_tcat = %d", tmp_dist, tmp_tcat); if (all) { if (anear <= count) { anear += 10 + nfrom / 10; Near = (NEAR *) G_realloc(Near, anear * sizeof(NEAR)); } near = &(Near[count]); /* store info about relation */ near->from_cat = fcat; near->to_cat = tmp_tcat; /* -1 is OK */ near->dist = tmp_dist; near->from_x = FPoints->x[0]; near->from_y = FPoints->y[0]; near->from_z = FPoints->z[0]; near->to_x = tmp_tx; near->to_y = tmp_ty; near->to_z = tmp_tz; near->to_along = tmp_talong; /* 0 for points */ near->to_angle = tmp_tangle; near->count++; count++; } else { if (tline == 0 || (tmp_dist < dist)) { tline = List->id[i]; tcat = tmp_tcat; dist = tmp_dist; tx = tmp_tx; ty = tmp_ty; tz = tmp_tz; talong = tmp_talong; tangle = tmp_tangle; } } } G_debug(4, " dist = %f", dist); if (curr_step < n_max_steps) { /* enlarging the search box is possible */ if (tline > 0 && dist > box_edge) { /* line found but distance > search edge: * line bbox overlaps with search box, line itself is outside search box */ done = 0; } else if (tline == 0) { /* no line within max dist, but search box can still be enlarged */ done = 0; } } if (done && !all && tline > 0) { /* find near by cat */ near = (NEAR *) bsearch((void *)&fcat, Near, nfcats, sizeof(NEAR), cmp_near); G_debug(4, " near.from_cat = %d near.count = %d", near->from_cat, near->count); /* store info about relation */ if (near->count == 0 || near->dist > dist) { near->to_cat = tcat; /* -1 is OK */ near->dist = dist; near->from_x = FPoints->x[0]; near->from_y = FPoints->y[0]; near->from_z = FPoints->z[0]; near->to_x = tx; near->to_y = ty; near->to_z = tz; near->to_along = talong; /* 0 for points */ near->to_angle = tangle; } near->count++; } } /* done */ } /* next feature */ if (LLPoints) { Vect_destroy_line_struct(LLPoints); } } /* Find nearest areas */ if (to_type & GV_AREA) { G_message(_("Finding nearest areas...")); for (fline = 1; fline <= nfrom; fline++) { double tmp_min = (min < 0 ? 0 : min); double box_edge = 0; int done = 0; curr_step = 0; G_debug(3, "fline = %d", fline); G_percent(fline, nfrom, 2); ftype = Vect_read_line(&From, FPoints, FCats, fline); if (!(ftype & from_type)) continue; Vect_cat_get(FCats, from_field, &fcat); if (fcat < 0 && !all) continue; while (!done) { done = 1; if (!all) { /* enlarge search box until we get a hit */ /* the objective is to enlarge the search box * in the first iterations just a little bit * to keep the number of hits low */ Vect_reset_boxlist(List); while (curr_step < n_max_steps) { box_edge = max_step[curr_step]; if (box_edge < tmp_min) continue; box.E = FPoints->x[0] + box_edge; box.W = FPoints->x[0] - box_edge; box.N = FPoints->y[0] + box_edge; box.S = FPoints->y[0] - box_edge; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_areas_by_box(&To, &box, List); curr_step++; if (List->n_values > 0) break; } } else { box.E = FPoints->x[0] + max; box.W = FPoints->x[0] - max; box.N = FPoints->y[0] + max; box.S = FPoints->y[0] - max; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; Vect_select_areas_by_box(&To, &box, List); } G_debug(4, "%d areas selected by box", List->n_values); /* For each area in box check the distance */ tarea = 0; dist = PORT_DOUBLE_MAX; for (i = 0; i < List->n_values; i++) { int tmp_tcat; area = List->id[i]; G_debug(4, "%d: area %d", i, area); Vect_get_area_points(&To, area, TPoints); /* Find the distance to this area */ if (Vect_point_in_area(FPoints->x[0], FPoints->y[0], &To, area, List->box[i])) { /* in area */ tmp_dist = 0; tmp_tx = FPoints->x[0]; tmp_ty = FPoints->y[0]; } else if (Vect_point_in_poly(FPoints->x[0], FPoints->y[0], TPoints) > 0) { /* in isle */ nisles = Vect_get_area_num_isles(&To, area); for (j = 0; j < nisles; j++) { double tmp2_dist, tmp2_tx, tmp2_ty; isle = Vect_get_area_isle(&To, area, j); Vect_get_isle_points(&To, isle, TPoints); Vect_line_distance(TPoints, FPoints->x[0], FPoints->y[0], FPoints->z[0], WITHOUT_Z, &tmp2_tx, &tmp2_ty, NULL, &tmp2_dist, NULL, NULL); if (j == 0 || tmp2_dist < tmp_dist) { tmp_dist = tmp2_dist; tmp_tx = tmp2_tx; tmp_ty = tmp2_ty; } } } else { /* outside area */ Vect_line_distance(TPoints, FPoints->x[0], FPoints->y[0], FPoints->z[0], WITHOUT_Z, &tmp_tx, &tmp_ty, NULL, &tmp_dist, NULL, NULL); } if (tmp_dist > max || tmp_dist < min) continue; /* not in threshold */ Vect_get_area_cats(&To, area, TCats); tmp_tcat = -1; /* TODO: all cats of given field ? */ for (j = 0; j < TCats->n_cats; j++) { if (TCats->field[j] == to_field) { if (tmp_tcat >= 0) G_warning(_("More cats found in to_layer (area=%d)"), area); tmp_tcat = TCats->cat[j]; } } G_debug(4, " tmp_dist = %f tmp_tcat = %d", tmp_dist, tmp_tcat); if (all) { if (anear <= count) { anear += 10 + nfrom / 10; Near = (NEAR *) G_realloc(Near, anear * sizeof(NEAR)); } near = &(Near[count]); /* store info about relation */ near->from_cat = fcat; near->to_cat = tmp_tcat; /* -1 is OK */ near->dist = tmp_dist; near->from_x = FPoints->x[0]; near->from_y = FPoints->y[0]; near->to_x = tmp_tx; near->to_y = tmp_ty; near->to_along = 0; /* nonsense for areas */ near->to_angle = 0; /* not supported for areas */ near->count++; count++; } else if (tarea == 0 || tmp_dist < dist) { tarea = area; tcat = tmp_tcat; dist = tmp_dist; tx = tmp_tx; ty = tmp_ty; } } if (curr_step < n_max_steps) { /* enlarging the search box is possible */ if (tarea > 0 && dist > box_edge) { /* area found but distance > search edge: * area bbox overlaps with search box, area itself is outside search box */ done = 0; } else if (tarea == 0) { /* no area within max dist, but search box can still be enlarged */ done = 0; } } if (done && !all && tarea > 0) { /* find near by cat */ near = (NEAR *) bsearch((void *)&fcat, Near, nfcats, sizeof(NEAR), cmp_near); G_debug(4, "near.from_cat = %d near.count = %d dist = %f", near->from_cat, near->count, near->dist); /* store info about relation */ if (near->count == 0 || near->dist > dist) { near->to_cat = tcat; /* -1 is OK */ near->dist = dist; near->from_x = FPoints->x[0]; near->from_y = FPoints->y[0]; near->to_x = tx; near->to_y = ty; near->to_along = 0; /* nonsense for areas */ near->to_angle = 0; /* not supported for areas */ } near->count++; } } /* done */ } /* next feature */ } G_debug(3, "count = %d", count); /* Update database / print to stdout / create output map */ if (print_flag->answer) { /* print header */ fprintf(stdout, "from_cat"); i = 0; while (Upload[i].upload != END) { fprintf(stdout, "|%s", Upload[i].column); i++; } fprintf(stdout, "\n"); } else if (all && table_opt->answer) { /* create new table */ db_set_string(&stmt, "create table "); db_append_string(&stmt, table_opt->answer); db_append_string(&stmt, " (from_cat integer"); j = 0; while (Upload[j].upload != END) { db_append_string(&stmt, ", "); switch (Upload[j].upload) { case CAT: sprintf(buf2, "%s integer", Upload[j].column); break; case DIST: case FROM_X: case FROM_Y: case TO_X: case TO_Y: case FROM_ALONG: case TO_ALONG: case TO_ANGLE: sprintf(buf2, "%s double precision", Upload[j].column); } db_append_string(&stmt, buf2); j++; } db_append_string(&stmt, " )"); G_debug(3, "SQL: %s", db_get_string(&stmt)); if (db_execute_immediate(driver, &stmt) != DB_OK) G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&stmt)); if (db_grant_on_table(driver, table_opt->answer, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Unable to grant privileges on table <%s>"), table_opt->answer); } else if (!all) { /* read existing cats from table */ ncatexist = db_select_int(driver, Fi->table, Fi->key, NULL, &catexist); G_debug(1, "%d cats selected from the table", ncatexist); } update_ok = update_err = update_exist = update_notexist = update_dupl = update_notfound = 0; if (!all) { count = nfcats; } else if (print_as_matrix) { qsort((void *)Near, count, sizeof(NEAR), cmp_near_to); } if (driver) db_begin_transaction(driver); /* select 'to' attributes */ if (to_column_opt->answer) { int nrec; db_CatValArray_init(&cvarr); nrec = db_select_CatValArray(to_driver, toFi->table, toFi->key, to_column_opt->answer, NULL, &cvarr); G_debug(3, "selected values = %d", nrec); if (cvarr.ctype == DB_C_TYPE_DATETIME) { G_warning(_("DATETIME type not yet supported, no attributes will be uploaded")); } db_close_database_shutdown_driver(to_driver); } if (!(print_flag->answer || (all && !table_opt->answer))) /* no printing */ G_message("Update database..."); for (i = 0; i < count; i++) { dbCatVal *catval = 0; if (!(print_flag->answer || (all && !table_opt->answer))) /* no printing */ G_percent(i, count, 1); /* Write line connecting nearest points */ if (Outp != NULL) { Vect_reset_line(FPoints); Vect_reset_cats(FCats); Vect_append_point(FPoints, Near[i].from_x, Near[i].from_y, 0); if (Near[i].dist == 0) { Vect_write_line(Outp, GV_POINT, FPoints, FCats); } else { Vect_append_point(FPoints, Near[i].to_x, Near[i].to_y, 0); Vect_write_line(Outp, GV_LINE, FPoints, FCats); } } if (Near[i].count > 1) update_dupl++; if (Near[i].count == 0) update_notfound++; if (to_column_opt->answer && Near[i].count > 0) { db_CatValArray_get_value(&cvarr, Near[i].to_cat, &catval); } if (print_flag->answer || (all && !table_opt->answer)) { /* print only */ /* input and output is the same && calculate distances && only one upload option given -> print as a matrix */ if (print_as_matrix) { if (i == 0) { for (j = 0; j < nfrom; j++) { if (j == 0) fprintf(stdout, " "); fprintf(stdout, "|%d", Near[j].to_cat); } fprintf(stdout, "\n"); } if (i % nfrom == 0) { fprintf(stdout, "%d", Near[i].from_cat); for (j = 0; j < nfrom; j++) { print_upload(Near, Upload, i + j, &cvarr, catval); } fprintf(stdout, "\n"); } } else { fprintf(stdout, "%d", Near[i].from_cat); print_upload(Near, Upload, i, &cvarr, catval); fprintf(stdout, "\n"); } } else if (all) { /* insert new record */ sprintf(buf1, "insert into %s values ( %d ", table_opt->answer, Near[i].from_cat); db_set_string(&stmt, buf1); j = 0; while (Upload[j].upload != END) { db_append_string(&stmt, ","); switch (Upload[j].upload) { case CAT: sprintf(buf2, " %d", Near[i].to_cat); break; case DIST: sprintf(buf2, " %f", Near[i].dist); break; case FROM_X: sprintf(buf2, " %f", Near[i].from_x); break; case FROM_Y: sprintf(buf2, " %f", Near[i].from_y); break; case TO_X: sprintf(buf2, " %f", Near[i].to_x); break; case TO_Y: sprintf(buf2, " %f", Near[i].to_y); break; case FROM_ALONG: sprintf(buf2, " %f", Near[i].from_along); break; case TO_ALONG: sprintf(buf2, " %f", Near[i].to_along); break; case TO_ANGLE: sprintf(buf2, " %f", Near[i].to_angle); break; case TO_ATTR: if (catval) { switch (cvarr.ctype) { case DB_C_TYPE_INT: sprintf(buf2, " %d", catval->val.i); break; case DB_C_TYPE_DOUBLE: sprintf(buf2, " %.15e", catval->val.d); break; case DB_C_TYPE_STRING: db_set_string(&dbstr, db_get_string(catval->val.s)); db_double_quote_string(&dbstr); sprintf(buf2, " '%s'", db_get_string(&dbstr)); break; case DB_C_TYPE_DATETIME: /* TODO: formating datetime */ sprintf(buf2, " null"); break; } } else { sprintf(buf2, " null"); } break; } db_append_string(&stmt, buf2); j++; } db_append_string(&stmt, " )"); G_debug(3, "SQL: %s", db_get_string(&stmt)); if (db_execute_immediate(driver, &stmt) == DB_OK) { update_ok++; } else { update_err++; } } else { /* update table */ /* check if exists in table */ cex = (int *)bsearch((void *)&(Near[i].from_cat), catexist, ncatexist, sizeof(int), cmp_exist); if (cex == NULL) { /* cat does not exist in DB */ update_notexist++; continue; } update_exist++; sprintf(buf1, "update %s set", Fi->table); db_set_string(&stmt, buf1); j = 0; while (Upload[j].upload != END) { if (j > 0) db_append_string(&stmt, ","); sprintf(buf2, " %s =", Upload[j].column); db_append_string(&stmt, buf2); if (Near[i].count == 0) { /* no nearest found */ db_append_string(&stmt, " null"); } else { switch (Upload[j].upload) { case CAT: if (Near[i].to_cat > 0) sprintf(buf2, " %d", Near[i].to_cat); else sprintf(buf2, " null"); break; case DIST: sprintf(buf2, " %f", Near[i].dist); break; case FROM_X: sprintf(buf2, " %f", Near[i].from_x); break; case FROM_Y: sprintf(buf2, " %f", Near[i].from_y); break; case TO_X: sprintf(buf2, " %f", Near[i].to_x); break; case TO_Y: sprintf(buf2, " %f", Near[i].to_y); break; case FROM_ALONG: sprintf(buf2, " %f", Near[i].from_along); break; case TO_ALONG: sprintf(buf2, " %f", Near[i].to_along); break; case TO_ANGLE: sprintf(buf2, " %f", Near[i].to_angle); break; case TO_ATTR: if (catval) { switch (cvarr.ctype) { case DB_C_TYPE_INT: sprintf(buf2, " %d", catval->val.i); break; case DB_C_TYPE_DOUBLE: sprintf(buf2, " %.15e", catval->val.d); break; case DB_C_TYPE_STRING: db_set_string(&dbstr, db_get_string(catval->val.s)); db_double_quote_string(&dbstr); sprintf(buf2, " '%s'", db_get_string(&dbstr)); break; case DB_C_TYPE_DATETIME: /* TODO: formating datetime */ sprintf(buf2, " null"); break; } } else { sprintf(buf2, " null"); } break; } db_append_string(&stmt, buf2); } j++; } sprintf(buf2, " where %s = %d", Fi->key, Near[i].from_cat); db_append_string(&stmt, buf2); G_debug(2, "SQL: %s", db_get_string(&stmt)); if (db_execute_immediate(driver, &stmt) == DB_OK) { update_ok++; } else { update_err++; } } } G_percent(count, count, 1); if (driver) db_commit_transaction(driver); /* print stats */ if (update_dupl > 0) G_message(_("%d categories with more than 1 feature in vector map <%s>"), update_dupl, from_opt->answer); if (update_notfound > 0) G_message(_("%d categories - no nearest feature found"), update_notfound); if (!print_flag->answer) { db_close_database_shutdown_driver(driver); db_free_string(&stmt); /* print stats */ if (all && table_opt->answer) { G_message(_("%d distances calculated"), count); G_message(_("%d records inserted"), update_ok); if (update_err > 0) G_message(_("%d insert errors"), update_err); } else if (!all) { if (nfcats > 0) G_message(_("%d categories read from the map"), nfcats); if (ncatexist > 0) G_message(_("%d categories exist in the table"), ncatexist); if (update_exist > 0) G_message(_("%d categories read from the map exist in the table"), update_exist); if (update_notexist > 0) G_message(_("%d categories read from the map don't exist in the table"), update_notexist); G_message(_("%d records updated"), update_ok); if (update_err > 0) G_message(_("%d update errors"), update_err); G_free(catexist); } Vect_set_db_updated(&From); } Vect_close(&From); if (Outp != NULL) { Vect_build(Outp); Vect_close(Outp); } G_done_msg(" "); exit(EXIT_SUCCESS); }