/* * open_new_vect - opens new vector map for writing */ int open_new_vect(struct Map_info *map, char *vect) { Vect_open_new(map, vect, 1); Vect_set_map_name(map, vect); Vect_set_comment(map, G_recreate_command()); Vect_hist_command(map); return 1; }
/* * open_new_vect - opens new vector map for writing */ int open_new_vect(struct Map_info *map, char *vect) { if (Vect_open_new(map, vect, 1) < 0) G_fatal_error(_("Unable to create vector map <%s>"), vect); Vect_set_map_name(map, vect); Vect_set_comment(map, G_recreate_command()); Vect_hist_command(map); return 1; }
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 close_streamvect(char *stream_vect) { int r, c, r_nbr, c_nbr, done; GW_LARGE_INT i; CELL stream_id, stream_nbr; ASP_FLAG af; int next_node; struct sstack { int stream_id; int next_trib; } *nodestack; int top = 0, stack_step = 1000; int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 }; int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 }; struct Map_info Out; static struct line_pnts *Points; struct line_cats *Cats; dbDriver *driver; dbHandle handle; dbString table_name, dbsql, valstr; struct field_info *Fi; char *cat_col_name = "cat", buf[2000]; struct Cell_head window; double north_offset, west_offset, ns_res, ew_res; int next_cat; G_message(_("Writing vector map <%s>..."), stream_vect); if (Vect_open_new(&Out, stream_vect, 0) < 0) G_fatal_error(_("Unable to create vector map <%s>"), stream_vect); nodestack = (struct sstack *)G_malloc(stack_step * sizeof(struct sstack)); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); G_get_set_window(&window); ns_res = window.ns_res; ew_res = window.ew_res; north_offset = window.north - 0.5 * ns_res; west_offset = window.west + 0.5 * ew_res; next_cat = n_stream_nodes + 1; for (i = 0; i < n_outlets; i++, next_cat++) { G_percent(i, n_outlets, 2); r = outlets[i].r; c = outlets[i].c; cseg_get(&stream, &stream_id, r, c); if (!stream_id) continue; Vect_reset_line(Points); Vect_reset_cats(Cats); /* outlet */ Vect_cat_set(Cats, 1, stream_id); Vect_cat_set(Cats, 2, 2); Vect_append_point(Points, west_offset + c * ew_res, north_offset - r * ns_res, 0); Vect_write_line(&Out, GV_POINT, Points, Cats); /* add root node to stack */ G_debug(3, "add root node"); top = 0; nodestack[top].stream_id = stream_id; nodestack[top].next_trib = 0; /* depth first post order traversal */ G_debug(3, "traverse"); while (top >= 0) { done = 1; stream_id = nodestack[top].stream_id; G_debug(3, "stream_id %d", stream_id); if (nodestack[top].next_trib < stream_node[stream_id].n_trib) { /* add to stack */ next_node = stream_node[stream_id].trib[nodestack[top].next_trib]; G_debug(3, "add to stack: next %d, trib %d, n trib %d", next_node, nodestack[top].next_trib, stream_node[stream_id].n_trib); nodestack[top].next_trib++; top++; if (top >= stack_step) { /* need more space */ stack_step += 1000; nodestack = (struct sstack *)G_realloc(nodestack, stack_step * sizeof(struct sstack)); } nodestack[top].next_trib = 0; nodestack[top].stream_id = next_node; done = 0; G_debug(3, "go further down"); } if (done) { G_debug(3, "write stream segment"); Vect_reset_line(Points); Vect_reset_cats(Cats); r_nbr = stream_node[stream_id].r; c_nbr = stream_node[stream_id].c; cseg_get(&stream, &stream_nbr, r_nbr, c_nbr); if (stream_nbr <= 0) G_fatal_error(_("Stream id %d not set, top is %d, parent is %d"), stream_id, top, nodestack[top - 1].stream_id); Vect_cat_set(Cats, 1, stream_id); if (stream_node[stream_id].n_trib == 0) Vect_cat_set(Cats, 2, 0); else Vect_cat_set(Cats, 2, 1); Vect_append_point(Points, west_offset + c_nbr * ew_res, north_offset - r_nbr * ns_res, 0); Vect_write_line(&Out, GV_POINT, Points, Cats); seg_get(&aspflag, (char *)&af, r_nbr, c_nbr); while (af.asp > 0) { r_nbr = r_nbr + asp_r[(int)af.asp]; c_nbr = c_nbr + asp_c[(int)af.asp]; cseg_get(&stream, &stream_nbr, r_nbr, c_nbr); if (stream_nbr <= 0) G_fatal_error(_("Stream id not set while tracing")); Vect_append_point(Points, west_offset + c_nbr * ew_res, north_offset - r_nbr * ns_res, 0); if (stream_nbr != stream_id) { /* first point of parent stream */ break; } seg_get(&aspflag, (char *)&af, r_nbr, c_nbr); } Vect_write_line(&Out, GV_LINE, Points, Cats); top--; } } } G_percent(n_outlets, n_outlets, 1); /* finish it */ G_message(_("Writing attribute data...")); /* Prepeare strings for use in db_* calls */ db_init_string(&dbsql); db_init_string(&valstr); db_init_string(&table_name); db_init_handle(&handle); /* Preparing database for use */ /* Create database for new vector map */ Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Out)); if (driver == NULL) { G_fatal_error(_("Unable to start driver <%s>"), Fi->driver); } db_set_error_handler_driver(driver); G_debug(1, "table: %s", Fi->table); G_debug(1, "driver: %s", Fi->driver); G_debug(1, "database: %s", Fi->database); sprintf(buf, "create table %s (%s integer, stream_type varchar(20), type_code integer)", Fi->table, cat_col_name); db_set_string(&dbsql, buf); if (db_execute_immediate(driver, &dbsql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&dbsql)); } if (db_create_index2(driver, Fi->table, cat_col_name) != DB_OK) G_warning(_("Unable to create index on table <%s>"), Fi->table); if (db_grant_on_table(driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Unable to grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); /* stream nodes */ for (i = 1; i <= n_stream_nodes; i++) { sprintf(buf, "insert into %s values ( %lld, \'%s\', %d )", Fi->table, i, (stream_node[i].n_trib > 0 ? "intermediate" : "start"), (stream_node[i].n_trib > 0)); db_set_string(&dbsql, buf); if (db_execute_immediate(driver, &dbsql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to insert new row: '%s'"), db_get_string(&dbsql)); } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, cat_col_name, Fi->database, Fi->driver); G_debug(1, "close vector"); Vect_hist_command(&Out); Vect_build(&Out); Vect_close(&Out); G_free(nodestack); return 1; }
int main(int argc, char *argv[]) { int i, type, stat; int day, yr, Out_proj; int out_zone = 0; int overwrite; /* overwrite output map */ const char *mapset; const char *omap_name, *map_name, *iset_name, *iloc_name; struct pj_info info_in; struct pj_info info_out; const char *gbase; char date[40], mon[4]; struct GModule *module; struct Option *omapopt, *mapopt, *isetopt, *ilocopt, *ibaseopt, *smax; struct Key_Value *in_proj_keys, *in_unit_keys; struct Key_Value *out_proj_keys, *out_unit_keys; struct line_pnts *Points, *Points2; struct line_cats *Cats; struct Map_info Map; struct Map_info Out_Map; struct bound_box src_box, tgt_box; int nowrap = 0, recommend_nowrap = 0; double lmax; struct { struct Flag *list; /* list files in source location */ struct Flag *transformz; /* treat z as ellipsoidal height */ struct Flag *wrap; /* latlon output: wrap to 0,360 */ struct Flag *no_topol; /* do not build topology */ } flag; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("projection")); G_add_keyword(_("transformation")); G_add_keyword(_("import")); module->description = _("Re-projects a vector map from one location to the current location."); /* set up the options and flags for the command line parser */ ilocopt = G_define_standard_option(G_OPT_M_LOCATION); ilocopt->required = YES; ilocopt->label = _("Location containing input vector map"); ilocopt->guisection = _("Source"); isetopt = G_define_standard_option(G_OPT_M_MAPSET); isetopt->label = _("Mapset containing input vector map"); isetopt->description = _("Default: name of current mapset"); isetopt->guisection = _("Source"); mapopt = G_define_standard_option(G_OPT_V_INPUT); mapopt->required = NO; mapopt->label = _("Name of input vector map to re-project"); mapopt->description = NULL; mapopt->guisection = _("Source"); ibaseopt = G_define_standard_option(G_OPT_M_DBASE); ibaseopt->label = _("Path to GRASS database of input location"); smax = G_define_option(); smax->key = "smax"; smax->type = TYPE_DOUBLE; smax->required = NO; smax->answer = "10000"; smax->label = _("Maximum segment length in meters in output vector map"); smax->description = _("Increases accuracy of reprojected shapes, disable with smax=0"); smax->guisection = _("Target"); omapopt = G_define_standard_option(G_OPT_V_OUTPUT); omapopt->required = NO; omapopt->description = _("Name for output vector map (default: input)"); omapopt->guisection = _("Target"); flag.list = G_define_flag(); flag.list->key = 'l'; flag.list->description = _("List vector maps in input mapset and exit"); flag.transformz = G_define_flag(); flag.transformz->key = 'z'; flag.transformz->description = _("3D vector maps only"); flag.transformz->label = _("Assume z coordinate is ellipsoidal height and " "transform if possible"); flag.transformz->guisection = _("Target"); flag.wrap = G_define_flag(); flag.wrap->key = 'w'; flag.wrap->description = _("Latlon output only, default is -180,180"); flag.wrap->label = _("Disable wrapping to -180,180 for latlon output"); flag.transformz->guisection = _("Target"); flag.no_topol = G_define_flag(); flag.no_topol->key = 'b'; flag.no_topol->label = _("Do not build vector topology"); flag.no_topol->description = _("Recommended for massive point projection"); /* The parser checks if the map already exists in current mapset, we switch out the check and do it in the module after the parser */ overwrite = G_check_overwrite(argc, argv); if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* start checking options and flags */ /* set input vector map name and mapset */ map_name = mapopt->answer; if (omapopt->answer) omap_name = omapopt->answer; else omap_name = map_name; if (omap_name && !flag.list->answer && !overwrite && G_find_vector2(omap_name, G_mapset())) G_fatal_error(_("option <%s>: <%s> exists. To overwrite, use the --overwrite flag"), omapopt->key, omap_name); if (isetopt->answer) iset_name = isetopt->answer; else iset_name = G_store(G_mapset()); iloc_name = ilocopt->answer; if (ibaseopt->answer) gbase = ibaseopt->answer; else gbase = G_store(G_gisdbase()); if (!ibaseopt->answer && strcmp(iloc_name, G_location()) == 0) G_fatal_error(_("Input and output locations can not be the same")); lmax = atof(smax->answer); if (lmax < 0) lmax = 0; Out_proj = G_projection(); if (Out_proj == PROJECTION_LL && flag.wrap->answer) nowrap = 1; G_begin_distance_calculations(); /* Change the location here and then come back */ select_target_env(); G_setenv_nogisrc("GISDBASE", gbase); G_setenv_nogisrc("LOCATION_NAME", iloc_name); stat = G_mapset_permissions(iset_name); if (stat >= 0) { /* yes, we can access the mapset */ /* if requested, list the vector maps in source location - MN 5/2001 */ if (flag.list->answer) { int i; char **list; G_verbose_message(_("Checking location <%s> mapset <%s>"), iloc_name, iset_name); list = G_list(G_ELEMENT_VECTOR, G_getenv_nofatal("GISDBASE"), G_getenv_nofatal("LOCATION_NAME"), iset_name); if (list[0]) { for (i = 0; list[i]; i++) { fprintf(stdout, "%s\n", list[i]); } fflush(stdout); } else { G_important_message(_("No vector maps found")); } exit(EXIT_SUCCESS); /* leave v.proj after listing */ } if (mapopt->answer == NULL) { G_fatal_error(_("Required parameter <%s> not set"), mapopt->key); } G_setenv_nogisrc("MAPSET", iset_name); /* Make sure map is available */ mapset = G_find_vector2(map_name, iset_name); if (mapset == NULL) G_fatal_error(_("Vector map <%s> in location <%s> mapset <%s> not found"), map_name, iloc_name, iset_name); /*** Get projection info for input mapset ***/ in_proj_keys = G_get_projinfo(); if (in_proj_keys == NULL) exit(EXIT_FAILURE); /* apparently the +over switch must be set in the input projection, * not the output latlon projection */ if (Out_proj == PROJECTION_LL && nowrap == 1) G_set_key_value("+over", "defined", in_proj_keys); in_unit_keys = G_get_projunits(); if (in_unit_keys == NULL) exit(EXIT_FAILURE); if (pj_get_kv(&info_in, in_proj_keys, in_unit_keys) < 0) exit(EXIT_FAILURE); Vect_set_open_level(1); G_debug(1, "Open old: location: %s mapset : %s", G_location_path(), G_mapset()); if (Vect_open_old(&Map, map_name, mapset) < 0) G_fatal_error(_("Unable to open vector map <%s>"), map_name); } else if (stat < 0) { /* allow 0 (i.e. denied permission) */ /* need to be able to read from others */ if (stat == 0) G_fatal_error(_("Mapset <%s> in input location <%s> - permission denied"), iset_name, iloc_name); else G_fatal_error(_("Mapset <%s> in input location <%s> not found"), iset_name, iloc_name); } select_current_env(); /****** get the output projection parameters ******/ out_proj_keys = G_get_projinfo(); if (out_proj_keys == NULL) exit(EXIT_FAILURE); out_unit_keys = G_get_projunits(); if (out_unit_keys == NULL) exit(EXIT_FAILURE); if (pj_get_kv(&info_out, out_proj_keys, out_unit_keys) < 0) exit(EXIT_FAILURE); G_free_key_value(in_proj_keys); G_free_key_value(in_unit_keys); G_free_key_value(out_proj_keys); G_free_key_value(out_unit_keys); if (G_verbose() == G_verbose_max()) { pj_print_proj_params(&info_in, &info_out); } /* Initialize the Point / Cat structure */ Points = Vect_new_line_struct(); Points2 = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); /* test if latlon wrapping to -180,180 should be disabled */ if (Out_proj == PROJECTION_LL && nowrap == 0) { int first = 1, counter = 0; double x, y; /* Cycle through all lines */ Vect_rewind(&Map); while (1) { type = Vect_read_next_line(&Map, Points, Cats); /* read line */ if (type == 0) continue; /* Dead */ if (type == -1) G_fatal_error(_("Reading input vector map")); if (type == -2) break; if (first && Points->n_points > 0) { first = 0; src_box.E = src_box.W = Points->x[0]; src_box.N = src_box.S = Points->y[0]; src_box.T = src_box.B = Points->z[0]; } for (i = 0; i < Points->n_points; i++) { if (src_box.E < Points->x[i]) src_box.E = Points->x[i]; if (src_box.W > Points->x[i]) src_box.W = Points->x[i]; if (src_box.N < Points->y[i]) src_box.N = Points->y[i]; if (src_box.S > Points->y[i]) src_box.S = Points->y[i]; } counter++; } if (counter == 0) { G_warning(_("Input vector map <%s> is empty"), omap_name); exit(EXIT_SUCCESS); } /* NW corner */ x = src_box.W; y = src_box.N; if (pj_do_transform(1, &x, &y, NULL, &info_in, &info_out) < 0) { G_fatal_error(_("Error in pj_do_transform")); } tgt_box.E = x; tgt_box.W = x; tgt_box.N = y; tgt_box.S = y; /* SW corner */ x = src_box.W; y = src_box.S; if (pj_do_transform(1, &x, &y, NULL, &info_in, &info_out) < 0) { G_fatal_error(_("Error in pj_do_transform")); } if (tgt_box.W > x) tgt_box.W = x; if (tgt_box.E < x) tgt_box.E = x; if (tgt_box.N < y) tgt_box.N = y; if (tgt_box.S > y) tgt_box.S = y; /* NE corner */ x = src_box.E; y = src_box.N; if (pj_do_transform(1, &x, &y, NULL, &info_in, &info_out) < 0) { G_fatal_error(_("Error in pj_do_transform")); } if (tgt_box.W > x) { tgt_box.E = x + 360; recommend_nowrap = 1; } if (tgt_box.N < y) tgt_box.N = y; if (tgt_box.S > y) tgt_box.S = y; /* SE corner */ x = src_box.E; y = src_box.S; if (pj_do_transform(1, &x, &y, NULL, &info_in, &info_out) < 0) { G_fatal_error(_("Error in pj_do_transform")); } if (tgt_box.W > x) { if (tgt_box.E < x + 360) tgt_box.E = x + 360; recommend_nowrap = 1; } if (tgt_box.N < y) tgt_box.N = y; if (tgt_box.S > y) tgt_box.S = y; } G_debug(1, "Open new: location: %s mapset : %s", G_location_path(), G_mapset()); if (Vect_open_new(&Out_Map, omap_name, Vect_is_3d(&Map)) < 0) G_fatal_error(_("Unable to create vector map <%s>"), omap_name); Vect_set_error_handler_io(NULL, &Out_Map); /* register standard i/o error handler */ Vect_copy_head_data(&Map, &Out_Map); Vect_hist_copy(&Map, &Out_Map); Vect_hist_command(&Out_Map); out_zone = info_out.zone; Vect_set_zone(&Out_Map, out_zone); /* Read and write header info */ sprintf(date, "%s", G_date()); sscanf(date, "%*s%s%d%*s%d", mon, &day, &yr); if (yr < 2000) yr = yr - 1900; else yr = yr - 2000; sprintf(date, "%s %d %d", mon, day, yr); Vect_set_date(&Out_Map, date); /* line densification works only with vector topology */ if (Map.format != GV_FORMAT_NATIVE) lmax = 0; /* Cycle through all lines */ Vect_rewind(&Map); i = 0; G_message(_("Reprojecting primitives ...")); while (TRUE) { ++i; G_progress(i, 1e3); type = Vect_read_next_line(&Map, Points, Cats); /* read line */ if (type == 0) continue; /* Dead */ if (type == -1) G_fatal_error(_("Reading input vector map")); if (type == -2) break; Vect_line_prune(Points); if (lmax > 0 && (type & GV_LINES) && Points->n_points > 1) { double x1, y1, z1, x2, y2, z2; double dx, dy, dz; double l; int i, n; Vect_reset_line(Points2); for (i = 0; i < Points->n_points - 1; i++) { x1 = Points->x[i]; y1 = Points->y[i]; z1 = Points->z[i]; n = i + 1; x2 = Points->x[n]; y2 = Points->y[n]; z2 = Points->z[n]; dx = x2 - x1; dy = y2 - y1; dz = z2 - z1; if (pj_do_transform(1, &x1, &y1, flag.transformz->answer ? &z1 : NULL, &info_in, &info_out) < 0) { G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"), Vect_get_full_name(&Map), ilocopt->answer); } if (pj_do_transform(1, &x2, &y2, flag.transformz->answer ? &z2 : NULL, &info_in, &info_out) < 0) { G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"), Vect_get_full_name(&Map), ilocopt->answer); } Vect_append_point(Points2, x1, y1, z1); l = G_distance(x1, y1, x2, y2); if (l > lmax) { int j; double x, y, z; x1 = Points->x[i]; y1 = Points->y[i]; z1 = Points->z[i]; n = ceil(l / lmax); for (j = 1; j < n; j++) { x = x1 + dx * j / n; y = y1 + dy * j / n; z = z1 + dz * j / n; if (pj_do_transform(1, &x, &y, flag.transformz->answer ? &z : NULL, &info_in, &info_out) < 0) { G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"), Vect_get_full_name(&Map), ilocopt->answer); } Vect_append_point(Points2, x, y, z); } } } Vect_append_point(Points2, x2, y2, z2); Vect_write_line(&Out_Map, type, Points2, Cats); /* write line */ } else { if (pj_do_transform(Points->n_points, Points->x, Points->y, flag.transformz->answer ? Points->z : NULL, &info_in, &info_out) < 0) { G_fatal_error(_("Unable to re-project vector map <%s> from <%s>"), Vect_get_full_name(&Map), ilocopt->answer); } Vect_write_line(&Out_Map, type, Points, Cats); /* write line */ } } /* end lines section */ G_progress(1, 1); /* Copy tables */ if (Vect_copy_tables(&Map, &Out_Map, 0)) G_warning(_("Failed to copy attribute table to output map")); Vect_close(&Map); if (!flag.no_topol->answer) Vect_build(&Out_Map); Vect_close(&Out_Map); if (recommend_nowrap) G_important_message(_("Try to disable wrapping to -180,180 " "if topological errors occurred")); 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 *cat_opt, *field_opt, *where_opt, *abcol, *afcol; struct Option *iter_opt, *error_opt; struct Flag *geo_f, *add_f; int chcat, with_z; int layer, mask_type; struct varray *varray; dglGraph_s *graph; int i, geo, nnodes, nlines, j, max_cat; char buf[2000], *covered; /* initialize GIS environment */ G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */ /* initialize module */ module = G_define_module(); module->keywords = _("vector, network, centrality measures"); module->description = _("Computes degree, centrality, betweeness, closeness and eigenvector " "centrality measures in the network."); /* Define the different options as defined in gis.h */ map_in = G_define_standard_option(G_OPT_V_INPUT); field_opt = G_define_standard_option(G_OPT_V_FIELD); map_out = G_define_standard_option(G_OPT_V_OUTPUT); cat_opt = G_define_standard_option(G_OPT_V_CATS); cat_opt->guisection = _("Selection"); where_opt = G_define_standard_option(G_OPT_WHERE); where_opt->guisection = _("Selection"); afcol = G_define_standard_option(G_OPT_COLUMN); afcol->key = "afcolumn"; afcol->required = NO; afcol->description = _("Name of arc forward/both direction(s) cost column"); afcol->guisection = _("Cost"); abcol = G_define_standard_option(G_OPT_COLUMN); abcol->key = "abcolumn"; abcol->required = NO; abcol->description = _("Name of arc backward direction cost column"); abcol->guisection = _("Cost"); deg_opt = G_define_standard_option(G_OPT_COLUMN); deg_opt->key = "degree"; deg_opt->required = NO; deg_opt->description = _("Name of degree centrality column"); deg_opt->guisection = _("Columns"); close_opt = G_define_standard_option(G_OPT_COLUMN); close_opt->key = "closeness"; close_opt->required = NO; close_opt->description = _("Name of closeness centrality column"); close_opt->guisection = _("Columns"); betw_opt = G_define_standard_option(G_OPT_COLUMN); betw_opt->key = "betweenness"; betw_opt->required = NO; betw_opt->description = _("Name of betweenness centrality column"); betw_opt->guisection = _("Columns"); eigen_opt = G_define_standard_option(G_OPT_COLUMN); eigen_opt->key = "eigenvector"; eigen_opt->required = NO; eigen_opt->description = _("Name of eigenvector centrality column"); eigen_opt->guisection = _("Columns"); iter_opt = G_define_option(); iter_opt->key = "iterations"; iter_opt->answer = "1000"; iter_opt->type = TYPE_INTEGER; iter_opt->required = NO; iter_opt->description = _("Maximum number of iterations to compute eigenvector centrality"); error_opt = G_define_option(); error_opt->key = "error"; error_opt->answer = "0.1"; error_opt->type = TYPE_DOUBLE; error_opt->required = NO; error_opt->description = _("Cummulative error tolerance for eigenvector centrality"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); add_f = G_define_flag(); add_f->key = 'a'; add_f->description = _("Add points on nodes"); /* options and flags parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* TODO: make an option for this */ mask_type = GV_LINE | GV_BOUNDARY; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Vect_check_input_output_name(map_in->answer, map_out->answer, GV_FATAL_EXIT); Vect_set_open_level(2); if (1 > Vect_open_old(&In, map_in->answer, "")) G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer); with_z = Vect_is_3d(&In); if (0 > Vect_open_new(&Out, map_out->answer, with_z)) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer); } if (geo_f->answer) { geo = 1; if (G_projection() != PROJECTION_LL) G_warning(_("The current projection is not longitude-latitude")); } else geo = 0; /* parse filter option and select appropriate lines */ layer = atoi(field_opt->answer); chcat = (NetA_initialise_varray (&In, layer, mask_type, where_opt->answer, cat_opt->answer, &varray) == 1); /* Create table */ Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", Fi->database, Fi->driver); db_init_string(&sql); driver = db_start_driver_open_database(Fi->driver, Fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_init_string(&tmp); if (deg_opt->answer) append_string(&tmp, deg_opt->answer); if (close_opt->answer) append_string(&tmp, close_opt->answer); if (betw_opt->answer) append_string(&tmp, betw_opt->answer); if (eigen_opt->answer) append_string(&tmp, eigen_opt->answer); sprintf(buf, "create table %s(cat integer%s)", Fi->table, db_get_string(&tmp)); db_set_string(&sql, buf); G_debug(2, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql)); } if (db_create_index2(driver, Fi->table, "cat") != DB_OK) G_warning(_("Cannot create index")); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); Vect_net_build_graph(&In, mask_type, atoi(field_opt->answer), 0, afcol->answer, abcol->answer, NULL, geo, 0); graph = &(In.graph); nnodes = dglGet_NodeCount(graph); deg = closeness = betw = eigen = NULL; covered = (char *)G_calloc(nnodes + 1, sizeof(char)); if (!covered) G_fatal_error(_("Out of memory")); if (deg_opt->answer) { deg = (double *)G_calloc(nnodes + 1, sizeof(double)); if (!deg) G_fatal_error(_("Out of memory")); } if (close_opt->answer) { closeness = (double *)G_calloc(nnodes + 1, sizeof(double)); if (!closeness) G_fatal_error(_("Out of memory")); } if (betw_opt->answer) { betw = (double *)G_calloc(nnodes + 1, sizeof(double)); if (!betw) G_fatal_error(_("Out of memory")); } if (eigen_opt->answer) { eigen = (double *)G_calloc(nnodes + 1, sizeof(double)); if (!eigen) G_fatal_error(_("Out of memory")); } if (deg_opt->answer) { G_message(_("Computing degree centrality measure")); NetA_degree_centrality(graph, deg); } if (betw_opt->answer || close_opt->answer) { G_message(_("Computing betweenness and/or closeness centrality measure")); NetA_betweenness_closeness(graph, betw, closeness); if (closeness) for (i = 1; i <= nnodes; i++) closeness[i] /= (double)In.cost_multip; } if (eigen_opt->answer) { G_message(_("Computing eigenvector centrality measure")); NetA_eigenvector_centrality(graph, atoi(iter_opt->answer), atof(error_opt->answer), eigen); } nlines = Vect_get_num_lines(&In); G_message(_("Writing data into the table...")); G_percent_reset(); for (i = 1; i <= nlines; i++) { G_percent(i, nlines, 1); int type = Vect_read_line(&In, Points, Cats, i); if (type == GV_POINT && (!chcat || varray->c[i])) { int cat, node; if (!Vect_cat_get(Cats, layer, &cat)) continue; Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, type, Points, Cats); Vect_get_line_nodes(&In, i, &node, NULL); process_node(node, cat); covered[node] = 1; } } if (add_f->answer && !chcat) { max_cat = 0; for (i = 1; i <= nlines; i++) { Vect_read_line(&In, NULL, Cats, i); for (j = 0; j < Cats->n_cats; j++) if (Cats->cat[j] > max_cat) max_cat = Cats->cat[j]; } max_cat++; for (i = 1; i <= nnodes; i++) if (!covered[i]) { Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, max_cat); NetA_add_point_on_node(&In, &Out, i, Cats); process_node(i, max_cat); max_cat++; } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); G_free(covered); if (deg) G_free(deg); if (closeness) G_free(closeness); if (betw) G_free(betw); if (eigen) G_free(eigen); Vect_build(&Out); Vect_close(&In); Vect_close(&Out); exit(EXIT_SUCCESS); }
int execute_random(struct rr_state *theState) { long nt; long nc; struct Cell_head window; int nrows, ncols, row, col; int infd, cinfd, outfd; struct Map_info Out; struct field_info *fi; dbTable *table; dbColumn *column; dbString sql; dbDriver *driver; struct line_pnts *Points; struct line_cats *Cats; int cat; RASTER_MAP_TYPE type; int do_check; G_get_window(&window); nrows = Rast_window_rows(); ncols = Rast_window_cols(); /* open the data files, input raster should be set-up already */ if ((infd = theState->fd_old) < 0) G_fatal_error(_("Unable to open raster map <%s>"), theState->inraster); if (theState->docover == TRUE) { if ((cinfd = theState->fd_cold) < 0) G_fatal_error(_("Unable to open raster map <%s>"), theState->inrcover); } if (theState->outraster != NULL) { if (theState->docover == TRUE) type = theState->cover.type; else type = theState->buf.type; outfd = Rast_open_new(theState->outraster, type); theState->fd_new = outfd; } if (theState->outvector) { if (Vect_open_new(&Out, theState->outvector, theState->z_geometry) < 0) G_fatal_error(_("Unable to create vector map <%s>"), theState->outvector); Vect_hist_command(&Out); fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); driver = db_start_driver_open_database(fi->driver, Vect_subst_var(fi->database, &Out)); if (!driver) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Vect_subst_var(fi->database, &Out), fi->driver); db_set_error_handler_driver(driver); Vect_map_add_dblink(&Out, 1, NULL, fi->table, GV_KEY_COLUMN, fi->database, fi->driver); if (theState->docover == TRUE) table = db_alloc_table(3); else table = db_alloc_table(2); db_set_table_name(table, fi->table); column = db_get_table_column(table, 0); db_set_column_name(column, GV_KEY_COLUMN); db_set_column_sqltype(column, DB_SQL_TYPE_INTEGER); column = db_get_table_column(table, 1); db_set_column_name(column, "value"); db_set_column_sqltype(column, DB_SQL_TYPE_DOUBLE_PRECISION); if (theState->docover == TRUE) { column = db_get_table_column(table, 2); db_set_column_name(column, "covervalue"); db_set_column_sqltype(column, DB_SQL_TYPE_DOUBLE_PRECISION); } if (db_create_table(driver, table) != DB_OK) G_warning(_("Cannot create new table")); db_begin_transaction(driver); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); db_init_string(&sql); } if (theState->outvector && theState->outraster) G_message(_("Writing raster map <%s> and vector map <%s> ..."), theState->outraster, theState->outvector); else if (theState->outraster) G_message(_("Writing raster map <%s> ..."), theState->outraster); else if (theState->outvector) G_message(_("Writing vector map <%s> ..."), theState->outvector); G_percent(0, theState->nRand, 2); init_rand(); nc = (theState->use_nulls) ? theState->nCells : theState->nCells - theState->nNulls; nt = theState->nRand; /* Number of points to generate */ cat = 1; /* Execute for loop for every row if nt>1 */ for (row = 0; row < nrows && nt; row++) { Rast_get_row(infd, theState->buf.data.v, row, theState->buf.type); if (theState->docover == TRUE) { Rast_get_row(cinfd, theState->cover.data.v, row, theState->cover.type); } for (col = 0; col < ncols && nt; col++) { do_check = 0; if (theState->use_nulls || !is_null_value(theState->buf, col)) do_check = 1; if (do_check && theState->docover == TRUE) { /* skip no data cover points */ if (!theState->use_nulls && is_null_value(theState->cover, col)) do_check = 0; } if (do_check && make_rand() % nc < nt) { nt--; if (is_null_value(theState->buf, col)) cpvalue(&theState->nulls, 0, &theState->buf, col); if (theState->docover == TRUE) { if (is_null_value(theState->cover, col)) cpvalue(&theState->cnulls, 0, &theState->cover, col); } if (theState->outvector) { double x, y, val, coverval; char buf[500]; Vect_reset_line(Points); Vect_reset_cats(Cats); x = window.west + (col + .5) * window.ew_res; y = window.north - (row + .5) * window.ns_res; val = cell_as_dbl(&theState->buf, col); if (theState->docover == 1) coverval = cell_as_dbl(&theState->cover, col); if (theState->z_geometry) Vect_append_point(Points, x, y, val); else Vect_append_point(Points, x, y, 0.0); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, GV_POINT, Points, Cats); if (theState->docover == 1) if (is_null_value(theState->cover, col)) sprintf(buf, "insert into %s values ( %d, %f, NULL )", fi->table, cat, val); else sprintf(buf, "insert into %s values ( %d, %f, %f )", fi->table, cat, val, coverval); else sprintf(buf, "insert into %s values ( %d, %f )", fi->table, cat, val); db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) G_fatal_error(_("Cannot insert new record: %s"), db_get_string(&sql)); cat++; } G_percent((theState->nRand - nt), theState->nRand, 2); } else { set_to_null(&theState->buf, col); if (theState->docover == 1) set_to_null(&theState->cover, col); } if (do_check) nc--; } while (col < ncols) { set_to_null(&theState->buf, col); if (theState->docover == 1) set_to_null(&theState->cover, col); col++; } if (theState->outraster) { if (theState->docover == 1) Rast_put_row(outfd, theState->cover.data.v, theState->cover.type); else Rast_put_row(outfd, theState->buf.data.v, theState->buf.type); } } /* Catch any remaining rows in the window */ if (theState->outraster && row < nrows) { for (col = 0; col < ncols; col++) { if (theState->docover == 1) set_to_null(&theState->cover, col); else set_to_null(&theState->buf, col); } for (; row < nrows; row++) { if (theState->docover == 1) Rast_put_row(outfd, theState->cover.data.v, theState->cover.type); else Rast_put_row(outfd, theState->buf.data.v, theState->buf.type); } } if (nt > 0) G_warning(_("Only [%ld] random points created"), theState->nRand - nt); /* close files */ Rast_close(infd); if (theState->docover == TRUE) Rast_close(cinfd); if (theState->outvector) { db_commit_transaction(driver); if (db_create_index2(driver, fi->table, GV_KEY_COLUMN) != DB_OK) G_warning(_("Unable to create index")); if (db_grant_on_table (driver, fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) { G_fatal_error(_("Unable to grant privileges on table <%s>"), fi->table); } db_close_database_shutdown_driver(driver); if (theState->notopol != 1) Vect_build(&Out); Vect_close(&Out); } if (theState->outraster) Rast_close(outfd); return 0; } /* execute_random() */
int main(int argc, char **argv) { double radius; double fisher, david, douglas, lloyd, lloydip, morisita; int i, nquads, *counts; struct Cell_head window; struct GModule *module; struct { struct Option *input, *field, *output, *n, *r; } parm; struct { struct Flag *g; } flag; COOR *quads; struct Map_info Map; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("statistics")); G_add_keyword(_("point pattern")); module->description = _("Indices for quadrat counts of vector point lists."); parm.input = G_define_standard_option(G_OPT_V_INPUT); parm.field = G_define_standard_option(G_OPT_V_FIELD_ALL); parm.output = G_define_standard_option(G_OPT_V_OUTPUT); parm.output->required = NO; parm.output->description = _("Name for output quadrat centers map (number of points is written as category)"); parm.n = G_define_option(); parm.n->key = "nquadrats"; parm.n->type = TYPE_INTEGER; parm.n->required = YES; parm.n->description = _("Number of quadrats"); parm.r = G_define_option(); parm.r->key = "radius"; parm.r->type = TYPE_DOUBLE; parm.r->required = YES; parm.r->description = _("Quadrat radius"); flag.g = G_define_flag(); flag.g->key = 'g'; flag.g->description = _("Print results in shell script style"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); sscanf(parm.n->answer, "%d", &nquads); sscanf(parm.r->answer, "%lf", &radius); G_get_window(&window); /* Open input */ Vect_set_open_level(2); if (Vect_open_old2(&Map, parm.input->answer, "", parm.field->answer) < 0) G_fatal_error(_("Unable to open vector map <%s>"), parm.input->answer); /* Get the quadrats */ G_message(_("Finding quadrats...")); quads = find_quadrats(nquads, radius, window); /* Get the counts per quadrat */ G_message(_("Counting points quadrats...")); counts = (int *)G_malloc(nquads * (sizeof(int))); count_sites(quads, nquads, counts, radius, &Map, Vect_get_field_number(&Map, parm.field->answer)); Vect_close(&Map); /* output if requested */ if (parm.output->answer) { struct Map_info Out; struct line_pnts *Points; struct line_cats *Cats; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); if (Vect_open_new(&Out, parm.output->answer, 0) < 0) G_fatal_error(_("Unable to create vector map <%s>"), parm.output->answer); Vect_hist_command(&Out); for (i = 0; i < nquads; i++) { Vect_reset_line(Points); Vect_reset_cats(Cats); Vect_append_point(Points, quads[i].x, quads[i].y, 0.0); Vect_cat_set(Cats, 1, counts[i]); Vect_write_line(&Out, GV_POINT, Points, Cats); } Vect_build(&Out); Vect_close(&Out); } /* Indices if requested */ qindices(counts, nquads, &fisher, &david, &douglas, &lloyd, &lloydip, &morisita); if (!flag.g->answer) { fprintf(stdout, "-----------------------------------------------------------\n"); fprintf(stdout, "Index Realization\n"); fprintf(stdout, "-----------------------------------------------------------\n"); fprintf(stdout, "Fisher el al (1922) Relative Variance %g\n", fisher); fprintf(stdout, "David & Moore (1954) Index of Cluster Size %g\n", david); fprintf(stdout, "Douglas (1975) Index of Cluster Frequency %g\n", douglas); fprintf(stdout, "Lloyd (1967) \"mean crowding\" %g\n", lloyd); fprintf(stdout, "Lloyd (1967) Index of patchiness %g\n", lloydip); fprintf(stdout, "Morisita's (1959) I (variability b/n patches) %g\n", morisita); fprintf(stdout, "-----------------------------------------------------------\n"); } else { fprintf(stdout, "fisher=%g\n", fisher); fprintf(stdout, "david=%g\n", david); fprintf(stdout, "douglas=%g\n", douglas); fprintf(stdout, "lloyd=%g\n", lloyd); fprintf(stdout, "lloydip=%g\n", lloydip); fprintf(stdout, "morisita=%g\n", morisita); } exit(EXIT_SUCCESS); }
/*----------------------------------------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { /* Declarations */ int dim_vect, nparameters, BW, npoints; int nsply, nsplx, nsplx_adj, nsply_adj; int nsubregion_col, nsubregion_row; int subregion = 0, nsubregions = 0; const char *dvr, *db, *mapset; char table_name[GNAME_MAX]; char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; double lambda, mean, stepN, stepE, HighThresh, LowThresh; double N_extension, E_extension, edgeE, edgeN; int i, nterrain, count_terrain; int last_row, last_column, flag_auxiliar = FALSE; int *lineVect; double *TN, *Q, *parVect; /* Interpolating and least-square vectors */ double **N, **obsVect, **obsVect_all; /* Interpolation and least-square matrix */ struct Map_info In, Out, Terrain; struct Option *in_opt, *out_opt, *out_terrain_opt, *stepE_opt, *stepN_opt, *lambda_f_opt, *Thresh_A_opt, *Thresh_B_opt; struct Flag *spline_step_flag; struct GModule *module; struct Cell_head elaboration_reg, original_reg; struct Reg_dimens dims; struct bound_box general_box, overlap_box; struct Point *observ; struct lidar_cat *lcat; dbDriver *driver; /*----------------------------------------------------------------------------------------------------------*/ /* Options' declaration */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("LIDAR")); module->description = _("Corrects the v.lidar.growing output. It is the last of the three algorithms for LIDAR filtering."); spline_step_flag = G_define_flag(); spline_step_flag->key = 'e'; spline_step_flag->label = _("Estimate point density and distance"); spline_step_flag->description = _("Estimate point density and distance for the input vector points within the current region extends and quit"); in_opt = G_define_standard_option(G_OPT_V_INPUT); in_opt->description = _("Input observation vector map name (v.lidar.growing output)"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->description = _("Output classified vector map name"); out_terrain_opt = G_define_option(); out_terrain_opt->key = "terrain"; out_terrain_opt->type = TYPE_STRING; out_terrain_opt->key_desc = "name"; out_terrain_opt->required = YES; out_terrain_opt->gisprompt = "new,vector,vector"; out_terrain_opt->description = _("Only 'terrain' points output vector map"); stepE_opt = G_define_option(); stepE_opt->key = "ew_step"; stepE_opt->type = TYPE_DOUBLE; stepE_opt->required = NO; stepE_opt->answer = "25"; 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 = "25"; 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_c"; lambda_f_opt->type = TYPE_DOUBLE; lambda_f_opt->required = NO; lambda_f_opt->description = _("Regularization weight in reclassification evaluation"); lambda_f_opt->answer = "1"; Thresh_A_opt = G_define_option(); Thresh_A_opt->key = "tch"; Thresh_A_opt->type = TYPE_DOUBLE; Thresh_A_opt->required = NO; Thresh_A_opt->description = _("High threshold for object to terrain reclassification"); Thresh_A_opt->answer = "2"; Thresh_B_opt = G_define_option(); Thresh_B_opt->key = "tcl"; Thresh_B_opt->type = TYPE_DOUBLE; Thresh_B_opt->required = NO; Thresh_B_opt->description = _("Low threshold for terrain to object reclassification"); Thresh_B_opt->answer = "1"; /* Parsing */ G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); stepN = atof(stepN_opt->answer); stepE = atof(stepE_opt->answer); lambda = atof(lambda_f_opt->answer); HighThresh = atof(Thresh_A_opt->answer); LowThresh = atof(Thresh_B_opt->answer); 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")); /* Setting auxiliar table's name */ 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.lidar.correction 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 auxiliar table could not be dropped")); db_close_database_shutdown_driver(driver); } /* Checking vector names */ Vect_check_input_output_name(in_opt->answer, out_opt->answer, G_FATAL_EXIT); /* Open input vector */ if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL) G_fatal_error(_("Vector map <%s> not found"), in_opt->answer); Vect_set_open_level(1); /* without topology */ if (1 > Vect_open_old(&In, in_opt->answer, mapset)) G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer); /* Input vector must be 3D */ if (!Vect_is_3d(&In)) G_fatal_error(_("Input vector map <%s> is not 3D!"), in_opt->answer); /* Estimate point density and mean distance for current region */ if (spline_step_flag->answer) { double dens, dist; if (P_estimate_splinestep(&In, &dens, &dist) == 0) { G_message("Estimated point density: %.4g", dens); G_message("Estimated mean distance between points: %.4g", dist); } else G_warning(_("No points in current region!")); Vect_close(&In); exit(EXIT_SUCCESS); } /* Open output vector */ if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z)) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); } if (0 > Vect_open_new(&Terrain, out_terrain_opt->answer, WITH_Z)) { Vect_close(&In); Vect_close(&Out); 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, &Terrain); Vect_hist_copy(&In, &Terrain); Vect_hist_command(&Terrain); /* Start driver and open db */ driver = db_start_driver_open_database(dvr, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."), dvr); db_set_error_handler_driver(driver); /* Create auxiliar table */ if ((flag_auxiliar = P_Create_Aux2_Table(driver, table_name)) == FALSE) { Vect_close(&In); Vect_close(&Out); Vect_close(&Terrain); exit(EXIT_FAILURE); } 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 overlaped by its neighbouring subregions. | The overlapping is calculated as a fixed OVERLAP_SIZE times | the largest spline step plus 2 * edge ----------------------------------------------------------------*/ /* Fixing parameters of the elaboration region */ P_zero_dim(&dims); nsplx_adj = NSPLX_MAX; nsply_adj = NSPLY_MAX; if (stepN > stepE) dims.overlap = OVERLAP_SIZE * stepN; else dims.overlap = OVERLAP_SIZE * stepE; P_get_edge(P_BILINEAR, &dims, stepE, stepN); P_set_dim(&dims, stepE, stepN, &nsplx_adj, &nsply_adj); G_verbose_message(n_("adjusted EW spline %d", "adjusted EW splines %d", nsplx_adj), nsplx_adj); G_verbose_message(n_("adjusted NS spline %d", "adjusted NS splines %d", nsply_adj), nsply_adj); /* calculate number of subregions */ edgeE = dims.ew_size - dims.overlap - 2 * dims.edge_v; edgeN = dims.sn_size - dims.overlap - 2 * dims.edge_h; N_extension = original_reg.north - original_reg.south; E_extension = original_reg.east - original_reg.west; nsubregion_col = ceil(E_extension / edgeE) + 0.5; nsubregion_row = ceil(N_extension / edgeN) + 0.5; if (nsubregion_col < 0) nsubregion_col = 0; if (nsubregion_row < 0) nsubregion_row = 0; nsubregions = nsubregion_row * nsubregion_col; elaboration_reg.south = original_reg.north; last_row = FALSE; while (last_row == FALSE) { /* For each row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, GENERAL_ROW); if (elaboration_reg.north > original_reg.north) { /* First row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, FIRST_ROW); } if (elaboration_reg.south <= original_reg.south) { /* Last row */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, LAST_ROW); last_row = TRUE; } nsply = ceil((elaboration_reg.north - elaboration_reg.south) / stepN) + 0.5; /* if (nsply > NSPLY_MAX) { nsply = NSPLY_MAX; } */ G_debug(1, _("nsply = %d"), nsply); elaboration_reg.east = original_reg.west; last_column = FALSE; while (last_column == FALSE) { /* For each column */ subregion++; if (nsubregions > 1) G_message(_("subregion %d of %d"), subregion, nsubregions); P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, GENERAL_COLUMN); if (elaboration_reg.west < original_reg.west) { /* First column */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, FIRST_COLUMN); } if (elaboration_reg.east >= original_reg.east) { /* Last column */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, LAST_COLUMN); last_column = TRUE; } nsplx = ceil((elaboration_reg.east - elaboration_reg.west) / stepE) + 0.5; /* if (nsplx > NSPLX_MAX) { nsplx = NSPLX_MAX; } */ G_debug(1, _("nsplx = %d"), nsplx); dim_vect = nsplx * nsply; G_debug(1, _("read vector region map")); observ = P_Read_Vector_Correction(&In, &elaboration_reg, &npoints, &nterrain, dim_vect, &lcat); G_debug(5, _("npoints = %d, nterrain = %d"), npoints, nterrain); if (npoints > 0) { /* If there is any point falling into elaboration_reg. */ count_terrain = 0; nparameters = nsplx * nsply; /* Mean calculation */ G_debug(3, _("Mean calculation")); mean = P_Mean_Calc(&elaboration_reg, observ, npoints); /*Least Squares system */ 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); /* Bilinear parameters vector */ obsVect = G_alloc_matrix(nterrain + 1, 3); /* Observation vector with terrain points */ obsVect_all = G_alloc_matrix(npoints + 1, 3); /* Observation vector with all points */ Q = G_alloc_vector(nterrain + 1); /* "a priori" var-cov matrix */ lineVect = G_alloc_ivector(npoints + 1); /* Setting obsVect vector & Q matrix */ G_debug(3, _("Only TERRAIN points")); for (i = 0; i < npoints; i++) { if (observ[i].cat == TERRAIN_SINGLE) { obsVect[count_terrain][0] = observ[i].coordX; obsVect[count_terrain][1] = observ[i].coordY; obsVect[count_terrain][2] = observ[i].coordZ - mean; Q[count_terrain] = 1; /* Q=I */ count_terrain++; } lineVect[i] = observ[i].lineID; obsVect_all[i][0] = observ[i].coordX; obsVect_all[i][1] = observ[i].coordY; obsVect_all[i][2] = observ[i].coordZ - mean; } G_free(observ); G_verbose_message(_("Bilinear interpolation")); normalDefBilin(N, TN, Q, obsVect, stepE, stepN, nsplx, nsply, elaboration_reg.west, elaboration_reg.south, nterrain, 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_free_matrix(obsVect); G_verbose_message( _("Correction and creation of terrain vector")); P_Sparse_Correction(&In, &Out, &Terrain, &elaboration_reg, general_box, overlap_box, obsVect_all, lcat, parVect, lineVect, stepN, stepE, dims.overlap, HighThresh, LowThresh, nsplx, nsply, npoints, driver, mean, table_name); G_free_vector(parVect); G_free_matrix(obsVect_all); G_free_ivector(lineVect); } else { G_free(observ); G_warning(_("No data within this subregion. " "Consider changing the spline step.")); } G_free(lcat); } /*! END WHILE; last_column = TRUE */ } /*! END WHILE; last_row = TRUE */ /* Dropping auxiliar table */ if (npoints > 0) { G_debug(1, _("Dropping <%s>"), table_name); if (P_Drop_Aux_Table(driver, table_name) != DB_OK) G_fatal_error(_("Auxiliar table could not be dropped")); } db_close_database_shutdown_driver(driver); Vect_close(&In); Vect_close(&Out); Vect_close(&Terrain); G_done_msg(" "); exit(EXIT_SUCCESS); } /*! END MAIN */
int main(int argc, char *argv[]) { struct GModule *module; struct GParams params; struct Map_info Map; struct Map_info **BgMap; /* backgroud 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(_("editing")); G_add_keyword(_("geometry")); 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; overwrite = G_check_overwrite(argc, argv); if (G_find_vector2(params.map->answer, G_mapset())) { if (!overwrite) G_fatal_error(_("Vector map <%s> already exists"), params.map->answer); } /* 3D vector maps? */ ret = Vect_open_new(&Map, params.map->answer, WITHOUT_Z); if (Vect_maptype(&Map) == GV_FORMAT_OGR_DIRECT) { int type; type = Vect_option_to_types(params.type); if (type != GV_POINT && type != GV_LINE && type != GV_BOUNDARY) G_fatal_error(_("Supported feature type for OGR layer: " "%s, %s or %s"), "point", "line", "boundary"); V2_open_new_ogr(&Map, type); } if (ret == -1) { 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> at topological level %d"), params.map->answer, 2); } G_debug(1, "Map opened"); /* open backgroud 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); Vect_open_update2(&Map, params.map->answer, G_mapset(), params.fld->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); G_message(_("%d features added"), ret); if (ret > 0) { int iline; struct ilist *List_added; 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(_("%d boundaries closed"), nclosed); } Vect_destroy_list(List_added); } break; case MODE_DEL: ret = Vedit_delete_lines(&Map, List); G_message(_("%d features deleted"), 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(_("%d features moved"), 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(_("%d vertices moved"), ret); break; case MODE_VERTEX_ADD: ret = Vedit_add_vertex(&Map, List, coord, thresh[THRESH_COORDS]); G_message(_("%d vertices added"), ret); break; case MODE_VERTEX_DELETE: ret = Vedit_remove_vertex(&Map, List, coord, thresh[THRESH_COORDS]); G_message(_("%d vertices removed"), 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(_("%d lines broken"), 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(_("%d lines connected"), ret); break; case MODE_MERGE: ret = Vedit_merge_lines(&Map, List); G_message(_("%d lines merged"), ret); break; case MODE_SELECT: ret = print_selected(List); break; case MODE_CATADD: ret = Vedit_modify_cats(&Map, List, layer, 0, Clist); G_message(_("%d features modified"), ret); break; case MODE_CATDEL: ret = Vedit_modify_cats(&Map, List, layer, 1, Clist); G_message(_("%d features modified"), 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(_("%d features copied"), 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(_("%d lines flipped"), 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(_("%d lines labeled"), ret); break; } case MODE_CHTYPE:{ ret = Vedit_chtype_lines(&Map, List); if (ret > 0) { G_message(_("%d features converted"), ret); } else { G_message(_("No feature modified")); } 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 || params.topo->answer == 1 || !MODE_NONE)) { 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[]) { /* 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")); 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"); in_opt = G_define_standard_option(G_OPT_V_INPUT); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); outlier_opt = G_define_option(); outlier_opt->key = "outlier"; outlier_opt->type = TYPE_STRING; outlier_opt->key_desc = "name"; outlier_opt->required = YES; outlier_opt->gisprompt = "new,vector,vector"; outlier_opt->description = _("Name of output outlier vector map"); qgis_opt = G_define_option(); qgis_opt->key = "qgis"; qgis_opt->type = TYPE_STRING; qgis_opt->key_desc = "name"; qgis_opt->required = NO; qgis_opt->gisprompt = "new,vector,vector"; qgis_opt->description = _("Name of 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"; /* Parsing */ G_gisinit(argv[0]); 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 */ 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 auxiliar table's name */ 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 auxiliar 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 auxiliar 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 overlaped by its neighbouring subregions. | The overlapping is calculated as a fixed OVERLAP_SIZE times | the largest spline step plus 2 * edge ----------------------------------------------------------------*/ /* Fixing parameters of the elaboration region */ P_zero_dim(&dims); /* 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 auxiliar 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 type, cat; struct Option *out_opt, *type_opt, *cat_opt; struct GModule *module; struct Map_info Out; struct Cell_head window; struct line_cats *Cats; struct line_pnts *Points; double diff_long, mid_long; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); module->description = _("Create a new vector from the current region."); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->multiple = NO; type_opt->options = "line,area"; type_opt->answer = "area"; type_opt->description = _("Select type: line or area"); cat_opt = G_define_standard_option(G_OPT_V_CAT); cat_opt->answer = "1"; 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); cat = atoi(cat_opt->answer); G_get_window(&window); diff_long = window.east - window.west; mid_long = (window.west + window.east) / 2; /* Open output segments */ Vect_open_new(&Out, out_opt->answer, 0); Vect_hist_command(&Out); /* Rectangle */ Vect_append_point(Points, window.west, window.south, 0.0); if (window.proj == PROJECTION_LL && diff_long >= 179) Vect_append_point(Points, mid_long, window.south, 0.0); Vect_append_point(Points, window.east, window.south, 0.0); Vect_append_point(Points, window.east, window.north, 0.0); if (window.proj == PROJECTION_LL && diff_long >= 179) Vect_append_point(Points, mid_long, window.north, 0.0); Vect_append_point(Points, window.west, window.north, 0.0); Vect_append_point(Points, window.west, window.south, 0.0); if (type == GV_AREA) { Vect_write_line(&Out, GV_BOUNDARY, Points, Cats); Vect_reset_line(Points); Vect_append_point(Points, (window.west + window.east) / 2, (window.south + window.north) / 2, 0.0); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, GV_CENTROID, Points, Cats); } else { /* GV_LINE */ Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, GV_LINE, Points, Cats); } Vect_build(&Out); Vect_close(&Out); exit(EXIT_SUCCESS); }
/* Create GRASS vector output map. Create attribute table. Calculate geometries and write them into the output map. Calculate attributes and write them into the output map's attribute table. */ void writeMap() { int i, j; double xlength, ylength, zlength; double length, flatLength, bailLength; double xoffset, yoffset, zoffset; double xys[12]; int ratio; double zRatio; /* attributes to be written to output map */ int boneID; int skelID; int unitID; int oldID; int cat; char *organization; char buf[MAXSTR]; if ( numPoints < 2 ) { G_fatal_error ("Less than two valid measurement points in input file"); } G_message (_("Constructing geometries for %i valid points:"), numPoints ); /* CREATE OUTPUT VECTOR MAP */ if (Vect_legal_filename(output->answer) < 0) { G_fatal_error(_("Use '%s' option to change vector map name"), output->key); } Map = (struct Map_info *) G_malloc (sizeof ( struct Map_info ) ); if (Vect_open_new(Map, output->answer, WITH_Z) < 0) { G_fatal_error(_("Unable to create vector map <%s>"), output->answer); } Vect_set_map_name(Map, output->answer); Vect_hist_command(Map); if ((organization = getenv("GRASS_ORGANIZATION"))) { Vect_set_organization(Map, organization); } else { Vect_set_organization(Map, "UNKNOWN ORGANIZATION"); } Vect_set_date(Map, G_date()); Vect_set_person(Map, G_whoami()); Vect_set_map_date(Map, ""); Vect_set_scale(Map, 2400); Vect_set_comment(Map, ""); Vect_set_zone(Map, 0); Vect_set_thresh(Map, 0.0); /* START DBMS INTERFACE */ /* prepare strings for use in db_* calls */ db_init_string(&sql); /* start default database driver */ Fi = Vect_default_field_info(Map, 1, NULL, GV_1TABLE); driver = db_start_driver_open_database(Fi->driver,Vect_subst_var(Fi->database, Map)); if (driver == NULL) { Vect_delete(output->answer); G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Vect_subst_var(Fi->database, Map), Fi->driver); } /* create attribute table */ db_begin_transaction ( driver ); sprintf(buf, "create table %s (cat integer, skel_id integer, bone_id integer, unit_id integer, GRASSRGB varchar(11),BONERGB varchar(11));", Fi->table); if ( DEBUG ) { fprintf ( stderr, "Creating attribute table: %s\n", buf ); } db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) { Vect_delete(output->answer); G_fatal_error(_("Unable to create attribute table: %s"), db_get_string(&sql)); } if (db_grant_on_table (driver, output->answer, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) { Vect_delete(output->answer); G_fatal_error(_("Unable to grant privileges on table <%s>"), output->answer); } if (db_create_index2(driver, output->answer, "cat") != DB_OK) { G_warning(_("Unable to create index for table <%s>, key <%s>"), output->answer, "cat"); } /* link vector map to attribute table */ if (Vect_map_add_dblink(Map, 1, NULL, Fi->table, "cat", Fi->database, Fi->driver) ) { Vect_delete(output->answer); G_fatal_error(_("Unable to add database link for vector map <%s>"), Vect_get_full_name(Map)); } /* PROCESS POINTS AND WRITE GEOMETRIES */ /* Now process point measurements and write geometries into output vector map. */ /* At this stage, the global points array has an even number of valid points. */ oldID = pointTable[0].SKEL_ID; unitID = 1; cat = 0; for ( i = 0; i < numPoints; i = i + 2 ) { /* This boneID is a generalized ID that does not differentiate between start and end measurement. */ boneID = (int) pointTable[i+1].BONE_ID / 2; skelID = pointTable[i+1].SKEL_ID; /* get coordinates for top and bottom of bone */ ax = pointTable[i].X; ay = pointTable[i].Y; az = pointTable[i].Z; bx = pointTable[i+1].X; by = pointTable[i+1].Y; bz = pointTable[i+1].Z; /* get vector lengths */ xlength = fabs (ax - bx); ylength = fabs (ay - by); zlength = fabs (az - bz); /* get real length */ length = sqrt ( (xlength*xlength) + (ylength*ylength) + (zlength*zlength) ); /* get length in x/y plane */ flatLength = sqrt ( (xlength*xlength) + (ylength*ylength) ); /* determine ratio for triangles, depending on bone type */ ratio = 12; /* default */ for ( j = 0; j < NUM_RATIOS; j ++ ) { if ( boneID == RATIO_ID[j] ) { ratio = RATIO_VAL[j]; } } /* get bail length */ bailLength = (double) ( length / (double) ratio); /* calculate bail offsets from top point (one bail is mirror of the other) */ xoffset = (bailLength * ylength) / flatLength; yoffset = ( (bailLength * xlength) / flatLength ) * (-1); zoffset = 0; xys[0]= ax + xoffset; xys[1]= ay + yoffset; xys[2]= az + zoffset; xys[6]= ax - xoffset; xys[7]= ay - yoffset; xys[8]= az - zoffset; /* get 3rd axis offsets */ zRatio = (zlength/ratio) / flatLength; xoffset = xlength * zRatio; yoffset = ylength * zRatio; zoffset = (flatLength/ratio) * (-1); xys[3]= ax + xoffset; xys[4]= ay + yoffset; xys[5]= az + zoffset; xys[9]= ax - xoffset; xys[10]= ay - yoffset; xys[11]= az - zoffset; /* Increase unit ID by "1", if we have another skeleton ID */ if ( oldID != pointTable[i+1].SKEL_ID ) { unitID ++; oldID = pointTable[i+1].SKEL_ID; /* switch to next colour for next geometry */ RGBNUM ++; if ( RGBNUM == RGBMAX ) { RGBNUM = 0; } } /* write geometries */ if ( MODE == MODE_DARTS ) { writeTriangle ( cat, skelID, boneID, unitID, xys, 0, 6 ); cat ++; writeTriangle ( cat, skelID, boneID, unitID, xys, 3, 9 ); cat ++; } if ( MODE == MODE_LINES ) { writeLine ( cat, skelID, boneID, unitID ); cat ++; } if ( MODE == MODE_PLANES_H ) { writeTriangle ( cat, skelID, boneID, unitID, xys, 0, 6 ); cat ++; } if ( MODE == MODE_PLANES_V ) { writeTriangle ( cat, skelID, boneID, unitID, xys, 3, 9 ); cat ++; } if ( MODE == MODE_POINTS ) { writePoints ( cat, skelID, boneID, unitID ); cat = cat + 2; } if ( MODE == MODE_PYRAMIDS ) { writeTriangle ( cat, skelID, boneID, unitID, xys, 0, 3 ); cat ++; writeTriangle ( cat, skelID, boneID, unitID, xys, 3, 6 ); cat ++; writeTriangle ( cat, skelID, boneID, unitID, xys, 6, 9 ); cat ++; writeTriangle ( cat, skelID, boneID, unitID, xys, 9, 0 ); cat ++; writeSquare ( cat, skelID, boneID, unitID, xys ); cat ++; } /* switch to next colour for bone colouring */ RGBNUM_BONE ++; if ( RGBNUM_BONE == RGBMAX ) { RGBNUM_BONE = 0; } G_percent ( i, numPoints - 2, 1 ); } fprintf ( stdout, "\n" ); /* commit DBMS actions */ db_commit_transaction(driver); db_close_database_shutdown_driver(driver); if (!Vect_build(Map)) { G_warning("Building topology failed"); } Vect_close(Map); db_free_string(&sql); }
int main(int argc, char **argv) { 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); }
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[]) { /* Variable declarations */ int nsply, nsplx, nrows, ncols, nsplx_adj, nsply_adj; int nsubregion_col, nsubregion_row, subregion_row, subregion_col; int subregion = 0, nsubregions = 0; int last_row, last_column, grid, bilin, ext, flag_auxiliar, cross; /* booleans */ double stepN, stepE, lambda, mean; double N_extension, E_extension, edgeE, edgeN; const char *mapset, *drv, *db, *vector, *map; char table_name[GNAME_MAX], title[64]; char xname[GNAME_MAX], xmapset[GMAPSET_MAX]; int dim_vect, nparameters, BW; int *lineVect; /* Vector restoring primitive's ID */ double *TN, *Q, *parVect; /* Interpolating and least-square vectors */ double **N, **obsVect; /* Interpolation and least-square matrix */ SEGMENT out_seg, mask_seg; const char *out_file, *mask_file; int out_fd, mask_fd; double seg_size; int seg_mb, segments_in_memory; int have_mask; /* Structs declarations */ int raster; struct Map_info In, In_ext, Out; struct History history; struct GModule *module; struct Option *in_opt, *in_ext_opt, *out_opt, *out_map_opt, *stepE_opt, *stepN_opt, *lambda_f_opt, *type_opt, *dfield_opt, *col_opt, *mask_opt, *memory_opt, *solver, *error, *iter; struct Flag *cross_corr_flag, *spline_step_flag; struct Reg_dimens dims; struct Cell_head elaboration_reg, original_reg; struct bound_box general_box, overlap_box, original_box; struct Point *observ; struct line_cats *Cats; dbCatValArray cvarr; int with_z; int nrec, ctype = 0; struct field_info *Fi; dbDriver *driver, *driver_cats; /*----------------------------------------------------------------*/ /* Options declarations */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("surface")); G_add_keyword(_("interpolation")); G_add_keyword(_("LIDAR")); module->description = _("Performs bicubic or bilinear spline interpolation with Tykhonov regularization."); cross_corr_flag = G_define_flag(); cross_corr_flag->key = 'c'; cross_corr_flag->description = _("Find the best Tykhonov regularizing parameter using a \"leave-one-out\" cross validation method"); spline_step_flag = G_define_flag(); spline_step_flag->key = 'e'; spline_step_flag->label = _("Estimate point density and distance"); spline_step_flag->description = _("Estimate point density and distance for the input vector points within the current region extends and quit"); in_opt = G_define_standard_option(G_OPT_V_INPUT); in_opt->label = _("Name of input vector point map"); dfield_opt = G_define_standard_option(G_OPT_V_FIELD); dfield_opt->guisection = _("Settings"); col_opt = G_define_standard_option(G_OPT_DB_COLUMN); col_opt->required = NO; col_opt->label = _("Name of the attribute column with values to be used for approximation"); col_opt->description = _("If not given and input is 3D vector map then z-coordinates are used."); col_opt->guisection = _("Settings"); in_ext_opt = G_define_standard_option(G_OPT_V_INPUT); in_ext_opt->key = "sparse_input"; in_ext_opt->required = NO; in_ext_opt->label = _("Name of input vector map with sparse points"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->required = NO; out_opt->guisection = _("Outputs"); out_map_opt = G_define_standard_option(G_OPT_R_OUTPUT); out_map_opt->key = "raster_output"; out_map_opt->required = NO; out_map_opt->guisection = _("Outputs"); mask_opt = G_define_standard_option(G_OPT_R_INPUT); mask_opt->key = "mask"; mask_opt->label = _("Raster map to use for masking (applies to raster output only)"); mask_opt->description = _("Only cells that are not NULL and not zero are interpolated"); mask_opt->required = NO; stepE_opt = G_define_option(); stepE_opt->key = "ew_step"; stepE_opt->type = TYPE_DOUBLE; stepE_opt->required = NO; stepE_opt->answer = "4"; 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 = "4"; stepN_opt->description = _("Length of each spline step in the north-south direction"); stepN_opt->guisection = _("Settings"); type_opt = G_define_option(); type_opt->key = "method"; type_opt->description = _("Spline interpolation algorithm"); type_opt->type = TYPE_STRING; type_opt->options = "bilinear,bicubic"; type_opt->answer = "bilinear"; type_opt->guisection = _("Settings"); G_asprintf((char **) &(type_opt->descriptions), "bilinear;%s;bicubic;%s", _("Bilinear interpolation"), _("Bicubic interpolation")); lambda_f_opt = G_define_option(); lambda_f_opt->key = "lambda_i"; lambda_f_opt->type = TYPE_DOUBLE; lambda_f_opt->required = NO; lambda_f_opt->description = _("Tykhonov regularization parameter (affects smoothing)"); lambda_f_opt->answer = "0.01"; lambda_f_opt->guisection = _("Settings"); solver = N_define_standard_option(N_OPT_SOLVER_SYMM); solver->options = "cholesky,cg"; solver->answer = "cholesky"; iter = N_define_standard_option(N_OPT_MAX_ITERATIONS); error = N_define_standard_option(N_OPT_ITERATION_ERROR); memory_opt = G_define_option(); memory_opt->key = "memory"; memory_opt->type = TYPE_INTEGER; memory_opt->required = NO; memory_opt->answer = "300"; memory_opt->label = _("Maximum memory to be used (in MB)"); memory_opt->description = _("Cache size for raster rows"); /*----------------------------------------------------------------*/ /* Parsing */ G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); vector = out_opt->answer; map = out_map_opt->answer; if (vector && map) G_fatal_error(_("Choose either vector or raster output, not both")); if (!vector && !map && !cross_corr_flag->answer) G_fatal_error(_("No raster or vector or cross-validation output")); if (!strcmp(type_opt->answer, "linear")) bilin = P_BILINEAR; else bilin = P_BICUBIC; stepN = atof(stepN_opt->answer); stepE = atof(stepE_opt->answer); lambda = atof(lambda_f_opt->answer); flag_auxiliar = FALSE; drv = db_get_default_driver_name(); if (!drv) { if (db_set_default_connection() != DB_OK) G_fatal_error(_("Unable to set default DB connection")); drv = db_get_default_driver_name(); } db = db_get_default_database_name(); if (!db) G_fatal_error(_("No default DB defined")); /* Set auxiliary table's name */ if (vector) { 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.surf.bspline execution */ if (db_table_exists(drv, db, table_name)) { /* Start driver and open db */ driver = db_start_driver_open_database(drv, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."), drv); 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 */ if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL) G_fatal_error(_("Vector map <%s> not found"), in_opt->answer); Vect_set_open_level(1); /* 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); bspline_field = 0; /* assume 3D input */ bspline_column = col_opt->answer; with_z = !bspline_column && Vect_is_3d(&In); if (Vect_is_3d(&In)) { 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 (!bspline_column) G_fatal_error(_("Input vector map is 2D. Parameter <%s> required."), col_opt->key); } if (!with_z) { bspline_field = Vect_get_field_number(&In, dfield_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) { fprintf(stdout, _("Estimated point density: %.4g"), dens); fprintf(stdout, _("Estimated mean distance between points: %.4g"), dist); } else { fprintf(stdout, _("No points in current region")); } Vect_close(&In); exit(EXIT_SUCCESS); } /*----------------------------------------------------------------*/ /* Cross-correlation begins */ if (cross_corr_flag->answer) { G_debug(1, "CrossCorrelation()"); cross = cross_correlation(&In, stepE, stepN); if (cross != TRUE) G_fatal_error(_("Cross validation didn't finish correctly")); else { G_debug(1, "Cross validation finished correctly"); Vect_close(&In); G_done_msg(_("Cross validation finished for ew_step = %f and ns_step = %f"), stepE, stepN); exit(EXIT_SUCCESS); } } /* Open input ext vector */ ext = FALSE; if (in_ext_opt->answer) { ext = TRUE; G_message(_("Vector map <%s> of sparse points will be interpolated"), in_ext_opt->answer); if ((mapset = G_find_vector2(in_ext_opt->answer, "")) == NULL) G_fatal_error(_("Vector map <%s> not found"), in_ext_opt->answer); Vect_set_open_level(1); /* WITHOUT TOPOLOGY */ if (1 > Vect_open_old(&In_ext, in_ext_opt->answer, mapset)) G_fatal_error(_("Unable to open vector map <%s> at the topological level"), in_opt->answer); } /* Open output map */ /* vector output */ if (vector && !map) { if (strcmp(drv, "dbf") == 0) G_fatal_error(_("Sorry, the <%s> driver is not compatible with " "the vector output of this module. " "Try with raster output or another driver."), drv); Vect_check_input_output_name(in_opt->answer, out_opt->answer, G_FATAL_EXIT); grid = FALSE; if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z)) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); /* Copy vector Head File */ if (ext == FALSE) { Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); } else { Vect_copy_head_data(&In_ext, &Out); Vect_hist_copy(&In_ext, &Out); } Vect_hist_command(&Out); G_verbose_message(_("Points in input vector map <%s> will be interpolated"), vector); } /* read z values from attribute table */ if (bspline_field > 0) { G_message(_("Reading values from attribute table...")); db_CatValArray_init(&cvarr); Fi = Vect_get_field(&In, bspline_field); if (Fi == NULL) G_fatal_error(_("Cannot read layer info")); driver_cats = db_start_driver_open_database(Fi->driver, Fi->database); /*G_debug (0, _("driver=%s db=%s"), Fi->driver, Fi->database); */ if (driver_cats == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); db_set_error_handler_driver(driver_cats); nrec = db_select_CatValArray(driver_cats, Fi->table, Fi->key, col_opt->answer, NULL, &cvarr); G_debug(3, "nrec = %d", nrec); ctype = cvarr.ctype; if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE) G_fatal_error(_("Column type not supported")); if (nrec < 0) G_fatal_error(_("Unable to select data from table")); G_verbose_message(_("%d records selected from table"), nrec); db_close_database_shutdown_driver(driver_cats); } /*----------------------------------------------------------------*/ /* Interpolation begins */ G_debug(1, "Interpolation()"); /* Open driver and database */ driver = db_start_driver_open_database(drv, db); if (driver == NULL) G_fatal_error(_("No database connection for driver <%s> is defined. " "Run db.connect."), drv); db_set_error_handler_driver(driver); /* Create auxiliary table */ if (vector) { if ((flag_auxiliar = P_Create_Aux4_Table(driver, table_name)) == FALSE) { P_Drop_Aux_Table(driver, table_name); G_fatal_error(_("Interpolation: Creating table: " "It was impossible to create table <%s>."), table_name); } /* db_create_index2(driver, table_name, "ID"); */ /* sqlite likes that ??? */ db_close_database_shutdown_driver(driver); driver = db_start_driver_open_database(drv, db); } /* raster output */ raster = -1; Rast_set_fp_type(DCELL_TYPE); if (!vector && map) { grid = TRUE; raster = Rast_open_fp_new(out_map_opt->answer); G_verbose_message(_("Cells for raster map <%s> will be interpolated"), map); } /* Setting regions and boxes */ G_debug(1, "Interpolation: Setting regions and boxes"); G_get_window(&original_reg); G_get_window(&elaboration_reg); Vect_region_box(&original_reg, &original_box); Vect_region_box(&elaboration_reg, &overlap_box); Vect_region_box(&elaboration_reg, &general_box); nrows = Rast_window_rows(); ncols = Rast_window_cols(); /* Alloc raster matrix */ have_mask = 0; out_file = mask_file = NULL; out_fd = mask_fd = -1; if (grid == TRUE) { int row; DCELL *drastbuf; seg_mb = atoi(memory_opt->answer); if (seg_mb < 3) G_fatal_error(_("Memory in MB must be >= 3")); if (mask_opt->answer) seg_size = sizeof(double) + sizeof(char); else seg_size = sizeof(double); seg_size = (seg_size * SEGSIZE * SEGSIZE) / (1 << 20); segments_in_memory = seg_mb / seg_size + 0.5; G_debug(1, "%d %dx%d segments held in memory", segments_in_memory, SEGSIZE, SEGSIZE); out_file = G_tempfile(); out_fd = creat(out_file, 0666); if (Segment_format(out_fd, nrows, ncols, SEGSIZE, SEGSIZE, sizeof(double)) != 1) G_fatal_error(_("Can not create temporary file")); close(out_fd); out_fd = open(out_file, 2); if (Segment_init(&out_seg, out_fd, segments_in_memory) != 1) G_fatal_error(_("Can not initialize temporary file")); /* initialize output */ G_message(_("Initializing output...")); drastbuf = Rast_allocate_buf(DCELL_TYPE); Rast_set_d_null_value(drastbuf, ncols); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); Segment_put_row(&out_seg, drastbuf, row); } G_percent(row, nrows, 2); if (mask_opt->answer) { int row, col, maskfd; DCELL dval, *drastbuf; char mask_val; G_message(_("Load masking map")); mask_file = G_tempfile(); mask_fd = creat(mask_file, 0666); if (Segment_format(mask_fd, nrows, ncols, SEGSIZE, SEGSIZE, sizeof(char)) != 1) G_fatal_error(_("Can not create temporary file")); close(mask_fd); mask_fd = open(mask_file, 2); if (Segment_init(&mask_seg, mask_fd, segments_in_memory) != 1) G_fatal_error(_("Can not initialize temporary file")); maskfd = Rast_open_old(mask_opt->answer, ""); drastbuf = Rast_allocate_buf(DCELL_TYPE); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); Rast_get_d_row(maskfd, drastbuf, row); for (col = 0; col < ncols; col++) { dval = drastbuf[col]; if (Rast_is_d_null_value(&dval) || dval == 0) mask_val = 0; else mask_val = 1; Segment_put(&mask_seg, &mask_val, row, col); } } G_percent(row, nrows, 2); G_free(drastbuf); Rast_close(maskfd); have_mask = 1; } } /*------------------------------------------------------------------ | Subdividing and working with tiles: | Each original region will be divided into several subregions. | Each one will be overlaped by its neighbouring subregions. | The overlapping is calculated as a fixed OVERLAP_SIZE times | the largest spline step plus 2 * edge ----------------------------------------------------------------*/ /* Fixing parameters of the elaboration region */ P_zero_dim(&dims); /* 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(bilin, &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; /* Creating line and categories structs */ Cats = Vect_new_cats_struct(); Vect_cat_set(Cats, 1, 0); subregion_row = 0; elaboration_reg.south = original_reg.north; last_row = FALSE; while (last_row == FALSE) { /* For each subregion row */ subregion_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; G_debug(1, "Interpolation: nsply = %d", nsply); /* if (nsply > NSPLY_MAX) nsply = NSPLY_MAX; */ elaboration_reg.east = original_reg.west; last_column = FALSE; subregion_col = 0; /* TODO: process each subregion using its own thread (via OpenMP or pthreads) */ /* I'm not sure about pthreads, but you can tell OpenMP to start all at the same time and it will keep num_workers supplied with the next job as free cpus become available */ while (last_column == FALSE) { /* For each subregion column */ int npoints = 0; /* needed for sparse points interpolation */ int npoints_ext, *lineVect_ext = NULL; double **obsVect_ext; /*, mean_ext = .0; */ struct Point *observ_ext; subregion_col++; subregion++; if (nsubregions > 1) G_message(_("Processing subregion %d of %d..."), subregion, nsubregions); P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, GENERAL_COLUMN); if (elaboration_reg.west < original_reg.west) { /* First column */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, FIRST_COLUMN); } if (elaboration_reg.east >= original_reg.east) { /* Last column */ P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims, LAST_COLUMN); last_column = TRUE; } nsplx = ceil((elaboration_reg.east - elaboration_reg.west) / stepE) + 0.5; G_debug(1, "Interpolation: nsplx = %d", nsplx); /* if (nsplx > NSPLX_MAX) nsplx = NSPLX_MAX; */ G_debug(1, "Interpolation: (%d,%d): subregion bounds", subregion_row, subregion_col); G_debug(1, "Interpolation: \t\tNORTH:%.2f\t", elaboration_reg.north); G_debug(1, "Interpolation: WEST:%.2f\t\tEAST:%.2f", elaboration_reg.west, elaboration_reg.east); G_debug(1, "Interpolation: \t\tSOUTH:%.2f", elaboration_reg.south); #ifdef DEBUG_SUBREGIONS fprintf(stdout, "B 5\n"); fprintf(stdout, " %.11g %.11g\n", elaboration_reg.east, elaboration_reg.north); fprintf(stdout, " %.11g %.11g\n", elaboration_reg.west, elaboration_reg.north); fprintf(stdout, " %.11g %.11g\n", elaboration_reg.west, elaboration_reg.south); fprintf(stdout, " %.11g %.11g\n", elaboration_reg.east, elaboration_reg.south); fprintf(stdout, " %.11g %.11g\n", elaboration_reg.east, elaboration_reg.north); fprintf(stdout, "C 1 1\n"); fprintf(stdout, " %.11g %.11g\n", (elaboration_reg.west + elaboration_reg.east) / 2, (elaboration_reg.south + elaboration_reg.north) / 2); fprintf(stdout, " 1 %d\n", subregion); #endif /* reading points in interpolation region */ dim_vect = nsplx * nsply; observ_ext = NULL; if (grid == FALSE && ext == TRUE) { observ_ext = P_Read_Vector_Region_Map(&In_ext, &elaboration_reg, &npoints_ext, dim_vect, 1); } else npoints_ext = 1; if (grid == TRUE && have_mask) { /* any unmasked cells in general region ? */ mean = 0; observ_ext = P_Read_Raster_Region_masked(&mask_seg, &original_reg, original_box, general_box, &npoints_ext, dim_vect, mean); } observ = NULL; if (npoints_ext > 0) { observ = P_Read_Vector_Region_Map(&In, &elaboration_reg, &npoints, dim_vect, bspline_field); } else npoints = 1; G_debug(1, "Interpolation: (%d,%d): Number of points in <elaboration_box> is %d", subregion_row, subregion_col, npoints); if (npoints > 0) G_verbose_message(_("%d points found in this subregion"), npoints); /* only interpolate if there are any points in current subregion */ if (npoints > 0 && npoints_ext > 0) { int i; nparameters = nsplx * nsply; BW = P_get_BandWidth(bilin, nsply); /* Least Squares system */ N = G_alloc_matrix(nparameters, BW); /* Normal matrix */ TN = G_alloc_vector(nparameters); /* vector */ parVect = G_alloc_vector(nparameters); /* 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); /* */ for (i = 0; i < npoints; i++) { /* Setting obsVect vector & Q matrix */ double dval; Q[i] = 1; /* Q=I */ lineVect[i] = observ[i].lineID; obsVect[i][0] = observ[i].coordX; obsVect[i][1] = observ[i].coordY; /* read z coordinates from attribute table */ if (bspline_field > 0) { int cat, ival, ret; cat = observ[i].cat; if (cat < 0) continue; if (ctype == DB_C_TYPE_INT) { ret = db_CatValArray_get_value_int(&cvarr, cat, &ival); obsVect[i][2] = ival; observ[i].coordZ = ival; } else { /* DB_C_TYPE_DOUBLE */ ret = db_CatValArray_get_value_double(&cvarr, cat, &dval); obsVect[i][2] = dval; observ[i].coordZ = dval; } if (ret != DB_OK) { G_warning(_("Interpolation: (%d,%d): No record for point (cat = %d)"), subregion_row, subregion_col, cat); continue; } } /* use z coordinates of 3D vector */ else { obsVect[i][2] = observ[i].coordZ; } } /* Mean calculation for every point */ mean = P_Mean_Calc(&elaboration_reg, observ, npoints); G_debug(1, "Interpolation: (%d,%d): mean=%lf", subregion_row, subregion_col, mean); G_free(observ); for (i = 0; i < npoints; i++) obsVect[i][2] -= mean; /* Bilinear interpolation */ if (bilin) { G_debug(1, "Interpolation: (%d,%d): Bilinear interpolation...", subregion_row, subregion_col); 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); } /* Bicubic interpolation */ else { G_debug(1, "Interpolation: (%d,%d): Bicubic interpolation...", subregion_row, subregion_col); normalDefBicubic(N, TN, Q, obsVect, stepE, stepN, nsplx, nsply, elaboration_reg.west, elaboration_reg.south, npoints, nparameters, BW); nCorrectGrad(N, lambda, nsplx, nsply, stepE, stepN); } if(G_strncasecmp(solver->answer, "cg", 2) == 0) G_math_solver_cg_sband(N, parVect, TN, nparameters, BW, atoi(iter->answer), atof(error->answer)); else G_math_solver_cholesky_sband(N, parVect, TN, nparameters, BW); G_free_matrix(N); G_free_vector(TN); G_free_vector(Q); if (grid == TRUE) { /* GRID INTERPOLATION ==> INTERPOLATION INTO A RASTER */ G_debug(1, "Interpolation: (%d,%d): Regular_Points...", subregion_row, subregion_col); if (!have_mask) { P_Regular_Points(&elaboration_reg, &original_reg, general_box, overlap_box, &out_seg, parVect, stepN, stepE, dims.overlap, mean, nsplx, nsply, nrows, ncols, bilin); } else { P_Sparse_Raster_Points(&out_seg, &elaboration_reg, &original_reg, general_box, overlap_box, observ_ext, parVect, stepE, stepN, dims.overlap, nsplx, nsply, npoints_ext, bilin, mean); } } else { /* OBSERVATION POINTS INTERPOLATION */ if (ext == FALSE) { G_debug(1, "Interpolation: (%d,%d): Sparse_Points...", subregion_row, subregion_col); P_Sparse_Points(&Out, &elaboration_reg, general_box, overlap_box, obsVect, parVect, lineVect, stepE, stepN, dims.overlap, nsplx, nsply, npoints, bilin, Cats, driver, mean, table_name); } else { /* FLAG_EXT == TRUE */ /* done that earlier */ /* int npoints_ext, *lineVect_ext = NULL; double **obsVect_ext; struct Point *observ_ext; observ_ext = P_Read_Vector_Region_Map(&In_ext, &elaboration_reg, &npoints_ext, dim_vect, 1); */ obsVect_ext = G_alloc_matrix(npoints_ext, 3); /* Observation vector_ext */ lineVect_ext = G_alloc_ivector(npoints_ext); for (i = 0; i < npoints_ext; i++) { /* Setting obsVect_ext vector & Q matrix */ obsVect_ext[i][0] = observ_ext[i].coordX; obsVect_ext[i][1] = observ_ext[i].coordY; obsVect_ext[i][2] = observ_ext[i].coordZ - mean; lineVect_ext[i] = observ_ext[i].lineID; } G_free(observ_ext); G_debug(1, "Interpolation: (%d,%d): Sparse_Points...", subregion_row, subregion_col); P_Sparse_Points(&Out, &elaboration_reg, general_box, overlap_box, obsVect_ext, parVect, lineVect_ext, stepE, stepN, dims.overlap, nsplx, nsply, npoints_ext, bilin, Cats, driver, mean, table_name); G_free_matrix(obsVect_ext); G_free_ivector(lineVect_ext); } /* END FLAG_EXT == TRUE */ } /* END GRID == FALSE */ G_free_vector(parVect); G_free_matrix(obsVect); G_free_ivector(lineVect); } else { if (observ) G_free(observ); if (observ_ext) G_free(observ_ext); if (npoints == 0) G_warning(_("No data within this subregion. " "Consider increasing spline step values.")); } } /*! END WHILE; last_column = TRUE */ } /*! END WHILE; last_row = TRUE */ G_verbose_message(_("Writing output...")); /* Writing the output raster map */ if (grid == TRUE) { int row, col; DCELL *drastbuf, dval; if (have_mask) { Segment_release(&mask_seg); /* release memory */ close(mask_fd); unlink(mask_file); } drastbuf = Rast_allocate_buf(DCELL_TYPE); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); for (col = 0; col < ncols; col++) { Segment_get(&out_seg, &dval, row, col); drastbuf[col] = dval; } Rast_put_d_row(raster, drastbuf); } Rast_close(raster); Segment_release(&out_seg); /* release memory */ close(out_fd); unlink(out_file); /* set map title */ sprintf(title, "%s interpolation with Tykhonov regularization", type_opt->answer); Rast_put_cell_title(out_map_opt->answer, title); /* write map history */ Rast_short_history(out_map_opt->answer, "raster", &history); Rast_command_history(&history); Rast_write_history(out_map_opt->answer, &history); } /* Writing to the output vector map the points from the overlapping zones */ else if (flag_auxiliar == TRUE) { if (ext == FALSE) P_Aux_to_Vector(&In, &Out, driver, table_name); else P_Aux_to_Vector(&In_ext, &Out, driver, table_name); /* Drop auxiliary table */ 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); if (ext != FALSE) Vect_close(&In_ext); if (vector) Vect_close(&Out); G_done_msg(" "); exit(EXIT_SUCCESS); } /*END MAIN */
int main(int argc, char *argv[]) { struct dxf_file *dxf; struct Map_info *Map; char *output = NULL; struct GModule *module; struct { struct Flag *list; struct Flag *extent; struct Flag *table; struct Flag *topo; struct Flag *invert; struct Flag *one_layer; struct Flag *frame; } flag; struct { struct Option *input; struct Option *output; struct Option *layers; } opt; G_gisinit(argv[0]); module = G_define_module(); module->keywords = _("vector, import"); module->description = _("Converts files in DXF format to GRASS vector map format."); flag.extent = G_define_flag(); flag.extent->key = 'e'; flag.extent->description = _("Ignore the map extent of DXF file"); flag.table = G_define_flag(); flag.table->key = 't'; flag.table->description = _("Do not create attribute tables"); flag.topo = G_define_flag(); flag.topo->key = 'b'; flag.topo->description = _("Do not build topology"); flag.frame = G_define_flag(); flag.frame->key = 'f'; flag.frame->description = _("Import polyface meshes as 3D wire frame"); flag.list = G_define_flag(); flag.list->key = 'l'; flag.list->description = _("List available layers and exit"); flag.list->guisection = _("DXF layers"); flag.invert = G_define_flag(); flag.invert->key = 'i'; flag.invert->description = _("Invert selection by layers (don't import layers in list)"); flag.invert->guisection = _("DXF layers"); flag.one_layer = G_define_flag(); flag.one_layer->key = '1'; flag.one_layer->description = _("Import all objects into one layer"); flag.one_layer->guisection = _("DXF layers"); opt.input = G_define_standard_option(G_OPT_F_INPUT); opt.input->description = _("Name of input DXF file"); opt.output = G_define_standard_option(G_OPT_V_OUTPUT); opt.output->required = NO; opt.layers = G_define_option(); opt.layers->key = "layers"; opt.layers->type = TYPE_STRING; opt.layers->required = NO; opt.layers->multiple = YES; opt.layers->description = _("List of layers to import"); opt.layers->guisection = _("DXF layers"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); flag_list = flag.list->answer; flag_extent = flag.extent->answer; flag_table = flag.table->answer; flag_invert = flag.invert->answer; flag_one_layer = flag.one_layer->answer; flag_frame = flag.frame->answer; /* open DXF file */ if (!(dxf = dxf_open(opt.input->answer))) G_fatal_error(_("Unable to open DXF file <%s>"), opt.input->answer); if (flag_list) { num_layers = 0; layers = NULL; Map = NULL; } else { /* make vector map name SQL compliant */ if (opt.output->answer) { output = G_store(opt.output->answer); } else { char *p, *p2; if ((p = G_rindex(dxf->name, '/'))) p++; else p = dxf->name; output = G_store(p); if ((p2 = G_rindex(p, '.'))) output[p2 - p] = 0; } { char *p; for (p = output; *p; p++) if (*p == '.') *p = '_'; } layers = opt.layers->answers; if (!G_check_overwrite(argc, argv) && G_find_vector2(output, G_mapset())) { G_fatal_error(_("Option <%s>: <%s> exists."), opt.output->key, output); } if (Vect_legal_filename(output) < 0) G_fatal_error(_("Use '%s' option to change vector map name"), opt.output->key); /* create vector map */ Map = (struct Map_info *)G_malloc(sizeof(struct Map_info)); if (Vect_open_new(Map, output, 1) < 0) G_fatal_error(_("Unable to create vector map <%s>"), output); Vect_set_map_name(Map, output); Vect_hist_command(Map); } /* import */ dxf_to_vect(dxf, Map); dxf_close(dxf); if (flag_list) init_list(); else { Vect_close(Map); if (found_layers) { if (Vect_open_old(Map, output, G_mapset())) { if (!flag_topo) if (!Vect_build(Map)) G_warning(_("Building topology failed")); Vect_close(Map); } } else { Vect_delete(output); G_fatal_error(_("Failed to import DXF file!")); } G_free(output); G_free(Map); } G_done_msg(" "); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int i, j, ret, centre, line, centre1, centre2, tfield, tucfield; 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, *tfield_opt, *tucfield_opt; struct Flag *geo_f, *turntable_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(); G_add_keyword(_("vector")); G_add_keyword(_("network")); G_add_keyword(_("isolines")); module->label = _("Splits net by cost isolines."); module->description = _ ("Splits net to bands between cost isolines (direction from center). " "Center node must be opened (costs >= 0). " "Costs of center node are used in calculation."); map = G_define_standard_option(G_OPT_V_INPUT); output = G_define_standard_option(G_OPT_V_OUTPUT); term_opt = G_define_standard_option(G_OPT_V_CATS); term_opt->key = "ccats"; term_opt->required = YES; term_opt->description = _("Categories of centers (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"); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "alayer"; afield_opt->answer = "1"; afield_opt->required = YES; afield_opt->label = _("Arc layer"); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "line,boundary"; type_opt->answer = "line,boundary"; type_opt->required = YES; type_opt->label = _("Arc type"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "nlayer"; nfield_opt->answer = "2"; nfield_opt->required = YES; 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)"); afcol->guisection = _("Cost"); abcol = G_define_standard_option(G_OPT_DB_COLUMN); abcol->key = "abcolumn"; abcol->description = _("Arc backward direction cost column (number)"); abcol->guisection = _("Cost"); ncol = G_define_standard_option(G_OPT_DB_COLUMN); ncol->key = "ncolumn"; ncol->description = _("Node cost column (number)"); ncol->guisection = _("Cost"); turntable_f = G_define_flag(); turntable_f->key = 't'; turntable_f->description = _("Use turntable"); turntable_f->guisection = _("Turntable"); tfield_opt = G_define_standard_option(G_OPT_V_FIELD); tfield_opt->key = "tlayer"; tfield_opt->answer = "3"; tfield_opt->label = _("Layer with turntable"); tfield_opt->description = _("Relevant only with -t flag"); tfield_opt->guisection = _("Turntable"); tucfield_opt = G_define_standard_option(G_OPT_V_FIELD); tucfield_opt->key = "tuclayer"; tucfield_opt->answer = "4"; tucfield_opt->label = _("Layer with unique categories used in turntable"); tucfield_opt->description = _("Relevant only with -t flag"); tucfield_opt->guisection = _("Turntable"); 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, G_FATAL_EXIT); Cats = Vect_new_cats_struct(); Points = Vect_new_line_struct(); SPoints = Vect_new_line_struct(); type = Vect_option_to_types(type_opt); catlist = Vect_new_cat_list(); Vect_str_to_cat_list(term_opt->answer, catlist); /* 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); if (Vect_open_old(&Map, map->answer, "") < 0) G_fatal_error(_("Unable to open vector map <%s>"), map->answer); afield = Vect_get_field_number(&Map, afield_opt->answer); nfield = Vect_get_field_number(&Map, nfield_opt->answer); tfield = Vect_get_field_number(&Map, tfield_opt->answer); tucfield = Vect_get_field_number(&Map, tucfield_opt->answer); /* Build graph */ if (turntable_f->answer) Vect_net_ttb_build_graph(&Map, type, afield, nfield, tfield, tucfield, afcol->answer, abcol->answer, ncol->answer, geo, 0); else 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 */ if (turntable_f->answer) { /* if turntable is used we are looking for lines as destinations, instead of the intersections (nodes) */ Nodes = (NODE *) G_calloc((nlines * 2 + 2), sizeof(NODE)); for (i = 2; i <= (nlines * 2 + 2); i++) { Nodes[i].centre = -1;/* NOTE: first two items of Nodes are not used */ } } else { 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); if (turntable_f->answer) for (line = 1; line <= nlines; line++) { G_debug(5, " node1 = %d line = %d", node1, line); Vect_net_get_node_cost(&Map, line, &n2cost); /* closed, left it as not attached */ if (Vect_read_line(&Map, Points, Cats, line) < 0) continue; if (Vect_get_line_type(&Map, line) != GV_LINE) continue; if (!Vect_cat_get(Cats, tucfield, &cat)) continue; for (j = 0; j < 2; j++) { if (j == 1) cat *= -1; ret = Vect_net_ttb_shortest_path(&Map, node1, 0, cat, 1, tucfield, 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 (ret != 1) cost += n1cost; G_debug(5, "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f", node1, line, cost, Nodes[line * 2 + j].centre, Nodes[line * 2 + j].cost); if (Nodes[line * 2 + j].centre == -1 || cost < Nodes[line * 2 + j].cost) { Nodes[line * 2 + j].cost = cost; Nodes[line * 2 + j].centre = centre; } } } else 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 */ 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_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; } l = Vect_line_length(Points); if (l == 0) continue; if (turntable_f->answer) { centre1 = Nodes[line * 2].centre; centre2 = Nodes[line * 2 + 1].centre; s1cost = Nodes[line * 2].cost; s2cost = Nodes[line * 2 + 1].cost; n1cost = n2cost = 0; } else { Vect_get_line_nodes(&Map, line, &node1, &node2); centre1 = Nodes[node1].centre; centre2 = Nodes[node2].centre; s1cost = Nodes[node1].cost; s2cost = Nodes[node2].cost; 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, "Line %d : length = %f", line, l); G_debug(3, "Arc centres: %d %d (nodes: %d %d)", centre1, centre2, node1, node2); 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) { struct Option *input_opt, *output_opt, *afield_opt, *nfield_opt, *tfield_opt, *tucfield_opt, *afcol, *abcol, *ncol, *type_opt; struct Option *max_dist, *file_opt; struct Flag *geo_f, *segments_f, *turntable_f; struct GModule *module; struct Map_info In, Out; int type, afield, nfield, tfield, tucfield, geo; double maxdist; /* Initialize the GIS calls */ G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("network")); G_add_keyword(_("shortest path")); module->description = _("Finds shortest path on vector network."); input_opt = G_define_standard_option(G_OPT_V_INPUT); output_opt = 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->required = YES; afield_opt->label = _("Arc layer"); 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->required = YES; type_opt->label = _("Arc type"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "node_layer"; nfield_opt->answer = "2"; nfield_opt->required = YES; nfield_opt->label = _("Node layer"); file_opt = G_define_standard_option(G_OPT_F_INPUT); file_opt->key = "file"; file_opt->required = NO; file_opt->description = _("Name of file containing start and end points. " "If not given, read from stdin"); afcol = G_define_option(); afcol->key = "arc_column"; afcol->type = TYPE_STRING; afcol->required = NO; afcol->description = _("Arc forward/both direction(s) cost column (number)"); afcol->guisection = _("Cost"); abcol = G_define_option(); abcol->key = "arc_backward_column"; abcol->type = TYPE_STRING; abcol->required = NO; abcol->description = _("Arc backward direction cost column (number)"); abcol->guisection = _("Cost"); ncol = G_define_option(); ncol->key = "node_column"; ncol->type = TYPE_STRING; ncol->required = NO; ncol->description = _("Node cost column (number)"); ncol->guisection = _("Cost"); max_dist = G_define_option(); max_dist->key = "dmax"; max_dist->type = TYPE_DOUBLE; max_dist->required = NO; max_dist->answer = "1000"; max_dist->label = _("Maximum distance to the network"); max_dist->description = _("If start/end are given as coordinates. " "If start/end point is outside this threshold, " "the path is not found " "and error message is printed. To speed up the process, keep this " "value as low as possible."); turntable_f = G_define_flag(); turntable_f->key = 't'; turntable_f->description = _("Use turntable"); turntable_f->guisection = _("Turntable"); tfield_opt = G_define_standard_option(G_OPT_V_FIELD); tfield_opt->key = "turn_layer"; tfield_opt->answer = "3"; tfield_opt->label = _("Layer with turntable"); tfield_opt->description = _("Relevant only with -t flag"); tfield_opt->guisection = _("Turntable"); tucfield_opt = G_define_standard_option(G_OPT_V_FIELD); tucfield_opt->key = "turn_cat_layer"; tucfield_opt->answer = "4"; tucfield_opt->label = _("Layer with unique categories used in turntable"); tucfield_opt->description = _("Relevant only with -t flag"); tucfield_opt->guisection = _("Turntable"); geo_f = G_define_flag(); geo_f->key = 'g'; geo_f->description = _("Use geodesic calculation for longitude-latitude locations"); segments_f = G_define_flag(); segments_f->key = 's'; segments_f->description = _("Write output as original input segments, " "not each path as one line."); if (G_parser(argc, argv)) exit(EXIT_FAILURE); type = Vect_option_to_types(type_opt); maxdist = atof(max_dist->answer); if (geo_f->answer) { geo = 1; if (G_projection() != PROJECTION_LL) G_warning(_("The current projection is not longitude-latitude")); } else geo = 0; Vect_check_input_output_name(input_opt->answer, output_opt->answer, G_FATAL_EXIT); Vect_set_open_level(2); if (Vect_open_old(&In, input_opt->answer, "") < 0) G_fatal_error(_("Unable to open vector map <%s>"), input_opt->answer); afield = Vect_get_field_number(&In, afield_opt->answer); nfield = Vect_get_field_number(&In, nfield_opt->answer); tfield = Vect_get_field_number(&In, tfield_opt->answer); tucfield = Vect_get_field_number(&In, tucfield_opt->answer); if (1 > Vect_open_new(&Out, output_opt->answer, Vect_is_3d(&In))) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), output_opt->answer); } Vect_hist_command(&Out); if (turntable_f->answer) Vect_net_ttb_build_graph(&In, type, afield, nfield, tfield, tucfield, afcol->answer, abcol->answer, ncol->answer, geo, 0); else Vect_net_build_graph(&In, type, afield, nfield, afcol->answer, abcol->answer, ncol->answer, geo, 0); path(&In, &Out, file_opt->answer, nfield, maxdist, segments_f->answer, tucfield, turntable_f->answer); Vect_close(&In); Vect_build(&Out); Vect_close(&Out); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct file_info Current, Trans, Coord; struct GModule *module; struct Option *vold, *vnew, *pointsfile, *xshift, *yshift, *zshift, *xscale, *yscale, *zscale, *zrot, *columns, *table, *field; struct Flag *quiet_flag, *tozero_flag, *shift_flag, *print_mat_flag; char *mapset, mon[4], date[40], buf[1000]; struct Map_info Old, New; int ifield; int day, yr; BOUND_BOX box; double ztozero; double trans_params[7]; /* xshift, ..., xscale, ..., zrot */ /* columns */ unsigned int i; int idx, out3d; char **tokens; char *columns_name[7]; /* xshift, yshift, zshift, xscale, yscale, zscale, zrot */ G_gisinit(argv[0]); module = G_define_module(); module->keywords = _("vector, transformation"); module->description = _("Performs an affine transformation (shift, scale and rotate, " "or GPCs) on vector map."); /* remove in GRASS7 */ quiet_flag = G_define_flag(); quiet_flag->key = 'q'; quiet_flag->description = _("Suppress display of residuals or other information"); tozero_flag = G_define_flag(); tozero_flag->key = 't'; tozero_flag->description = _("Shift all z values to bottom=0"); tozero_flag->guisection = _("Custom"); print_mat_flag = G_define_flag(); print_mat_flag->key = 'm'; print_mat_flag->description = _("Print the transformation matrix to stdout"); shift_flag = G_define_flag(); shift_flag->key = 's'; shift_flag->description = _("Instead of points use transformation parameters " "(xshift, yshift, zshift, xscale, yscale, zscale, zrot)"); shift_flag->guisection = _("Custom"); vold = G_define_standard_option(G_OPT_V_INPUT); field = G_define_standard_option(G_OPT_V_FIELD); field->answer = "-1"; vnew = G_define_standard_option(G_OPT_V_OUTPUT); pointsfile = G_define_standard_option(G_OPT_F_INPUT); pointsfile->key = "pointsfile"; pointsfile->required = NO; pointsfile->label = _("ASCII file holding transform coordinates"); pointsfile->description = _("If not given, transformation parameters " "(xshift, yshift, zshift, xscale, yscale, zscale, zrot) are used instead"); pointsfile->gisprompt = "old_file,file,points"; pointsfile->guisection = _("Points"); xshift = G_define_option(); xshift->key = "xshift"; xshift->type = TYPE_DOUBLE; xshift->required = NO; xshift->multiple = NO; xshift->description = _("Shifting value for x coordinates"); xshift->answer = "0.0"; xshift->guisection = _("Custom"); yshift = G_define_option(); yshift->key = "yshift"; yshift->type = TYPE_DOUBLE; yshift->required = NO; yshift->multiple = NO; yshift->description = _("Shifting value for y coordinates"); yshift->answer = "0.0"; yshift->guisection = _("Custom"); zshift = G_define_option(); zshift->key = "zshift"; zshift->type = TYPE_DOUBLE; zshift->required = NO; zshift->multiple = NO; zshift->description = _("Shifting value for z coordinates"); zshift->answer = "0.0"; zshift->guisection = _("Custom"); xscale = G_define_option(); xscale->key = "xscale"; xscale->type = TYPE_DOUBLE; xscale->required = NO; xscale->multiple = NO; xscale->description = _("Scaling factor for x coordinates"); xscale->answer = "1.0"; xscale->guisection = _("Custom"); yscale = G_define_option(); yscale->key = "yscale"; yscale->type = TYPE_DOUBLE; yscale->required = NO; yscale->multiple = NO; yscale->description = _("Scaling factor for y coordinates"); yscale->answer = "1.0"; yscale->guisection = _("Custom"); zscale = G_define_option(); zscale->key = "zscale"; zscale->type = TYPE_DOUBLE; zscale->required = NO; zscale->multiple = NO; zscale->description = _("Scaling factor for z coordinates"); zscale->answer = "1.0"; zscale->guisection = _("Custom"); zrot = G_define_option(); zrot->key = "zrot"; zrot->type = TYPE_DOUBLE; zrot->required = NO; zrot->multiple = NO; zrot->description = _("Rotation around z axis in degrees counterclockwise"); zrot->answer = "0.0"; zrot->guisection = _("Custom"); table = G_define_standard_option(G_OPT_TABLE); table->description = _("Name of table containing transformation parameters"); table->guisection = _("Attributes"); columns = G_define_option(); columns->key = "columns"; columns->type = TYPE_STRING; columns->required = NO; columns->multiple = NO; columns->label = _("Name of attribute column(s) used as transformation parameters"); columns->description = _("Format: parameter:column, e.g. xshift:xs,yshift:ys,zrot:zr"); columns->guisection = _("Attributes"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); G_strcpy(Current.name, vold->answer); G_strcpy(Trans.name, vnew->answer); Vect_check_input_output_name(vold->answer, vnew->answer, GV_FATAL_EXIT); out3d = WITHOUT_Z; ifield = atoi(field->answer); if (shift_flag->answer) G_warning(_("The '%c' flag is deprecated and will be removed in future. " "Transformation parameters are used automatically when no pointsfile is given."), shift_flag->key); /* please remove in GRASS7 */ if (quiet_flag->answer) { G_warning(_("The '%c' flag is deprecated and will be removed in future. " "Please use '--quiet' instead."), quiet_flag->key); G_putenv("GRASS_VERBOSE", "0"); } /* if a table is specified, require columns and layer */ /* if columns are specified, but no table, require layer > 0 and use * the table attached to that layer */ if (table->answer && !columns->answer) { G_fatal_error(_("Column names are not defined. Please use '%s' parameter."), columns->key); } if ((columns->answer || table->answer) && ifield < 1) { G_fatal_error(_("Please specify a valid layer with '%s' parameter."), field->key); } if (table->answer && strcmp(vnew->answer, table->answer) == 0) { G_fatal_error(_("Name of table and name for output vector map must be different. " "Otherwise the table is overwritten.")); } if (!columns->answer && !table->answer) ifield = -1; if (pointsfile->answer != NULL && !shift_flag->answer) { G_strcpy(Coord.name, pointsfile->answer); } else { Coord.name[0] = '\0'; } /* open coord file */ if (Coord.name[0] != '\0') { if ((Coord.fp = fopen(Coord.name, "r")) == NULL) G_fatal_error(_("Unable to open file with coordinates <%s>"), Coord.name); } /* tokenize columns names */ for (i = 0; i <= IDX_ZROT; i++) { columns_name[i] = NULL; } i = 0; if (columns->answer) { while (columns->answers[i]) { tokens = G_tokenize(columns->answers[i], ":"); if (G_number_of_tokens(tokens) == 2) { if (strcmp(tokens[0], xshift->key) == 0) idx = IDX_XSHIFT; else if (strcmp(tokens[0], yshift->key) == 0) idx = IDX_YSHIFT; else if (strcmp(tokens[0], zshift->key) == 0) idx = IDX_ZSHIFT; else if (strcmp(tokens[0], xscale->key) == 0) idx = IDX_XSCALE; else if (strcmp(tokens[0], yscale->key) == 0) idx = IDX_YSCALE; else if (strcmp(tokens[0], zscale->key) == 0) idx = IDX_ZSCALE; else if (strcmp(tokens[0], zrot->key) == 0) idx = IDX_ZROT; else idx = -1; if (idx != -1) columns_name[idx] = G_store(tokens[1]); G_free_tokens(tokens); } else { G_fatal_error(_("Unable to tokenize column string: [%s]"), columns->answers[i]); } i++; } } /* determine transformation parameters */ trans_params[IDX_XSHIFT] = atof(xshift->answer); trans_params[IDX_YSHIFT] = atof(yshift->answer); trans_params[IDX_ZSHIFT] = atof(zshift->answer); trans_params[IDX_XSCALE] = atof(xscale->answer); trans_params[IDX_YSCALE] = atof(yscale->answer); trans_params[IDX_ZSCALE] = atof(zscale->answer); trans_params[IDX_ZROT] = atof(zrot->answer); /* open vector maps */ if ((mapset = G_find_vector2(vold->answer, "")) == NULL) G_fatal_error(_("Vector map <%s> not found"), vold->answer); Vect_open_old(&Old, vold->answer, mapset); /* should output be 3D ? * note that z-scale and ztozero have no effect with input 2D */ if (Vect_is_3d(&Old) || trans_params[IDX_ZSHIFT] != 0. || columns_name[IDX_ZSHIFT]) out3d = WITH_Z; Vect_open_new(&New, vnew->answer, out3d); /* copy and set header */ Vect_copy_head_data(&Old, &New); Vect_hist_copy(&Old, &New); Vect_hist_command(&New); sprintf(date, "%s", G_date()); sscanf(date, "%*s%s%d%*s%d", mon, &day, &yr); sprintf(date, "%s %d %d", mon, day, yr); Vect_set_date(&New, date); Vect_set_person(&New, G_whoami()); sprintf(buf, "transformed from %s", vold->answer); Vect_set_map_name(&New, buf); Vect_set_scale(&New, 1); Vect_set_zone(&New, 0); Vect_set_thresh(&New, 0.0); /* points file */ if (Coord.name[0]) { create_transform_from_file(&Coord, quiet_flag->answer); if (Coord.name[0] != '\0') fclose(Coord.fp); } Vect_get_map_box(&Old, &box); /* z to zero */ if (tozero_flag->answer) ztozero = 0 - box.B; else ztozero = 0; /* do the transformation */ transform_digit_file(&Old, &New, Coord.name[0] ? 1 : 0, ztozero, trans_params, table->answer, columns_name, ifield); if (Vect_copy_tables(&Old, &New, 0)) G_warning(_("Failed to copy attribute table to output map")); Vect_close(&Old); Vect_build(&New); if (!quiet_flag->answer) { Vect_get_map_box(&New, &box); G_message(_("\nNew vector map <%s> boundary coordinates:"), vnew->answer); G_message(_(" N: %-10.3f S: %-10.3f"), box.N, box.S); G_message(_(" E: %-10.3f W: %-10.3f"), box.E, box.W); G_message(_(" B: %6.3f T: %6.3f"), box.B, box.T); /* print the transformation matrix if requested */ if (print_mat_flag->answer) print_transform_matrix(); } Vect_close(&New); G_done_msg(" "); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct Option *vector_opt, *seed_opt, *flowlines_opt, *flowacc_opt, *sampled_opt, *scalar_opt, *unit_opt, *step_opt, *limit_opt, *skip_opt, *dir_opt, *error_opt; struct Flag *table_fl; struct GModule *module; RASTER3D_Region region; RASTER3D_Map *flowacc, *sampled; struct Integration integration; struct Seed seed; struct Gradient_info gradient_info; struct Map_info seed_Map; struct line_pnts *seed_points; struct line_cats *seed_cats; struct Map_info fl_map; struct line_cats *fl_cats; /* for flowlines */ struct line_pnts *fl_points; /* for flowlines */ struct field_info *finfo; dbDriver *driver; int cat; /* cat of flowlines */ int if_table; int i, r, c, d; char *desc; int n_seeds, seed_count, ltype; int skip[3]; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster3d")); G_add_keyword(_("hydrology")); G_add_keyword(_("voxel")); module->description = _("Computes 3D flow lines and 3D flow accumulation."); scalar_opt = G_define_standard_option(G_OPT_R3_INPUT); scalar_opt->required = NO; scalar_opt->guisection = _("Input"); vector_opt = G_define_standard_option(G_OPT_R3_INPUTS); vector_opt->key = "vector_field"; vector_opt->required = NO; vector_opt->description = _("Names of three 3D raster maps describing " "x, y, z components of vector field"); vector_opt->guisection = _("Input"); seed_opt = G_define_standard_option(G_OPT_V_INPUT); seed_opt->required = NO; seed_opt->key = "seed_points"; seed_opt->description = _("If no map is provided, " "flow lines are generated " "from each cell of the input 3D raster"); seed_opt->label = _("Name of vector map with points " "from which flow lines are generated"); seed_opt->guisection = _("Input"); flowlines_opt = G_define_standard_option(G_OPT_V_OUTPUT); flowlines_opt->key = "flowline"; flowlines_opt->required = NO; flowlines_opt->description = _("Name for vector map of flow lines"); flowlines_opt->guisection = _("Output"); flowacc_opt = G_define_standard_option(G_OPT_R3_OUTPUT); flowacc_opt->key = "flowaccumulation"; flowacc_opt->required = NO; flowacc_opt->description = _("Name for output flowaccumulation 3D raster"); flowacc_opt->guisection = _("Output"); sampled_opt = G_define_standard_option(G_OPT_R3_INPUT); sampled_opt->key = "sampled"; sampled_opt->required = NO; sampled_opt->label = _("Name for 3D raster sampled by flowlines"); sampled_opt->description = _("Values of this 3D raster will be stored " "as attributes of flowlines segments"); unit_opt = G_define_option(); unit_opt->key = "unit"; unit_opt->type = TYPE_STRING; unit_opt->required = NO; unit_opt->answer = "cell"; unit_opt->options = "time,length,cell"; desc = NULL; G_asprintf(&desc, "time;%s;" "length;%s;" "cell;%s", _("elapsed time"), _("length in map units"), _("length in cells (voxels)")); unit_opt->descriptions = desc; unit_opt->label = _("Unit of integration step"); unit_opt->description = _("Default unit is cell"); unit_opt->guisection = _("Integration"); step_opt = G_define_option(); step_opt->key = "step"; step_opt->type = TYPE_DOUBLE; step_opt->required = NO; step_opt->answer = "0.25"; step_opt->label = _("Integration step in selected unit"); step_opt->description = _("Default step is 0.25 cell"); step_opt->guisection = _("Integration"); limit_opt = G_define_option(); limit_opt->key = "limit"; limit_opt->type = TYPE_INTEGER; limit_opt->required = NO; limit_opt->answer = "2000"; limit_opt->description = _("Maximum number of steps"); limit_opt->guisection = _("Integration"); error_opt = G_define_option(); error_opt->key = "max_error"; error_opt->type = TYPE_DOUBLE; error_opt->required = NO; error_opt->answer = "1e-5"; error_opt->label = _("Maximum error of integration"); error_opt->description = _("Influences step, increase maximum error " "to allow bigger steps"); error_opt->guisection = _("Integration"); skip_opt = G_define_option(); skip_opt->key = "skip"; skip_opt->type = TYPE_INTEGER; skip_opt->required = NO; skip_opt->multiple = YES; skip_opt->description = _("Number of cells between flow lines in x, y and z direction"); dir_opt = G_define_option(); dir_opt->key = "direction"; dir_opt->type = TYPE_STRING; dir_opt->required = NO; dir_opt->multiple = NO; dir_opt->options = "up,down,both"; dir_opt->answer = "down"; dir_opt->description = _("Compute flowlines upstream, " "downstream or in both direction."); table_fl = G_define_flag(); table_fl->key = 'a'; table_fl->description = _("Create and fill attribute table"); G_option_required(scalar_opt, vector_opt, NULL); G_option_exclusive(scalar_opt, vector_opt, NULL); G_option_required(flowlines_opt, flowacc_opt, NULL); G_option_requires(seed_opt, flowlines_opt, NULL); G_option_requires(table_fl, flowlines_opt, NULL); G_option_requires(sampled_opt, table_fl, NULL); if (G_parser(argc, argv)) exit(EXIT_FAILURE); driver = NULL; finfo = NULL; if_table = table_fl->answer ? TRUE : FALSE; check_vector_input_maps(vector_opt, seed_opt); Rast3d_init_defaults(); Rast3d_get_window(®ion); /* set up integration variables */ if (step_opt->answer) { integration.step = atof(step_opt->answer); integration.unit = unit_opt->answer; } else { integration.unit = "cell"; integration.step = 0.25; } integration.max_error = atof(error_opt->answer); integration.max_step = 5 * integration.step; integration.min_step = integration.step / 5; integration.limit = atof(limit_opt->answer); if (strcmp(dir_opt->answer, "up") == 0) integration.direction_type = FLOWDIR_UP; else if (strcmp(dir_opt->answer, "down") == 0) integration.direction_type = FLOWDIR_DOWN; else integration.direction_type = FLOWDIR_BOTH; /* cell size is the diagonal */ integration.cell_size = sqrt(region.ns_res * region.ns_res + region.ew_res * region.ew_res + region.tb_res * region.tb_res); /* set default skip if needed */ if (skip_opt->answers) { for (i = 0; i < 3; i++) { if (skip_opt->answers[i] != NULL) { skip[i] = atoi(skip_opt->answers[i]); } else { G_fatal_error(_("Please provide 3 integer values for skip option.")); } } } else { skip[0] = fmax(1, region.cols / 10); skip[1] = fmax(1, region.rows / 10); skip[2] = fmax(1, region.depths / 10); } /* open raster 3D maps of velocity components */ gradient_info.initialized = FALSE; load_input_raster3d_maps(scalar_opt, vector_opt, &gradient_info, ®ion); /* open new 3D raster map of flowacumulation */ if (flowacc_opt->answer) { flowacc = Rast3d_open_new_opt_tile_size(flowacc_opt->answer, RASTER3D_USE_CACHE_DEFAULT, ®ion, FCELL_TYPE, 32); if (!flowacc) Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"), flowacc_opt->answer); init_flowaccum(®ion, flowacc); } /* open 3D raster map used for sampling */ if (sampled_opt->answer) { sampled = Rast3d_open_cell_old(sampled_opt->answer, G_find_raster3d(sampled_opt->answer, ""), ®ion, RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT); if (!sampled) Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"), sampled_opt->answer); } else sampled = NULL; /* open new vector map of flowlines */ if (flowlines_opt->answer) { fl_cats = Vect_new_cats_struct(); fl_points = Vect_new_line_struct(); if (Vect_open_new(&fl_map, flowlines_opt->answer, TRUE) < 0) G_fatal_error(_("Unable to create vector map <%s>"), flowlines_opt->answer); Vect_hist_command(&fl_map); if (if_table) { create_table(&fl_map, &finfo, &driver, gradient_info.compute_gradient, sampled ? 1 : 0); } } n_seeds = 0; /* open vector map of seeds */ if (seed_opt->answer) { if (Vect_open_old2(&seed_Map, seed_opt->answer, "", "1") < 0) G_fatal_error(_("Unable to open vector map <%s>"), seed_opt->answer); if (!Vect_is_3d(&seed_Map)) G_fatal_error(_("Vector map <%s> is not 3D"), seed_opt->answer); n_seeds = Vect_get_num_primitives(&seed_Map, GV_POINT); } if (flowacc_opt->answer || (!seed_opt->answer && flowlines_opt->answer)) { if (flowacc_opt->answer) n_seeds += region.cols * region.rows * region.depths; else { n_seeds += ceil(region.cols / (double)skip[0]) * ceil(region.rows / (double)skip[1]) * ceil(region.depths / (double)skip[2]); } } G_debug(1, "Number of seeds is %d", n_seeds); seed_count = 0; cat = 1; if (seed_opt->answer) { seed_points = Vect_new_line_struct(); seed_cats = Vect_new_cats_struct(); /* compute flowlines from vector seed map */ while (TRUE) { ltype = Vect_read_next_line(&seed_Map, seed_points, seed_cats); if (ltype == -1) { Vect_close(&seed_Map); G_fatal_error(_("Error during reading seed vector map")); } else if (ltype == -2) { break; } else if (ltype == GV_POINT) { seed.x = seed_points->x[0]; seed.y = seed_points->y[0]; seed.z = seed_points->z[0]; seed.flowline = TRUE; seed.flowaccum = FALSE; } G_percent(seed_count, n_seeds, 1); if (integration.direction_type == FLOWDIR_UP || integration.direction_type == FLOWDIR_BOTH) { integration.actual_direction = FLOWDIR_UP; compute_flowline(®ion, &seed, &gradient_info, flowacc, sampled, &integration, &fl_map, fl_cats, fl_points, &cat, if_table, finfo, driver); } if (integration.direction_type == FLOWDIR_DOWN || integration.direction_type == FLOWDIR_BOTH) { integration.actual_direction = FLOWDIR_DOWN; compute_flowline(®ion, &seed, &gradient_info, flowacc, sampled, &integration, &fl_map, fl_cats, fl_points, &cat, if_table, finfo, driver); } seed_count++; } Vect_destroy_line_struct(seed_points); Vect_destroy_cats_struct(seed_cats); Vect_close(&seed_Map); } if (flowacc_opt->answer || (!seed_opt->answer && flowlines_opt->answer)) { /* compute flowlines from points on grid */ for (r = region.rows; r > 0; r--) { for (c = 0; c < region.cols; c++) { for (d = 0; d < region.depths; d++) { seed.x = region.west + c * region.ew_res + region.ew_res / 2; seed.y = region.south + r * region.ns_res - region.ns_res / 2; seed.z = region.bottom + d * region.tb_res + region.tb_res / 2; seed.flowline = FALSE; seed.flowaccum = FALSE; if (flowacc_opt->answer) seed.flowaccum = TRUE; if (flowlines_opt->answer && !seed_opt->answer && (c % skip[0] == 0) && (r % skip[1] == 0) && (d % skip[2] == 0)) seed.flowline = TRUE; if (seed.flowaccum || seed.flowline) { G_percent(seed_count, n_seeds, 1); if (integration.direction_type == FLOWDIR_UP || integration.direction_type == FLOWDIR_BOTH) { integration.actual_direction = FLOWDIR_UP; compute_flowline(®ion, &seed, &gradient_info, flowacc, sampled, &integration, &fl_map, fl_cats, fl_points, &cat, if_table, finfo, driver); } if (integration.direction_type == FLOWDIR_DOWN || integration.direction_type == FLOWDIR_BOTH) { integration.actual_direction = FLOWDIR_DOWN; compute_flowline(®ion, &seed, &gradient_info, flowacc, sampled, &integration, &fl_map, fl_cats, fl_points, &cat, if_table, finfo, driver); } seed_count++; } } } } } G_percent(1, 1, 1); if (flowlines_opt->answer) { if (if_table) { db_commit_transaction(driver); db_close_database_shutdown_driver(driver); } Vect_destroy_line_struct(fl_points); Vect_destroy_cats_struct(fl_cats); Vect_build(&fl_map); Vect_close(&fl_map); } if (flowacc_opt->answer) Rast3d_close(flowacc); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { struct GModule *module; struct Option *out_opt, *in_opt; struct Flag *z_flag, *circle_flag, *l_flag, *int_flag; char buf[2000]; /* DWG */ char path[2000]; short initerror, entset, retval; AD_OBJHANDLE pspace, mspace; PAD_ENT_HDR adenhd; PAD_ENT aden; AD_VMADDR entlist; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("import")); module->description = _("Converts DWG/DXF to GRASS vector map"); in_opt = G_define_standard_option(G_OPT_F_INPUT); in_opt->description = _("Name of DWG or DXF file"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->required = YES; layers_opt = G_define_option(); layers_opt->key = "layers"; layers_opt->type = TYPE_STRING; layers_opt->required = NO; layers_opt->multiple = YES; layers_opt->description = _("List of layers to import"); invert_flag = G_define_flag(); invert_flag->key = 'i'; invert_flag->description = _("Invert selection by layers (don't import layers in list)"); z_flag = G_define_flag(); z_flag->key = 'z'; z_flag->description = _("Create 3D vector map"); circle_flag = G_define_flag(); circle_flag->key = 'c'; circle_flag->description = _("Write circles as points (centre)"); l_flag = G_define_flag(); l_flag->key = 'l'; l_flag->description = _("List available layers and exit"); int_flag = G_define_flag(); int_flag->key = 'n'; int_flag->description = _("Use numeric type for attribute \"layer\""); if (G_parser(argc, argv)) exit(EXIT_FAILURE); db_init_string(&sql); db_init_string(&str); adenhd = (PAD_ENT_HDR) G_malloc(sizeof(AD_ENT_HDR)); aden = (PAD_ENT) G_malloc(sizeof(AD_ENT)); Layer = (PAD_LAY) G_malloc(sizeof(AD_LAY)); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Block = NULL; atrans = 20; /* nested, recursive levels */ Trans = (TRANS *) G_malloc(atrans * sizeof(TRANS)); /* Init OpenDWG */ sprintf(path, "%s/etc/adinit.dat", G_gisbase()); if (!adInitAd2(path, &initerror)) { sprintf(buf, _("Unable to initialize OpenDWG Toolkit, error: %d: %s."), initerror, adErrorStr(initerror)); if (initerror == AD_UNABLE_TO_OPEN_INIT_FILE) sprintf(buf, _("%s Cannot open %s"), buf, path); G_fatal_error(buf); } adSetupDwgRead(); adSetupDxfRead(); /* Open input file */ if ((dwghandle = adLoadFile(in_opt->answer, AD_PRELOAD_ALL, 1)) == NULL) { G_fatal_error(_("Unable to open input file <%s>. Error %d: %s"), in_opt->answer, adError(), adErrorStr(adError())); } if (l_flag->answer) { /* List layers */ PAD_TB adtb; AD_DWGHDR adhd; int i; char on, frozen, vpfrozen, locked; adtb = (PAD_TB) G_malloc(sizeof(AD_TB)); G_debug(2, "%d layers", (int)adNumLayers(dwghandle)); adReadHeaderBlock(dwghandle, &adhd); adStartLayerGet(dwghandle); fprintf(stdout, "%d layers:\n", (int)adNumLayers(dwghandle)); for (i = 0; i < (int)adNumLayers(dwghandle); i++) { adGetLayer(dwghandle, &(adtb->lay)); if (!adtb->lay.purgedflag) { fprintf(stdout, "%s COLOR %d, ", adtb->lay.name, adtb->lay.color); } adGetLayerState(dwghandle, adtb->lay.objhandle, &on, &frozen, &vpfrozen, &locked); if (on) fprintf(stdout, "ON, "); else fprintf(stdout, "OFF, "); if (frozen) fprintf(stdout, "FROZEN, "); else fprintf(stdout, "THAWED, "); if (vpfrozen) fprintf(stdout, "VPFROZEN, "); else fprintf(stdout, "VPTHAWED, "); if (locked) fprintf(stdout, "LOCKED\n"); else fprintf(stdout, "UNLOCKED\n"); } adCloseFile(dwghandle); adCloseAd2(); exit(EXIT_SUCCESS); } /* open output vector */ if (Vect_open_new(&Map, out_opt->answer, z_flag->answer) < 0) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); Vect_hist_command(&Map); /* Add DB link */ Fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Map, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Map)); if (driver == NULL) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Vect_subst_var(Fi->database, &Map), Fi->driver); } db_set_error_handler_driver(driver); db_begin_transaction(driver); /* Create table */ if (int_flag->answer) { /* List layers */ sprintf(buf, "create table %s ( cat integer, entity_name varchar(20), color int, weight int, " "layer real, block varchar(100), txt varchar(100) )", Fi->table); } else { sprintf(buf, "create table %s ( cat integer, entity_name varchar(20), color int, weight int, " "layer varchar(100), block varchar(100), txt varchar(100) )", Fi->table); } db_set_string(&sql, buf); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql)); } if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK) G_warning(_("Unable to create index for table <%s>, key <%s>"), Fi->table, GV_KEY_COLUMN); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Unable to grant privileges on table <%s>"), Fi->table); cat = 1; n_elements = n_skipped = 0; /* Write each entity. Some entities may be composed by other entities (like INSERT or BLOCK) */ /* Set transformation for first (index 0) level */ Trans[0].dx = Trans[0].dy = Trans[0].dz = 0; Trans[0].xscale = Trans[0].yscale = Trans[0].zscale = 1; Trans[0].rotang = 0; if (adGetBlockHandle(dwghandle, pspace, AD_PAPERSPACE_HANDLE)) { entlist = adEntityList(dwghandle, pspace); adStartEntityGet(entlist); for (entset = 0; entset < 2; entset++) { do { if (!(retval = adGetEntity(entlist, adenhd, aden))) continue; wrentity(adenhd, aden, 0, entlist, circle_flag->answer); } while (retval == 1); if (entset == 0) { if (adGetBlockHandle(dwghandle, mspace, AD_MODELSPACE_HANDLE)) { entlist = adEntityList(dwghandle, mspace); adStartEntityGet(entlist); } } } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); adCloseFile(dwghandle); adCloseAd2(); Vect_build(&Map, stderr); Vect_close(&Map); if (n_skipped > 0) G_message(_("%d elements skipped (layer name was not in list)"), n_skipped); G_done_msg(_("%d elements processed"), n_elements); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct GModule *module; struct _param { struct Option *dsn, *out, *layer, *spat, *where, *min_area; struct Option *snap, *type, *outloc, *cnames; } param; struct _flag { struct Flag *list, *tlist, *no_clean, *z, *notab, *region; struct Flag *over, *extend, *formats, *tolower, *no_import; } flag; int i, j, layer, arg_s_num, nogeom, ncnames; float xmin, ymin, xmax, ymax; int ncols = 0, type; double min_area, snap; char buf[2000], namebuf[2000], tempvect[GNAME_MAX]; char *separator; struct Key_Value *loc_proj_info, *loc_proj_units; struct Key_Value *proj_info, *proj_units; struct Cell_head cellhd, loc_wind, cur_wind; char error_msg[8192]; /* Vector */ struct Map_info Map, Tmp, *Out; int cat; /* Attributes */ struct field_info *Fi; dbDriver *driver; dbString sql, strval; int dim, with_z; /* OGR */ OGRDataSourceH Ogr_ds; OGRLayerH Ogr_layer; OGRFieldDefnH Ogr_field; char *Ogr_fieldname; OGRFieldType Ogr_ftype; OGRFeatureH Ogr_feature; OGRFeatureDefnH Ogr_featuredefn; OGRGeometryH Ogr_geometry, Ogr_oRing, poSpatialFilter; OGRSpatialReferenceH Ogr_projection; OGREnvelope oExt; OGRwkbGeometryType Ogr_geom_type; int OFTIntegerListlength; char *output; char **layer_names; /* names of layers to be imported */ int *layers; /* layer indexes */ int nlayers; /* number of layers to import */ char **available_layer_names; /* names of layers to be imported */ int navailable_layers; int layer_id; unsigned int n_features, feature_count; int overwrite; double area_size; int use_tmp_vect; xmin = ymin = xmax = ymax = 0.0; loc_proj_info = loc_proj_units = NULL; Ogr_ds = Ogr_oRing = poSpatialFilter = NULL; OFTIntegerListlength = 40; /* hack due to limitation in OGR */ area_size = 0.0; use_tmp_vect = FALSE; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("import")); module->description = _("Converts vector data into a GRASS vector map using OGR library."); param.dsn = G_define_option(); param.dsn->key = "dsn"; param.dsn->type = TYPE_STRING; param.dsn->required =YES; param.dsn->label = _("OGR datasource name"); param.dsn->description = _("Examples:\n" "\t\tESRI Shapefile: directory containing shapefiles\n" "\t\tMapInfo File: directory containing mapinfo files"); param.layer = G_define_option(); param.layer->key = "layer"; param.layer->type = TYPE_STRING; param.layer->required = NO; param.layer->multiple = YES; param.layer->label = _("OGR layer name. If not given, all available layers are imported"); param.layer->description = _("Examples:\n" "\t\tESRI Shapefile: shapefile name\n" "\t\tMapInfo File: mapinfo file name"); param.layer->guisection = _("Selection"); param.out = G_define_standard_option(G_OPT_V_OUTPUT); param.out->required = NO; param.out->guisection = _("Output"); param.spat = G_define_option(); param.spat->key = "spatial"; param.spat->type = TYPE_DOUBLE; param.spat->multiple = YES; param.spat->required = NO; param.spat->key_desc = "xmin,ymin,xmax,ymax"; param.spat->label = _("Import subregion only"); param.spat->guisection = _("Selection"); param.spat->description = _("Format: xmin,ymin,xmax,ymax - usually W,S,E,N"); param.where = G_define_standard_option(G_OPT_DB_WHERE); param.where->guisection = _("Selection"); param.min_area = G_define_option(); param.min_area->key = "min_area"; param.min_area->type = TYPE_DOUBLE; param.min_area->required = NO; param.min_area->answer = "0.0001"; param.min_area->label = _("Minimum size of area to be imported (square units)"); param.min_area->guisection = _("Selection"); param.min_area->description = _("Smaller areas and " "islands are ignored. Should be greater than snap^2"); param.type = G_define_standard_option(G_OPT_V_TYPE); param.type->options = "point,line,boundary,centroid"; param.type->answer = ""; param.type->description = _("Optionally change default input type"); param.type->descriptions = _("point;import area centroids as points;" "line;import area boundaries as lines;" "boundary;import lines as area boundaries;" "centroid;import points as centroids"); param.type->guisection = _("Selection"); param.snap = G_define_option(); param.snap->key = "snap"; param.snap->type = TYPE_DOUBLE; param.snap->required = NO; param.snap->answer = "-1"; param.snap->label = _("Snapping threshold for boundaries"); param.snap->description = _("'-1' for no snap"); param.outloc = G_define_option(); param.outloc->key = "location"; param.outloc->type = TYPE_STRING; param.outloc->required = NO; param.outloc->description = _("Name for new location to create"); param.outloc->key_desc = "name"; param.cnames = G_define_option(); param.cnames->key = "cnames"; param.cnames->type = TYPE_STRING; param.cnames->required = NO; param.cnames->multiple = YES; param.cnames->description = _("List of column names to be used instead of original names, " "first is used for category column"); param.cnames->guisection = _("Attributes"); flag.list = G_define_flag(); flag.list->key = 'l'; flag.list->description = _("List available OGR layers in data source and exit"); flag.list->suppress_required = YES; flag.list->guisection = _("Print"); flag.tlist = G_define_flag(); flag.tlist->key = 'a'; flag.tlist->description = _("List available OGR layers including feature types " "in data source and exit"); flag.tlist->suppress_required = YES; flag.tlist->guisection = _("Print"); flag.formats = G_define_flag(); flag.formats->key = 'f'; flag.formats->description = _("List supported formats and exit"); flag.formats->suppress_required = YES; flag.formats->guisection = _("Print"); /* if using -c, you lose topological information ! */ flag.no_clean = G_define_flag(); flag.no_clean->key = 'c'; flag.no_clean->description = _("Do not clean polygons (not recommended)"); flag.no_clean->guisection = _("Output"); flag.z = G_define_flag(); flag.z->key = 'z'; flag.z->description = _("Create 3D output"); flag.z->guisection = _("Output"); flag.notab = G_define_flag(); flag.notab->key = 't'; flag.notab->description = _("Do not create attribute table"); flag.notab->guisection = _("Attributes"); flag.over = G_define_flag(); flag.over->key = 'o'; flag.over->description = _("Override dataset projection (use location's projection)"); flag.region = G_define_flag(); flag.region->key = 'r'; flag.region->guisection = _("Selection"); flag.region->description = _("Limit import to the current region"); flag.extend = G_define_flag(); flag.extend->key = 'e'; flag.extend->description = _("Extend location extents based on new dataset"); flag.tolower = G_define_flag(); flag.tolower->key = 'w'; flag.tolower->description = _("Change column names to lowercase characters"); flag.tolower->guisection = _("Attributes"); flag.no_import = G_define_flag(); flag.no_import->key = 'i'; flag.no_import->description = _("Create the location specified by the \"location\" parameter and exit." " Do not import the vector data."); /* The parser checks if the map already exists in current mapset, this is * wrong if location options is used, so we switch out the check and do it * in the module after the parser */ overwrite = G_check_overwrite(argc, argv); if (G_parser(argc, argv)) exit(EXIT_FAILURE); G_begin_polygon_area_calculations(); /* Used in geom() */ OGRRegisterAll(); /* list supported formats */ if (flag.formats->answer) { int iDriver; G_message(_("Available OGR Drivers:")); for (iDriver = 0; iDriver < OGRGetDriverCount(); iDriver++) { OGRSFDriverH poDriver = OGRGetDriver(iDriver); const char *pszRWFlag; if (OGR_Dr_TestCapability(poDriver, ODrCCreateDataSource)) pszRWFlag = "rw"; else pszRWFlag = "ro"; fprintf(stdout, " %s (%s): %s\n", OGR_Dr_GetName(poDriver), pszRWFlag, OGR_Dr_GetName(poDriver)); } exit(EXIT_SUCCESS); } if (param.dsn->answer == NULL) { G_fatal_error(_("Required parameter <%s> not set"), param.dsn->key); } min_area = atof(param.min_area->answer); snap = atof(param.snap->answer); type = Vect_option_to_types(param.type); ncnames = 0; if (param.cnames->answers) { i = 0; while (param.cnames->answers[i++]) { ncnames++; } } /* Open OGR DSN */ Ogr_ds = NULL; if (strlen(param.dsn->answer) > 0) Ogr_ds = OGROpen(param.dsn->answer, FALSE, NULL); if (Ogr_ds == NULL) G_fatal_error(_("Unable to open data source <%s>"), param.dsn->answer); /* Make a list of available layers */ navailable_layers = OGR_DS_GetLayerCount(Ogr_ds); available_layer_names = (char **)G_malloc(navailable_layers * sizeof(char *)); if (flag.list->answer || flag.tlist->answer) G_message(_("Data source <%s> (format '%s') contains %d layers:"), param.dsn->answer, OGR_Dr_GetName(OGR_DS_GetDriver(Ogr_ds)), navailable_layers); for (i = 0; i < navailable_layers; i++) { Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i); Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer); Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn); available_layer_names[i] = G_store((char *)OGR_FD_GetName(Ogr_featuredefn)); if (flag.tlist->answer) fprintf(stdout, "%s (%s)\n", available_layer_names[i], OGRGeometryTypeToName(Ogr_geom_type)); else if (flag.list->answer) fprintf(stdout, "%s\n", available_layer_names[i]); } if (flag.list->answer || flag.tlist->answer) { fflush(stdout); exit(EXIT_SUCCESS); } /* Make a list of layers to be imported */ if (param.layer->answer) { /* From option */ nlayers = 0; while (param.layer->answers[nlayers]) nlayers++; layer_names = (char **)G_malloc(nlayers * sizeof(char *)); layers = (int *)G_malloc(nlayers * sizeof(int)); for (i = 0; i < nlayers; i++) { layer_names[i] = G_store(param.layer->answers[i]); /* Find it in the source */ layers[i] = -1; for (j = 0; j < navailable_layers; j++) { if (strcmp(available_layer_names[j], layer_names[i]) == 0) { layers[i] = j; break; } } if (layers[i] == -1) G_fatal_error(_("Layer <%s> not available"), layer_names[i]); } } else { /* use list of all layers */ nlayers = navailable_layers; layer_names = available_layer_names; layers = (int *)G_malloc(nlayers * sizeof(int)); for (i = 0; i < nlayers; i++) layers[i] = i; } if (param.out->answer) { output = G_store(param.out->answer); } else { if (nlayers < 1) G_fatal_error(_("No OGR layers available")); output = G_store(layer_names[0]); G_message(_("All available OGR layers will be imported into vector map <%s>"), output); } if (!param.outloc->answer) { /* Check if the map exists */ if (G_find_vector2(output, G_mapset()) && !overwrite) G_fatal_error(_("Vector map <%s> already exists"), output); } /* Get first imported layer to use for extents and projection check */ Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layers[0]); if (flag.region->answer) { if (param.spat->answer) G_fatal_error(_("Select either the current region flag or the spatial option, not both")); G_get_window(&cur_wind); xmin = cur_wind.west; xmax = cur_wind.east; ymin = cur_wind.south; ymax = cur_wind.north; } if (param.spat->answer) { /* See as reference: gdal/ogr/ogr_capi_test.c */ /* cut out a piece of the map */ /* order: xmin,ymin,xmax,ymax */ arg_s_num = 0; i = 0; while (param.spat->answers[i]) { if (i == 0) xmin = atof(param.spat->answers[i]); if (i == 1) ymin = atof(param.spat->answers[i]); if (i == 2) xmax = atof(param.spat->answers[i]); if (i == 3) ymax = atof(param.spat->answers[i]); arg_s_num++; i++; } if (arg_s_num != 4) G_fatal_error(_("4 parameters required for 'spatial' parameter")); } if (param.spat->answer || flag.region->answer) { G_debug(2, "cut out with boundaries: xmin:%f ymin:%f xmax:%f ymax:%f", xmin, ymin, xmax, ymax); /* in theory this could be an irregular polygon */ poSpatialFilter = OGR_G_CreateGeometry(wkbPolygon); Ogr_oRing = OGR_G_CreateGeometry(wkbLinearRing); OGR_G_AddPoint(Ogr_oRing, xmin, ymin, 0.0); OGR_G_AddPoint(Ogr_oRing, xmin, ymax, 0.0); OGR_G_AddPoint(Ogr_oRing, xmax, ymax, 0.0); OGR_G_AddPoint(Ogr_oRing, xmax, ymin, 0.0); OGR_G_AddPoint(Ogr_oRing, xmin, ymin, 0.0); OGR_G_AddGeometryDirectly(poSpatialFilter, Ogr_oRing); OGR_L_SetSpatialFilter(Ogr_layer, poSpatialFilter); } if (param.where->answer) { /* select by attribute */ OGR_L_SetAttributeFilter(Ogr_layer, param.where->answer); } /* fetch boundaries */ if ((OGR_L_GetExtent(Ogr_layer, &oExt, 1)) == OGRERR_NONE) { G_get_window(&cellhd); cellhd.north = oExt.MaxY; cellhd.south = oExt.MinY; cellhd.west = oExt.MinX; cellhd.east = oExt.MaxX; cellhd.rows = 20; /* TODO - calculate useful values */ cellhd.cols = 20; cellhd.ns_res = (cellhd.north - cellhd.south) / cellhd.rows; cellhd.ew_res = (cellhd.east - cellhd.west) / cellhd.cols; } else { cellhd.north = 1.; cellhd.south = 0.; cellhd.west = 0.; cellhd.east = 1.; cellhd.top = 1.; cellhd.bottom = 1.; cellhd.rows = 1; cellhd.rows3 = 1; cellhd.cols = 1; cellhd.cols3 = 1; cellhd.depths = 1; cellhd.ns_res = 1.; cellhd.ns_res3 = 1.; cellhd.ew_res = 1.; cellhd.ew_res3 = 1.; cellhd.tb_res = 1.; } /* suppress boundary splitting ? */ if (flag.no_clean->answer) { split_distance = -1.; } else { split_distance = 0.; area_size = sqrt((cellhd.east - cellhd.west) * (cellhd.north - cellhd.south)); } /* Fetch input map projection in GRASS form. */ proj_info = NULL; proj_units = NULL; Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer); /* should not be freed later */ /* Do we need to create a new location? */ if (param.outloc->answer != NULL) { /* Convert projection information non-interactively as we can't * assume the user has a terminal open */ if (GPJ_osr_to_grass(&cellhd, &proj_info, &proj_units, Ogr_projection, 0) < 0) { G_fatal_error(_("Unable to convert input map projection to GRASS " "format; cannot create new location.")); } else { G_make_location(param.outloc->answer, &cellhd, proj_info, proj_units, NULL); G_message(_("Location <%s> created"), param.outloc->answer); } /* If the i flag is set, clean up? and exit here */ if(flag.no_import->answer) { exit(EXIT_SUCCESS); } } else { int err = 0; /* Projection only required for checking so convert non-interactively */ if (GPJ_osr_to_grass(&cellhd, &proj_info, &proj_units, Ogr_projection, 0) < 0) G_warning(_("Unable to convert input map projection information to " "GRASS format for checking")); /* Does the projection of the current location match the dataset? */ /* G_get_window seems to be unreliable if the location has been changed */ G__get_window(&loc_wind, "", "DEFAULT_WIND", "PERMANENT"); /* fetch LOCATION PROJ info */ if (loc_wind.proj != PROJECTION_XY) { loc_proj_info = G_get_projinfo(); loc_proj_units = G_get_projunits(); } if (flag.over->answer) { cellhd.proj = loc_wind.proj; cellhd.zone = loc_wind.zone; G_message(_("Over-riding projection check")); } else if (loc_wind.proj != cellhd.proj || (err = G_compare_projections(loc_proj_info, loc_proj_units, proj_info, proj_units)) != TRUE) { int i_value; strcpy(error_msg, _("Projection of dataset does not" " appear to match current location.\n\n")); /* TODO: output this info sorted by key: */ if (loc_wind.proj != cellhd.proj || err != -2) { if (loc_proj_info != NULL) { strcat(error_msg, _("GRASS LOCATION PROJ_INFO is:\n")); for (i_value = 0; i_value < loc_proj_info->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", loc_proj_info->key[i_value], loc_proj_info->value[i_value]); strcat(error_msg, "\n"); } if (proj_info != NULL) { strcat(error_msg, _("Import dataset PROJ_INFO is:\n")); for (i_value = 0; i_value < proj_info->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", proj_info->key[i_value], proj_info->value[i_value]); } else { strcat(error_msg, _("Import dataset PROJ_INFO is:\n")); if (cellhd.proj == PROJECTION_XY) sprintf(error_msg + strlen(error_msg), "Dataset proj = %d (unreferenced/unknown)\n", cellhd.proj); else if (cellhd.proj == PROJECTION_LL) sprintf(error_msg + strlen(error_msg), "Dataset proj = %d (lat/long)\n", cellhd.proj); else if (cellhd.proj == PROJECTION_UTM) sprintf(error_msg + strlen(error_msg), "Dataset proj = %d (UTM), zone = %d\n", cellhd.proj, cellhd.zone); else if (cellhd.proj == PROJECTION_SP) sprintf(error_msg + strlen(error_msg), "Dataset proj = %d (State Plane), zone = %d\n", cellhd.proj, cellhd.zone); else sprintf(error_msg + strlen(error_msg), "Dataset proj = %d (unknown), zone = %d\n", cellhd.proj, cellhd.zone); } } else { if (loc_proj_units != NULL) { strcat(error_msg, "GRASS LOCATION PROJ_UNITS is:\n"); for (i_value = 0; i_value < loc_proj_units->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", loc_proj_units->key[i_value], loc_proj_units->value[i_value]); strcat(error_msg, "\n"); } if (proj_units != NULL) { strcat(error_msg, "Import dataset PROJ_UNITS is:\n"); for (i_value = 0; i_value < proj_units->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", proj_units->key[i_value], proj_units->value[i_value]); } } sprintf(error_msg + strlen(error_msg), _("\nYou can use the -o flag to %s to override this projection check.\n"), G_program_name()); strcat(error_msg, _("Consider generating a new location with 'location' parameter" " from input data set.\n")); G_fatal_error(error_msg); } else { G_message(_("Projection of input dataset and current location " "appear to match")); } } db_init_string(&sql); db_init_string(&strval); /* open output vector */ /* strip any @mapset from vector output name */ G_find_vector(output, G_mapset()); Vect_open_new(&Map, output, flag.z->answer != 0); Out = ⤅ n_polygon_boundaries = 0; if (!flag.no_clean->answer) { /* check if we need a tmp vector */ /* estimate distance for boundary splitting --> */ for (layer = 0; layer < nlayers; layer++) { layer_id = layers[layer]; Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id); Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer); n_features = feature_count = 0; n_features = OGR_L_GetFeatureCount(Ogr_layer, 1); OGR_L_ResetReading(Ogr_layer); /* count polygons and isles */ G_message(_("Counting polygons for %d features (OGR layer <%s>)..."), n_features, layer_names[layer]); while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) { G_percent(feature_count++, n_features, 1); /* show something happens */ /* Geometry */ Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature); if (Ogr_geometry != NULL) { poly_count(Ogr_geometry, (type & GV_BOUNDARY)); } OGR_F_Destroy(Ogr_feature); } } G_debug(1, "n polygon boundaries: %d", n_polygon_boundaries); if (n_polygon_boundaries > 50) { split_distance = area_size / log(n_polygon_boundaries); /* divisor is the handle: increase divisor to decrease split_distance */ split_distance = split_distance / 5.; G_debug(1, "root of area size: %f", area_size); G_verbose_message(_("Boundary splitting distance in map units: %G"), split_distance); } /* <-- estimate distance for boundary splitting */ use_tmp_vect = n_polygon_boundaries > 0; if (use_tmp_vect) { /* open temporary vector, do the work in the temporary vector * at the end copy alive lines to output vector * in case of polygons this reduces the coor file size by a factor of 2 to 5 * only needed when cleaning polygons */ sprintf(tempvect, "%s_tmp", output); G_verbose_message(_("Using temporary vector <%s>"), tempvect); Vect_open_new(&Tmp, tempvect, flag.z->answer != 0); Out = &Tmp; } } Vect_hist_command(&Map); /* Points and lines are written immediately with categories. Boundaries of polygons are * written to the vector then cleaned and centroids are calculated for all areas in cleaan vector. * Then second pass through finds all centroids in each polygon feature and adds its category * to the centroid. The result is that one centroids may have 0, 1 ore more categories * of one ore more (more input layers) fields. */ with_z = 0; for (layer = 0; layer < nlayers; layer++) { layer_id = layers[layer]; Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id); Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer); /* Add DB link */ if (!flag.notab->answer) { char *cat_col_name = GV_KEY_COLUMN; if (nlayers == 1) { /* one layer only */ Fi = Vect_default_field_info(&Map, layer + 1, NULL, GV_1TABLE); } else { Fi = Vect_default_field_info(&Map, layer + 1, NULL, GV_MTABLE); } if (ncnames > 0) { cat_col_name = param.cnames->answers[0]; } Vect_map_add_dblink(&Map, layer + 1, layer_names[layer], Fi->table, cat_col_name, Fi->database, Fi->driver); ncols = OGR_FD_GetFieldCount(Ogr_featuredefn); G_debug(2, "%d columns", ncols); /* Create table */ sprintf(buf, "create table %s (%s integer", Fi->table, cat_col_name); db_set_string(&sql, buf); for (i = 0; i < ncols; i++) { Ogr_field = OGR_FD_GetFieldDefn(Ogr_featuredefn, i); Ogr_ftype = OGR_Fld_GetType(Ogr_field); G_debug(3, "Ogr_ftype: %i", Ogr_ftype); /* look up below */ if (i < ncnames - 1) { Ogr_fieldname = G_store(param.cnames->answers[i + 1]); } else { /* Change column names to [A-Za-z][A-Za-z0-9_]* */ Ogr_fieldname = G_store(OGR_Fld_GetNameRef(Ogr_field)); G_debug(3, "Ogr_fieldname: '%s'", Ogr_fieldname); G_str_to_sql(Ogr_fieldname); G_debug(3, "Ogr_fieldname: '%s'", Ogr_fieldname); } /* avoid that we get the 'cat' column twice */ if (strcmp(Ogr_fieldname, GV_KEY_COLUMN) == 0) { sprintf(namebuf, "%s_", Ogr_fieldname); Ogr_fieldname = G_store(namebuf); } /* captial column names are a pain in SQL */ if (flag.tolower->answer) G_str_to_lower(Ogr_fieldname); if (strcmp(OGR_Fld_GetNameRef(Ogr_field), Ogr_fieldname) != 0) { G_warning(_("Column name changed: '%s' -> '%s'"), OGR_Fld_GetNameRef(Ogr_field), Ogr_fieldname); } /** Simple 32bit integer OFTInteger = 0 **/ /** List of 32bit integers OFTIntegerList = 1 **/ /** Double Precision floating point OFTReal = 2 **/ /** List of doubles OFTRealList = 3 **/ /** String of ASCII chars OFTString = 4 **/ /** Array of strings OFTStringList = 5 **/ /** Double byte string (unsupported) OFTWideString = 6 **/ /** List of wide strings (unsupported) OFTWideStringList = 7 **/ /** Raw Binary data (unsupported) OFTBinary = 8 **/ /** OFTDate = 9 **/ /** OFTTime = 10 **/ /** OFTDateTime = 11 **/ if (Ogr_ftype == OFTInteger) { sprintf(buf, ", %s integer", Ogr_fieldname); } else if (Ogr_ftype == OFTIntegerList) { /* hack: treat as string */ sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname, OFTIntegerListlength); G_warning(_("Writing column <%s> with fixed length %d chars (may be truncated)"), Ogr_fieldname, OFTIntegerListlength); } else if (Ogr_ftype == OFTReal) { sprintf(buf, ", %s double precision", Ogr_fieldname); #if GDAL_VERSION_NUM >= 1320 } else if (Ogr_ftype == OFTDate) { sprintf(buf, ", %s date", Ogr_fieldname); } else if (Ogr_ftype == OFTTime) { sprintf(buf, ", %s time", Ogr_fieldname); } else if (Ogr_ftype == OFTDateTime) { sprintf(buf, ", %s datetime", Ogr_fieldname); #endif } else if (Ogr_ftype == OFTString) { int fwidth; fwidth = OGR_Fld_GetWidth(Ogr_field); /* TODO: read all records first and find the longest string length */ if (fwidth == 0) { G_warning(_("Width for column %s set to 255 (was not specified by OGR), " "some strings may be truncated!"), Ogr_fieldname); fwidth = 255; } sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname, fwidth); } else if (Ogr_ftype == OFTStringList) { /* hack: treat as string */ sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname, OFTIntegerListlength); G_warning(_("Writing column %s with fixed length %d chars (may be truncated)"), Ogr_fieldname, OFTIntegerListlength); } else { G_warning(_("Column type not supported (%s)"), Ogr_fieldname); buf[0] = 0; } db_append_string(&sql, buf); G_free(Ogr_fieldname); } db_append_string(&sql, ")"); G_debug(3, db_get_string(&sql)); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Map)); if (driver == NULL) { G_fatal_error(_("Unable open database <%s> by driver <%s>"), Vect_subst_var(Fi->database, &Map), Fi->driver); } if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql)); } if (db_create_index2(driver, Fi->table, cat_col_name) != DB_OK) G_warning(_("Unable to create index for table <%s>, key <%s>"), Fi->table, cat_col_name); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Unable to grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); } /* Import feature */ cat = 1; nogeom = 0; OGR_L_ResetReading(Ogr_layer); n_features = feature_count = 0; n_features = OGR_L_GetFeatureCount(Ogr_layer, 1); G_important_message(_("Importing %d features (OGR layer <%s>)..."), n_features, layer_names[layer]); while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) { G_percent(feature_count++, n_features, 1); /* show something happens */ /* Geometry */ Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature); if (Ogr_geometry == NULL) { nogeom++; } else { dim = OGR_G_GetCoordinateDimension(Ogr_geometry); if (dim > 2) with_z = 1; geom(Ogr_geometry, Out, layer + 1, cat, min_area, type, flag.no_clean->answer); } /* Attributes */ if (!flag.notab->answer) { sprintf(buf, "insert into %s values ( %d", Fi->table, cat); db_set_string(&sql, buf); for (i = 0; i < ncols; i++) { Ogr_field = OGR_FD_GetFieldDefn(Ogr_featuredefn, i); Ogr_ftype = OGR_Fld_GetType(Ogr_field); if (OGR_F_IsFieldSet(Ogr_feature, i)) { if (Ogr_ftype == OFTInteger || Ogr_ftype == OFTReal) { sprintf(buf, ", %s", OGR_F_GetFieldAsString(Ogr_feature, i)); #if GDAL_VERSION_NUM >= 1320 /* should we use OGR_F_GetFieldAsDateTime() here ? */ } else if (Ogr_ftype == OFTDate || Ogr_ftype == OFTTime || Ogr_ftype == OFTDateTime) { char *newbuf; db_set_string(&strval, (char *) OGR_F_GetFieldAsString(Ogr_feature, i)); db_double_quote_string(&strval); sprintf(buf, ", '%s'", db_get_string(&strval)); newbuf = G_str_replace(buf, "/", "-"); /* fix 2001/10/21 to 2001-10-21 */ sprintf(buf, "%s", newbuf); #endif } else if (Ogr_ftype == OFTString || Ogr_ftype == OFTIntegerList) { db_set_string(&strval, (char *) OGR_F_GetFieldAsString(Ogr_feature, i)); db_double_quote_string(&strval); sprintf(buf, ", '%s'", db_get_string(&strval)); } } else { /* G_warning (_("Column value not set" )); */ if (Ogr_ftype == OFTInteger || Ogr_ftype == OFTReal) { sprintf(buf, ", NULL"); #if GDAL_VERSION_NUM >= 1320 } else if (Ogr_ftype == OFTString || Ogr_ftype == OFTIntegerList || Ogr_ftype == OFTDate) { #else } else if (Ogr_ftype == OFTString || Ogr_ftype == OFTIntegerList) { #endif sprintf(buf, ", ''"); } } db_append_string(&sql, buf); } db_append_string(&sql, " )"); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Cannot insert new row: %s"), db_get_string(&sql)); } } OGR_F_Destroy(Ogr_feature); cat++; } G_percent(1, 1, 1); /* finish it */ if (!flag.notab->answer) { db_commit_transaction(driver); db_close_database_shutdown_driver(driver); } if (nogeom > 0) G_warning(_("%d %s without geometry"), nogeom, nogeom == 1 ? "feature" : "features"); } separator = "-----------------------------------------------------"; G_message("%s", separator); if (use_tmp_vect) { /* TODO: is it necessary to build here? probably not, consumes time */ /* GV_BUILD_BASE is sufficient to toggle boundary cleaning */ Vect_build_partial(&Tmp, GV_BUILD_BASE); } if (use_tmp_vect && !flag.no_clean->answer && Vect_get_num_primitives(Out, GV_BOUNDARY) > 0) { int ret, centr, ncentr, otype, n_overlaps, n_nocat; CENTR *Centr; struct spatial_index si; double x, y, total_area, overlap_area, nocat_area; struct bound_box box; struct line_pnts *Points; int nmodif; Points = Vect_new_line_struct(); G_message("%s", separator); G_warning(_("Cleaning polygons, result is not guaranteed!")); if (snap >= 0) { G_message("%s", separator); G_message(_("Snapping boundaries (threshold = %.3e)..."), snap); Vect_snap_lines(&Tmp, GV_BOUNDARY, snap, NULL); } /* It is not to clean to snap centroids, but I have seen data with 2 duplicate polygons * (as far as decimal places were printed) and centroids were not identical */ /* Disabled, because overlapping polygons result in many duplicate centroids anyway */ /* fprintf ( stderr, separator ); fprintf ( stderr, "Snap centroids (threshold 0.000001):\n" ); Vect_snap_lines ( &Map, GV_CENTROID, 0.000001, NULL, stderr ); */ G_message("%s", separator); G_message(_("Breaking polygons...")); Vect_break_polygons(&Tmp, GV_BOUNDARY, NULL); /* It is important to remove also duplicate centroids in case of duplicate input polygons */ G_message("%s", separator); G_message(_("Removing duplicates...")); Vect_remove_duplicates(&Tmp, GV_BOUNDARY | GV_CENTROID, NULL); /* in non-pathological cases, the bulk of the cleaning is now done */ /* Vect_clean_small_angles_at_nodes() can change the geometry so that new intersections * are created. We must call Vect_break_lines(), Vect_remove_duplicates() * and Vect_clean_small_angles_at_nodes() until no more small angles are found */ do { G_message("%s", separator); G_message(_("Breaking boundaries...")); Vect_break_lines(&Tmp, GV_BOUNDARY, NULL); G_message("%s", separator); G_message(_("Removing duplicates...")); Vect_remove_duplicates(&Tmp, GV_BOUNDARY, NULL); G_message("%s", separator); G_message(_("Cleaning boundaries at nodes...")); nmodif = Vect_clean_small_angles_at_nodes(&Tmp, GV_BOUNDARY, NULL); } while (nmodif > 0); /* merge boundaries */ G_message("%s", separator); G_message(_("Merging boundaries...")); Vect_merge_lines(&Tmp, GV_BOUNDARY, NULL, NULL); G_message("%s", separator); if (type & GV_BOUNDARY) { /* that means lines were converted to boundaries */ G_message(_("Changing boundary dangles to lines...")); Vect_chtype_dangles(&Tmp, -1.0, NULL); } else { G_message(_("Removing dangles...")); Vect_remove_dangles(&Tmp, GV_BOUNDARY, -1.0, NULL); } G_message("%s", separator); if (type & GV_BOUNDARY) { G_message(_("Changing boundary bridges to lines...")); Vect_chtype_bridges(&Tmp, NULL); } else { G_message(_("Removing bridges...")); Vect_remove_bridges(&Tmp, NULL); } /* Boundaries are hopefully clean, build areas */ G_message("%s", separator); Vect_build_partial(&Tmp, GV_BUILD_ATTACH_ISLES); /* Calculate new centroids for all areas, centroids have the same id as area */ ncentr = Vect_get_num_areas(&Tmp); G_debug(3, "%d centroids/areas", ncentr); Centr = (CENTR *) G_calloc(ncentr + 1, sizeof(CENTR)); Vect_spatial_index_init(&si, 0); for (centr = 1; centr <= ncentr; centr++) { Centr[centr].valid = 0; Centr[centr].cats = Vect_new_cats_struct(); ret = Vect_get_point_in_area(&Tmp, centr, &x, &y); if (ret < 0) { G_warning(_("Unable to calculate area centroid")); continue; } Centr[centr].x = x; Centr[centr].y = y; Centr[centr].valid = 1; box.N = box.S = y; box.E = box.W = x; box.T = box.B = 0; Vect_spatial_index_add_item(&si, centr, &box); } /* Go through all layers and find centroids for each polygon */ for (layer = 0; layer < nlayers; layer++) { G_message("%s", separator); G_message(_("Finding centroids for OGR layer <%s>..."), layer_names[layer]); layer_id = layers[layer]; Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id); n_features = OGR_L_GetFeatureCount(Ogr_layer, 1); OGR_L_ResetReading(Ogr_layer); cat = 0; /* field = layer + 1 */ G_percent(cat, n_features, 2); while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) { cat++; G_percent(cat, n_features, 2); /* Geometry */ Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature); if (Ogr_geometry != NULL) { centroid(Ogr_geometry, Centr, &si, layer + 1, cat, min_area, type); } OGR_F_Destroy(Ogr_feature); } } /* Write centroids */ G_message("%s", separator); G_message(_("Writing centroids...")); n_overlaps = n_nocat = 0; total_area = overlap_area = nocat_area = 0.0; for (centr = 1; centr <= ncentr; centr++) { double area; G_percent(centr, ncentr, 2); area = Vect_get_area_area(&Tmp, centr); total_area += area; if (!(Centr[centr].valid)) { continue; } if (Centr[centr].cats->n_cats == 0) { nocat_area += area; n_nocat++; continue; } if (Centr[centr].cats->n_cats > 1) { Vect_cat_set(Centr[centr].cats, nlayers + 1, Centr[centr].cats->n_cats); overlap_area += area; n_overlaps++; } Vect_reset_line(Points); Vect_append_point(Points, Centr[centr].x, Centr[centr].y, 0.0); if (type & GV_POINT) otype = GV_POINT; else otype = GV_CENTROID; Vect_write_line(&Tmp, otype, Points, Centr[centr].cats); } if (Centr) G_free(Centr); Vect_spatial_index_destroy(&si); if (n_overlaps > 0) { G_warning(_("%d areas represent more (overlapping) features, because polygons overlap " "in input layer(s). Such areas are linked to more than 1 row in attribute table. " "The number of features for those areas is stored as category in layer %d"), n_overlaps, nlayers + 1); } G_message("%s", separator); Vect_hist_write(&Map, separator); Vect_hist_write(&Map, "\n"); sprintf(buf, _("%d input polygons\n"), n_polygons); G_message(_("%d input polygons"), n_polygons); Vect_hist_write(&Map, buf); sprintf(buf, _("Total area: %G (%d areas)\n"), total_area, ncentr); G_message(_("Total area: %G (%d areas)"), total_area, ncentr); Vect_hist_write(&Map, buf); sprintf(buf, _("Overlapping area: %G (%d areas)\n"), overlap_area, n_overlaps); G_message(_("Overlapping area: %G (%d areas)"), overlap_area, n_overlaps); Vect_hist_write(&Map, buf); sprintf(buf, _("Area without category: %G (%d areas)\n"), nocat_area, n_nocat); G_message(_("Area without category: %G (%d areas)"), nocat_area, n_nocat); Vect_hist_write(&Map, buf); G_message("%s", separator); } /* needed? * OGR_DS_Destroy( Ogr_ds ); */ if (use_tmp_vect) { /* Copy temporary vector to output vector */ Vect_copy_map_lines(&Tmp, &Map); /* release memory occupied by topo, we may need that memory for main output */ Vect_set_release_support(&Tmp); Vect_close(&Tmp); Vect_delete(tempvect); } Vect_build(&Map); Vect_close(&Map); /* -------------------------------------------------------------------- */ /* Extend current window based on dataset. */ /* -------------------------------------------------------------------- */ if (flag.extend->answer) { G_get_default_window(&loc_wind); loc_wind.north = MAX(loc_wind.north, cellhd.north); loc_wind.south = MIN(loc_wind.south, cellhd.south); loc_wind.west = MIN(loc_wind.west, cellhd.west); loc_wind.east = MAX(loc_wind.east, cellhd.east); loc_wind.rows = (int)ceil((loc_wind.north - loc_wind.south) / loc_wind.ns_res); loc_wind.south = loc_wind.north - loc_wind.rows * loc_wind.ns_res; loc_wind.cols = (int)ceil((loc_wind.east - loc_wind.west) / loc_wind.ew_res); loc_wind.east = loc_wind.west + loc_wind.cols * loc_wind.ew_res; G__put_window(&loc_wind, "../PERMANENT", "DEFAULT_WIND"); } if (with_z && !flag.z->answer) G_warning(_("Input data contains 3D features. Created vector is 2D only, " "use -z flag to import 3D vector.")); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct Map_info In, Out, Buf; struct line_pnts *Points; struct line_cats *Cats, *BCats; char bufname[GNAME_MAX]; struct GModule *module; struct Option *in_opt, *out_opt, *type_opt, *dista_opt, *distb_opt, *angle_opt; struct Flag *straight_flag, *nocaps_flag; struct Option *tol_opt, *bufcol_opt, *scale_opt, *field_opt; int verbose; double da, db, dalpha, tolerance, unit_tolerance; int type; int i, ret, nareas, area, nlines, line; char *Areas, *Lines; int field; struct buf_contours *arr_bc; struct buf_contours_pts arr_bc_pts; int buffers_count = 0, line_id; struct spatial_index si; struct bound_box bbox; /* Attributes if sizecol is used */ int nrec, ctype; struct field_info *Fi; dbDriver *Driver; dbCatValArray cvarr; double size_val, scale; module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); G_add_keyword(_("buffer")); module->description = _("Creates a buffer around vector features of given type."); in_opt = G_define_standard_option(G_OPT_V_INPUT); field_opt = G_define_standard_option(G_OPT_V_FIELD_ALL); field_opt->guisection = _("Selection"); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "point,line,boundary,centroid,area"; type_opt->answer = "point,line,area"; type_opt->guisection = _("Selection"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); dista_opt = G_define_option(); dista_opt->key = "distance"; dista_opt->type = TYPE_DOUBLE; dista_opt->required = NO; dista_opt->description = _("Buffer distance along major axis in map units"); dista_opt->guisection = _("Distance"); distb_opt = G_define_option(); distb_opt->key = "minordistance"; distb_opt->type = TYPE_DOUBLE; distb_opt->required = NO; distb_opt->description = _("Buffer distance along minor axis in map units"); distb_opt->guisection = _("Distance"); angle_opt = G_define_option(); angle_opt->key = "angle"; angle_opt->type = TYPE_DOUBLE; angle_opt->required = NO; angle_opt->answer = "0"; angle_opt->description = _("Angle of major axis in degrees"); angle_opt->guisection = _("Distance"); bufcol_opt = G_define_standard_option(G_OPT_DB_COLUMN); bufcol_opt->key = "bufcolumn"; bufcol_opt->description = _("Name of column to use for buffer distances"); bufcol_opt->guisection = _("Distance"); scale_opt = G_define_option(); scale_opt->key = "scale"; scale_opt->type = TYPE_DOUBLE; scale_opt->required = NO; scale_opt->answer = "1.0"; scale_opt->description = _("Scaling factor for attribute column values"); scale_opt->guisection = _("Distance"); tol_opt = G_define_option(); tol_opt->key = "tolerance"; tol_opt->type = TYPE_DOUBLE; tol_opt->required = NO; tol_opt->answer = "0.01"; tol_opt->description = _("Maximum distance between theoretical arc and polygon segments as multiple of buffer"); tol_opt->guisection = _("Distance"); straight_flag = G_define_flag(); straight_flag->key = 's'; straight_flag->description = _("Make outside corners straight"); nocaps_flag = G_define_flag(); nocaps_flag->key = 'c'; nocaps_flag->description = _("Don't make caps at the ends of polylines"); G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); type = Vect_option_to_types(type_opt); if ((dista_opt->answer && bufcol_opt->answer) || (!(dista_opt->answer || bufcol_opt->answer))) G_fatal_error(_("Select a buffer distance/minordistance/angle " "or column, but not both.")); if (bufcol_opt->answer) G_warning(_("The bufcol option may contain bugs during the cleaning " "step. If you encounter problems, use the debug " "option or clean manually with v.clean tool=break; " "v.category step=0; v.extract -d type=area")); if (field_opt->answer) field = Vect_get_field_number(&In, field_opt->answer); else field = -1; if (bufcol_opt->answer && field == -1) G_fatal_error(_("The bufcol option requires a valid layer.")); tolerance = atof(tol_opt->answer); if (tolerance <= 0) G_fatal_error(_("The tolerance must be > 0.")); if (adjust_tolerance(&tolerance)) G_warning(_("The tolerance was reset to %g"), tolerance); scale = atof(scale_opt->answer); if (scale <= 0.0) G_fatal_error("Illegal scale value"); da = db = dalpha = 0; if (dista_opt->answer) { da = atof(dista_opt->answer); if (distb_opt->answer) db = atof(distb_opt->answer); else db = da; if (angle_opt->answer) dalpha = atof(angle_opt->answer); else dalpha = 0; unit_tolerance = tolerance * MIN(da, db); G_verbose_message(_("The tolerance in map units = %g"), unit_tolerance); } Vect_check_input_output_name(in_opt->answer, out_opt->answer, GV_FATAL_EXIT); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); BCats = Vect_new_cats_struct(); Vect_set_open_level(2); /* topology required */ if (1 > Vect_open_old2(&In, in_opt->answer, "", field_opt->answer)) G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer); if (0 > Vect_open_new(&Out, out_opt->answer, WITHOUT_Z)) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); } /* open tmp vector for buffers, needed for cleaning */ sprintf(bufname, "%s_tmp_%d", out_opt->answer, getpid()); if (0 > Vect_open_new(&Buf, bufname, 0)) { Vect_close(&In); Vect_close(&Out); Vect_delete(out_opt->answer); exit(EXIT_FAILURE); } Vect_build_partial(&Buf, GV_BUILD_BASE); /* check and load attribute column data */ if (bufcol_opt->answer) { db_CatValArray_init(&cvarr); Fi = Vect_get_field(&In, field); if (Fi == NULL) G_fatal_error(_("Database connection not defined for layer %d"), 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); /* Note do not check if the column exists in the table because it may be expression */ /* TODO: only select values we need instead of all in column */ nrec = db_select_CatValArray(Driver, Fi->table, Fi->key, bufcol_opt->answer, NULL, &cvarr); if (nrec < 0) G_fatal_error(_("Unable to select data from table <%s>"), Fi->table); G_debug(2, "%d records selected from table", nrec); ctype = cvarr.ctype; if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE) G_fatal_error(_("Column type not supported")); db_close_database_shutdown_driver(Driver); /* Output cats/values list */ for (i = 0; i < cvarr.n_values; i++) { if (ctype == DB_C_TYPE_INT) { G_debug(4, "cat = %d val = %d", cvarr.value[i].cat, cvarr.value[i].val.i); } else if (ctype == DB_C_TYPE_DOUBLE) { G_debug(4, "cat = %d val = %f", cvarr.value[i].cat, cvarr.value[i].val.d); } } } Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); /* Create buffers' boundaries */ nlines = nareas = 0; if ((type & GV_POINTS) || (type & GV_LINES)) nlines += Vect_get_num_primitives(&In, type); if (type & GV_AREA) nareas = Vect_get_num_areas(&In); if (nlines + nareas == 0) { G_warning(_("No features available for buffering. " "Check type option and features available in the input vector.")); exit(EXIT_SUCCESS); } buffers_count = 1; arr_bc = G_malloc((nlines + nareas + 1) * sizeof(struct buf_contours)); Vect_spatial_index_init(&si, 0); /* Lines (and Points) */ if ((type & GV_POINTS) || (type & GV_LINES)) { int ltype; if (nlines > 0) G_message(_("Buffering lines...")); for (line = 1; line <= nlines; line++) { int cat; G_debug(2, "line = %d", line); G_percent(line, nlines, 2); if (!Vect_line_alive(&In, line)) continue; ltype = Vect_read_line(&In, Points, Cats, line); if (!(ltype & type)) continue; if (field > 0 && !Vect_cat_get(Cats, field, &cat)) continue; if (bufcol_opt->answer) { ret = db_CatValArray_get_value_di(&cvarr, cat, &size_val); if (ret != DB_OK) { G_warning(_("No record for category %d in table <%s>"), cat, Fi->table); continue; } if (size_val < 0.0) { G_warning(_("Attribute is of invalid size (%.3f) for category %d"), size_val, cat); continue; } if (size_val == 0.0) continue; da = size_val * scale; db = da; dalpha = 0; unit_tolerance = tolerance * MIN(da, db); G_debug(2, " dynamic buffer size = %.2f", da); G_debug(2, _("The tolerance in map units: %g"), unit_tolerance); } Vect_line_prune(Points); if (ltype & GV_POINTS || Points->n_points == 1) { Vect_point_buffer2(Points->x[0], Points->y[0], da, db, dalpha, !(straight_flag->answer), unit_tolerance, &(arr_bc_pts.oPoints)); Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats); line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats); Vect_destroy_line_struct(arr_bc_pts.oPoints); /* add buffer to spatial index */ Vect_get_line_box(&Buf, line_id, &bbox); Vect_spatial_index_add_item(&si, buffers_count, &bbox); arr_bc[buffers_count].outer = line_id; arr_bc[buffers_count].inner_count = 0; arr_bc[buffers_count].inner = NULL; buffers_count++; } else { Vect_line_buffer2(Points, da, db, dalpha, !(straight_flag->answer), !(nocaps_flag->answer), unit_tolerance, &(arr_bc_pts.oPoints), &(arr_bc_pts.iPoints), &(arr_bc_pts.inner_count)); Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats); line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats); Vect_destroy_line_struct(arr_bc_pts.oPoints); /* add buffer to spatial index */ Vect_get_line_box(&Buf, line_id, &bbox); Vect_spatial_index_add_item(&si, buffers_count, &bbox); arr_bc[buffers_count].outer = line_id; arr_bc[buffers_count].inner_count = arr_bc_pts.inner_count; if (arr_bc_pts.inner_count > 0) { arr_bc[buffers_count].inner = G_malloc(arr_bc_pts.inner_count * sizeof(int)); for (i = 0; i < arr_bc_pts.inner_count; i++) { Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.iPoints[i], BCats); line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.iPoints[i], Cats); Vect_destroy_line_struct(arr_bc_pts.iPoints[i]); /* add buffer to spatial index */ Vect_get_line_box(&Buf, line_id, &bbox); Vect_spatial_index_add_item(&si, buffers_count, &bbox); arr_bc[buffers_count].inner[i] = line_id; } G_free(arr_bc_pts.iPoints); } buffers_count++; } } } /* Areas */ if (type & GV_AREA) { int centroid; if (nareas > 0) G_message(_("Buffering areas...")); for (area = 1; area <= nareas; area++) { int cat; G_percent(area, nareas, 2); if (!Vect_area_alive(&In, area)) continue; centroid = Vect_get_area_centroid(&In, area); if (centroid == 0) continue; Vect_read_line(&In, NULL, Cats, centroid); if (field > 0 && !Vect_cat_get(Cats, field, &cat)) continue; if (bufcol_opt->answer) { ret = db_CatValArray_get_value_di(&cvarr, cat, &size_val); if (ret != DB_OK) { G_warning(_("No record for category %d in table <%s>"), cat, Fi->table); continue; } if (size_val < 0.0) { G_warning(_("Attribute is of invalid size (%.3f) for category %d"), size_val, cat); continue; } if (size_val == 0.0) continue; da = size_val * scale; db = da; dalpha = 0; unit_tolerance = tolerance * MIN(da, db); G_debug(2, " dynamic buffer size = %.2f", da); G_debug(2, _("The tolerance in map units: %g"), unit_tolerance); } Vect_area_buffer2(&In, area, da, db, dalpha, !(straight_flag->answer), !(nocaps_flag->answer), unit_tolerance, &(arr_bc_pts.oPoints), &(arr_bc_pts.iPoints), &(arr_bc_pts.inner_count)); Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats); line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats); Vect_destroy_line_struct(arr_bc_pts.oPoints); /* add buffer to spatial index */ Vect_get_line_box(&Buf, line_id, &bbox); Vect_spatial_index_add_item(&si, buffers_count, &bbox); arr_bc[buffers_count].outer = line_id; arr_bc[buffers_count].inner_count = arr_bc_pts.inner_count; if (arr_bc_pts.inner_count > 0) { arr_bc[buffers_count].inner = G_malloc(arr_bc_pts.inner_count * sizeof(int)); for (i = 0; i < arr_bc_pts.inner_count; i++) { Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.iPoints[i], BCats); line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.iPoints[i], Cats); Vect_destroy_line_struct(arr_bc_pts.iPoints[i]); /* add buffer to spatial index */ Vect_get_line_box(&Buf, line_id, &bbox); Vect_spatial_index_add_item(&si, buffers_count, &bbox); arr_bc[buffers_count].inner[i] = line_id; } G_free(arr_bc_pts.iPoints); } buffers_count++; } } verbose = G_verbose(); G_message(_("Cleaning buffers...")); /* Break lines */ G_message(_("Building parts of topology...")); Vect_build_partial(&Out, GV_BUILD_BASE); G_message(_("Snapping boundaries...")); Vect_snap_lines(&Out, GV_BOUNDARY, 1e-7, NULL); G_message(_("Breaking polygons...")); Vect_break_polygons(&Out, GV_BOUNDARY, NULL); G_message(_("Removing duplicates...")); Vect_remove_duplicates(&Out, GV_BOUNDARY, NULL); do { G_message(_("Breaking boundaries...")); Vect_break_lines(&Out, GV_BOUNDARY, NULL); G_message(_("Removing duplicates...")); Vect_remove_duplicates(&Out, GV_BOUNDARY, NULL); G_message(_("Cleaning boundaries at nodes")); } while (Vect_clean_small_angles_at_nodes(&Out, GV_BOUNDARY, NULL) > 0); /* Dangles and bridges don't seem to be necessary if snapping is small enough. */ /* Still needed for larger buffer distances ? */ /* G_message(_("Removing dangles...")); Vect_remove_dangles(&Out, GV_BOUNDARY, -1, NULL); G_message (_("Removing bridges...")); Vect_remove_bridges(&Out, NULL); */ G_message(_("Attaching islands...")); Vect_build_partial(&Out, GV_BUILD_ATTACH_ISLES); /* Calculate new centroids for all areas */ nareas = Vect_get_num_areas(&Out); Areas = (char *)G_calloc(nareas + 1, sizeof(char)); G_message(_("Calculating centroids for areas...")); G_percent(0, nareas, 2); for (area = 1; area <= nareas; area++) { double x, y; G_percent(area, nareas, 2); G_debug(3, "area = %d", area); if (!Vect_area_alive(&Out, area)) continue; ret = Vect_get_point_in_area(&Out, area, &x, &y); if (ret < 0) { G_warning(_("Cannot calculate area centroid")); continue; } ret = point_in_buffer(arr_bc, &si, &Buf, x, y); if (ret) { G_debug(3, " -> in buffer"); Areas[area] = 1; } } /* Make a list of boundaries to be deleted (both sides inside) */ nlines = Vect_get_num_lines(&Out); G_debug(3, "nlines = %d", nlines); Lines = (char *)G_calloc(nlines + 1, sizeof(char)); G_message(_("Generating list of boundaries to be deleted...")); for (line = 1; line <= nlines; line++) { int j, side[2], areas[2]; G_percent(line, nlines, 2); G_debug(3, "line = %d", line); if (!Vect_line_alive(&Out, line)) continue; Vect_get_line_areas(&Out, line, &side[0], &side[1]); for (j = 0; j < 2; j++) { if (side[j] == 0) { /* area/isle not build */ areas[j] = 0; } else if (side[j] > 0) { /* area */ areas[j] = side[j]; } else { /* < 0 -> island */ areas[j] = Vect_get_isle_area(&Out, abs(side[j])); } } G_debug(3, " areas = %d , %d -> Areas = %d, %d", areas[0], areas[1], Areas[areas[0]], Areas[areas[1]]); if (Areas[areas[0]] && Areas[areas[1]]) Lines[line] = 1; } G_free(Areas); /* Delete boundaries */ G_message(_("Deleting boundaries...")); for (line = 1; line <= nlines; line++) { G_percent(line, nlines, 2); if (!Vect_line_alive(&Out, line)) continue; if (Lines[line]) { G_debug(3, " delete line %d", line); Vect_delete_line(&Out, line); } else { /* delete incorrect boundaries */ int side[2]; Vect_get_line_areas(&Out, line, &side[0], &side[1]); if (!side[0] && !side[1]) Vect_delete_line(&Out, line); } } G_free(Lines); /* Create new centroids */ Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, 1); nareas = Vect_get_num_areas(&Out); G_message(_("Calculating centroids for areas...")); for (area = 1; area <= nareas; area++) { double x, y; G_percent(area, nareas, 2); G_debug(3, "area = %d", area); if (!Vect_area_alive(&Out, area)) continue; ret = Vect_get_point_in_area(&Out, area, &x, &y); if (ret < 0) { G_warning(_("Cannot calculate area centroid")); continue; } ret = point_in_buffer(arr_bc, &si, &Buf, x, y); if (ret) { Vect_reset_line(Points); Vect_append_point(Points, x, y, 0.); Vect_write_line(&Out, GV_CENTROID, Points, Cats); } } /* free arr_bc[] */ /* will only slow down the module for (i = 0; i < buffers_count; i++) { Vect_destroy_line_struct(arr_bc[i].oPoints); for (j = 0; j < arr_bc[i].inner_count; j++) Vect_destroy_line_struct(arr_bc[i].iPoints[j]); G_free(arr_bc[i].iPoints); } */ Vect_spatial_index_destroy(&si); Vect_close(&Buf); Vect_delete(bufname); G_set_verbose(verbose); Vect_close(&In); Vect_build_partial(&Out, GV_BUILD_NONE); Vect_build(&Out); Vect_close(&Out); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int i, j, nlines, type, field, cat; int fd; /* struct Categories RCats; *//* TODO */ struct Cell_head window; RASTER_MAP_TYPE out_type; CELL *cell; DCELL *dcell; double drow, dcol; char buf[2000]; struct Option *vect_opt, *rast_opt, *field_opt, *col_opt, *where_opt; int Cache_size; struct order *cache; int cur_row; struct GModule *module; struct Map_info Map; struct line_pnts *Points; struct line_cats *Cats; int point; int point_cnt; /* number of points in cache */ int outside_cnt; /* points outside region */ int nocat_cnt; /* points inside region but without category */ int dupl_cnt; /* duplicate categories */ struct bound_box box; int *catexst, *cex; struct field_info *Fi; dbString stmt; dbDriver *driver; int select, norec_cnt, update_cnt, upderr_cnt, col_type; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("raster")); G_add_keyword(_("position")); G_add_keyword(_("querying")); G_add_keyword(_("attribute table")); module->description = _("Uploads raster values at positions of vector points to the table."); vect_opt = G_define_standard_option(G_OPT_V_INPUT); vect_opt->key = "vector"; vect_opt->description = _("Name of input vector points map for which to edit attribute table"); rast_opt = G_define_standard_option(G_OPT_R_INPUT); rast_opt->key = "raster"; rast_opt->description = _("Name of existing raster map to be queried"); field_opt = G_define_standard_option(G_OPT_V_FIELD); col_opt = G_define_option(); col_opt->key = "column"; col_opt->type = TYPE_STRING; col_opt->required = YES; col_opt->description = _("Column name (will be updated by raster values)"); where_opt = G_define_standard_option(G_OPT_DB_WHERE); if (G_parser(argc, argv)) exit(EXIT_FAILURE); field = atoi(field_opt->answer); db_init_string(&stmt); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); G_get_window(&window); Vect_region_box(&window, &box); /* T and B set to +/- PORT_DOUBLE_MAX */ /* Open vector */ Vect_set_open_level(2); Vect_open_old(&Map, vect_opt->answer, ""); Fi = Vect_get_field(&Map, field); if (Fi == NULL) G_fatal_error(_("Database connection not defined for layer %d"), field); /* 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); } /* Open raster */ fd = Rast_open_old(rast_opt->answer, ""); out_type = Rast_get_map_type(fd); /* TODO: Later possibly category labels */ /* if ( Rast_read_cats (name, "", &RCats) < 0 ) G_fatal_error ( "Cannot read category file"); */ /* Check column type */ col_type = db_column_Ctype(driver, Fi->table, col_opt->answer); if (col_type == -1) G_fatal_error(_("Column <%s> not found"), col_opt->answer); if (col_type != DB_C_TYPE_INT && col_type != DB_C_TYPE_DOUBLE) G_fatal_error(_("Column type not supported")); if (out_type == CELL_TYPE && col_type == DB_C_TYPE_DOUBLE) G_warning(_("Raster type is integer and column type is float")); if (out_type != CELL_TYPE && col_type == DB_C_TYPE_INT) G_warning(_("Raster type is float and column type is integer, some data lost!!")); /* Read vector points to cache */ Cache_size = Vect_get_num_primitives(&Map, GV_POINT); /* Note: Some space may be wasted (outside region or no category) */ cache = (struct order *)G_calloc(Cache_size, sizeof(struct order)); point_cnt = outside_cnt = nocat_cnt = 0; nlines = Vect_get_num_lines(&Map); G_debug(1, "Reading %d vector features fom map", nlines); for (i = 1; i <= nlines; i++) { type = Vect_read_line(&Map, Points, Cats, i); G_debug(4, "line = %d type = %d", i, type); /* check type */ if (!(type & GV_POINT)) continue; /* Points only */ /* check region */ if (!Vect_point_in_box(Points->x[0], Points->y[0], 0.0, &box)) { outside_cnt++; continue; } Vect_cat_get(Cats, field, &cat); if (cat < 0) { /* no category of given field */ nocat_cnt++; continue; } G_debug(4, " cat = %d", cat); /* Add point to cache */ drow = Rast_northing_to_row(Points->y[0], &window); dcol = Rast_easting_to_col(Points->x[0], &window); /* a special case. * if north falls at southern edge, or east falls on eastern edge, * the point will appear outside the window. * So, for these edges, bring the point inside the window */ if (drow == window.rows) drow--; if (dcol == window.cols) dcol--; cache[point_cnt].row = (int)drow; cache[point_cnt].col = (int)dcol; cache[point_cnt].cat = cat; cache[point_cnt].count = 1; point_cnt++; } Vect_set_db_updated(&Map); Vect_hist_command(&Map); Vect_close(&Map); G_debug(1, "Read %d vector points", point_cnt); /* Cache may contain duplicate categories, sort by cat, find and remove duplicates * and recalc count and decrease point_cnt */ qsort(cache, point_cnt, sizeof(struct order), by_cat); G_debug(1, "Points are sorted, starting duplicate removal loop"); for (i = 0, j = 1; j < point_cnt; j++) if (cache[i].cat != cache[j].cat) cache[++i] = cache[j]; else cache[i].count++; point_cnt = i + 1; G_debug(1, "%d vector points left after removal of duplicates", point_cnt); /* Report number of points not used */ if (outside_cnt) G_warning(_("%d points outside current region were skipped"), outside_cnt); if (nocat_cnt) G_warning(_("%d points without category were skipped"), nocat_cnt); /* Sort cache by current region row */ qsort(cache, point_cnt, sizeof(struct order), by_row); /* Allocate space for raster row */ if (out_type == CELL_TYPE) cell = Rast_allocate_c_buf(); else dcell = Rast_allocate_d_buf(); /* Extract raster values from file and store in cache */ G_debug(1, "Extracting raster values"); cur_row = -1; for (point = 0; point < point_cnt; point++) { if (cache[point].count > 1) continue; /* duplicate cats */ if (cur_row != cache[point].row) { if (out_type == CELL_TYPE) Rast_get_c_row(fd, cell, cache[point].row); else Rast_get_d_row(fd, dcell, cache[point].row); } cur_row = cache[point].row; if (out_type == CELL_TYPE) { cache[point].value = cell[cache[point].col]; } else { cache[point].dvalue = dcell[cache[point].col]; } } /* point loop */ /* Update table from cache */ G_debug(1, "Updating db table"); /* select existing categories to array (array is sorted) */ select = db_select_int(driver, Fi->table, Fi->key, NULL, &catexst); db_begin_transaction(driver); norec_cnt = update_cnt = upderr_cnt = dupl_cnt = 0; for (point = 0; point < point_cnt; point++) { if (cache[point].count > 1) { G_warning(_("More points (%d) of category %d, value set to 'NULL'"), cache[point].count, cache[point].cat); dupl_cnt++; } /* category exist in DB ? */ cex = (int *)bsearch((void *)&(cache[point].cat), catexst, select, sizeof(int), srch_cat); if (cex == NULL) { /* cat does not exist in DB */ norec_cnt++; G_warning(_("No record for category %d in table <%s>"), cache[point].cat, Fi->table); continue; } sprintf(buf, "update %s set %s = ", Fi->table, col_opt->answer); db_set_string(&stmt, buf); if (out_type == CELL_TYPE) { if (cache[point].count > 1 || Rast_is_c_null_value(&cache[point].value)) { sprintf(buf, "NULL"); } else { sprintf(buf, "%d ", cache[point].value); } } else { /* FCELL or DCELL */ if (cache[point].count > 1 || Rast_is_d_null_value(&cache[point].dvalue)) { sprintf(buf, "NULL"); } else { sprintf(buf, "%.10f", cache[point].dvalue); } } db_append_string(&stmt, buf); sprintf(buf, " where %s = %d", Fi->key, cache[point].cat); db_append_string(&stmt, buf); /* user provides where condition: */ if (where_opt->answer) { sprintf(buf, " AND %s", where_opt->answer); db_append_string(&stmt, buf); } G_debug(3, db_get_string(&stmt)); /* Update table */ if (db_execute_immediate(driver, &stmt) == DB_OK) { update_cnt++; } else { upderr_cnt++; } } G_debug(1, "Committing DB transaction"); db_commit_transaction(driver); G_free(catexst); db_close_database_shutdown_driver(driver); db_free_string(&stmt); /* Report */ G_message(_("%d categories loaded from table"), select); G_message(_("%d categories loaded from vector"), point_cnt); G_message(_("%d categories from vector missing in table"), norec_cnt); G_message(_("%d duplicate categories in vector"), dupl_cnt); if (!where_opt->answer) G_message(_("%d records updated"), update_cnt); G_message(_("%d update errors"), upderr_cnt); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct Map_info In, Out; static struct line_pnts *Points; struct line_cats *Cats; struct GModule *module; /* GRASS module for parsing arguments */ struct Option *map_in, *map_out; struct Option *method_opt, *afield_opt, *nfield_opt, *abcol, *afcol, *ncol; struct Flag *add_f; int with_z; int afield, nfield, mask_type; dglGraph_s *graph; int *component, nnodes, type, i, nlines, components, max_cat; char buf[2000], *covered; char *desc; /* Attribute table */ dbString sql; dbDriver *driver; struct field_info *Fi; /* initialize GIS environment */ G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */ /* initialize module */ module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("network")); G_add_keyword(_("components")); module->description = _("Computes strongly and weakly connected components in the network."); /* Define the different options as defined in gis.h */ map_in = G_define_standard_option(G_OPT_V_INPUT); afield_opt = G_define_standard_option(G_OPT_V_FIELD); afield_opt->key = "arc_layer"; afield_opt->answer = "1"; afield_opt->label = _("Arc layer"); afield_opt->guisection = _("Cost"); nfield_opt = G_define_standard_option(G_OPT_V_FIELD); nfield_opt->key = "node_layer"; nfield_opt->answer = "2"; nfield_opt->label = _("Node layer"); nfield_opt->guisection = _("Cost"); afcol = G_define_standard_option(G_OPT_DB_COLUMN); afcol->key = "arc_column"; afcol->required = NO; afcol->description = _("Arc forward/both direction(s) cost column (number)"); afcol->guisection = _("Cost"); abcol = G_define_standard_option(G_OPT_DB_COLUMN); abcol->key = "arc_backward_column"; abcol->required = NO; abcol->description = _("Arc backward direction cost column (number)"); abcol->guisection = _("Cost"); ncol = G_define_option(); ncol->key = "node_column"; ncol->type = TYPE_STRING; ncol->required = NO; ncol->description = _("Node cost column (number)"); ncol->guisection = _("Cost"); map_out = G_define_standard_option(G_OPT_V_OUTPUT); method_opt = G_define_option(); method_opt->key = "method"; method_opt->type = TYPE_STRING; method_opt->required = YES; method_opt->multiple = NO; method_opt->options = "weak,strong"; desc = NULL; G_asprintf(&desc, "weak;%s;strong;%s", _("Weakly connected components"), _("Strongly connected components")); method_opt->descriptions = desc; method_opt->description = _("Type of components"); add_f = G_define_flag(); add_f->key = 'a'; add_f->description = _("Add points on nodes"); /* options and flags parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* TODO: make an option for this */ mask_type = GV_LINE | GV_BOUNDARY; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Vect_check_input_output_name(map_in->answer, map_out->answer, G_FATAL_EXIT); Vect_set_open_level(2); if (1 > Vect_open_old(&In, map_in->answer, "")) G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer); with_z = Vect_is_3d(&In); if (0 > Vect_open_new(&Out, map_out->answer, with_z)) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer); } /* parse filter option and select appropriate lines */ afield = Vect_get_field_number(&In, afield_opt->answer); nfield = Vect_get_field_number(&In, nfield_opt->answer); if (0 != Vect_net_build_graph(&In, mask_type, afield, nfield, afcol->answer, abcol->answer, ncol->answer, 0, 2)) G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In)); graph = Vect_net_get_graph(&In); nnodes = Vect_get_num_nodes(&In); component = (int *)G_calloc(nnodes + 1, sizeof(int)); covered = (char *)G_calloc(nnodes + 1, sizeof(char)); if (!component || !covered) { G_fatal_error(_("Out of memory")); exit(EXIT_FAILURE); } /* Create table */ Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); db_init_string(&sql); driver = db_start_driver_open_database(Fi->driver, Fi->database); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); sprintf(buf, "create table %s ( cat integer, comp integer)", Fi->table); db_set_string(&sql, buf); G_debug(2, "%s", db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql)); } if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK) G_warning(_("Cannot create index")); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); if (method_opt->answer[0] == 'w') { G_message(_("Computing weakly connected components...")); components = NetA_weakly_connected_components(graph, component); } else { G_message(_("Computing strongly connected components...")); components = NetA_strongly_connected_components(graph, component); } G_debug(3, "Components: %d", components); G_message(_("Writing output...")); Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); nlines = Vect_get_num_lines(&In); max_cat = 1; G_percent(0, nlines, 4); for (i = 1; i <= nlines; i++) { int comp, cat; G_percent(i, nlines, 4); type = Vect_read_line(&In, Points, Cats, i); if (!Vect_cat_get(Cats, afield, &cat)) continue; if (type == GV_LINE || type == GV_BOUNDARY) { int node1, node2; Vect_get_line_nodes(&In, i, &node1, &node2); if (component[node1] == component[node2]) { comp = component[node1]; } else { continue; } } else if (type == GV_POINT) { int node; /* Vect_get_line_nodes(&In, i, &node, NULL); */ node = Vect_find_node(&In, Points->x[0], Points->y[0], Points->z[0], 0, 0); if (!node) continue; comp = component[node]; covered[node] = 1; } else continue; cat = max_cat++; Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Out, type, Points, Cats); insert_new_record(driver, Fi, &sql, cat, comp); } /*add points on nodes not covered by any point in the network */ if (add_f->answer) { for (i = 1; i <= nnodes; i++) if (!covered[i]) { Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, max_cat); NetA_add_point_on_node(&In, &Out, i, Cats); insert_new_record(driver, Fi, &sql, max_cat++, component[i]); } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); Vect_close(&In); Vect_build(&Out); Vect_close(&Out); G_done_msg(_("Found %d components."), components); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct GModule *module; struct Option *in_opt, *layer_opt, *out_opt, *length_opt, *units_opt, *vertices_opt; struct Map_info In, Out; struct line_pnts *Points, *Points2; struct line_cats *Cats; int line, nlines, layer; double length = -1; int vertices = 0; double (*line_length) (); int latlon = 0; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); 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 = "meters,kilometers,feet,miles,nautmiles"; units_opt->answer = "meters"; 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"); 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, "miles") == 0) length *= FROM_MILES; else if (strcmp(units_opt->answer, "nautmiles") == 0) length *= FROM_NAUTMILES; else G_fatal_error(_("Unknown unit %s"), units_opt->answer); /* set line length function */ if ((latlon = (G_projection() == PROJECTION_LL)) == 1) line_length = Vect_line_geodesic_length; 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 { /* meters to units */ length = length / factor; } } G_verbose_message(_("length in %s: %g"), (latlon ? "meters" : "map units"), length); } if (vertices_opt->answer) { vertices = atoi(vertices_opt->answer); if (vertices < 2) G_fatal_error(_("Number of vertices must be at least 2")); } Vect_set_open_level(2); Vect_open_old2(&In, in_opt->answer, "", layer_opt->answer); layer = Vect_get_field_number(&In, layer_opt->answer); 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); Vect_copy_tables(&In, &Out, layer); Points = Vect_new_line_struct(); Points2 = 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 { int n, i; n = ceil(l / length); if (latlon) l = Vect_line_length(Points); step = l / n; from = 0.; 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]; } 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; } } } else { int start = 0; /* number of coordinates written */ while (start < Points->n_points - 1) { int i, v; 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 main(int argc, char *argv[]) { struct GModule *module; struct Option *in_opt, *out_opt, *feature_opt, *column_name; struct Flag *smooth_flg, *value_flg, *z_flg, *no_topol; int feature; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("conversion")); G_add_keyword(_("geometry")); G_add_keyword(_("vectorization")); module->description = _("Converts a raster map into a vector map."); in_opt = G_define_standard_option(G_OPT_R_INPUT); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); feature_opt = G_define_standard_option(G_OPT_V_TYPE); feature_opt->required = YES; feature_opt->multiple = NO; feature_opt->options = "point,line,area"; feature_opt->answer = NULL; column_name = G_define_standard_option(G_OPT_DB_COLUMN); column_name->label = _("Name of attribute column to store value"); column_name->description = _("Name must be SQL compliant"); column_name->answer = "value"; smooth_flg = G_define_flag(); smooth_flg->key = 's'; smooth_flg->description = _("Smooth corners of area features"); value_flg = G_define_flag(); value_flg->key = 'v'; value_flg->description = _("Use raster values as categories instead of unique sequence (CELL only)"); value_flg->guisection = _("Attributes"); z_flg = G_define_flag(); z_flg->key = 'z'; z_flg->label = _("Write raster values as z coordinate"); z_flg->description = _("Table is not created. " "Currently supported only for points."); z_flg->guisection = _("Attributes"); no_topol = G_define_flag(); no_topol->key = 'b'; no_topol->label = _("Do not build vector topology"); no_topol->description = _("Recommended for massive point conversion"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); feature = Vect_option_to_types(feature_opt); smooth_flag = (smooth_flg->answer) ? SMOOTH : NO_SMOOTH; value_flag = value_flg->answer; if (z_flg->answer && (feature != GV_POINT)) G_fatal_error(_("z flag is supported only for points")); /* Open files */ input_fd = Rast_open_old(in_opt->answer, ""); data_type = Rast_get_map_type(input_fd); data_size = Rast_cell_size(data_type); G_get_window(&cell_head); if (value_flag && data_type != CELL_TYPE) { G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be written to the table.")); value_flag = 0; } if (z_flg->answer) Vect_open_new(&Map, out_opt->answer, 1); else Vect_open_new(&Map, out_opt->answer, 0); Vect_hist_command(&Map); Cats = Vect_new_cats_struct(); /* Open category labels */ if (data_type == CELL_TYPE) { if (0 == Rast_read_cats(in_opt->answer, "", &RastCats)) has_cats = 1; } else has_cats = 0; db_init_string(&sql); db_init_string(&label); /* Create table */ if ((feature & (GV_AREA | GV_POINT | GV_LINE)) && (!value_flag || (value_flag && has_cats)) && !(z_flg->answer)) { char buf[1000]; Fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Map, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Map)); if (driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); /* Create new table */ db_zero_string(&sql); sprintf(buf, "create table %s ( cat integer", Fi->table); db_append_string(&sql, buf); if (!value_flag) { /* add value to the table */ if (data_type == CELL_TYPE) { db_append_string(&sql, ", "); db_append_string(&sql, column_name->answer); db_append_string(&sql, " integer"); } else { db_append_string(&sql, ","); db_append_string(&sql, column_name->answer); db_append_string(&sql, " double precision"); } } if (has_cats) { int i, len; int clen = 0; /* Get maximum column length */ for (i = 0; i < RastCats.ncats; i++) { len = strlen(RastCats.labels[i]); if (len > clen) clen = len; } clen += 10; sprintf(buf, ", label varchar(%d)", clen); db_append_string(&sql, buf); } db_append_string(&sql, ")"); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) G_fatal_error(_("Unable to create table: %s"), db_get_string(&sql)); if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK) G_warning(_("Unable to create index")); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Unable to grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); } else { driver = NULL; } /* init variables for lines and areas */ first_read = 1; last_read = 0; direction = FORWARD; row_length = cell_head.cols; n_rows = cell_head.rows; row_count = 0; if (feature == GV_LINE) { alloc_lines_bufs(row_length + 2); extract_lines(); } else if (feature == GV_AREA) { alloc_areas_bufs(row_length + 2); extract_areas(); } else { /* GV_POINT */ extract_points(z_flg->answer); } Rast_close(input_fd); if (!no_topol->answer) Vect_build(&Map); /* insert cats and optionally labels if raster cats were used */ if (driver && value_flag) { char buf[1000]; int c, i, cat, fidx, ncats, lastcat, tp, id; fidx = Vect_cidx_get_field_index(&Map, 1); if (fidx >= 0) { ncats = Vect_cidx_get_num_cats_by_index(&Map, fidx); lastcat = -1; for (c = 0; c < ncats; c++) { Vect_cidx_get_cat_by_index(&Map, fidx, c, &cat, &tp, &id); if (lastcat == cat) continue; /* find label, slow -> TODO faster */ db_set_string(&label, ""); for (i = 0; i < RastCats.ncats; i++) { if (cat == (int)RastCats.q.table[i].dLow) { /* cats are in dLow/High not in cLow/High !!! */ db_set_string(&label, RastCats.labels[i]); db_double_quote_string(&label); break; } } G_debug(3, "cat = %d label = %s", cat, db_get_string(&label)); sprintf(buf, "insert into %s values ( %d, '%s')", Fi->table, cat, db_get_string(&label)); db_set_string(&sql, buf); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) G_fatal_error(_("Unable to insert into table: %s"), db_get_string(&sql)); lastcat = cat; } } } if (has_cats) Rast_free_cats(&RastCats); if (driver != NULL) { db_commit_transaction(driver); db_close_database_shutdown_driver(driver); } Vect_close(&Map); G_done_msg(" "); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int i, cat, with_z, more, ctype, nrows; char buf[DB_SQL_MAX]; int count; double coor[3]; int ncoor; struct Option *driver_opt, *database_opt, *table_opt; struct Option *xcol_opt, *ycol_opt, *zcol_opt, *keycol_opt, *where_opt, *outvect; struct Flag *same_table_flag; struct GModule *module; struct Map_info Map; struct line_pnts *Points; struct line_cats *Cats; dbString sql; dbDriver *driver; dbCursor cursor; dbTable *table; dbColumn *column; dbValue *value; struct field_info *fi; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("import")); G_add_keyword(_("database")); G_add_keyword(_("points")); module->description = _("Creates new vector (points) map from database table containing coordinates."); table_opt = G_define_standard_option(G_OPT_DB_TABLE); table_opt->required = YES; table_opt->description = _("Input table name"); driver_opt = G_define_standard_option(G_OPT_DB_DRIVER); driver_opt->options = db_list_drivers(); driver_opt->answer = (char *)db_get_default_driver_name(); driver_opt->guisection = _("Input DB"); database_opt = G_define_standard_option(G_OPT_DB_DATABASE); database_opt->answer = (char *)db_get_default_database_name(); database_opt->guisection = _("Input DB"); xcol_opt = G_define_standard_option(G_OPT_DB_COLUMN); xcol_opt->key = "x"; xcol_opt->required = YES; xcol_opt->description = _("Name of column containing x coordinate"); ycol_opt = G_define_standard_option(G_OPT_DB_COLUMN); ycol_opt->key = "y"; ycol_opt->required = YES; ycol_opt->description = _("Name of column containing y coordinate"); zcol_opt = G_define_standard_option(G_OPT_DB_COLUMN); zcol_opt->key = "z"; zcol_opt->description = _("Name of column containing z coordinate"); zcol_opt->guisection = _("3D output"); keycol_opt = G_define_standard_option(G_OPT_DB_COLUMN); keycol_opt->key = "key"; keycol_opt->required = NO; keycol_opt->label = _("Name of column containing category number"); keycol_opt->description = _("Must refer to an integer column"); where_opt = G_define_standard_option(G_OPT_DB_WHERE); where_opt->guisection = _("Selection"); outvect = G_define_standard_option(G_OPT_V_OUTPUT); same_table_flag = G_define_flag(); same_table_flag->key = 't'; same_table_flag->description = _("Use imported table as attribute table for new map"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (zcol_opt->answer) { with_z = WITH_Z; ncoor = 3; } else { with_z = WITHOUT_Z; ncoor = 2; } Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); db_init_string(&sql); if (G_get_overwrite()) { /* We don't want to delete the input table when overwriting the output * vector. */ char name[GNAME_MAX], mapset[GMAPSET_MAX]; if (!G_name_is_fully_qualified(outvect->answer, name, mapset)) { strcpy(name, outvect->answer); strcpy(mapset, G_mapset()); } Vect_set_open_level(1); /* no topo needed */ if (strcmp(mapset, G_mapset()) == 0 && G_find_vector2(name, mapset) && Vect_open_old(&Map, name, mapset) >= 0) { int num_dblinks; num_dblinks = Vect_get_num_dblinks(&Map); for (i = 0; i < num_dblinks; i++) { if ((fi = Vect_get_dblink(&Map, i)) != NULL && strcmp(fi->driver, driver_opt->answer) == 0 && strcmp(fi->database, database_opt->answer) == 0 && strcmp(fi->table, table_opt->answer) == 0) G_fatal_error(_("Vector map <%s> cannot be overwritten " "because input table <%s> is linked to " "this map."), outvect->answer, table_opt->answer); } Vect_close(&Map); } } if (Vect_open_new(&Map, outvect->answer, with_z) < 0) G_fatal_error(_("Unable to create vector map <%s>"), outvect->answer); Vect_set_error_handler_io(NULL, &Map); Vect_hist_command(&Map); fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE); /* Open driver */ driver = db_start_driver_open_database(driver_opt->answer, database_opt->answer); if (driver == NULL) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), fi->database, fi->driver); } db_set_error_handler_driver(driver); /* check if target table already exists */ G_debug(3, "Output vector table <%s>, driver: <%s>, database: <%s>", outvect->answer, db_get_default_driver_name(), db_get_default_database_name()); if (!same_table_flag->answer && db_table_exists(db_get_default_driver_name(), db_get_default_database_name(), outvect->answer) == 1) G_fatal_error(_("Output vector map, table <%s> (driver: <%s>, database: <%s>) " "already exists"), outvect->answer, db_get_default_driver_name(), db_get_default_database_name()); if (keycol_opt->answer) { int coltype; coltype = db_column_Ctype(driver, table_opt->answer, keycol_opt->answer); if (coltype == -1) G_fatal_error(_("Column <%s> not found in table <%s>"), keycol_opt->answer, table_opt->answer); if (coltype != DB_C_TYPE_INT) G_fatal_error(_("Data type of key column must be integer")); } else { if (same_table_flag->answer) { G_fatal_error(_("Option <%s> must be specified when -%c flag is given"), keycol_opt->key, same_table_flag->key); } if (strcmp(db_get_default_driver_name(), "sqlite") != 0) G_fatal_error(_("Unable to define key column. This operation is not supported " "by <%s> driver. You need to define <%s> option."), fi->driver, keycol_opt->key); } /* Open select cursor */ sprintf(buf, "SELECT %s, %s", xcol_opt->answer, ycol_opt->answer); db_set_string(&sql, buf); if (with_z) { sprintf(buf, ", %s", zcol_opt->answer); db_append_string(&sql, buf); } if (keycol_opt->answer) { sprintf(buf, ", %s", keycol_opt->answer); db_append_string(&sql, buf); } sprintf(buf, " FROM %s", table_opt->answer); db_append_string(&sql, buf); if (where_opt->answer) { sprintf(buf, " WHERE %s", where_opt->answer); db_append_string(&sql, buf); } G_debug(2, "SQL: %s", db_get_string(&sql)); if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) { G_fatal_error(_("Unable to open select cursor: '%s'"), db_get_string(&sql)); } table = db_get_cursor_table(&cursor); nrows = db_get_num_rows(&cursor); G_debug(2, "%d points selected", nrows); count = cat = 0; G_message(_("Writing features...")); while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) { G_percent(count, nrows, 2); /* key column */ if (keycol_opt->answer) { column = db_get_table_column(table, with_z ? 3 : 2); ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column)); if (ctype != DB_C_TYPE_INT) G_fatal_error(_("Key column must be integer")); value = db_get_column_value(column); cat = db_get_value_int(value); } else { cat++; } /* coordinates */ for (i = 0; i < ncoor; i++) { column = db_get_table_column(table, i); ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column)); if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE) G_fatal_error(_("x/y/z column must be integer or double")); value = db_get_column_value(column); if (ctype == DB_C_TYPE_INT) coor[i] = (double)db_get_value_int(value); else coor[i] = db_get_value_double(value); } Vect_reset_line(Points); Vect_reset_cats(Cats); Vect_append_point(Points, coor[0], coor[1], coor[2]); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Map, GV_POINT, Points, Cats); count++; } G_percent(1, 1, 1); /* close connection to input DB before copying attributes */ db_close_database_shutdown_driver(driver); /* Copy table */ if (!same_table_flag->answer) { G_message(_("Copying attributes...")); if (DB_FAILED == db_copy_table_where(driver_opt->answer, database_opt->answer, table_opt->answer, fi->driver, fi->database, fi->table, where_opt->answer)) { /* where can be NULL */ G_warning(_("Unable to copy table")); } else { Vect_map_add_dblink(&Map, 1, NULL, fi->table, keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN, fi->database, fi->driver); } if (!keycol_opt->answer) { /* TODO: implement for all DB drivers in generic way if * possible */ driver = db_start_driver_open_database(fi->driver, fi->database); if (driver == NULL) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), fi->database, fi->driver); } db_set_error_handler_driver(driver); /* add key column */ sprintf(buf, "ALTER TABLE %s ADD COLUMN %s INTEGER", fi->table, GV_KEY_COLUMN); db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Unable to add key column <%s>: " "SERIAL type is not supported by <%s>"), GV_KEY_COLUMN, fi->driver); } /* update key column */ sprintf(buf, "UPDATE %s SET %s = _ROWID_", fi->table, GV_KEY_COLUMN); db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Failed to update key column <%s>"), GV_KEY_COLUMN); } } } else { /* do not copy attributes, link original table */ Vect_map_add_dblink(&Map, 1, NULL, table_opt->answer, keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN, database_opt->answer, driver_opt->answer); } Vect_build(&Map); Vect_close(&Map); G_done_msg(_n("%d point written to vector map.", "%d points written to vector map.", count), count); return (EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct Map_info In, Out, Error; struct line_pnts *Points; struct line_cats *Cats; int i, type, iter; struct GModule *module; /* GRASS module for parsing arguments */ struct Option *map_in, *map_out, *error_out, *thresh_opt, *method_opt, *look_ahead_opt; struct Option *iterations_opt, *cat_opt, *alpha_opt, *beta_opt, *type_opt; struct Option *field_opt, *where_opt, *reduction_opt, *slide_opt; struct Option *angle_thresh_opt, *degree_thresh_opt, *closeness_thresh_opt; struct Option *betweeness_thresh_opt; struct Flag *notab_flag, *loop_support_flag; int with_z; int total_input, total_output; /* Number of points in the input/output map respectively */ double thresh, alpha, beta, reduction, slide, angle_thresh; double degree_thresh, closeness_thresh, betweeness_thresh; int method; int look_ahead, iterations; int loop_support; int layer; int n_lines; int simplification, mask_type; struct cat_list *cat_list = NULL; char *s, *descriptions; /* 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(_("generalization")); G_add_keyword(_("simplification")); G_add_keyword(_("smoothing")); G_add_keyword(_("displacement")); G_add_keyword(_("network generalization")); module->description = _("Performs vector based generalization."); /* Define the different options as defined in gis.h */ map_in = G_define_standard_option(G_OPT_V_INPUT); field_opt = G_define_standard_option(G_OPT_V_FIELD_ALL); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "line,boundary,area"; type_opt->answer = "line,boundary,area"; type_opt->guisection = _("Selection"); map_out = G_define_standard_option(G_OPT_V_OUTPUT); error_out = G_define_standard_option(G_OPT_V_OUTPUT); error_out->key = "error"; error_out->required = NO; error_out->description = _("Error map of all lines and boundaries not being generalized due to topology issues or over-simplification"); 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 = "douglas,douglas_reduction,lang,reduction,reumann,boyle,sliding_averaging,distance_weighting,chaiken,hermite,snakes,network,displacement"; descriptions = NULL; G_asprintf(&descriptions, "douglas;%s;" "douglas_reduction;%s;" "lang;%s;" "reduction;%s;" "reumann;%s;" "boyle;%s;" "sliding_averaging;%s;" "distance_weighting;%s;" "chaiken;%s;" "hermite;%s;" "snakes;%s;" "network;%s;" "displacement;%s;", _("Douglas-Peucker Algorithm"), _("Douglas-Peucker Algorithm with reduction parameter"), _("Lang Simplification Algorithm"), _("Vertex Reduction Algorithm eliminates points close to each other"), _("Reumann-Witkam Algorithm"), _("Boyle's Forward-Looking Algorithm"), _("McMaster's Sliding Averaging Algorithm"), _("McMaster's Distance-Weighting Algorithm"), _("Chaiken's Algorithm"), _("Interpolation by Cubic Hermite Splines"), _("Snakes method for line smoothing"), _("Network generalization"), _("Displacement of lines close to each other")); method_opt->descriptions = G_store(descriptions); method_opt->description = _("Generalization algorithm"); thresh_opt = G_define_option(); thresh_opt->key = "threshold"; thresh_opt->type = TYPE_DOUBLE; thresh_opt->required = YES; thresh_opt->options = "0-1000000000"; thresh_opt->description = _("Maximal tolerance value"); look_ahead_opt = G_define_option(); look_ahead_opt->key = "look_ahead"; look_ahead_opt->type = TYPE_INTEGER; look_ahead_opt->required = NO; look_ahead_opt->answer = "7"; look_ahead_opt->description = _("Look-ahead parameter"); reduction_opt = G_define_option(); reduction_opt->key = "reduction"; reduction_opt->type = TYPE_DOUBLE; reduction_opt->required = NO; reduction_opt->answer = "50"; reduction_opt->options = "0-100"; reduction_opt->description = _("Percentage of the points in the output of 'douglas_reduction' algorithm"); slide_opt = G_define_option(); slide_opt->key = "slide"; slide_opt->type = TYPE_DOUBLE; slide_opt->required = NO; slide_opt->answer = "0.5"; slide_opt->options = "0-1"; slide_opt->description = _("Slide of computed point toward the original point"); angle_thresh_opt = G_define_option(); angle_thresh_opt->key = "angle_thresh"; angle_thresh_opt->type = TYPE_DOUBLE; angle_thresh_opt->required = NO; angle_thresh_opt->answer = "3"; angle_thresh_opt->options = "0-180"; angle_thresh_opt->description = _("Minimum angle between two consecutive segments in Hermite method"); degree_thresh_opt = G_define_option(); degree_thresh_opt->key = "degree_thresh"; degree_thresh_opt->type = TYPE_INTEGER; degree_thresh_opt->required = NO; degree_thresh_opt->answer = "0"; degree_thresh_opt->description = _("Degree threshold in network generalization"); closeness_thresh_opt = G_define_option(); closeness_thresh_opt->key = "closeness_thresh"; closeness_thresh_opt->type = TYPE_DOUBLE; closeness_thresh_opt->required = NO; closeness_thresh_opt->answer = "0"; closeness_thresh_opt->options = "0-1"; closeness_thresh_opt->description = _("Closeness threshold in network generalization"); betweeness_thresh_opt = G_define_option(); betweeness_thresh_opt->key = "betweeness_thresh"; betweeness_thresh_opt->type = TYPE_DOUBLE; betweeness_thresh_opt->required = NO; betweeness_thresh_opt->answer = "0"; betweeness_thresh_opt->description = _("Betweeness threshold in network generalization"); alpha_opt = G_define_option(); alpha_opt->key = "alpha"; alpha_opt->type = TYPE_DOUBLE; alpha_opt->required = NO; alpha_opt->answer = "1.0"; alpha_opt->description = _("Snakes alpha parameter"); beta_opt = G_define_option(); beta_opt->key = "beta"; beta_opt->type = TYPE_DOUBLE; beta_opt->required = NO; beta_opt->answer = "1.0"; beta_opt->description = _("Snakes beta parameter"); iterations_opt = G_define_option(); iterations_opt->key = "iterations"; iterations_opt->type = TYPE_INTEGER; iterations_opt->required = NO; iterations_opt->answer = "1"; iterations_opt->description = _("Number of iterations"); cat_opt = G_define_standard_option(G_OPT_V_CATS); cat_opt->guisection = _("Selection"); where_opt = G_define_standard_option(G_OPT_DB_WHERE); where_opt->guisection = _("Selection"); loop_support_flag = G_define_flag(); loop_support_flag->key = 'l'; loop_support_flag->label = _("Disable loop support"); loop_support_flag->description = _("Do not modify end points of lines forming a closed loop"); notab_flag = G_define_standard_flag(G_FLG_V_TABLE); notab_flag->description = _("Do not copy attributes"); notab_flag->guisection = _("Attributes"); /* options and flags parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); thresh = atof(thresh_opt->answer); look_ahead = atoi(look_ahead_opt->answer); alpha = atof(alpha_opt->answer); beta = atof(beta_opt->answer); reduction = atof(reduction_opt->answer); iterations = atoi(iterations_opt->answer); slide = atof(slide_opt->answer); angle_thresh = atof(angle_thresh_opt->answer); degree_thresh = atof(degree_thresh_opt->answer); closeness_thresh = atof(closeness_thresh_opt->answer); betweeness_thresh = atof(betweeness_thresh_opt->answer); mask_type = type_mask(type_opt); G_debug(3, "Method: %s", method_opt->answer); s = method_opt->answer; if (strcmp(s, "douglas") == 0) method = DOUGLAS; else if (strcmp(s, "lang") == 0) method = LANG; else if (strcmp(s, "reduction") == 0) method = VERTEX_REDUCTION; else if (strcmp(s, "reumann") == 0) method = REUMANN; else if (strcmp(s, "boyle") == 0) method = BOYLE; else if (strcmp(s, "distance_weighting") == 0) method = DISTANCE_WEIGHTING; else if (strcmp(s, "chaiken") == 0) method = CHAIKEN; else if (strcmp(s, "hermite") == 0) method = HERMITE; else if (strcmp(s, "snakes") == 0) method = SNAKES; else if (strcmp(s, "douglas_reduction") == 0) method = DOUGLAS_REDUCTION; else if (strcmp(s, "sliding_averaging") == 0) method = SLIDING_AVERAGING; else if (strcmp(s, "network") == 0) method = NETWORK; else if (strcmp(s, "displacement") == 0) { method = DISPLACEMENT; /* we can displace only the lines */ mask_type = GV_LINE; } else { G_fatal_error(_("Unknown method")); exit(EXIT_FAILURE); } /* simplification or smoothing? */ switch (method) { case DOUGLAS: case DOUGLAS_REDUCTION: case LANG: case VERTEX_REDUCTION: case REUMANN: simplification = 1; break; default: simplification = 0; break; } 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 (Vect_open_old2(&In, map_in->answer, "", field_opt->answer) < 1) G_fatal_error(_("Unable to open vector map <%s>"), map_in->answer); if (Vect_get_num_primitives(&In, mask_type) == 0) { G_warning(_("No lines found in input map <%s>"), map_in->answer); Vect_close(&In); exit(EXIT_SUCCESS); } 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 (error_out->answer) { if (0 > Vect_open_new(&Error, error_out->answer, with_z)) { Vect_close(&In); G_fatal_error(_("Unable to create error vector map <%s>"), error_out->answer); } } Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); total_input = total_output = 0; layer = Vect_get_field_number(&In, field_opt->answer); /* parse filter options */ if (layer > 0) cat_list = Vect_cats_set_constraint(&In, layer, where_opt->answer, cat_opt->answer); if (method == DISPLACEMENT) { /* modifies only lines, all other features including boundaries are preserved */ /* options where, cats, and layer are respected */ G_message(_("Displacement...")); snakes_displacement(&In, &Out, thresh, alpha, beta, 1.0, 10.0, iterations, cat_list, layer); } /* TODO: rearrange code below. It's really messy */ if (method == NETWORK) { /* extracts lines of selected type, all other features are discarded */ /* options where, cats, and layer are ignored */ G_message(_("Network generalization...")); total_output = graph_generalization(&In, &Out, mask_type, degree_thresh, closeness_thresh, betweeness_thresh); } /* copy tables here because method == NETWORK is complete and * tables for Out may be needed for parse_filter_options() below */ if (!notab_flag->answer) { if (method == NETWORK) copy_tables_by_cats(&In, &Out); else Vect_copy_tables(&In, &Out, -1); } else if (where_opt->answer && method < NETWORK) { G_warning(_("Attributes are needed for 'where' option, copying table")); Vect_copy_tables(&In, &Out, -1); } /* smoothing/simplification */ if (method < NETWORK) { /* modifies only lines of selected type, all other features are preserved */ int not_modified_boundaries = 0, n_oversimplified = 0; struct line_pnts *APoints; /* original Points */ set_topo_debug(); Vect_copy_map_lines(&In, &Out); Vect_build_partial(&Out, GV_BUILD_CENTROIDS); G_message("-----------------------------------------------------"); G_message(_("Generalization (%s)..."), method_opt->answer); G_message(_("Using threshold: %g %s"), thresh, G_database_unit_name(1)); G_percent_reset(); APoints = Vect_new_line_struct(); n_lines = Vect_get_num_lines(&Out); for (i = 1; i <= n_lines; i++) { int after = 0; G_percent(i, n_lines, 1); type = Vect_read_line(&Out, APoints, Cats, i); if (!(type & GV_LINES) || !(mask_type & type)) continue; if (layer > 0) { if ((type & GV_LINE) && !Vect_cats_in_constraint(Cats, layer, cat_list)) continue; else if ((type & GV_BOUNDARY)) { int do_line = 0; int left, right; do_line = Vect_cats_in_constraint(Cats, layer, cat_list); if (!do_line) { /* check if any of the centroids is selected */ Vect_get_line_areas(&Out, i, &left, &right); if (left < 0) left = Vect_get_isle_area(&Out, abs(left)); if (right < 0) right = Vect_get_isle_area(&Out, abs(right)); if (left > 0) { Vect_get_area_cats(&Out, left, Cats); do_line = Vect_cats_in_constraint(Cats, layer, cat_list); } if (!do_line && right > 0) { Vect_get_area_cats(&Out, right, Cats); do_line = Vect_cats_in_constraint(Cats, layer, cat_list); } } if (!do_line) continue; } } Vect_line_prune(APoints); if (APoints->n_points < 2) /* Line of length zero, delete if boundary ? */ continue; total_input += APoints->n_points; /* copy points */ Vect_reset_line(Points); Vect_append_points(Points, APoints, GV_FORWARD); loop_support = 0; if (!loop_support_flag->answer) { int n1, n2; Vect_get_line_nodes(&Out, i, &n1, &n2); if (n1 == n2) { if (Vect_get_node_n_lines(&Out, n1) == 2) { if (abs(Vect_get_node_line(&Out, n1, 0)) == i && abs(Vect_get_node_line(&Out, n1, 1)) == i) loop_support = 1; } } } for (iter = 0; iter < iterations; iter++) { switch (method) { case DOUGLAS: douglas_peucker(Points, thresh, with_z); break; case DOUGLAS_REDUCTION: douglas_peucker_reduction(Points, thresh, reduction, with_z); break; case LANG: lang(Points, thresh, look_ahead, with_z); break; case VERTEX_REDUCTION: vertex_reduction(Points, thresh, with_z); break; case REUMANN: reumann_witkam(Points, thresh, with_z); break; case BOYLE: boyle(Points, look_ahead, loop_support, with_z); break; case SLIDING_AVERAGING: sliding_averaging(Points, slide, look_ahead, loop_support, with_z); break; case DISTANCE_WEIGHTING: distance_weighting(Points, slide, look_ahead, loop_support, with_z); break; case CHAIKEN: chaiken(Points, thresh, loop_support, with_z); break; case HERMITE: hermite(Points, thresh, angle_thresh, loop_support, with_z); break; case SNAKES: snakes(Points, alpha, beta, loop_support, with_z); break; } } if (loop_support == 0) { /* safety check, BUG in method if not passed */ if (APoints->x[0] != Points->x[0] || APoints->y[0] != Points->y[0] || APoints->z[0] != Points->z[0]) G_fatal_error(_("Method '%s' did not preserve first point"), method_opt->answer); if (APoints->x[APoints->n_points - 1] != Points->x[Points->n_points - 1] || APoints->y[APoints->n_points - 1] != Points->y[Points->n_points - 1] || APoints->z[APoints->n_points - 1] != Points->z[Points->n_points - 1]) G_fatal_error(_("Method '%s' did not preserve last point"), method_opt->answer); } else { /* safety check, BUG in method if not passed */ if (Points->x[0] != Points->x[Points->n_points - 1] || Points->y[0] != Points->y[Points->n_points - 1] || Points->z[0] != Points->z[Points->n_points - 1]) G_fatal_error(_("Method '%s' did not preserve loop"), method_opt->answer); } Vect_line_prune(Points); /* oversimplified line */ if (Points->n_points < 2) { after = APoints->n_points; n_oversimplified++; if (error_out->answer) Vect_write_line(&Error, type, APoints, Cats); } /* check for topology corruption */ else if (type == GV_BOUNDARY) { if (!check_topo(&Out, i, APoints, Points, Cats)) { after = APoints->n_points; not_modified_boundaries++; if (error_out->answer) Vect_write_line(&Error, type, APoints, Cats); } else after = Points->n_points; } else { /* type == GV_LINE */ Vect_rewrite_line(&Out, i, type, Points, Cats); after = Points->n_points; } total_output += after; } if (not_modified_boundaries > 0) G_warning(_("%d boundaries were not modified because modification would damage topology"), not_modified_boundaries); if (n_oversimplified > 0) G_warning(_("%d lines/boundaries were not modified due to over-simplification"), n_oversimplified); G_message("-----------------------------------------------------"); /* make sure that clean topo is built at the end */ Vect_build_partial(&Out, GV_BUILD_NONE); if (error_out->answer) Vect_build_partial(&Error, GV_BUILD_NONE); } Vect_build(&Out); if (error_out->answer) Vect_build(&Error); Vect_close(&In); Vect_close(&Out); if (error_out->answer) Vect_close(&Error); G_message("-----------------------------------------------------"); if (total_input != 0 && total_input != total_output) G_done_msg(_("Number of vertices for selected features %s from %d to %d (%d%% remaining)"), simplification ? _("reduced") : _("changed"), total_input, total_output, (total_output * 100) / total_input); else G_done_msg(" "); exit(EXIT_SUCCESS); }