[GRASS-SVN] r30376 -
grass/branches/releasebranch_6_3/lib/vector/vedit
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Feb 27 13:08:19 EST 2008
Author: martinl
Date: 2008-02-27 13:08:19 -0500 (Wed, 27 Feb 2008)
New Revision: 30376
Added:
grass/branches/releasebranch_6_3/lib/vector/vedit/Makefile
grass/branches/releasebranch_6_3/lib/vector/vedit/break.c
grass/branches/releasebranch_6_3/lib/vector/vedit/cats.c
grass/branches/releasebranch_6_3/lib/vector/vedit/chtype.c
grass/branches/releasebranch_6_3/lib/vector/vedit/copy.c
grass/branches/releasebranch_6_3/lib/vector/vedit/delete.c
grass/branches/releasebranch_6_3/lib/vector/vedit/distance.c
grass/branches/releasebranch_6_3/lib/vector/vedit/flip.c
grass/branches/releasebranch_6_3/lib/vector/vedit/merge.c
grass/branches/releasebranch_6_3/lib/vector/vedit/move.c
grass/branches/releasebranch_6_3/lib/vector/vedit/select.c
grass/branches/releasebranch_6_3/lib/vector/vedit/snap.c
grass/branches/releasebranch_6_3/lib/vector/vedit/vertex.c
grass/branches/releasebranch_6_3/lib/vector/vedit/zbulk.c
Log:
veditlib backported from trunk (moved from vector/v.edit/lib)
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/Makefile
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/Makefile (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/Makefile 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,13 @@
+MODULE_TOPDIR = ../../..
+
+LIB_NAME = $(VEDIT_LIBNAME)
+DEPENDENCIES = $(GISDEP)
+EXTRA_INC = $(VECT_INC)
+EXTRA_CFLAGS = $(VECT_CFLAGS)
+EXTRA_LIBS = $(VECTLIB) $(DBMILIB) $(GISLIB)
+
+include $(MODULE_TOPDIR)/include/Make/Lib.make
+
+default: lib
+
+
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/break.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/break.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/break.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,337 @@
+/**
+ \file break.c
+
+ \brief Vedit library - split/break lines
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2007-2008 by the GRASS Development Team
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2007-2008
+*/
+
+#include <math.h>
+#include <grass/vedit.h>
+
+/**
+ \brief Split selected lines on given position
+
+ \param[in] Map vector map
+ \param[in] List list of selected lines
+ \param[in] coord points location
+ \param[in] 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 */
+ 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 */
+ newline = Vect_rewrite_line (Map, line, 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 *two* lines
+
+ The first line from the list is connected to the second one
+ if necessary the second line is broken
+
+ \ \
+ id1 \ -> \
+ \
+ id2 --------- ---------
+
+ \param[in] Map vector map
+ \param[in] List list of selected lines
+ \param[in] thresh threshold value for connect
+
+ \return 1 lines connected
+ \return 0 lines not connected
+ \return -1 on error
+ */
+int Vedit_connect_lines (struct Map_info *Map, struct ilist *List,
+ double thresh)
+{
+ int nlines_modified, newline, intersection, linep, nlines_to_modify;
+ int i, idx, pnt_idx[2];
+ int line[2], type[2], seg[2];
+ double px[2], py[2], pz[2], dist[2], spdist[2], lpdist[2];
+ double nx[2], ny[2], nz[2];
+ char n_on_line[2], connected;
+ double angle, dseg, dist_connect;
+
+ struct ilist *List_break, *List_updated;
+
+ struct line_pnts *Points[2];
+ struct line_cats *Cats[2];
+
+ nlines_modified = 0;
+ nlines_to_modify = 2; /* modify *two* lines at the time */
+
+ Points[0] = Points[1] = NULL;
+ Cats[0] = Cats[1] = NULL;
+
+ List_break = Vect_new_list ();
+ List_updated = Vect_new_list();
+
+ for (linep = 0; linep < List -> n_values; linep += 2) {
+ connected = 0;
+ /* read the lines */
+ for (i = 0; i < nlines_to_modify; i++) {
+ line[i] = List -> value[linep + i];
+
+ if (!Vect_line_alive (Map, line[i])) {
+ line[i] = -1;
+ break;
+ }
+ if (!Points[i])
+ Points[i] = Vect_new_line_struct();
+ if (!Cats[i])
+ Cats[i] = Vect_new_cats_struct();
+
+ type[i] = Vect_read_line(Map, Points[i], Cats[i], line[i]);
+
+ if (!(type[i] & GV_LINES)) {
+ line[i] = -1;
+ break;
+ }
+ }
+
+ if (line[0] == -1 || line[1] == -1)
+ continue;
+
+ /* check lines intersection
+ if (Vect_line_check_intersection (Points[0], Points[1], WITHOUT_Z))
+ return 0;
+ */
+
+ /* find node to connect */
+ for (i = 0; i < nlines_to_modify; i++) {
+ if (i == 0)
+ idx = 0;
+ else
+ idx = Points[0] -> n_points - 1;
+
+ seg[i] = Vect_line_distance (Points[1], Points[0]->x[idx], Points[0]->y[idx], Points[0]->z[idx],
+ WITHOUT_Z,
+ &px[i], &py[i], &pz[i],
+ &dist[i], &spdist[i], &lpdist[i]);
+ }
+
+ idx = (dist[0] <= dist[1]) ? 0 : 1;
+ pnt_idx[0] = (idx == 0) ? 0 : Points[0] -> n_points - 1; /* which node to connect */
+
+ angle =
+ M_PI / 2 -
+ acos (fabs (Points[0] -> x[0] - Points[0] -> x[Points[0] -> n_points - 1]) /
+ Vect_line_length (Points[0])) -
+ asin (fabs (Points[1] -> y[seg[idx] - 1] - py[idx]) / spdist[idx]);
+
+ dseg = dist[idx] * tan (angle);
+
+ /* compute connect points */
+ for (i = 0; i < nlines_to_modify; i++) {
+ if (0 == Vect_point_on_line (Points[1], lpdist[idx] + dseg, &nx[i], &ny[i], &nz[i], NULL, NULL)) {
+ n_on_line[i] = 0;
+ }
+ else {
+ n_on_line[i] = 1;
+ }
+ dseg *= -1.0;
+ }
+
+ if (!n_on_line[0] || !n_on_line[1]) {
+ G_warning (_("Unable to connect lines %d,%d"), line[0], line[1]);
+ continue;
+ }
+
+ /* choose connect point */
+ if (idx == 0)
+ pnt_idx[1] = Points[0] -> n_points - 1;
+ else
+ pnt_idx[1] = 0;
+
+ if (Vect_points_distance (nx[0], ny[0], nz[0],
+ Points[0] -> x[pnt_idx[1]], Points[0] -> y[pnt_idx[1]],
+ Points[0] -> z[pnt_idx[1]],
+ WITHOUT_Z) >
+ Vect_points_distance (nx[1], ny[1], nz[1],
+ Points[0] -> x[pnt_idx[1]], Points[0] -> y[pnt_idx[1]],
+ Points[0] -> z[pnt_idx[1]],
+ WITHOUT_Z))
+ pnt_idx[1] = 0;
+ else
+ pnt_idx[1] = 1;
+
+ dist_connect = Vect_points_distance (nx[pnt_idx[1]], ny[pnt_idx[1]], nz[pnt_idx[1]],
+ Points[0] -> x[pnt_idx[0]], Points[0] -> y[pnt_idx[0]],
+ Points[0] -> z[pnt_idx[0]],
+ WITHOUT_Z);
+
+ G_debug (3, "Vedit_connect_lines(): dist=%f/%f -> pnt_idx=%d -> "
+ "x=%f, y=%f / dist_connect=%f (thresh=%f)",
+ dist[0], dist[1], pnt_idx[0], nx[pnt_idx[1]], ny[pnt_idx[1]], dist_connect, thresh);
+
+ if (thresh >= 0.0 && dist_connect > thresh) {
+ continue;
+ }
+
+ /* modify the first line */
+ Vect_reset_list (List_updated);
+ intersection = Vect_line_check_intersection (Points[0], Points[1], WITHOUT_Z);
+
+ if (!intersection) {
+ if (pnt_idx[0] == 0)
+ Vect_line_insert_point (Points[0], 0, nx[pnt_idx[1]], ny[pnt_idx[1]], 0.0);
+ else
+ Vect_append_point (Points[0], nx[pnt_idx[1]], ny[pnt_idx[1]], 0.0);
+
+ /* rewrite the first line */
+ newline = Vect_rewrite_line (Map, line[0], type[0], Points[0], Cats[0]);
+ if (newline < 0) {
+ return -1;
+ }
+ Vect_list_append (List_updated, newline);
+ connected = 1;
+ }
+ else
+ Vect_list_append (List_updated, line[0]);
+
+ /* break the second line */
+ Vect_reset_list (List_break);
+ if (!intersection ||
+ (intersection &&
+ Vect_points_distance (nx[pnt_idx[1]], ny[pnt_idx[1]], nz[pnt_idx[1]],
+ Points[0] -> x[pnt_idx[0]], Points[0] -> y[pnt_idx[0]],
+ Points[0] -> z[pnt_idx[0]],
+ WITHOUT_Z) <= 0.0)) {
+ Vect_list_append (List_break, line[1]);
+ struct line_pnts *coord = Vect_new_line_struct();
+ Vect_append_point(coord, nx[pnt_idx[1]], ny[pnt_idx[1]], nz[pnt_idx[1]]);
+ Vedit_split_lines(Map, List_break,
+ coord, 1e-1,
+ List_updated);
+ Vect_destroy_line_struct(coord);
+ /* snap lines */
+ Vect_snap_lines_list (Map, List_updated, 1e-1, NULL, NULL);
+ connected = 1;
+ }
+
+ if (connected)
+ nlines_modified += 2;
+
+ } /* for each line pair */
+
+ /* destroy structures */
+ for (i = 0; i < nlines_to_modify; i++) {
+ if (Points[i])
+ Vect_destroy_line_struct(Points[i]);
+ if (Cats[i])
+ Vect_destroy_cats_struct(Cats[i]);
+ }
+ Vect_destroy_list (List_break);
+ Vect_destroy_list (List_updated);
+
+ return nlines_modified == 2 ? 1 : 0;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/cats.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/cats.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/cats.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,100 @@
+/**
+ \file cats.c
+
+ \brief Vedit library - category manipulation
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2006-2008 by the GRASS Development Team
+ Jachym Cepicky <jachym.cepicky gmail.com>
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2006-2008
+*/
+
+#include <grass/vedit.h>
+
+/**
+ \brief Add/remove categories of selected vector features
+
+ \param[in] Map vector map
+ \param[in] List list of selected features
+ \param[in] layer layer number
+ \param[in] del action (non-zero for delete otherwise add)
+ \param[in] cats_list list of category numbers
+
+ \return number of modified features
+ \return -1 on error
+*/
+int Vedit_modify_cats (struct Map_info *Map, struct ilist *List,
+ int layer, int del, struct cat_list *Clist)
+{
+ int i, j;
+ struct line_cats *Cats;
+ struct line_pnts *Points;
+ int line, type, cat;
+ int nlines_modified, rewrite;
+
+ /* features defined by cats */
+ if(Clist->n_ranges <= 0) {
+ return 0;
+ }
+
+ nlines_modified = 0;
+
+ Cats = Vect_new_cats_struct ();
+ Points = Vect_new_line_struct();
+
+ /* for each line, set new category */
+ for (i = 0; i < List->n_values; i++) {
+ line = List->value[i];
+ type = Vect_read_line(Map, Points, Cats, line);
+
+ if (!Vect_line_alive (Map, line))
+ continue;
+
+ rewrite = 0;
+ for (j = 0; j < Clist -> n_ranges; j++) {
+ for (cat = Clist -> min[j]; cat <= Clist -> max[j]; cat++) {
+ /* add new category */
+ if (!del) {
+ if(Vect_cat_set (Cats, layer, cat) < 1) {
+ G_warning (_("Unable to set category %d for line %d"),
+ cat, line);
+ }
+ else {
+ rewrite = 1;
+ }
+ }
+ else { /* delete old category */
+ if(Vect_field_cat_del (Cats, layer, cat) == 0) {
+ G_warning (_("Unable to delete layer/category %d/%d line %d"),
+ layer, cat, line);
+ }
+ else {
+ rewrite = 1;
+ }
+ }
+ }
+ }
+
+ if (rewrite == 0)
+ continue;
+
+ if (Vect_rewrite_line (Map, line, type, Points, Cats) < 0) {
+ return -1;
+ }
+
+ nlines_modified++;
+
+ }
+
+ /* destroy structures */
+ Vect_destroy_line_struct(Points);
+ Vect_destroy_cats_struct(Cats);
+
+ return nlines_modified;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/chtype.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/chtype.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/chtype.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,84 @@
+/**
+ \file chtype.c
+
+ \brief Vedit library - change feature type
+
+ Supported conversions:
+ - point<->centroid
+ - line<->boundary
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2008 by the GRASS Development Team
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2008
+*/
+
+#include <grass/vedit.h>
+
+int Vedit_chtype_lines(struct Map_info *Map, struct ilist *List,
+ int *npoints, int *ncentroids,
+ int *nlines, int *nboundaries)
+{
+ int i;
+ int nret, line;
+ int type, newtype;
+ struct line_pnts *Points;
+ struct line_cats *Cats;
+
+ nret = 0;
+ *npoints = *ncentroids = *nlines = *nboundaries = 0;
+
+ Points = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ 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 < 0) {
+ return -1;
+ }
+ switch (type) {
+ case GV_POINT:
+ newtype = GV_CENTROID;
+ (*npoints)++;
+ break;
+ case GV_CENTROID:
+ newtype = GV_POINT;
+ (*ncentroids)++;
+ break;
+ case GV_LINE:
+ newtype = GV_BOUNDARY;
+ (*nlines)++;
+ break;
+ case GV_BOUNDARY:
+ newtype = GV_LINE;
+ (*nboundaries)++;
+ break;
+ default:
+ newtype = -1;
+ break;
+ }
+
+ G_debug(3, "Vedit_chtype_lines(): line=%d, from_type=%d, to_type=%d",
+ line, type, newtype);
+
+ if (newtype > 0) {
+ if (Vect_rewrite_line(Map, line, newtype, Points, Cats) < 0) {
+ return -1;
+ }
+ nret++;
+ }
+ }
+
+ Vect_destroy_line_struct(Points);
+ Vect_destroy_cats_struct(Cats);
+
+ return nret;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/copy.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/copy.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/copy.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,70 @@
+/**
+ \file copy.c
+
+ \brief Vedit library - copy features
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2007-2008 by the GRASS Development Team
+ Jachym Cepicky <jachym.cepicky gmail.com>
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2007-2008
+*/
+
+#include <grass/vedit.h>
+
+/**
+ \brief Copy selected features
+
+ \param[in] Map vector map copy to
+ \param[in] FromMap vector map copy from (if not given use Map)
+ \param[in] List list of selected features (to be copied)
+
+ \return number of copied features
+ \return -1 on error
+ */
+int Vedit_copy_lines (struct Map_info *Map, struct Map_info *FromMap,
+ struct ilist *List)
+{
+ struct line_cats *Cats;
+ struct line_pnts *Points;
+ int i;
+ int type, line;
+ int nlines_copied;
+
+ nlines_copied = 0;
+ Cats = Vect_new_cats_struct();
+ Points = Vect_new_line_struct();
+
+ if (!FromMap) {
+ FromMap = Map;
+ }
+
+ /* for each line, make a copy */
+ for (i = 0; i < List->n_values; i++) {
+ line = List -> value[i];
+
+ if (!Vect_line_alive(FromMap, line))
+ continue;
+
+ type = Vect_read_line(FromMap, Points, Cats, line);
+
+ G_debug(3, "Vedit_copy_lines(): type=%d, line=%d", type, line);
+
+ /* copy */
+ if (Vect_write_line (Map, type, Points, Cats) < 0) {
+ return -1;
+ }
+
+ nlines_copied++;
+ }
+
+ Vect_destroy_line_struct (Points);
+ Vect_destroy_cats_struct (Cats);
+
+ return nlines_copied;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/delete.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/delete.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/delete.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,50 @@
+/**
+ \file delete.c
+
+ \brief Vedit library - delete features
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2007-2008 by the GRASS Development Team
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2007-2008
+*/
+
+#include <grass/vedit.h>
+
+/**
+ \brief Delete selected features
+
+ \param[in] Map vector map
+ \param[in] List list of features to be deleted
+
+ \return number of deleted features
+ \return -1 on on error
+ */
+int Vedit_delete_lines(struct Map_info *Map, struct ilist *List)
+{
+ int i, line;
+ int nlines_removed;
+
+ nlines_removed = 0;
+
+ /* delete */
+ for (i = 0; i < List->n_values; i++) {
+ line = List -> value[i];
+
+ if (Vect_line_alive(Map, line)) {
+ if (Vect_delete_line(Map, line) < 0) {
+ return -1;
+ }
+
+ G_debug (3, "Vedit_delete_lines(): line=%d", line);
+ nlines_removed++;
+ }
+ }
+
+ return nlines_removed;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/distance.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/distance.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/distance.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,75 @@
+/**
+ \file distance.c
+
+ \brief Vedit library - distance calculation
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ (C) 2007-2008 by the GRASS Development Team
+
+ \author Martin Landa <landa.martin gmail.com>
+
+ \date 2007-2008
+*/
+
+#include <grass/vedit.h>
+
+/**
+ \brief Calculate distances between two lines
+
+ TODO: LL projection
+
+ \param[in] Points1 first line
+ \param[in] Points2 second line
+ \param[out] index of minimal distance
+
+ \return minimal distance betwen two lines (their nodes)
+*/
+double Vedit_get_min_distance(struct line_pnts *Points1, struct line_pnts *Points2,
+ int with_z, int* mindistidx)
+{
+ unsigned int i;
+ double distances [4];
+
+ /*
+ distances[0] = first-first
+ distances[1] = first-last
+ distances[2] = last-first
+ distances[3] = last-last
+ */
+
+ distances[0] = Vect_points_distance(Points1->x[0], Points1->y[0], Points1->z[0],
+ Points2->x[0], Points2->y[0], Points2->z[0], with_z);
+
+ distances[1] = Vect_points_distance(Points1->x[0], Points1->y[0], Points1->z[0],
+ Points2->x[Points2->n_points-1],
+ Points2->y[Points2->n_points-1],
+ Points2->z[Points2->n_points-1], with_z);
+
+ distances[2] = Vect_points_distance(Points1->x[Points1->n_points-1],
+ Points1->y[Points1->n_points-1],
+ Points1->z[Points1->n_points-1],
+ Points2->x[0], Points2->y[0], Points2->z[0], with_z);
+
+ distances[3] = Vect_points_distance(Points1->x[Points1->n_points-1],
+ Points1->y[Points1->n_points-1],
+ Points1->z[Points1->n_points-1],
+ Points2->x[Points2->n_points-1],
+ Points2->y[Points2->n_points-1],
+ Points2->z[Points2->n_points-1], with_z);
+
+ /* find the minimal distance between first or last point of both lines */
+ *mindistidx = 0;
+ for (i = 0; i < sizeof (distances) / sizeof (double); i++) {
+ if (distances[i] >= 0.0 && distances[i] < distances[*mindistidx])
+ *mindistidx = i;
+ }
+
+ G_debug(3, "Vedit_get_min_distance(): dists=%f,%f,%f,%f",
+ distances[0], distances[1], distances[2], distances[3]);
+
+ return distances[*mindistidx];
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/flip.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/flip.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/flip.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,67 @@
+/**
+ \file flip.c
+
+ \brief Vedit library - lines flipping
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2007-2008 by the GRASS Development Team
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2007-2008
+*/
+
+#include <grass/vedit.h>
+
+/**
+ \brief Flip direction of selected vector lines
+
+ \param[in] Map vector map
+ \param[in] List list of selected lines
+
+ \return number of modified lines
+ \return -1 on error
+ */
+int Vedit_flip_lines(struct Map_info *Map, struct ilist *List)
+{
+ struct line_cats *Cats;
+ struct line_pnts *Points;
+ int i, line, type;
+ int nlines_flipped;
+
+ nlines_flipped = 0;
+
+ Points = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ 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;
+
+ Vect_line_reverse (Points);
+
+ if (Vect_rewrite_line (Map, line, type, Points, Cats) < 0) {
+ return -1;
+ }
+
+ G_debug(3, "Vedit_flip_lines(): line=%d", line);
+
+ nlines_flipped++;
+ }
+
+ /* destroy structures */
+ Vect_destroy_line_struct(Points);
+ Vect_destroy_cats_struct(Cats);
+
+ return nlines_flipped;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/merge.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/merge.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/merge.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,244 @@
+/**
+ \file merge.c
+
+ \brief Vedit library - merge lines
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2006-2008 by the GRASS Development Team
+ Jachym Cepicky <jachym.cepicky gmail.com>
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2006-2008
+*/
+
+#include <grass/vedit.h>
+
+/**
+ \brief Merge two given lines a, b
+
+ a : Points1/Cats1
+ b : Points2/Cats2
+ merged line : Points/Cats
+
+ \param[in] Points1,Cats1 first line
+ \param[in] Points2,Cats2 second line
+ \param[in] thresh threshold value
+ \param[out] Points result line
+
+ \return 1 on success
+ \return 0 on error
+*/
+static int merge_lines (struct line_pnts *Points1, struct line_cats *Cats1,
+ struct line_pnts *Points2, struct line_cats *Cats2,
+ double thresh, struct line_pnts **Points);
+
+/**
+ \brief Merge lines/boundaries
+
+ At least two lines need to be given.
+
+ \param[in] Map vector map
+ \param[in] List list of selected features
+
+ \return number of merged lines
+ \return -1 on error
+*/
+int Vedit_merge_lines(struct Map_info *Map, struct ilist *List)
+{
+ struct ilist *List_in_box;
+
+ struct line_pnts *Points1, *Points2, *Points;
+ struct line_cats *Cats1, *Cats2;
+
+ int line_i, i, j;
+ int line, line1, type1, line2, type2;
+ int do_merge;
+ /* number of lines (original, selected, merged) */
+ int nlines, nlines_selected, nlines_merged;
+
+ nlines_merged = 0;
+
+ if (List->n_values < 2) {
+ return 0;
+ }
+
+ Points1 = Vect_new_line_struct();
+ Cats1 = Vect_new_cats_struct();
+ Points2 = Vect_new_line_struct();
+ Cats2 = Vect_new_cats_struct();
+ Points = Vect_new_line_struct();
+
+ List_in_box = Vect_new_list();
+
+ nlines = Vect_get_num_lines (Map);
+ nlines_selected = List -> n_values;
+
+ /* merge lines */
+ for (line_i = 0; line_i < List -> n_values; line_i++) {
+ G_percent (line_i, List -> n_values, 2);
+
+ line1 = List -> value[line_i];
+
+ if (!Vect_line_alive (Map, line1))
+ continue;
+
+ type1 = Vect_read_line (Map, Points1, Cats1, line1);
+
+ if (!(type1 & GV_LINES))
+ continue;
+
+ Vect_reset_line (Points);
+
+ for (i = 0; i < Points1 -> n_points; i += Points1 -> n_points - 1) {
+ Vect_reset_list (List_in_box);
+
+ /* define searching region */
+ Vect_reset_line (Points2);
+ /*
+ Vect_append_point (Points2, Points1 -> x[i] - thresh,
+ Points1 -> y[i] + thresh, Points1 -> z[i]);
+ Vect_append_point (Points2, Points1 -> x[i] + thresh,
+ Points1 -> y[i] + thresh, Points1 -> z[i]);
+ Vect_append_point (Points2, Points1 -> x[i] + thresh,
+ Points1 -> y[i] - thresh, Points1 -> z[i]);
+ Vect_append_point (Points2, Points1 -> x[i] - thresh,
+ Points1 -> y[i] - thresh, Points1 -> z[i]);
+ */
+ Vect_append_point (Points2, Points1 -> x[i],
+ Points1 -> y[i], Points1 -> z[i]);
+
+ /*
+ * merge lines only if two lines found in the region
+ * i.e. the current line and an adjacent line
+ */
+ if (1 < Vect_select_lines_by_polygon (Map, Points2, 0, NULL,
+ GV_LINES, List_in_box)) {
+ do_merge = 1;
+ line2 = -1;
+ for (j = 0; do_merge && j < List -> n_values; j++) {
+ if (List -> value[j] == line1 ||
+ !Vect_line_alive(Map, List -> value[j]))
+ continue;
+
+ if (Vect_val_in_list (List_in_box, List -> value[j])) {
+ if (line2 > 0) {
+ /* three lines found
+ * selected lines will be not merged
+ */
+ do_merge = 0;
+ }
+ else {
+ line2 = List -> value[j];
+ }
+ }
+ }
+
+ if (!do_merge || line2 < 0)
+ continue;
+
+ type2 = Vect_read_line (Map, Points2, Cats2, line2);
+
+ merge_lines (Points1, Cats1,
+ Points2, Cats2,
+ -1.0, &Points); /* do not use threshold value */
+
+ G_debug (3, "Vedit_merge_lines(): lines=%d,%d", line1, line2);
+
+ if (Points -> n_points > 0) {
+ if (Vect_delete_line(Map, line2) == -1) {
+ return -1;
+ }
+
+ if (line2 <= nlines)
+ nlines_merged++;
+ }
+ }
+ } /* for each node */
+
+ if (Points -> n_points > 0) {
+ line = Vect_rewrite_line (Map, line1, type1, Points, Cats1);
+ if (line < 0) {
+ return -1;
+ }
+
+ if (line1 <= nlines)
+ nlines_merged++;
+
+ /* update number of lines */
+ Vect_list_append (List, line);
+ }
+ } /* for each line */
+
+ /* destroy stuctures */
+ Vect_destroy_line_struct(Points1);
+ Vect_destroy_line_struct(Points2);
+ Vect_destroy_line_struct(Points);
+
+ Vect_destroy_cats_struct(Cats1);
+ Vect_destroy_cats_struct(Cats2);
+
+ return nlines_merged;
+}
+
+static int merge_lines (struct line_pnts *Points1, struct line_cats *Cats1,
+ struct line_pnts *Points2, struct line_cats *Cats2,
+ double thresh, struct line_pnts **Points)
+{
+ struct line_pnts *ps = *Points;
+ struct line_cats *cs = Cats1;
+
+ int i, mindistidx;
+ double mindist;
+
+ /* find mininal distance and its index */
+ mindist = Vedit_get_min_distance(Points1, Points2, 0, /* TODO 3D */
+ &mindistidx);
+
+ G_debug (3, " merge line ? index: %d, mindist: %g, thresh: %g",
+ mindistidx, mindist, thresh);
+
+ if (thresh > 0 && mindist > thresh) {
+ return 0;
+ }
+
+ /* set index and other things */
+ switch(mindistidx) {
+ /* for each mindistidx create new line */
+ case 0:
+ Vect_append_points (ps, Points2, GV_BACKWARD);
+ if (ps -> n_points == Points2 -> n_points)
+ Vect_append_points (ps, Points1, GV_FORWARD);
+ break;
+ case 1:
+ Vect_append_points (ps, Points2, GV_FORWARD);
+ if (ps -> n_points == Points2 -> n_points)
+ Vect_append_points (ps, Points1, GV_FORWARD);
+ break;
+ case 2:
+ if (ps -> n_points == 0)
+ Vect_append_points (ps, Points1, GV_FORWARD);
+ Vect_append_points (ps, Points2, GV_FORWARD);
+ break;
+ case 3:
+ if (ps -> n_points == 0)
+ Vect_append_points (ps, Points1, GV_FORWARD);
+ Vect_append_points (ps, Points2, GV_BACKWARD);
+ break;
+ default:
+ break;
+ }
+
+ /* remove duplicate points */
+ Vect_line_prune (ps);
+
+ /* copy categories if needed */
+ for (i = 0; i < Cats2 -> n_cats; i++) {
+ Vect_cat_set (cs, Cats2 -> field[i], Cats2 -> cat[i]);
+ }
+
+ return 1;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/move.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/move.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/move.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,97 @@
+/**
+ \file move.c
+
+ \brief Vedit library - snapping
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2007-2008 by the GRASS Development Team
+ Martin Landa <landa.martin gmail.com>
+ Jachym Cepicky <jachym.cepicky gmail.com>
+
+ \date 2007-2008
+*/
+
+#include <grass/vedit.h>
+
+/**
+ \brief Move selected features
+
+ \param[in] Map vector map
+ \param[in] BgMap, nbgmaps list of background vector maps for snapping
+ \param[in] List list of features to be moved
+ \param[in] move_x,move_y,move_z direction (move_z used only if map is 3D)
+ \param[in] snap enable snapping (see globals.h)
+
+ \return number of modified features
+ \return -1 on error
+*/
+int Vedit_move_lines(struct Map_info *Map, struct Map_info **BgMap, int nbgmaps,
+ struct ilist *List,
+ double move_x, double move_y, double move_z,
+ int snap, double thresh)
+{
+ struct line_pnts *Points;
+ struct line_cats *Cats;
+ int i, j;
+ int type, newline, line;
+ int nlines_moved;
+ double *x, *y, *z;
+
+ nlines_moved = 0;
+
+ Points = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ 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);
+
+ G_debug(3, "Vedit_move_lines(): type=%d, line=%d", type, line);
+
+ x = Points->x;
+ y = Points->y;
+ z = Points->z;
+
+ /* move */
+ for (j = 0; j < Points -> n_points; j++) {
+ x[j] += move_x;
+ y[j] += move_y;
+ if (Vect_is_3d(Map))
+ z[j] += move_z;
+
+ if (snap != NO_SNAP) {
+ if (Vedit_snap_point(Map, line, &x[j], &y[j], &z[j], thresh,
+ (snap == SNAPVERTEX) ? 1 : 0) == 0) {
+ /* check also background maps */
+ int bgi;
+ for (bgi = 0; bgi < nbgmaps; bgi++) {
+ if (Vedit_snap_point(BgMap[bgi], line, &x[j], &y[j], &z[j], thresh,
+ (snap == SNAPVERTEX) ? 1 : 0))
+ break; /* snapped, don't continue */
+ }
+ }
+ }
+ } /* for each point at line */
+
+ newline = Vect_rewrite_line (Map, line, type, Points, Cats);
+
+ if (newline < 0) {
+ return -1;
+ }
+
+ nlines_moved++;
+ }
+
+ Vect_destroy_line_struct (Points);
+ Vect_destroy_cats_struct (Cats);
+
+ return nlines_moved;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/select.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/select.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/select.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,199 @@
+/**
+ \brief Vedit library - select vector features (by query)
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2007-2008 by the GRASS Development Team
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2007-2008
+*/
+
+#include <grass/vedit.h>
+
+static int select_by_query(struct Map_info *, int, int, int,
+ int, double,
+ struct line_pnts *, struct line_cats *);
+
+/**
+ \brief Select features by query (based on geometry)
+
+ Currently supported:
+ - QUERY_LENGTH, select all lines longer then threshold (or shorter if threshold is negative)
+ - QUERY_DANGLE, select all dangles then threshold (or shorter if threshold is negative)
+
+ If <em>List</em> is not empty query only those feature, otherwise query all
+ vector features stored in the vector map.
+
+ \todo Rewrite dangle part to use Vector library functionality
+
+ \param[in] Map vector map
+ \param[in] type feature type
+ \param[in] layer layer number
+ \param[in] thresh threshold value (< 0 for 'shorter', > 0 for 'longer')
+ \param[in] query query (length, dangle, ...)
+ \param[in,out] List list of selected features
+
+ \return number of selected lines
+*/
+int Vedit_select_by_query(struct Map_info *Map,
+ int type, int layer, double thresh, int query,
+ struct ilist* List)
+{
+ int num, line, i;
+ struct line_pnts *Points;
+ struct line_cats *Cats;
+ struct ilist *List_query;
+
+ Points = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ List_query = Vect_new_list();
+
+ if (List->n_values > 0) { /* query only selected */
+ for (i = 0; i < List->n_values; i++) {
+ line = List->value[i];
+ if (select_by_query(Map, line, type, layer,
+ query, thresh,
+ Points, Cats) == 1) {
+ if (!Vect_val_in_list(List, line)) {
+ Vect_list_append(List, line);
+ }
+ }
+ else {
+ if (Vect_val_in_list(List, line)) {
+ Vect_list_delete(List, line);
+ i--;
+ }
+ }
+ }
+ }
+ else { /* global query */
+ num = Vect_get_num_lines (Map);
+ for (line = 1; line <= num; line++) {
+ if (select_by_query(Map, line, type, layer,
+ query, thresh,
+ Points, Cats) == 1) {
+ Vect_list_append(List, line);
+ }
+ }
+ }
+
+ G_debug (3, "Vedit_select_by_query(): %d lines selected (by query %d)", List -> n_values, query);
+
+ Vect_destroy_line_struct(Points);
+ Vect_destroy_cats_struct(Cats);
+ Vect_destroy_list(List_query);
+
+ return List -> n_values;
+}
+
+/**
+ \brief Query given line
+
+ \return 1 line test positive
+ \return 0 line test negative
+ \return -1 on error (line is dead)
+*/
+static int select_by_query(struct Map_info *Map, int line, int type, int layer,
+ int query, double thresh,
+ struct line_pnts* Points, struct line_cats* Cats)
+{
+ int ltype, cat;
+ double length;
+
+ if (!Vect_line_alive(Map, line))
+ return -1;
+
+ ltype = Vect_read_line(Map, Points, Cats, line);
+ Vect_cat_get(Cats, layer, &cat); /* get first category from layer */
+
+ if (!(ltype & type))
+ return -1;
+
+ if (query == QUERY_LENGTH) {
+ length = Vect_line_length(Points);
+ if (thresh <= 0.0) { /* shorter then */
+ if (length <= fabs(thresh))
+ return 1;
+ }
+ else { /* longer then */
+ if (length > thresh)
+ return 1;
+ }
+ }
+ else if (query == QUERY_DANGLE) {
+ if (!(type & GV_LINES))
+ return -1;
+ /* check if line is dangle */
+
+ int i, cat_curr;
+ int node1, node2, node; /* nodes */
+ int nnode1, nnode2; /* number of line in node */
+ double nx, ny, nz; /* node coordinates */
+ struct ilist *exclude, *found; /* line id of nearest lines */
+ struct line_cats *Cats_curr;
+
+ Vect_get_line_nodes(Map, line, &node1, &node2);
+
+ node = -1;
+ nnode1 = Vect_get_node_n_lines(Map, node1);
+ nnode2 = Vect_get_node_n_lines(Map, node2);
+
+ if ((nnode1 == 4 && nnode2 == 1) ||
+ (nnode1 == 1 && nnode2 == 4)) {
+ if (nnode1 == 4)
+ node = node1;
+ else
+ node = node2;
+ }
+
+ /* no dangle ? */
+ if (node == -1)
+ return -1;
+
+ length = Vect_line_length(Points);
+ if (thresh <= 0.0) { /* shorter then */
+ if (length > fabs(thresh))
+ return -1;
+ }
+ else { /* longer then */
+ if (length <= thresh)
+ return -1;
+ }
+
+ /* at least one of the lines need to have same category number */
+ exclude = Vect_new_list();
+ found = Vect_new_list();
+
+ Vect_get_node_coor(Map, node, &nx, &ny, &nz);
+
+ Vect_list_append(exclude, line);
+ Vect_find_line_list(Map, nx, ny, nz,
+ GV_LINES, 0.0, WITHOUT_Z,
+ exclude, found);
+
+ Cats_curr = Vect_new_cats_struct();
+
+ for (i = 0; i < found->n_values; i++) {
+ Vect_read_line(Map, NULL, Cats_curr, found->value[i]);
+ if (Vect_cat_get(Cats_curr, layer, &cat_curr) > -1) {
+ if (cat == cat_curr)
+ return 1;
+ }
+ }
+
+ Vect_destroy_cats_struct(Cats_curr);
+ Vect_destroy_list(exclude);
+ Vect_destroy_list(found);
+ }
+ else {
+ /* this shouldn't happen */
+ G_fatal_error ("Vedit_select_by_query(): %s", _("Unknown query tool"));
+ }
+
+ return 0;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/snap.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/snap.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/snap.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,213 @@
+/**
+ \file snap.c
+
+ \brief Vedit library - snapping
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2007-2008 by the GRASS Development Team
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2007-2008
+*/
+
+#include <grass/vedit.h>
+
+/**
+ \brief Snap given point to the nearest feature
+
+ \param[in] Map vector map
+ \param[in] line line to be excluded (point on line)
+ \param[in] x,y,z point on line to be snapped
+ \param[in] thresh snapping threshold (>0)
+ \param[in] vertex snap also to vertex
+
+ \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 lines/boudaries to the nearest feature
+
+ If 'line' > 0, given line is snapped and rewritten.
+
+ \param[in] Map pointer to vector map
+ \param[in] BgMap,nbgmaps list of background maps used for snapping
+ \param[in] line line to be snapped (if already written, otherwise -1)
+ \param[in] Points line geometry
+ \param[in] layer layer number
+ \param[in] thresh threshold value used for snapping (>0)
+ \param[in] 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, type, 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 && (type & GV_LINES) &&
+ 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/boudaries to the nearest feature
+
+ \param[in] Map vector map
+ \param[in] BgMap,nbgmaps List of background maps
+ \param[in] List list of lines to be snapped
+ \param[in] layer layer number
+ \param[in] thresh threshold value used for snapping (>0)
+ \param[in] 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;
+
+ 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 < 0) {
+ return -1;
+ }
+ 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;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/vertex.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/vertex.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/vertex.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,341 @@
+/**
+ \file vertex.c
+
+ \brief Vedit library - vertex manipulation
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2006-2008 by the GRASS Development Team
+ Jachym Cepicky <jachym.cepicky gmail.com>
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2006-2008
+*/
+
+#include <grass/vedit.h>
+
+/**
+ \brief Move all vertices in bounding box(es)
+
+ \param[in] Map vector map
+ \param[in] BgMap, nbgmaps list of background vector maps for snapping
+ \param[in] List list of selected features
+ \param[in] coord points location
+ \param[in] thresh threshold value (also size of bounding boxes) (>0)
+ \param[in] move_x,move_y,move_z direction (move_z is used when map is 3D)
+ \param[in] move_first move only first vertex found in the bounding box
+ \param[in] snap snapping mode (see vedit.h)
+
+ \return number of moved verteces
+ \return -1 on error
+ */
+int Vedit_move_vertex(struct Map_info *Map, struct Map_info **BgMap, int nbgmaps,
+ struct ilist *List,
+ struct line_pnts* coord, double thresh,
+ double move_x, double move_y, double move_z,
+ int move_first, int snap)
+{
+ int nvertices_moved, nlines_modified, nvertices_snapped;
+
+ int i, j, k;
+ int line, type, rewrite;
+ int npoints;
+ double east, north, dist;
+ double *x, *y, *z;
+ char *moved;
+
+ struct line_pnts *Points, *Points_snap;
+ struct line_cats *Cats;
+
+ nlines_modified = 0;
+ nvertices_moved = nvertices_snapped = 0;
+ moved = NULL;
+
+ Points = Vect_new_line_struct();
+ Points_snap = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ 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;
+
+ npoints = Points -> n_points;
+ x = Points -> x;
+ y = Points -> y;
+ z = Points -> z;
+
+ /* vertex moved
+ 0 not moved
+ 1 moved
+ 2 moved and snapped
+ */
+ moved = (char *) G_realloc ((void *) moved, Points -> n_points * sizeof (char));
+ G_zero ((void *) moved, Points -> n_points * sizeof (char));
+
+ rewrite = 0;
+ for (j = 0; j < coord -> n_points; j++) {
+ east = coord->x[j];
+ north = coord->y[j];
+
+ /* move all vertices in the bounding box */
+ for (k = 0; k < Points -> n_points; k++) {
+ if (moved[k] == 0) {
+ dist = Vect_points_distance (east, north, 0.0,
+ x[k], y[k], z[k],
+ WITHOUT_Z);
+ if (dist <= thresh) {
+ G_debug (3, "Vedit_move_vertex(): line=%d; x=%f, y=%f -> x=%f, y=%f",
+ line, x[k], y[k], x[k] + move_x, y[k] + move_y);
+ x[k] += move_x;
+ y[k] += move_y;
+ if (Vect_is_3d(Map))
+ z[k] += move_z;
+
+ moved[k] = 1;
+
+ G_debug (3, "Vedit_move_vertex(): line=%d, point=%d", line, k);
+
+ if (snap != NO_SNAP) {
+ if (Vedit_snap_point(Map, line, &x[k], &y[k], &z[k], thresh,
+ (snap == SNAPVERTEX) ? 1 : 0) == 0) {
+ /* check also background maps */
+ int bgi;
+ for (bgi = 0; bgi < nbgmaps; bgi++) {
+ if (Vedit_snap_point(BgMap[bgi], line, &x[k], &y[k], &z[k], thresh,
+ (snap == SNAPVERTEX) ? 1 : 0))
+ moved[k] = 2;
+ break; /* snapped, don't continue */
+ }
+ }
+ else {
+ moved[k] = 2;
+ }
+ }
+
+ rewrite = 1;
+ nvertices_moved++;
+
+ if (move_first)
+ break;
+ }
+ }
+ } /* for each line vertex */
+
+ /* close line or boundary */
+ if ((type & GV_LINES) &&
+ Vect_points_distance(x[0], y[0], z[0],
+ x[npoints-1], y[npoints-1], z[npoints-1],
+ WITHOUT_Z) <= thresh) {
+
+ if (moved[0] == 1) { /* first node moved */
+ x[0] = x[npoints-1];
+ y[0] = y[npoints-1];
+ if (Vect_is_3d(Map))
+ z[0] = z[npoints-1];
+ }
+ else if (moved[npoints-1] == 1) { /* last node moved */
+ x[npoints-1] = x[0];
+ y[npoints-1] = y[0];
+ if (Vect_is_3d(Map))
+ z[npoints-1] = z[0];
+ }
+ }
+ } /* for each coord */
+
+ if (rewrite) {
+ if (Vect_rewrite_line (Map, line, type, Points, Cats) < 0) {
+ return -1;
+ }
+
+ nlines_modified++;
+ }
+ } /* for each selected line */
+
+ /* destroy structures */
+ Vect_destroy_line_struct(Points);
+ Vect_destroy_line_struct(Points_snap);
+ Vect_destroy_cats_struct(Cats);
+/* G_free ((void *) moved); */
+
+ return nvertices_moved;
+}
+
+/**
+ \brief Add new vertex to line.
+
+ Shape of line is not changed.
+
+ TODO: 3D
+
+ \param[in] Map vector map
+ \param[in] List list of features
+ \param[in] coord points location
+ \param[in] thresh find line in given threshold
+
+ \return number of add verteces
+ \return -1 on error
+*/
+int Vedit_add_vertex(struct Map_info *Map, struct ilist *List,
+ struct line_pnts* coord, double thresh)
+{
+ int i, j;
+ int type, line, seg;
+ int nlines_modified, nvertices_added, rewrite;
+ double east, north, dist;
+ double *x, *y, *z;
+ double px, py;
+
+ struct line_pnts *Points;
+ struct line_cats *Cats;
+
+ nlines_modified = 0;
+ nvertices_added = 0;
+ Points = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ 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;
+ rewrite = 0;
+ for (j = 0; j < coord -> n_points; j++) {
+ east = coord->x[j];
+ north = coord->y[j];
+
+ seg = Vect_line_distance (Points,
+ east, north, 0.0, /* standpoint */
+ WITHOUT_Z,
+ &px, &py, NULL, /* point on line */
+ &dist, /* distance to line */
+ NULL, NULL);
+
+ if (dist <= thresh &&
+ Vect_points_distance (px, py, 0.0, x[seg], y[seg], z[seg], WITHOUT_Z) > 0 &&
+ Vect_points_distance (px, py, 0.0, x[seg-1], y[seg-1], z[seg-1], WITHOUT_Z) > 0) {
+ /* add new vertex */
+ Vect_line_insert_point (Points, seg, px, py, 0.0);
+ G_debug (3, "Vedit_add_vertex(): line=%d; x=%f, y=%f, index=%d", line, px, py, seg);
+ rewrite = 1;
+ nvertices_added++;
+ }
+ } /* for each point */
+
+ /* rewrite the line */
+ if (rewrite) {
+ Vect_line_prune (Points);
+ if (Vect_rewrite_line (Map, line, type, Points, Cats) < 0) {
+ return -1;
+ }
+
+ nlines_modified++;
+ }
+ } /* for each line */
+
+ /* destroy structures */
+ Vect_destroy_line_struct(Points);
+ Vect_destroy_cats_struct(Cats);
+
+ return nvertices_added;
+}
+
+/**
+ \brief Remove vertex from line
+
+ TODO: 3D
+
+ \param[in] Map vector map
+ \param[in] List list of selected features
+ \param[in] coord points location
+ \param[in] thresh threshold value to find a line
+
+ \return number of removed vertices
+ \return -1 on error
+*/
+int Vedit_remove_vertex(struct Map_info *Map, struct ilist *List,
+ struct line_pnts *coord, double thresh)
+{
+ int i, j, k;
+ int type, line;
+ int nvertices_removed, rewrite, nlines_modified;
+ double east, north;
+ double dist;
+ double *x, *y, *z;
+
+ struct line_pnts *Points;
+ struct line_cats *Cats;
+
+ nvertices_removed = nlines_modified = 0;
+
+ Points = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ 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;
+ rewrite = 0;
+ for (j = 0; j < coord -> n_points; j++) {
+ east = coord->x[j];
+ north = coord->y[j];
+
+ for (k = 0; k < Points -> n_points; k++) {
+ dist = Vect_points_distance (east, north, 0.0,
+ x[k], y[k], z[k],
+ WITHOUT_Z);
+ if (dist <= thresh) {
+ /* remove vertex */
+ Vect_line_delete_point (Points, k);
+ G_debug (3, "Vedit_remove_vertex(): line=%d; x=%f, y=%f, index=%d", line, x[k], y[k], k);
+ k--;
+ nvertices_removed++;
+ rewrite = 1;
+ }
+ } /* for each point */
+ } /* for each bounding box */
+
+ if (rewrite) {
+ /* rewrite the line */
+ if (Vect_rewrite_line (Map, line, type, Points, Cats) < 0) {
+ return -1;
+ }
+
+ nlines_modified++;
+ }
+ } /* for each line */
+
+ /* destroy structures */
+ Vect_destroy_line_struct(Points);
+ Vect_destroy_cats_struct(Cats);
+
+ return nvertices_removed;
+}
Added: grass/branches/releasebranch_6_3/lib/vector/vedit/zbulk.c
===================================================================
--- grass/branches/releasebranch_6_3/lib/vector/vedit/zbulk.c (rev 0)
+++ grass/branches/releasebranch_6_3/lib/vector/vedit/zbulk.c 2008-02-27 18:08:19 UTC (rev 30376)
@@ -0,0 +1,136 @@
+/**
+ \file zbulk.c
+
+ \brief Vedit library - Bulk labeling (automated labeling of vector features)
+
+ This program is free software under the
+ GNU General Public License (>=v2).
+ Read the file COPYING that comes with GRASS
+ for details.
+
+ \author (C) 2007-2008 by the GRASS Development Team
+ Martin Landa <landa.martin gmail.com>
+
+ \date 2007-2008
+*/
+
+#include <grass/dbmi.h>
+#include <grass/vedit.h>
+
+/**
+ \brief Z bulk-labeling.
+
+ Automated labeling (z coordinate assignment) of vector lines (contours).
+
+ \param[in] Map vector map
+ \param[in] List list of selected features
+ \param[in] point_start_end staring and ending point
+ \param[in] start starting value
+ \param[in] step step
+
+ \return number of modified features
+ \return -1 on error
+*/
+int Vedit_bulk_labeling (struct Map_info *Map, struct ilist *List,
+ double x1, double y1, double x2, double y2,
+ double start, double step)
+{
+ int i, cv_i, p_i;
+ int line, type, temp_line;
+ int nlines_modified;
+ double value, dist;
+
+ struct line_cats *Cats;
+ struct line_pnts *Points, *Points_se; /* start - end */
+ /* for intersection */
+ struct line_pnts **Points_a, **Points_b;
+ int nlines_a, nlines_b;
+
+ dbCatValArray cv; /* line_id / dist */
+
+ nlines_modified = 0;
+
+ value = start;
+
+ Points = Vect_new_line_struct();
+ Points_se = Vect_new_line_struct();
+ Cats = Vect_new_cats_struct();
+
+ //cv = (dbCatValArray *) G_malloc (sizeof (dbCatValArray));
+ db_CatValArray_alloc(&cv, List->n_values);
+ cv.ctype = DB_C_TYPE_DOUBLE;
+ cv.n_values = 0;
+
+ Vect_append_point(Points_se, x1, y1, -PORT_DOUBLE_MAX);
+ Vect_append_point(Points_se, x2, y2, PORT_DOUBLE_MAX);
+
+ /* write temporaly line */
+ temp_line = Vect_write_line(Map, GV_LINE, Points_se, Cats);
+ if (temp_line < 0) {
+ return -1;
+ }
+
+ /* determine order of lines */
+ cv_i = 0;
+ 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, NULL, line);
+
+ if (!(type & GV_LINE))
+ continue;
+
+ if (Vect_line_check_intersection(Points_se, Points, WITH_Z)) {
+ Vect_line_intersection (Points_se, Points,
+ &Points_a, &Points_b, &nlines_a, &nlines_b,
+ WITHOUT_Z);
+
+ if (nlines_a < 2 || nlines_b < 1) /* should not happen */
+ continue;
+
+ /* calculate distance start point -> point of intersection */
+ for (p_i = 0; p_i < Points_a[0]->n_points; p_i++) {
+ Points_a[0]->z[p_i] = 0;
+ }
+ dist = Vect_line_length(Points_a[0]); /* always first line in array? */
+
+ cv.value[cv_i].cat = line;
+ cv.value[cv_i++].val.d = dist;
+ cv.n_values++;
+ }
+ }
+
+ /* sort array by distance */
+ db_CatValArray_sort_by_value(&cv);
+
+ /* z bulk-labeling */
+ for (cv_i = 0; cv_i < cv.n_values; cv_i++) {
+ line = cv.value[cv_i].cat;
+ Vect_read_line(Map, Points, Cats, line);
+
+ for(p_i = 0; p_i < Points->n_points; p_i++) {
+ Points->z[p_i] = value;
+ }
+
+ if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
+ return -1;
+ }
+ nlines_modified++;
+
+ value += step;
+ }
+
+ if (Vect_delete_line(Map, temp_line) < 0) {
+ return -1;
+ }
+
+ db_CatValArray_free(&cv);
+ Vect_destroy_line_struct(Points);
+ Vect_destroy_line_struct(Points_se);
+ Vect_destroy_cats_struct(Cats);
+
+ return nlines_modified;
+}
More information about the grass-commit
mailing list