123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /*!
- \file lib/vector/vedit/snap.c
- \brief Vedit library - snapping
-
- (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 <grass/vedit.h>
- /*!
- \brief Snap given point to the nearest primitive
-
- \param Map pointer to Map_info
- \param line line to be excluded (point on line)
- \param x,y,z point on line to be snapped
- \param thresh snapping threshold (>0)
- \param vertex snap also to vertex (non-zero)
-
- \return 1 snapped
- \return 0 not snapped
- */
- int Vedit_snap_point(struct Map_info *Map,
- int line, double *x, double *y, double *z, double thresh,
- int vertex)
- {
- struct line_pnts *Points;
- int i, snapped;
- int line2snap, mindist_idx;
- double dist, mindist;
- snapped = 0;
- mindist_idx = -1;
- mindist = thresh;
- Points = Vect_new_line_struct();
- line2snap = Vect_find_line(Map, *x, *y, *z, -1, thresh, WITHOUT_Z, line);
- if (line2snap > 0) {
- Vect_read_line(Map, Points, NULL, line2snap);
- if (!Vect_line_alive(Map, line2snap)) {
- Vect_destroy_line_struct(Points);
- return snapped;
- }
- for (i = 0; i < Points->n_points; i++) {
- if (i > 0 && i < Points->n_points - 1)
- if (!vertex)
- continue;
- dist = Vect_points_distance(*x, *y, *z,
- Points->x[i], Points->y[i],
- Points->z[i], WITHOUT_Z);
- if (mindist >= dist) {
- mindist = dist;
- mindist_idx = i;
- }
- }
- if (mindist_idx > -1) {
- *x = Points->x[mindist_idx];
- *y = Points->y[mindist_idx];
- *z = Points->z[mindist_idx];
- snapped = 1;
- }
- }
- G_debug(3, "Vedit_snap_point(): map=%s, line2snap=%d, snapped=%d",
- Map->name, line2snap, snapped);
- Vect_destroy_line_struct(Points);
- return snapped;
- }
- /*!
- \brief Snap selected primitive to its nearest primitive
-
- \param Map pointer to Map_info
- \param BgMap,nbgmaps list of background maps used for snapping
- \param line line id to be snapped (if already written, otherwise -1)
- \param Points line geometry
- \param layer layer number
- \param thresh threshold value used for snapping (>0)
- \param to_vertex allow snapping also to vertex
-
- \return 1 line snapped
- \return 0 line not snapped
- \return -1 line is dead (if 'line' is > 0)
- */
- int Vedit_snap_line(struct Map_info *Map, struct Map_info **BgMap,
- int nbgmaps, int line, struct line_pnts *Points,
- double thresh, int to_vertex)
- {
- int i, npoints, node, rewrite;
- double *x, *y, *z;
- struct line_cats *Cats;
- Cats = Vect_new_cats_struct();
- G_debug(3, "Vedit_snap_line(): thresh=%g, to_vertex=%d", thresh,
- to_vertex);
- if (line > 0 && !Vect_line_alive(Map, line))
- return -1;
- npoints = Points->n_points;
- x = Points->x;
- y = Points->y;
- z = Points->z;
- rewrite = 0;
- for (node = 0; node < npoints; node++) {
- if ((node > 0 && node < npoints - 1) && !to_vertex)
- continue;
- if (Vedit_snap_point(Map, line, &x[node], &y[node], &z[node], thresh,
- to_vertex)) {
- rewrite = 1;
- }
- else {
- /* check also background maps */
- for (i = 0; i < nbgmaps; i++) {
- if (Vedit_snap_point
- (BgMap[i], -1, &x[node], &y[node], &z[node], thresh,
- to_vertex)) {
- rewrite = 1;
- break; /* snapped, don't continue */
- }
- }
- }
- } /* for each line vertex */
- /* close boundaries or lines */
- if (!rewrite &&
- Vect_points_distance(x[0], y[0], z[0],
- x[npoints - 1], y[npoints - 1], z[npoints - 1],
- WITHOUT_Z) <= thresh) {
- x[npoints - 1] = x[0];
- y[npoints - 1] = y[0];
- z[npoints - 1] = z[0];
- rewrite = 1;
- }
- G_debug(3, "Vedit_snap_line(): line=%d, snapped=%d", line, rewrite);
- Vect_destroy_cats_struct(Cats);
- return rewrite;
- }
- /*!
- \brief Snap lines/boundaries
-
- \param Map pointer to Map_info
- \param BgMap,nbgmaps list of background maps used for snapping
- \param List list of lines to be snapped
- \param layer layer number
- \param thresh threshold value used for snapping (>0)
- \param to_vertex allow snapping also to vertex
-
- \return number of snapped lines
- \return -1 on error
- */
- int Vedit_snap_lines(struct Map_info *Map, struct Map_info **BgMap,
- int nbgmaps, struct ilist *List, double thresh,
- int to_vertex)
- {
- int i, line, type;
- int nlines_modified = 0;
- struct line_pnts *Points;
- struct line_cats *Cats;
- Points = Vect_new_line_struct();
- Cats = Vect_new_cats_struct();
- for (i = 0; i < List->n_values; i++) {
- line = List->value[i];
- type = Vect_read_line(Map, Points, Cats, line);
- if (!(type & (GV_POINT | GV_LINES))) {
- continue;
- }
- if (Vedit_snap_line(Map, BgMap, nbgmaps,
- line, Points, thresh, to_vertex) == 1) {
- if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
- return -1;
- }
- nlines_modified++;
- }
- }
- Vect_destroy_line_struct(Points);
- Vect_destroy_cats_struct(Cats);
- return nlines_modified;
- }
|