123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- /*!
- \file lib/vector/vedit/break.c
- \brief Vedit library - split, break, connect lines
-
- (C) 2007-2008 by the GRASS Development Team
-
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
-
- \author Martin Landa <landa.martin gmail.com>
- */
- #include <math.h>
- #include <grass/vedit.h>
- static int connect_lines(struct Map_info *, int, int, int,
- double, struct ilist *);
- /*!
- \brief Split selected lines on given position
-
- \param Map pointer to Map_info
- \param List list of selected lines
- \param coord points location
- \param thresh threshold
- \param[out] List_updated list of rewritten features (or NULL)
-
- \return number of modified lines
- \return -1 on error
- */
- int Vedit_split_lines(struct Map_info *Map, struct ilist *List,
- struct line_pnts *coord, double thresh,
- struct ilist *List_updated)
- {
- int i, j, l;
- int type, line, seg, newline;
- int nlines_modified;
- double px, py, spdist, lpdist, dist;
- double *x, *y, *z;
- struct line_pnts *Points, *Points2;
- struct line_cats *Cats;
- struct ilist *List_in_box;
- nlines_modified = 0;
- Points = Vect_new_line_struct();
- Points2 = Vect_new_line_struct();
- Cats = Vect_new_cats_struct();
- List_in_box = Vect_new_list();
- for (i = 0; i < List->n_values; i++) {
- line = List->value[i];
- if (!Vect_line_alive(Map, line))
- continue;
- type = Vect_read_line(Map, Points, Cats, line);
- if (!(type & GV_LINES))
- continue;
- x = Points->x;
- y = Points->y;
- z = Points->z;
- for (j = 0; j < coord->n_points; j++) {
- seg =
- Vect_line_distance(Points, coord->x[j], coord->y[j],
- coord->z[j], WITHOUT_Z, &px, &py, NULL,
- &dist, &spdist, &lpdist);
- if (dist > thresh) {
- continue;
- }
- G_debug(3, "Vedit_split_lines(): line=%d, x=%f, y=%f, px=%f, py=%f, seg=%d, "
- "dist=%f, spdist=%f, lpdist=%f", line, coord->x[j],
- coord->y[j], px, py, seg, dist, spdist, lpdist);
-
- if (spdist <= 0.0 || spdist >= Vect_line_length(Points))
- continue;
- G_debug(3, "Vedit_split_lines(): line=%d", line);
- /* copy first line part */
- Vect_reset_line(Points2);
- for (l = 0; l < seg; l++) {
- Vect_append_point(Points2, x[l], y[l], z[l]);
- }
- /* add last vertex */
- Vect_append_point(Points2, px, py, 0.0);
- /* rewrite the line */
- if (j == 0)
- newline = Vect_rewrite_line(Map, line, type, Points2, Cats);
- else
- newline = Vect_write_line(Map, type, Points2, Cats);
- if (newline < 0) {
- return -1;
- }
- if (List_updated)
- Vect_list_append(List_updated, newline);
- Vect_reset_line(Points2);
- /* add given vertex */
- Vect_append_point(Points2, px, py, 0.0);
- /* copy second line part */
- for (l = seg; l < Points->n_points; l++) {
- Vect_append_point(Points2, x[l], y[l], z[l]);
- }
- /* rewrite the line */
- newline = Vect_write_line(Map, type, Points2, Cats);
- if (newline < 0) {
- return -1;
- }
- if (List_updated)
- Vect_list_append(List_updated, newline);
- nlines_modified++;
- } /* for each bounding box */
- } /* for each selected line */
- Vect_destroy_line_struct(Points);
- Vect_destroy_line_struct(Points2);
- Vect_destroy_cats_struct(Cats);
- Vect_destroy_list(List_in_box);
- return nlines_modified;
- }
- /*!
- \brief Connect lines in given threshold
-
- \code
- \ \
- id1 \ -> \
- \
- id2 --------- -----+---
- \endcode
- If two lines are selected and <i>thresh</i> is -1, no limit is
- applied.
- \param Map pointer to Map_info
- \param List list of selected lines
- \param thresh threshold value
- \return number of modified lines
- \return -1 on error
- */
- int Vedit_connect_lines(struct Map_info *Map, struct ilist *List,
- double thresh)
- {
- int nlines_modified, connected;
- int i, j, node[2], n_nodes;
- int line, found;
- double x, y, z;
- struct ilist *List_exclude, *List_found;
- nlines_modified = 0;
- List_exclude = Vect_new_list();
- List_found = Vect_new_list();
- n_nodes = 2;
- /* collect lines to be modified */
- for (i = 0; i < List->n_values; i++) {
- line = List->value[i];
- if (!Vect_line_alive(Map, line))
- continue;
- if (Vect_get_line_type(Map, line) & GV_POINTS)
- continue;
- node[0] = node[1] = -1;
- Vect_get_line_nodes(Map, line, &(node[0]), &(node[1]));
- if (node[0] < 0 || node[1] < 0)
- continue;
- connected = 0;
- Vect_reset_list(List_exclude);
- Vect_list_append(List_exclude, line);
- for (j = 0; j < n_nodes && !connected; j++) {
- /* for each line node find lines in threshold */
- Vect_get_node_coor(Map, node[j], &x, &y, &z);
- do {
- /* find first nearest line */
- found = Vect_find_line_list(Map, x, y, z,
- GV_LINES, thresh, WITHOUT_Z,
- List_exclude, List_found);
-
- if (found > 0 && Vect_line_alive(Map, found)) {
- /* try to connect lines (given node) */
- G_debug(3, "Vedit_connect_lines(): lines=%d,%d", line, found);
- if (connect_lines(Map, !j, line, found, thresh, List)) {
- G_debug(3, "Vedit_connect_lines(): lines=%d,%d -> connected",
- line, found);
- nlines_modified += 2;
- connected = 1;
- }
- }
-
- Vect_list_append(List_exclude, found);
- } while(List_found->n_values > 0 && !connected);
- }
- }
-
- Vect_destroy_list(List_exclude);
- Vect_destroy_list(List_found);
- return nlines_modified;
- }
- int connect_lines(struct Map_info *Map, int first, int line_from, int line_to,
- double thresh, struct ilist *List)
- {
- int line_new;
- int type_from, type_to;
- int n_points, seg, is;
- double x, y, px, py, x1, y1;
- double dist, spdist, lpdist, length, dist_p;
- double angle_t, angle_f, angle;
- struct line_pnts *Points_from, *Points_to, *Points_final;
- struct line_cats *Cats_from, *Cats_to;
- Points_from = Vect_new_line_struct();
- Points_to = Vect_new_line_struct();
- Points_final = Vect_new_line_struct();
- Cats_from = Vect_new_cats_struct();
- Cats_to = Vect_new_cats_struct();
- type_from = Vect_read_line(Map, Points_from, Cats_from, line_from);
- type_to = Vect_read_line(Map, Points_to, Cats_to, line_to);
- line_new = 0;
- if (!(type_from & GV_LINES) || !(type_to & GV_LINES))
- line_new = -1;
- if (line_new > -1) {
- n_points = Points_from->n_points - 1;
- if (first) {
- x = Points_from->x[0];
- y = Points_from->y[0];
- }
- else {
- x = Points_from->x[n_points];
- y = Points_from->y[n_points];
- }
- seg = Vect_line_distance(Points_to, x, y, 0.0, WITHOUT_Z,
- &px, &py, NULL, &dist, &spdist, &lpdist);
-
- if (seg > 0 && dist > 0.0 && (thresh < 0. || dist <= thresh)) {
- /* lines in threshold */
- if (first)
- length = 0;
- else
- length = Vect_line_length(Points_from);
- if (Vect_point_on_line(Points_from, length,
- NULL, NULL, NULL, &angle_f, NULL) > 0) {
- if (Vect_point_on_line(Points_to, lpdist,
- NULL, NULL, NULL, &angle_t,
- NULL) > 0) {
- angle = angle_t - angle_f;
- dist_p = fabs(dist / sin(angle));
-
- if (first) {
- if (angle_f < 0)
- angle_f -= M_PI;
- else
- angle_f += M_PI;
- }
- x1 = x + dist_p * cos(angle_f);
- y1 = y + dist_p * sin(angle_f);
- length = Vect_line_length(Points_to);
- Vect_line_insert_point(Points_to, seg, x1, y1, 0.);
- if (fabs(Vect_line_length(Points_to) - length) < length * 1e-3) {
- /* lines connected -> split line_to */
- /* update line_from */
- if (first) {
- Points_from->x[0] = x1;
- Points_from->y[0] = y1;
- }
- else {
- Points_from->x[n_points] = x1;
- Points_from->y[n_points] = y1;
- }
-
- line_new = Vect_rewrite_line(Map, line_from, type_from,
- Points_from, Cats_from);
- /* Vect_list_append(List, line_new); */
-
- /* update line_to -- first part */
- Vect_reset_line(Points_final);
- for (is = 0; is < seg; is++) {
- Vect_append_point(Points_final, Points_to->x[is],
- Points_to->y[is],
- Points_to->z[is]);
- }
- Vect_append_point(Points_final, x1, y1, 0.0);
- line_new = Vect_rewrite_line(Map, line_to, type_to,
- Points_final, Cats_to);
- /* Vect_list_append(List, line_new); */
-
- /* write second part */
- Vect_reset_line(Points_final);
- Vect_append_point(Points_final, x1, y1, 0.0);
- for (is = seg; is < Points_to->n_points; is++) {
- Vect_append_point(Points_final, Points_to->x[is],
- Points_to->y[is],
- Points_to->z[is]);
- }
-
- /* rewrite first part */
- line_new = Vect_write_line(Map, type_to,
- Points_final, Cats_to);
- /* Vect_list_append(List, line_new); */
- }
- }
- }
- }
- }
- Vect_destroy_line_struct(Points_from);
- Vect_destroy_line_struct(Points_to);
- Vect_destroy_line_struct(Points_final);
- Vect_destroy_cats_struct(Cats_from);
- Vect_destroy_cats_struct(Cats_to);
- return line_new > 0 ? 1 : 0;
- }
|