[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