/** * \brief Consolidate network arcs (edge) based on given point vector map (nodes) * * If there is no connection between network edge and point, new edge * is added, the line broken, and new point added to nfield layer * * \param In,Points input vector maps * \param Out output vector map * \param nfield nodes layer * \param thresh threshold value to find neareast line * * \return number of new arcs */ int connect_arcs(struct Map_info *In, struct Map_info *Pnts, struct Map_info *Out, int afield, int nfield, double thresh, int snap) { int narcs; int type, line, seg, i, ltype, broken; double px, py, pz, spdist, dist; struct line_pnts *Points, *Pline, *Pout; struct line_cats *Cats, *Cline, *Cnew; int maxcat, findex, ncats; narcs = 0; Points = Vect_new_line_struct(); Pline = Vect_new_line_struct(); Pout = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Cline = Vect_new_cats_struct(); Cnew = Vect_new_cats_struct(); /* rewrite all primitives to output file */ Vect_copy_map_lines(In, Out); Vect_build_partial(Out, GV_BUILD_BASE); findex = Vect_cidx_get_field_index(In, afield); ncats = Vect_cidx_get_num_cats_by_index(In, findex); Vect_cidx_get_cat_by_index(In, findex, ncats - 1, &maxcat, &type, &line); /* go thorough all points in point map and write a new arcs if missing */ while ((type = Vect_read_next_line(Pnts, Points, Cats)) >= 0) { if (type != GV_POINT) continue; /* find the nearest line in given threshold */ line = Vect_find_line(Out, Points->x[0], Points->y[0], Points->z[0], GV_LINES, thresh, WITHOUT_Z, 0); if (line < 1 || !Vect_line_alive(Out, line)) continue; ltype = Vect_read_line(Out, Pline, Cline, line); /* find point on the line */ seg = Vect_line_distance(Pline, Points->x[0], Points->y[0], Points->z[0], WITHOUT_Z, &px, &py, &pz, &dist, &spdist, NULL); if (seg == 0) G_fatal_error(_("Failed to find intersection segment")); /* break the line */ broken = 0; Vect_reset_line(Pout); for (i = 0; i < seg; i++) { Vect_append_point(Pout, Pline->x[i], Pline->y[i], Pline->z[i]); } Vect_append_point(Pout, px, py, pz); Vect_line_prune(Pout); if (Pout->n_points > 1) { Vect_rewrite_line(Out, line, ltype, Pout, Cline); broken++; } Vect_reset_line(Pout); Vect_append_point(Pout, px, py, pz); for (i = seg; i < Pline->n_points; i++) { Vect_append_point(Pout, Pline->x[i], Pline->y[i], Pline->z[i]); } Vect_line_prune(Pout); if (Pout->n_points > 1) { if (broken) Vect_write_line(Out, ltype, Pout, Cline); else Vect_rewrite_line(Out, line, ltype, Pout, Cline); broken++; } if (broken == 2) narcs++; if (dist > 0.0) { if (snap) { /* snap point */ Points->x[0] = px; Points->y[0] = py; Points->z[0] = pz; } else { /* write new arc */ Vect_reset_line(Pout); Vect_append_point(Pout, px, py, pz); Vect_append_point(Pout, Points->x[0], Points->y[0], Points->z[0]); maxcat++; Vect_reset_cats(Cnew); Vect_cat_set(Cnew, afield, maxcat); Vect_write_line(Out, ltype, Pout, Cnew); narcs++; } } /* add points to 'nfield' layer */ for (i = 0; i < Cats->n_cats; i++) { Cats->field[i] = nfield; /* all points to 'nfield' layer */ } Vect_write_line(Out, type, Points, Cats); } Vect_destroy_line_struct(Points); Vect_destroy_line_struct(Pline); Vect_destroy_line_struct(Pout); Vect_destroy_cats_struct(Cats); Vect_destroy_cats_struct(Cline); Vect_destroy_cats_struct(Cnew); return narcs; }
int main(int argc, char **argv) { int lfield, pfield, n_points, n_outside, n_found, n_no_record, n_many_records; int line, type, nlines; double thresh, multip; struct Option *lines_opt, *points_opt; struct Option *lfield_opt, *pfield_opt; struct Option *driver_opt, *database_opt, *table_opt, *thresh_opt; struct GModule *module; const char *mapset; struct Map_info LMap, PMap; struct line_cats *LCats, *PCats; struct line_pnts *LPoints, *PPoints; dbDriver *rsdriver; dbHandle rshandle; dbString rsstmt; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("Linear Reference System")); G_add_keyword(_("networking")); module->description = _("Finds line id and real km+offset for given points in vector map " "using linear reference system."); lines_opt = G_define_standard_option(G_OPT_V_INPUT); lines_opt->key = "lines"; lines_opt->description = _("Input vector map containing lines"); points_opt = G_define_standard_option(G_OPT_V_INPUT); points_opt->key = "points"; points_opt->description = _("Input vector map containing points"); lfield_opt = G_define_standard_option(G_OPT_V_FIELD); lfield_opt->key = "llayer"; lfield_opt->answer = "1"; lfield_opt->description = _("Line layer"); pfield_opt = G_define_standard_option(G_OPT_V_FIELD); pfield_opt->key = "player"; pfield_opt->answer = "1"; pfield_opt->description = _("Point layer"); driver_opt = G_define_option(); driver_opt->key = "rsdriver"; driver_opt->type = TYPE_STRING; driver_opt->required = NO; driver_opt->description = _("Driver name for reference system table"); driver_opt->options = db_list_drivers(); driver_opt->answer = db_get_default_driver_name(); database_opt = G_define_option(); database_opt->key = "rsdatabase"; database_opt->type = TYPE_STRING; database_opt->required = NO; database_opt->description = _("Database name for reference system table"); database_opt->answer = db_get_default_database_name(); table_opt = G_define_option(); table_opt->key = "rstable"; table_opt->type = TYPE_STRING; table_opt->required = YES; table_opt->description = _("Name of the reference system table"); thresh_opt = G_define_option(); thresh_opt->key = "threshold"; thresh_opt->type = TYPE_DOUBLE; thresh_opt->required = NO; thresh_opt->answer = "1000"; thresh_opt->description = _("Maximum distance to nearest line"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); LCats = Vect_new_cats_struct(); PCats = Vect_new_cats_struct(); LPoints = Vect_new_line_struct(); PPoints = Vect_new_line_struct(); lfield = atoi(lfield_opt->answer); pfield = atoi(pfield_opt->answer); multip = 1000; /* Number of map units per MP unit */ thresh = atof(thresh_opt->answer); /* Open input lines */ mapset = G_find_vector2(lines_opt->answer, NULL); if (mapset == NULL) G_fatal_error(_("Vector map <%s> not found"), lines_opt->answer); Vect_set_open_level(2); if (Vect_open_old(&LMap, lines_opt->answer, mapset) < 0) G_fatal_error(_("Unable to open vector map <%s>"), lines_opt->answer); /* Open input points */ mapset = G_find_vector2(points_opt->answer, NULL); if (mapset == NULL) G_fatal_error(_("Vector map <%s> not found"), points_opt->answer); Vect_set_open_level(2); if (Vect_open_old(&PMap, points_opt->answer, mapset) < 0) G_fatal_error(_("Unable to open vector map <%s>"), points_opt->answer); db_init_handle(&rshandle); db_init_string(&rsstmt); rsdriver = db_start_driver(driver_opt->answer); db_set_handle(&rshandle, database_opt->answer, NULL); if (db_open_database(rsdriver, &rshandle) != DB_OK) G_fatal_error(_("Unable to open database for reference table")); n_points = n_outside = n_found = n_no_record = n_many_records = 0; nlines = Vect_get_num_lines(&PMap); G_debug(2, "nlines = %d", nlines); G_message("pcat|lid|mpost|offset"); for (line = 1; line <= nlines; line++) { int nearest, pcat, lcat, lid, ret; double along, mpost, offset; G_debug(3, "point = %d", line); type = Vect_read_line(&PMap, PPoints, PCats, line); if (type != GV_POINT) continue; Vect_cat_get(PCats, pfield, &pcat); if (pcat < 0) continue; n_points++; nearest = Vect_find_line(&LMap, PPoints->x[0], PPoints->y[0], 0.0, GV_LINE, thresh, 0, 0); fprintf(stdout, "%d", pcat); if (nearest <= 0) { fprintf(stdout, "|-|- # outside threshold\n"); n_outside++; continue; } /* Read nearest line */ Vect_read_line(&LMap, LPoints, LCats, nearest); Vect_cat_get(LCats, lfield, &lcat); Vect_line_distance(LPoints, PPoints->x[0], PPoints->y[0], 0.0, 0, NULL, NULL, NULL, NULL, NULL, &along); G_debug(3, " nearest = %d lcat = %d along = %f", nearest, lcat, along); if (lcat >= 0) { ret = LR_get_milepost(rsdriver, table_opt->answer, "lcat", "lid", "start_map", "end_map", "start_mp", "start_off", "end_mp", "end_off", lcat, along, multip, &lid, &mpost, &offset); } else { ret = 0; } if (ret == 0) { n_no_record++; fprintf(stdout, "|-|- # no record\n"); continue; } if (ret == 2) { n_many_records++; fprintf(stdout, "|-|- # too many records\n"); continue; } G_debug(3, " lid = %d mpost = %f offset = %f", lid, mpost, offset); fprintf(stdout, "|%d|%f+%f\n", lid, mpost, offset); n_found++; } db_close_database(rsdriver); /* Free, close ... */ Vect_close(&LMap); Vect_close(&PMap); G_message(_n("[%d] point read from input", "[%d] points read from input", n_points), n_points); G_message(_n("[%d] position found", "[%d] positions found", n_found), n_found); if (n_outside) G_message(_n("[%d] point outside threshold", "[%d] points outside threshold", n_outside), n_outside); if (n_no_record) G_message(_n("[%d] point - no record found", "[%d] points - no record found", n_no_record), n_no_record); if (n_many_records) G_message(_n("[%d] point - too many records found", "[%d] points - too many records found", n_many_records), n_many_records); exit(EXIT_SUCCESS); }
int delete_line_update(void *closure, int sxn, int syn, int button) { struct delete_line *dl = closure; double x = D_d_to_u_col(sxn); double y = D_d_to_u_row(syn); G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y); /* Display last highlighted in normal color */ if (dl->last_line > 0) { display_line(dl->last_line, SYMB_DEFAULT, 1); } if (button == 3) /* Quit tool */ return 1; if (button == 1) { /* Confirm / select */ /* Delete last if any */ if (dl->last_line > 0) { int node1, node2; int i; /* Erase line and nodes !!! (because if the line is not connected to any other, nodes will die */ display_line(dl->last_line, SYMB_BACKGROUND, 1); Vect_get_line_nodes(&Map, dl->line, &node1, &node2); G_debug(2, "delete line = %d node1 = %d node2 = %d", dl->last_line, node1, node2); display_node(node1, SYMB_BACKGROUND, 1); display_node(node2, SYMB_BACKGROUND, 1); Vect_read_line(&Map, NULL, dl->Cats, dl->last_line); Vect_delete_line(&Map, dl->last_line); for (i = 0; i < dl->Cats->n_cats; i++) { check_record(dl->Cats->field[i], dl->Cats->cat[i]); } for (i = 0; i < Vect_get_num_updated_lines(&Map); i++) G_debug(2, "Updated line: %d", Vect_get_updated_line(&Map, i)); for (i = 0; i < Vect_get_num_updated_nodes(&Map); i++) G_debug(2, "Updated node: %d", Vect_get_updated_node(&Map, i)); updated_lines_and_nodes_erase_refresh_display(); } /* Find neares point or line */ dl->line = Vect_find_line(&Map, x, y, 0, GV_POINT | GV_CENTROID, dl->thresh, 0, 0); G_debug(2, "point found = %d", dl->line); if (dl->line == 0) dl->line = Vect_find_line(&Map, x, y, 0, GV_LINE | GV_BOUNDARY, dl->thresh, 0, 0); G_debug(2, "line found = %d", dl->line); /* Display new selected line if any */ if (dl->line > 0) { display_line(dl->line, SYMB_HIGHLIGHT, 1); } } else { /* button == 2 -> unselect */ dl->line = 0; } if (dl->line > 0) i_prompt_buttons(_("Confirm and select next"), _("Unselect"), _("Quit tool")); else i_prompt_buttons(_("Select"), _("Unselect"), _("Quit tool")); dl->last_line = dl->line; dl->first = 0; return 0; }
int move_line_update(void *closure, int sxn, int syn, int button) { struct move_line *ml = closure; double x = D_d_to_u_col(sxn); double y = D_d_to_u_row(syn); G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y); if (ml->last_line > 0) { display_line(ml->last_line, SYMB_DEFAULT, 1); } if (button == 3) return 1; if (button == 1) { /* Select / new location */ int type; if (ml->last_line == 0) { /* Select line */ ml->line = Vect_find_line(&Map, x, y, 0, GV_POINT | GV_CENTROID, ml->thresh, 0, 0); G_debug(2, "point found = %d", ml->line); if (ml->line == 0) ml->line = Vect_find_line(&Map, x, y, 0, GV_LINE | GV_BOUNDARY, ml->thresh, 0, 0); G_debug(2, "line found = %d", ml->line); /* Display new selected line if any */ if (ml->line > 0) { display_line(ml->line, SYMB_HIGHLIGHT, 1); /* Find the nearest point on the line */ type = Vect_read_line(&Map, ml->Points, NULL, ml->line); Vect_line_distance(ml->Points, x, y, 0, 0, &ml->xo, &ml->yo, NULL, NULL, NULL, NULL); set_location(D_u_to_d_col(ml->xo), D_u_to_d_row(ml->yo)); i_prompt_buttons(_("New location"), _("Unselect"), _("Quit tool")); } ml->last_line = ml->line; } else { /* Line is already selected */ int node1, node2; int i; display_line(ml->last_line, SYMB_BACKGROUND, 1); Vect_get_line_nodes(&Map, ml->last_line, &node1, &node2); display_node(node1, SYMB_BACKGROUND, 1); display_node(node2, SYMB_BACKGROUND, 1); type = Vect_read_line(&Map, ml->Points, ml->Cats, ml->last_line); for (i = 0; i < ml->Points->n_points; i++) { ml->Points->x[i] = ml->Points->x[i] + x - ml->xo; ml->Points->y[i] = ml->Points->y[i] + y - ml->yo; } Vect_rewrite_line(&Map, ml->last_line, type, ml->Points, ml->Cats); updated_lines_and_nodes_erase_refresh_display(); ml->last_line = 0; } } if (button == 2) { /* Unselect */ if (ml->last_line > 0) { ml->last_line = 0; } } if (ml->last_line == 0) { i_prompt_buttons(_("Select"), "", _("Quit tool")); set_mode(MOUSE_POINT); } else set_mode(MOUSE_LINE); return 0; }
int edit_line_update(void *closure, int sxn, int syn, int button) { struct edit_line *el = closure; double x = D_d_to_u_col(sxn); double y = D_d_to_u_row(syn); G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y); if (button == 3) /* Tool broken by GUI */ return 1; switch (el->phase) { case 1: if (button != 1) return 0; /* Find nearest point or line */ el->line = Vect_find_line(&Map, x, y, 0, GV_LINE | GV_BOUNDARY, el->thresh, 0, 0); G_debug(2, "line found = %d", el->line); /* Display new selected line if any */ if (el->line > 0) { display_line(el->line, SYMB_HIGHLIGHT, 1); edit_line_phase2(el, x, y); } break; case 2: if (button == 1) { /* New point */ snap(&x, &y); Vect_append_point(el->Points, x, y, 0); if (el->line_type == GV_LINE) symb_set_driver_color(SYMB_LINE); else symb_set_driver_color(SYMB_BOUNDARY_0); display_points(el->Points, 1); set_location(sxn, syn); i_prompt_buttons(_("New Point"), _("Undo Last Point"), _("Close line")); } else if (button == 2) { /* Undo last point */ if (el->Points->n_points > 1) { symb_set_driver_color(SYMB_BACKGROUND); display_points(el->Points, 1); el->Points->n_points--; if (el->line_type == GV_LINE) symb_set_driver_color(SYMB_LINE); else symb_set_driver_color(SYMB_BOUNDARY_0); display_points(el->Points, 1); set_location(D_u_to_d_col (el->Points->x[el->Points->n_points - 1]), D_u_to_d_row(el->Points-> y[el->Points->n_points - 1]) ); if (el->Points->n_points == 1) i_prompt_buttons(_("New Point"), "", _("Delete line and exit")); } } break; } return 0; }