[GRASS-SVN] r30374 - grass/branches/releasebranch_6_3/vector/v.edit

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Feb 27 10:10:07 EST 2008


Author: martinl
Date: 2008-02-27 10:10:07 -0500 (Wed, 27 Feb 2008)
New Revision: 30374

Added:
   grass/branches/releasebranch_6_3/vector/v.edit/a2b.c
   grass/branches/releasebranch_6_3/vector/v.edit/args.c
   grass/branches/releasebranch_6_3/vector/v.edit/description.html
   grass/branches/releasebranch_6_3/vector/v.edit/global.h
   grass/branches/releasebranch_6_3/vector/v.edit/main.c
   grass/branches/releasebranch_6_3/vector/v.edit/max_distance.c
   grass/branches/releasebranch_6_3/vector/v.edit/proto.h
   grass/branches/releasebranch_6_3/vector/v.edit/select.c
   grass/branches/releasebranch_6_3/vector/v.edit/snap.c
Removed:
   grass/branches/releasebranch_6_3/vector/v.edit/cmd/
   grass/branches/releasebranch_6_3/vector/v.edit/lib/
Modified:
   grass/branches/releasebranch_6_3/vector/v.edit/Makefile
Log:
v.edit backported from trunk (lib moved to lib/vector/vedit)

Modified: grass/branches/releasebranch_6_3/vector/v.edit/Makefile
===================================================================
--- grass/branches/releasebranch_6_3/vector/v.edit/Makefile	2008-02-27 08:45:08 UTC (rev 30373)
+++ grass/branches/releasebranch_6_3/vector/v.edit/Makefile	2008-02-27 15:10:07 UTC (rev 30374)
@@ -1,13 +1,12 @@
 MODULE_TOPDIR = ../..
 
-SUBDIRS1 = cmd
+PGM = v.edit
 
-SUBDIRS = lib $(SUBDIRS1)
+LIBES = $(VEDITLIB) $(VECTLIB) $(GISLIB)
+DEPENDENCIES= $(VEDITDEP) $(VECTDEP) $(GISDEP)
+EXTRA_INC = $(VECT_INC)
+EXTRA_CFLAGS = $(VECT_CFLAGS)
 
-include $(MODULE_TOPDIR)/include/Make/Dir.make
+include $(MODULE_TOPDIR)/include/Make/Module.make
 
-default: parsubdirs
-
-clean: cleansubdirs
-
-$(SUBDIRS1): lib
+default: cmd

Copied: grass/branches/releasebranch_6_3/vector/v.edit/a2b.c (from rev 30279, grass/branches/releasebranch_6_3/vector/v.edit/cmd/a2b.c)
===================================================================
--- grass/branches/releasebranch_6_3/vector/v.edit/a2b.c	                        (rev 0)
+++ grass/branches/releasebranch_6_3/vector/v.edit/a2b.c	2008-02-27 15:10:07 UTC (rev 30374)
@@ -0,0 +1,330 @@
+/****************************************************************
+ *
+ * MODULE:     v.edit
+ *
+ * PURPOSE:    Editing vector map.
+ *
+ * AUTHOR(S):  GRASS Development Team
+ *             Wolf Bergenheim, Jachym Cepicky, Martin Landa
+ *
+ * COPYRIGHT:  (C) 2006-2008 by the GRASS Development Team
+ *
+ *             This program is free software under the
+ *             GNU General Public License (>=v2).
+ *             Read the file COPYING that comes with GRASS
+ *             for details.
+ *
+ * TODO:       3D support
+ ****************************************************************/
+
+#include <string.h>
+#include "global.h"
+
+#define BUFFSIZE 128
+
+/**
+   \brief Add new vector features to the vector map
+   
+   Input format is GRASS ASCII vector, the code adopted from v.in.ascii
+
+   \param[in] ascii file containing definition of new vector features
+   \param[in] Map vector map
+   \param[out] List list of added features (if given)
+
+   \return number of added features
+*/
+int asc_to_bin(FILE *ascii , struct Map_info *Map, struct ilist *List)
+{
+    char ctype;
+    char buff[BUFFSIZE];
+    double *xarray;
+    double *yarray;
+    double *zarray;	
+    double *x, *y, *z;
+    int i, n_points, n_coors, n_cats;
+    int type, newline;
+    int alloc_points;
+    int end_of_file;
+    int catn;
+    int cat;
+    int nlines;
+
+    struct line_pnts *Points;
+    struct line_cats *Cats;	
+    
+    nlines = 0;
+
+    Points = Vect_new_line_struct ();
+    Cats = Vect_new_cats_struct ();	
+    
+    if (List) {
+	Vect_reset_list(List);
+    }
+
+    end_of_file = 0 ;
+    /*alloc_points     = 1000 ; */
+    alloc_points     = 1;
+    xarray = (double *) G_calloc(alloc_points, sizeof(double)) ;
+    yarray = (double *) G_calloc(alloc_points, sizeof(double)) ;
+    zarray = (double *) G_calloc(alloc_points, sizeof(double)) ;
+    
+    while( G_getl2(buff,BUFFSIZE-1,ascii) != 0 )
+    {
+	n_cats=0;
+	if (buff[0] == '\0') {
+	    G_debug(3, "a2b: skipping blank line");
+	    continue;
+	}
+
+	if (  sscanf(buff, "%1c%d%d", &ctype, &n_coors, &n_cats) < 2  || n_coors < 0 || n_cats < 0 ) {
+	    if (ctype == '#') {
+		G_debug(2, "a2b: skipping commented line");
+		continue;
+	    }
+	    G_warning (_("Error reading ASCII file: '%s'"), buff);
+	    return -1;
+	}
+	if (ctype == '#') {
+	    G_debug(2, "a2b: Skipping commented line");
+	    continue;
+	}
+	
+	switch(ctype){
+	case 'A':
+	    type = GV_BOUNDARY ;
+	    break ;
+	case 'B':
+	    type = GV_BOUNDARY ;
+	    break ;
+	case 'C':
+	    type = GV_CENTROID ;
+	    break ;			
+	case 'L':
+	    type = GV_LINE ;
+	    break ;
+	case 'P':
+	    type = GV_POINT ;
+	    break ;
+	case 'F':
+	    type = GV_FACE ;
+	    break ;
+	case 'K':
+	    type = GV_KERNEL ;
+	    break ;
+	case 'a':
+	case 'b':
+	case 'c':
+	case 'l':
+	case 'p':
+	    type = 0; /* dead -> ignore */
+	    break;
+	default:
+	    G_warning (_("Error reading ASCII file: '%s'"), buff) ;
+	    return -1;
+	}
+	G_debug(5, "feature type = %d", type);
+	
+	n_points = 0 ;
+	x = xarray ;
+	y = yarray ;
+	z = zarray ;		
+	
+	/* Collect the points */
+	for(i = 0; i < n_coors; i++)
+	{
+	    if ( G_getl2 (buff, BUFFSIZE-1, ascii) == 0 ) {
+		G_warning (_("End of ASCII file reached before end of coordinates")) ;
+		return -1;
+	    }
+	    if (buff[0] == '\0') {
+		G_debug(3, "a2b: skipping blank line while reading vertices");
+		i--;
+		continue;
+	    }
+	    
+	    *z=0;
+	    if ( sscanf(buff, "%lf%lf%lf", x, y, z) < 2 ) {			
+		G_warning (_("Error reading ASCII file: '%s'"), buff) ;
+		return -1;
+	    }    
+	    G_debug( 5, "coor in: %s -> x = %f y = %f z = %f", G_chop(buff), *x, *y, *z);
+	    
+	    n_points++;
+	    x++;
+	    y++;
+	    z++;			
+	    
+	    if (n_points >= alloc_points)
+	    {
+		alloc_points = n_points + 1000 ;
+		xarray = (double *) G_realloc((void *)xarray, alloc_points * sizeof(double) );
+		yarray = (double *) G_realloc((void *)yarray, alloc_points * sizeof(double) );
+		zarray = (double *) G_realloc((void *)zarray, alloc_points * sizeof(double) );
+		x = xarray + n_points ;
+		y = yarray + n_points ;
+		z = zarray + n_points ;
+	    }
+	}
+	
+	/* Collect the cats */
+	for( i=0; i<n_cats; i++)
+	{
+	    if ( G_getl2(buff,BUFFSIZE-1,ascii) == 0 ) {
+		G_warning (_("End of ascii file reached before end of categories")) ;
+		return -1;
+	    }
+	    if (buff[0] == '\0') {
+		G_debug(3, "a2b: skipping blank line while reading category info");
+		i--;
+		continue;
+	    }
+	    
+	    if ( sscanf(buff, "%u%u", &catn, &cat) != 2 ) {
+		G_warning (_("Error reading categories: '%s'"), buff) ;
+		return -1;
+	    }
+	    Vect_cat_set ( Cats, catn, cat );
+	}
+	
+	/* Allocation is handled for line_pnts */
+	if (0 > Vect_copy_xyz_to_pnts (Points, xarray, yarray, zarray, n_points))
+	    G_fatal_error(_("Out of memory"));
+	
+	if ( type > 0 ) {
+	    newline = Vect_write_line ( Map, type, Points, Cats );
+	    if (List) {
+		Vect_list_append(List, newline);
+	    }
+	    nlines++;
+
+	    Vect_reset_cats ( Cats ); 
+	}
+    }
+
+    return nlines;	
+}
+
+/**
+   \brief Read header of input file
+   
+   \param[in] dascii file containing definition of vector features to be added
+   \param[in] Map vector map
+   
+   \return 0
+*/
+int 
+read_head ( FILE * dascii, struct Map_info *Map )
+{
+    char buff[1024];
+    char *ptr;
+    
+    for (;;)
+    {
+	if (0 == G_getl2(buff, sizeof(buff) -1, dascii))
+	    return 0;
+	
+	/* Last line of header */
+	if (strncmp (buff, "VERTI:", 6) == 0)	  
+	    return 0;
+	
+	if (!(ptr = G_index (buff, ':')))
+	    G_fatal_error(_("Unexpected data in vector head: '%s'"), buff);
+	
+	ptr++;			/* Search for the start of text */
+	while (*ptr == ' ')
+	    ptr++;
+	
+	if (strncmp (buff, "ORGANIZATION:", 12) == 0)
+	    Vect_set_organization ( Map, ptr );  
+	else if (strncmp (buff, "DIGIT DATE:", 11) == 0)
+	    Vect_set_date ( Map, ptr );  
+	else if (strncmp (buff, "DIGIT NAME:", 11) == 0)
+	    Vect_set_person ( Map, ptr );  
+	else if (strncmp (buff, "MAP NAME:", 9) == 0)
+	    Vect_set_map_name ( Map, ptr );  
+	else if (strncmp (buff, "MAP DATE:", 9) == 0)
+	    Vect_set_map_date ( Map, ptr );  
+	else if (strncmp (buff, "MAP SCALE:", 10) == 0)
+	    Vect_set_scale ( Map, atoi (ptr) );  
+	else if (strncmp (buff, "OTHER INFO:", 11) == 0)
+	    Vect_set_comment ( Map, ptr );  
+	else if (strncmp (buff, "ZONE:", 5) == 0 || strncmp (buff, "UTM ZONE:", 9) == 0)
+	    Vect_set_zone ( Map, atoi (ptr) );  
+	else if (strncmp (buff, "WEST EDGE:", 10) == 0) {}
+	else if (strncmp (buff, "EAST EDGE:", 10) == 0) {}
+	else if (strncmp (buff, "SOUTH EDGE:", 11) == 0) {}
+	else if (strncmp (buff, "NORTH EDGE:", 11) == 0) {}
+	else if (strncmp (buff, "MAP THRESH:", 11) == 0)
+	    Vect_set_thresh ( Map, atof (ptr) );  
+	else
+        {
+	  G_warning(_("Unknown keyword '%s' in vector head"), buff);
+	}
+    }
+    /* NOTREACHED */
+}
+
+/**
+   \brief Close lines (boudaries)
+   
+   Using threshold distance (-1 for no limit)
+   
+   \param[in] Map vector map
+   \param[in] ltype vector feature type (line | boundary)
+   \param[in] thresh threshold distance
+
+   \return number of modified features
+*/
+int close_lines(struct Map_info *Map, int ltype, double thresh)
+{
+    int nlines, line, type, nlines_modified, newline;
+    int npoints;
+    double *x, *y, *z;
+    double dist;
+
+    struct line_pnts *Points;
+    struct line_cats *Cats;
+
+    Points = Vect_new_line_struct();
+    Cats   = Vect_new_cats_struct();
+
+    nlines_modified = 0;
+
+    Vect_build_partial (Map, GV_BUILD_BASE, NULL);
+    nlines = Vect_get_num_lines (Map);
+
+    for (line = 1; line <= nlines; line++) {
+	if (!Vect_line_alive (Map, line))
+	    continue;
+
+        type = Vect_read_line(Map, Points, Cats, line);
+
+	if (!(type & ltype))
+	    continue;
+
+	npoints = Points -> n_points - 1;
+	x = Points -> x;
+	y = Points -> y;
+	z = Points -> z;
+
+	dist = Vect_points_distance (x[npoints], y[npoints], z[npoints],
+				     x[0], y[0], z[0], WITHOUT_Z);
+
+	if (dist > 0 && (thresh < 0.0 || dist <= thresh)) {
+	    Vect_line_delete_point (Points, npoints);
+	    Vect_append_point (Points, x[0], y[0], z[0]); 
+	    
+	    newline = Vect_rewrite_line (Map, line, type, Points, Cats);
+	    if (newline < 0)  {
+		G_warning(_("Unable to rewrite line %d"), line);
+		return -1;
+	    }
+	    nlines_modified++;
+	}
+    }
+
+    Vect_destroy_line_struct(Points);
+    Vect_destroy_cats_struct(Cats);
+
+    return nlines_modified;
+}

Copied: grass/branches/releasebranch_6_3/vector/v.edit/args.c (from rev 30279, grass/branches/releasebranch_6_3/vector/v.edit/cmd/args.c)
===================================================================
--- grass/branches/releasebranch_6_3/vector/v.edit/args.c	                        (rev 0)
+++ grass/branches/releasebranch_6_3/vector/v.edit/args.c	2008-02-27 15:10:07 UTC (rev 30374)
@@ -0,0 +1,367 @@
+/****************************************************************
+ *
+ * MODULE:     v.edit
+ *
+ * PURPOSE:    Editing vector map.
+ *
+ * AUTHOR(S):  GRASS Development Team
+ *             Wolf Bergenheim, Jachym Cepicky, Martin Landa
+ *
+ * COPYRIGHT:  (C) 2006-2008 by the GRASS Development Team
+ *
+ *             This program is free software under the
+ *             GNU General Public License (>=v2).
+ *             Read the file COPYING that comes with GRASS
+ *             for details.
+ *
+ * TODO:       3D support
+ ****************************************************************/
+
+#include "global.h"
+
+/**
+   \brief Parser stuff
+
+   \param[in] argc number of arguments
+   \param[in] argv arguments array
+   \param[in] params GRASS paramenters
+   \param[out] action mode selected tool
+
+   \return 1
+*/
+int parser(int argc, char* argv[], struct GParams *params,
+	   enum mode *action_mode)
+{
+    /* parameters */
+    params -> map = G_define_standard_option(G_OPT_V_MAP);
+    params -> map -> description = _("Name of vector map to edit");
+
+    params -> fld = G_define_standard_option(G_OPT_V_FIELD);
+    params -> fld->guisection  = _("Query");
+
+    params -> type = G_define_standard_option(G_OPT_V_TYPE);
+    params -> type->answer           = "point,line,boundary,centroid";
+    params -> type->options          = "point,line,boundary,centroid";
+    params -> type->guisection  = _("Query");
+
+    params -> tool = G_define_option();
+    params -> tool->key         = "tool";
+    params -> tool->type        = TYPE_STRING;
+    params -> tool->required    = YES;
+    params -> tool->multiple    = NO;
+    params -> tool->description = _("Tool");
+    params -> tool->descriptions = _("create;"
+				     "Create new (empty) vector map;"
+				     "add;"
+				     "Add new features to existing vector map;"
+				     "delete;"
+				     "Delete selected features from vector map;"
+				     "move;"
+				     "Move selected features in vector map;"
+				     "vertexmove;"
+				     "Move vertex of selected vector lines;"
+				     "vertexdel;"
+				     "Remove vertex from selected vector lines;"
+				     "vertexadd;"
+				     "Add new vertex to selected vector lines;"
+				     "merge;"
+				     "Merge selected vector lines;"
+				     "break;"
+				     "Break/split vector lines;"
+				     "select;"
+				     "Select lines and print their ID's;"
+				     "catadd;"
+				     "Set new categories to selected vector features "
+				     "for defined layer;"
+				     "catdel;"
+				     "Delete categories from selected vector features "
+				     "for defined layer;"
+				     "copy;"
+				     "Copy selected features;"
+				     "snap;"
+				     "Snap vector features in given threshold;"
+				     "flip;"
+				     "Flip direction of selected vector lines;"
+				     "connect;"
+				     "Connect two lines;"
+				     "zbulk;"
+				     "Z bulk-labeling (automated assignment of z coordinate to "
+				     "vector lines);"
+				     "chtype;"
+				     "Change feature type (point<->centroid, line<->boundary)");
+    params -> tool->options     = "create,add,delete,copy,move,flip,catadd,catdel,"
+      "merge,break,snap,connect,chtype,"
+      "vertexadd,vertexdel,vertexmove,zbulk,select";
+
+    params -> in = G_define_standard_option (G_OPT_F_INPUT);
+    params -> in -> required    = NO;
+    params -> in -> label       = _("ASCII file to be converted to binary vector map");
+    params -> in -> description = _("If not given (or \"-\") reads from standard input");
+    params -> in -> guisection  = _("Input");
+
+    params -> move = G_define_option();
+    params -> move->key         = "move";
+    params -> move->key_desc    = "x,y";
+    params -> move->type        = TYPE_DOUBLE;
+    params -> move->required    = NO;
+    params -> move->multiple    = NO;
+    params -> move->description = _("Difference in x,y direction for moving feature or vertex");
+    
+    params -> maxdist = G_define_option();
+    params -> maxdist->key         = "thresh";
+    params -> maxdist->type        = TYPE_DOUBLE;
+    params -> maxdist->required    = NO;
+    params -> maxdist->multiple    = NO;
+    params -> maxdist->label       = _("Threshold distance");
+    params -> maxdist->description = _("'-1' for threshold based on the current resolution settings");
+    params -> maxdist->answer      = "-1";
+
+    params -> id = G_define_standard_option(G_OPT_V_CATS);
+    params -> id->required    = NO;
+    params -> id->key         = "ids";
+    params -> id->label       = _("ID values");
+    params -> id->guisection  = _("Query");
+
+
+    params -> cat = G_define_standard_option(G_OPT_V_CATS);
+    params -> cat->required    = NO;
+    params -> cat->guisection  = _("Query");
+
+    params -> coord = G_define_option();
+    params -> coord->key         = "coords";
+    params -> coord->key_desc    = "x,y";
+    params -> coord->type        = TYPE_DOUBLE;
+    params -> coord->required    = NO;
+    params -> coord->multiple    = YES;
+    params -> coord->description = _("List of point coordinates");
+    params -> coord->guisection  = _("Query");
+
+    params -> bbox =  G_define_option();
+    params -> bbox->key         = "bbox";
+    params -> bbox->key_desc    = "x1,y1,x2,y2";
+    params -> bbox->type        = TYPE_DOUBLE;
+    params -> bbox->required    = NO;
+    params -> bbox->multiple    = NO;
+    params -> bbox->description = _("Bounding box for selecting features");
+    params -> bbox->guisection  = _("Query");
+
+    params -> poly =  G_define_option();
+    params -> poly->key         = "polygon";
+    params -> poly->key_desc    = "x,y";
+    params -> poly->type        = TYPE_DOUBLE;
+    params -> poly->required    = NO;
+    params -> poly->multiple    = YES;
+    params -> poly->description = _("Polygon for selecting features");
+    params -> poly->guisection  = _("Query");
+
+    params -> where = G_define_standard_option(G_OPT_WHERE);
+    params -> where->guisection  = _("Query");
+
+    params -> query = G_define_option();
+    params -> query -> key          = "query";
+    params -> query ->type          = TYPE_STRING;
+    params -> query -> options      = "length,dangle";
+    params -> query -> label        = _("Query tool");
+    params -> query -> description  = _("For 'shorter' use negative threshold value, "
+					"positive value for 'longer'");
+    params -> query -> descriptions = _("length;Select only lines or boudaries shorter"
+					"/longer than threshold distance;"
+					"dangle;Select dangles shorter/longer than "
+					"threshold distance");
+    params -> query->guisection  = _("Query");
+
+    params -> bmaps = G_define_standard_option(G_OPT_V_MAPS);
+    params -> bmaps -> key = "bgmap";
+    params -> bmaps -> required = NO;
+    params -> bmaps -> description = _("Name of background vector map(s)");
+
+    params -> snap = G_define_option();
+    params -> snap -> key          = "snap";
+    params -> snap ->type          = TYPE_STRING;
+    params -> snap -> options      = "no,node,vertex";
+    params -> snap -> description  = _("Snap added or modified features in the given threshold to the nearest existing feature");
+    params -> snap -> descriptions = _("no;Not apply snapping;"
+				       "node;Snap only to node;"
+				       "vertex;Allow snapping also to vertex");
+    params -> snap -> answer       = "no";
+
+    params -> zbulk = G_define_option();
+    params -> zbulk -> key          = "zbulk";
+    params -> zbulk ->type          = TYPE_DOUBLE;
+    params -> zbulk -> key_desc     = "value,step";
+    params -> zbulk -> label        = _("Starting value and step for z bulk-labeling");
+    params -> zbulk -> description  = _("Pair: value,step (e.g. 1100,10)");
+
+    /* flags */
+    params -> reverse = G_define_flag();
+    params -> reverse -> key = 'r';
+    params -> reverse -> description = _("Reverse selection");
+
+    /*
+    params -> print = G_define_flag();
+    params -> print -> key = 'i';
+    params -> print -> description = _("Print ID's of edited features");
+    */
+
+    params -> close = G_define_flag();
+    params -> close -> key = 'c';
+    params -> close -> description = _("Close added boundaries (using threshold distance)");
+
+    params -> header = G_define_flag();
+    params -> header -> key          = 'n';
+    params -> header -> description  = _("Do not expect header of input data");
+    params -> header -> guisection  = _("Input");
+
+    params -> topo = G_define_flag();
+    params -> topo -> key = 't';
+    params -> topo -> description = _("Do not build topology");
+
+    params -> move_first = G_define_flag();
+    params -> move_first -> key = '1';
+    params -> move_first -> description = _("Modify only first found feature in bounding box");
+
+    /*
+    params -> boundary = G_define_flag();
+    params -> boundary -> key = 'b';
+    params -> boundary -> description = _("Assign cats to boundaries too");
+
+    params -> print_cat = G_define_flag();
+    params -> print_cat -> key = 'c';
+    params -> print_cat -> description = _("Print category numbers instead of ID's");
+    */
+
+    if(G_parser(argc, argv))
+	exit (EXIT_FAILURE);
+
+    /* check for polygon param */
+    if (params -> poly -> answers != NULL) {
+        int i = 0;
+        while (params -> poly -> answers[i++])
+            ;
+
+	if (i < 6)
+            G_fatal_error (_("Polygon must have at least 3 coordinate pairs"));
+    }
+    
+    /*
+      check that the given arguments makes sense together
+    */
+    if(G_strcasecmp (params -> tool -> answer, "create") == 0) { 
+	*action_mode = MODE_CREATE;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "add") == 0) { 
+	*action_mode = MODE_ADD;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "delete")==0) {
+	*action_mode = MODE_DEL;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "move") == 0) {
+	*action_mode = MODE_MOVE;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "merge") == 0) { 
+	*action_mode = MODE_MERGE;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "break") == 0) { 
+	*action_mode = MODE_BREAK;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "connect") == 0) { 
+	*action_mode = MODE_CONNECT;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "vertexadd") == 0) { 
+        *action_mode = MODE_VERTEX_ADD;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "vertexdel") ==0 ) { 
+	*action_mode = MODE_VERTEX_DELETE;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "vertexmove") == 0) { 
+	*action_mode = MODE_VERTEX_MOVE;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "select") == 0) { 
+	*action_mode = MODE_SELECT;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "catadd") == 0) { 
+	*action_mode = MODE_CATADD;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "catdel") == 0) {
+	*action_mode = MODE_CATDEL;
+    }
+    else if(G_strcasecmp(params -> tool -> answer, "copy") == 0) { 
+	*action_mode = MODE_COPY;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "snap") == 0) {
+	*action_mode = MODE_SNAP;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "flip") == 0) {
+	*action_mode = MODE_FLIP;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "zbulk") == 0) {
+	*action_mode = MODE_ZBULK;
+    }
+    else if(G_strcasecmp (params -> tool -> answer, "chtype") == 0) {
+      	*action_mode = MODE_CHTYPE;
+    }
+    else
+    {
+	G_fatal_error (_("Operation '%s' not implemented"),
+		       params -> tool -> answer);
+    }
+
+    if((*action_mode != MODE_CREATE && *action_mode != MODE_ADD && *action_mode != MODE_ZBULK) &&
+       (params -> cat   -> answers  == NULL) && 
+       (params -> coord -> answers  == NULL) &&
+       (params -> poly  -> answers  == NULL) &&
+       (params -> id    -> answers  == NULL) &&
+       (params -> bbox  -> answers  == NULL) &&
+       (params -> where -> answer   == NULL) &&
+       (params -> query -> answer   == NULL)) {
+	G_fatal_error (_("At least one option from %s must be specified"),
+		       "cats, ids, coords, bbox, polygon, where, query");
+    }
+    
+    if (*action_mode == MODE_MOVE ||
+	*action_mode == MODE_VERTEX_MOVE)
+    {
+	if(params -> move -> answers == NULL) { 
+            G_fatal_error (_("Tool %s requires option %s"),
+			   params -> tool -> answer,
+			   params -> move -> key);
+        }
+    }
+    
+    if (*action_mode == MODE_VERTEX_ADD ||
+	*action_mode == MODE_VERTEX_DELETE ||
+	*action_mode == MODE_VERTEX_MOVE)
+    {
+	if(params -> coord -> answers == NULL) {
+	    G_fatal_error (_("Tool %s requires option %s"),
+			   params -> tool -> answer,
+			   params -> coord -> key);
+	}
+    }
+
+    if (*action_mode == MODE_CATADD ||
+	*action_mode == MODE_CATDEL)
+    {
+        if (params -> cat -> answers == NULL)
+	  {
+	      G_fatal_error (_("Tool %s requires option %s"),
+			     params -> tool -> answer,
+			     params -> cat -> key);
+	  }
+    }
+
+    if (*action_mode == MODE_ZBULK) {
+	if (params -> bbox -> answers == NULL) {
+	    G_fatal_error (_("Tool %s requires option %s"),
+			   params -> tool -> answer,
+			   params -> bbox -> key);
+	}
+	if (params -> zbulk -> answers == NULL) {
+	    G_fatal_error (_("Tool %s requires option %s"),
+			   params -> tool -> answer,
+			   params -> zbulk -> key);
+	}
+    }
+
+    return 1;
+}

Copied: grass/branches/releasebranch_6_3/vector/v.edit/description.html (from rev 30279, grass/branches/releasebranch_6_3/vector/v.edit/cmd/description.html)
===================================================================
--- grass/branches/releasebranch_6_3/vector/v.edit/description.html	                        (rev 0)
+++ grass/branches/releasebranch_6_3/vector/v.edit/description.html	2008-02-27 15:10:07 UTC (rev 30374)
@@ -0,0 +1,430 @@
+<h2>DESCRIPTION</h2>
+
+The module <em>v.edit</em> allows the user to edit a vector map
+via command line interface. 
+
+<p>
+<em>v.edit</em> supports only "simple" vector features: points,
+centroids, lines and boundaries. Currently, only 2D vector features
+(except of tool <b>zbulk</b>) are supported.
+
+<p>
+Provides editing features' geometry. Attribute data connected to the
+vector map are not modified at all.
+
+<p>
+Vector features can be selected either by internal <b>id</b>,
+category number <b>cats</b>, coordinates <b>coords</b>, bounding
+box <b>bbox</b>, <b>polygon</b>, <b>where</b> statement (attribute
+data) or by <b>query</b>. Selecting features by
+coordinates is affected by the current 2D resolution. It can be
+changed using threshold distance <b>thresh</b>. The options
+are <em>orthogonal</em>, i.e. can be used in various combinations. For
+example:
+
+<div class="code"><pre>
+v.edit map=roads tool=select \
+  coord=599505,4921010,603389.0625,4918292.1875 \
+  thresh=10000 where="label='interstate'"
+</pre></div>
+
+selects all features (and prints their id's to standard output)
+covered by two bounding boxes (center at 599505,4921010 and
+603389.0625,4918292.1875, size 2*10000) with attribute
+label='interstate'.
+
+<h2>NOTES</h2>
+
+If no vector features are selected or the flag <b>-t</b> is
+used, topology is not build at the end.
+
+<h2>USAGE</h2>
+
+<h3>Feature selection</h3>
+
+Vector features can be selected in several ways:
+<ul>
+    <li><b>ids</b> - using internal (unique) feature id's</li>
+    <li><b>cats</b> - using category numbers</li>
+    <li><b>coords</b> - using x,y coordinate pairs (center of bounding
+    box, size defined by <b>thresh</b>)</li>
+    <li><b>bbox</b> - using bounding box</li>
+    <li><b>polygon</b> - using polygon (at least 3 coordinate pairs have to be set)</li>
+    <li><b>where</b> - using where statement (attribute data)
+    <li><b>query</b> - special query (e.g. minimal vector line length)
+</ul>
+
+Additional parameters for vector feature specification are:
+<ul>
+    <li><b>layer</b> - layer number (currently used only
+    with <b>cats</b> or <b>where</b> option)</li>
+    <li><b>thresh</b> - threshold distance used for selecting vector
+    features by coordinates</li>
+</ul>
+
+<h3>Tool description</h3>
+
+<ul>
+    <li><b>create</b> - Create new (empty) vector map
+    (see <em><a href="v.in.ascii.html">v.in.ascii</a></em>). Optionally vector
+    features (in GRASS ASCII standard format) can be read from
+    standard input (<b>input=-</b>) or from the text file given by
+    the <b>input</b> option.</li>
+
+    <li><b>add</b> - Add new vector features (defined in GRASS ASCII
+    standard format) to existing vector map. Features can be read from
+    standard input or from the given text file (<b>input</b>
+    option). If no header is given, the <b>-n</b> flag must be
+    used. Added features can be snapped (based on <b>snap</b>
+    parameter) using threshold distance <b>thresh</b>.</li>
+
+    <li><b>delete</b> - Delete selected vector features from existing
+    vector map.</li>
+   
+    <li><b>copy</b> - Make identical copy of selected vector
+    features. If background map <b>bgmap</b> is given copy features
+    from background map, not from currently modified vector map.</li>
+
+    <li><b>move</b> - Move selected features of existing vector map
+    relatively to their current location. This tool requires
+    <b>move</b> option. The option defines coordinates of the movement
+    direction. Moved features can be snapped (based on <b>snap</b>
+    parameter) using threshold distance <b>thresh</b>.</li>
+
+    <li><b>flip</b> - Flip direction of selected vector lines
+    (lines or boundaries).</li>
+
+    <li><b>catadd</b> - Add new layer category(ies) to selected vector
+    feature(s). Category can be later used for new database
+    entry.</li>
+
+    <li><b>catdel</b> - Delete layer category(ies) of selected vector
+    feature(s).</li>
+
+    <li><b>merge</b> - Merge (at least two) selected vector lines or
+    boundaries. The geometry of the merged vector lines can be
+    changed. If the second line from two selected lines is in opposite
+    direction to the first, it will be flipped. See also
+    module <em><a href="v.build.polylines.html">v.build.polylines</a></em>.</li>
+
+    <li><b>break</b> - Split given vector line or boundary into two
+    lines on location given by <b>coords</b>. If <b>coords</b> not
+    given, breaks all selected lines at each intersection (based
+    on <em><a href="v.clean.html">v.clean</a></em>, tool=break).</li>
+    
+    <li><b>snap</b> - Snap vector features in given threshold. See
+    also module <em><a href="v.clean.html">v.clean</a></em>. Note that this
+    tool supports only snapping to nodes. Parameters <b>snap</b> and
+    <b>bgmap</b> are ignored.</li>
+
+    <li><b>connect</b> - Connect selected lines or boundaries, the
+    first given line is connected to the second one. The second line
+    is broken if necessary. The lines are connected regarding
+    threshold distance <b>thresh</b>.</li>
+
+    <li><b>chtype</b> - Change feature type of selected geometry
+    objects. Points are converted to centroids, centroids to points,
+    lines to boundaries and boundaries to lines.
+
+    <li><b>vertexadd</b> - Add vertex(ces) to the given vector lines
+    or boundaries. Location of the new vertex is given by <b>coord</b>
+    option. If <b>-1</b> is given only first found line or boundary in bounding
+    box is modified.</li>
+
+    <li><b>vertexdel</b> - Remove vertex(ces) specified by
+    <b>coords</b> option. If <b>-1</b> is given only first found line or
+    boundary in bounding box is modified.</li>
+
+    <li><b>vertexmove</b> - Move vertex(ces) specified
+    by <b>coords</b> option. Direction of the movement is specified by
+    the <b>move</b> option. If <b>-1</b> is given only first found line or
+    boundary in bounding box is modified. Moved vertex can be snapped
+    (based on <b>snap</b> parameter) using threshold
+    distance <b>thresh</b>.</li>
+    
+    <li><b>zbulk</b> - Assign z coordinate to 3D vector lines in given
+    bounding box. The first found line will get z coordinate based on
+    value given by <b>zbulk</b> parameter. Z coordinate of other
+    selected lines will be increased by step given by <b>zbulk</b>
+    parameter. This tool strictly requires <b>bbox</b>
+    and <b>zbulk</b> parameter. Also input vector map must be 3D.</li>
+
+    <li><b>select</b> - Print comma separated list of selected line
+      id's. No editing is done.
+</ul>
+
+<h2>EXAMPLES</h2>
+
+<h3>Create new vector map</h3>
+
+Create new (empty) vector map:
+
+<div class="code"><pre>
+v.edit tool=create map=vectmap
+</pre></div>
+
+Create new vector map and read data from file 'roads.txt':
+
+<div class="code"><pre>
+v.out.ascii in=roads format=standard > roads.txt;
+v.edit tool=create map=vectmap input=roads.txt
+</pre></div>
+
+or alternatively
+
+<div class="code"><pre>
+cat roads.txt | v.edit tool=create map=vectmap input=-
+</pre></div>
+
+<h3>Add new features to existing vector map</h3>
+
+Add point to the vector map (without header):
+
+<div class="code"><pre>
+echo "P 1 1
+ 640794 214874
+ 1 1" | v.edit -n tool=add map=vectmap
+</pre></div>
+
+Add new features read from standard input:
+
+<div class="code"><pre>
+v.out.ascii in=railroads format=standard | v.edit tool=add map=vectmap
+</pre></div>
+
+<h3>Delete selected features from vector map layer</h3>
+
+Remove all vector features with category number 1 or 2:
+
+<div class="code"><pre>
+v.edit tool=delete map=roads cats=1,2
+</pre></div>
+
+Remove all vector features except of those with category number 1 or 2
+(reverse selection):
+
+<div class="code"><pre>
+v.edit -r tool=delete map=roads cats=1,2
+</pre></div>
+
+Remove features with category 1 or 2 located on coordinates
+600952.625,4926107 (bounding box based on the current 2D resolution):
+
+<div class="code"><pre>
+g.region -d;
+v.edit tool=delete map=roads cats=1,2 coords=600952.625,4926107
+</pre></div>
+
+Remove all features with category 1 and 2 covered by two bounding boxes
+(center coordinates 592542.892,4924766.996 and 603389.062,4918292.187, 
+size 2000 map units):
+
+<div class="code"><pre>
+v.edit map=roads tool=delete \
+  coord=592542.892,4924766.996,603389.062,4918292.187 \
+  thresh=1000 cat=1,2
+</pre></div>
+
+<h3>Copy selected features from background map</h3>
+
+Copy all features with category number 1 from background map:
+
+<div class="code"><pre>
+v.edit map=roads tool=copy bgmap=archsites cat=1
+</pre></div>
+
+<h3>Move features</h3>
+
+Move feature (vector point) located on coordinates 602580,4918480 to
+coordinates 603580,4919480:
+
+<div class="code"><pre>
+v.edit tool=move map=archsites coord=602580,4918480 th=1e-2 move=1000,1000
+</pre></div>
+
+Move all features with category 1 1000 map units to the west and 1000
+map units to the south. Moved features snap to nodes in threshold
+distance 10 map units:
+
+<div class="code"><pre>
+v.edit tool=move map=roads cat=1 move=1000,-1000 snap=node thresh=10
+</pre></div>
+
+Move all features defined by bounding box
+601530,4921560,602520,4922310 (W,S,E,N) 1000 map units to the
+east and 1000 map units to the north:
+
+<div class="code"><pre>
+v.edit tool=move map=roads bbox=601530,4921560,602520,4922310 move=-1000,1000
+</pre></div>
+
+<h3>Flip direction of vector lines</h3>
+
+Flip direction of all vector lines:
+
+<div class="code"><pre>
+v.edit tool=flip map=streams cats=1-9999 type=line
+</pre></div>
+
+<h3>Add / delete layer category number</h3>
+
+Add new layer/category 2/1, 2/3, 2/4, 2/5 to features covered by given polygon:
+
+<div class="code"><pre>
+v.edit tool=catadd map=roads \
+  polygon=599877.75,4925088.375,597164.812,4922524.5,601338.562,4920914.625 \
+  layer=2 cat=1,3-5
+</pre></div>
+
+Delete layer/category 1/1, line id 1:
+
+<div class="code"><pre>
+v.edit tool=catdel map=roads id=1 cats=5
+</pre></div>
+
+<h3>Merge lines</h3>
+
+Merge two lines with given category number:
+
+<div class="code"><pre>
+v.edit map=roads tool=merge cat=4
+</pre></div>
+
+<h3>Split line on given point</h3>
+
+Split line id 810 on coordinates 604268,4923570 in threshold 50 map units:
+
+<div class="code"><pre>
+v.edit map=roads tool=break coords=604268,4923570 id=810 thresh=50
+</pre></div>
+
+<h3>Break selected lines at each intersection</h3>
+
+Break selected lines (with category number 1) at each intersection:
+
+<div class="code"><pre>
+v.edit map=roads tool=break cat=1
+</pre></div>
+
+<h3>Snap lines</h3>
+
+Snap all lines using threshold distance 20 map units:
+
+<div class="code"><pre>
+v.edit map=roads id=1-9999 tool=snap thresh=20 type=line
+</pre></div>
+
+<h3>Connect lines</h3>
+
+Connect line id 48 to line id 565:
+
+<div class="code"><pre>
+v.edit map=roads tool=connect id=48,565
+</pre></div>
+
+Connect line id 48 to line id 565; line id 60 to line id
+50. Maximum threshold distance is 700 map units:
+
+<div class="code"><pre>
+v.edit map=roads tool=connect id=48,565,60,50 thresh=1000
+</pre></div>
+
+<h3>Add vertex</h3>
+
+Add new vertex to the line located at 600952,4926107, threshold is
+set to 1 map unit:
+
+<div class="code"><pre>
+v.edit tool=vertexadd map=roads coords=600952,4926107 thresh=1
+</pre></div>
+
+<h3>Delete vertices</h3>
+
+Delete vertex located at 593191.608,4925684.849 (threshold set to 0.1 map units).
+Modify only lines with category 1:
+
+<div class="code"><pre>
+v.edit tool=vertexdel map=roads coord=593191.608,4925684.849 \
+  thresh=1-e1 cats=1
+</pre></div>
+
+<h3>Move vertices</h3>
+
+Move vertices located at 604441,4921088 (threshold set to 100 map units).
+Modify only lines with categories 1-10:
+
+<div class="code"><pre>
+v.edit tool=vertexmove map=roads cats=1-10 coord=604441,4921088 \
+  thresh=100 move=1000,1000
+</pre></div>
+
+<h3>Select features and print their id's</h3>
+
+Print id's of selected features, e.g.:
+
+<div class="code"><pre>
+v.edit map=soils at PERMANENT tool=select \
+  bbox=595733.8125,4919781.75,598536.1875,4917396.75 --q
+</pre></div>
+
+Example with <em><a href="d.vect.html">d.vect</a></em>:
+
+<div class="code"><pre>
+d.erase;
+d.vect roads;
+d.vect -i map=roads cats=`v.edit map=roads tool=select \
+  coord=592542.89243878,4924766.99622811,603389.0625,4918292.1875 \
+  thresh=1000 --q` col=red
+</pre></div>
+
+Select all lines shorter (or equal) than 10 map units:
+
+<div class="code"><pre>
+v.edit map=roads tool=select query=length thresh=-10
+</pre></div>
+
+Select from given bounding box all lines longer then 200 map units:
+
+<div class="code"><pre>
+v.edit map=roads tool=select bbox=598260,4919730,605100,4926240 query=length thresh=1000
+</pre></div>
+
+<h3>Fix height of contours</h3>
+
+Intput vector map contains 2D lines representing contours. Height can
+be assign to the contours using tool <b>zbulk</b>. First of all 2D
+lines need to be converted to 3D lines:
+
+<div class="code"><pre>
+v.extrude input=line2 output=line3 height=0 type=line
+</pre></div>
+
+All lines which intersect with the line given by coordinates will be
+modified. First found line will get height 1000 map units, height of
+other selected lines will be increased by 10 map units.
+
+<div class="code"><pre>
+v.edit a2 tool=zbulk bbox=586121.25049368,4911970.21547109,603092.60466035,4927071.25713776 \
+   zbulk=1000,10
+</pre></div>
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a HREF="v.in.ascii.html">v.in.ascii</a>,
+<a HREF="v.info.html">v.info</a>,
+<a HREF="v.build.html">v.build</a>,
+<a HREF="v.clean.html">v.clean</a>,
+<a HREF="v.digit.html">v.digit</a>,
+<a HREF="v.extrude.html">v.extrude</a>
+</em>
+
+<h2>AUTHOR</h2>
+
+Original author: Wolf Bergenheim - independent developer<br>
+Various updates: Jachym Cepicky, Mendel University of Agriculture and Forestry in Brno, Czech Republic<br>
+Martin Landa, FBK-irst (formerly ITC-irst), Trento, Italy
+
+<p>
+<i>Last changed: $Date$</i>

Copied: grass/branches/releasebranch_6_3/vector/v.edit/global.h (from rev 30279, grass/branches/releasebranch_6_3/vector/v.edit/cmd/global.h)
===================================================================
--- grass/branches/releasebranch_6_3/vector/v.edit/global.h	                        (rev 0)
+++ grass/branches/releasebranch_6_3/vector/v.edit/global.h	2008-02-27 15:10:07 UTC (rev 30374)
@@ -0,0 +1,51 @@
+#ifndef _V_EDIT_GLOBAL
+# define _V_EDIT_GLOBAL
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <grass/gis.h>
+# include <grass/Vect.h>
+# include <grass/glocale.h>
+# include <grass/vedit.h>
+
+# define SEP "----------------------------------"
+
+enum mode {
+    /* geometry of features is not changed */
+    MODE_CREATE,         /* create new vector map */
+    MODE_ADD,            /* add new vector features */
+    MODE_DEL,            /* delete new vector features */
+    MODE_COPY,           /* copy vector features */
+    MODE_MOVE,           /* move vector features */
+    MODE_FLIP,           /* flip direction of vector lines */
+    MODE_CATADD,         /* add layer category */
+    MODE_CATDEL,         /* delete layer category */
+    /* geometry of features changed */
+    MODE_MERGE,          /* merge vector lines */
+    MODE_BREAK,          /* break (split) vector lines */
+    MODE_CONNECT,        /* connect *two* lines */
+    MODE_SNAP,           /* snap vector lines */
+    /* geometry of feature changed */
+    MODE_VERTEX_ADD,     /* add vertex */
+    MODE_VERTEX_DELETE, /* delete vertex(ces) */
+    MODE_VERTEX_MOVE,    /* move vertex(ces) */
+    /* only print selected features */
+    MODE_SELECT,
+    /* */
+    MODE_NONE,
+    /* z bulk-labeling */
+    MODE_ZBULK,
+    /* change feature type (point<->centroid, line<->boundary) */
+    MODE_CHTYPE,
+};
+
+struct GParams { 
+    struct Option *map, *in, *maxdist, *tool,
+	*coord, *cat, *move, *bbox, *fld,
+      *poly, *type, *id, *where, *bmaps, *snap, *query, *zbulk;
+    struct Flag *header, *topo, *close, *reverse, *move_first;
+};
+
+# include "proto.h"
+
+#endif

Copied: grass/branches/releasebranch_6_3/vector/v.edit/main.c (from rev 30279, grass/branches/releasebranch_6_3/vector/v.edit/cmd/main.c)
===================================================================
--- grass/branches/releasebranch_6_3/vector/v.edit/main.c	                        (rev 0)
+++ grass/branches/releasebranch_6_3/vector/v.edit/main.c	2008-02-27 15:10:07 UTC (rev 30374)
@@ -0,0 +1,436 @@
+/****************************************************************
+ *
+ * MODULE:     v.edit
+ *
+ * PURPOSE:    Editing vector map.
+ *
+ * AUTHOR(S):  GRASS Development Team
+ *             Wolf Bergenheim, Jachym Cepicky, Martin Landa
+ *
+ * COPYRIGHT:  (C) 2006-2008 by the GRASS Development Team
+ *
+ *             This program is free software under the
+ *             GNU General Public License (>=v2).
+ *             Read the file COPYING that comes with GRASS
+ *             for details.
+ *
+ * TODO:       3D support
+ ****************************************************************/
+
+#include "global.h"
+
+int main (int argc, char *argv[])
+{
+    struct GModule *module;
+    struct GParams params;
+    struct Map_info Map;
+    struct Map_info **BgMap; /* backgroud vector maps */
+    int nbgmaps;             /* number of registrated background maps */
+    char *mapset;
+    enum mode action_mode;
+    FILE *ascii;
+
+    int i;
+    int move_first, snap;
+    int ret, print, layer;
+    double move_x, move_y, thresh;
+    
+    struct line_pnts *coord;
+
+    struct ilist *List;
+
+    struct cat_list *Clist;
+
+    ascii  = NULL;
+    List   = NULL;
+    BgMap  = NULL;
+    nbgmaps = 0;
+    coord  = NULL;
+    Clist  = NULL;
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    module->keywords = _("vector, editing, geometry");
+    module->description = _("Edits a vector map, allows adding, deleting "
+			    "and modifying selected vector features.");
+
+    if(!parser(argc, argv, &params, &action_mode))
+	exit(EXIT_FAILURE);
+
+    /* get list of categories */
+    Clist = Vect_new_cat_list();
+    if (params.cat->answer && Vect_str_to_cat_list(params.cat->answer, Clist)) {
+	G_fatal_error (_("Unable to get category list <%s>"),
+		       params.cat->answer);
+    }
+
+    /* open input file */
+    if (G_strcasecmp (params.in -> answer, "-") == 0 ||
+	(action_mode != MODE_CREATE && params.in -> answer == NULL)) {
+	ascii = stdin;
+    }
+    else if (params.in -> answer) {
+	ascii = fopen (params.in -> answer, "r");
+	if (ascii == NULL) {
+	    G_fatal_error(_("Unable to open ASCII file <%s>"),
+			  params.in -> answer);
+	}
+    }
+
+    if (action_mode == MODE_CREATE) {
+	/* 3D vector maps? */
+	ret = Vect_open_new (&Map, params.map -> answer, WITHOUT_Z);
+	if (ret == -1) {
+	    G_fatal_error (_("Unable to create vector map <%s>"),
+			   params.map -> answer);
+	}
+
+	G_debug(1, "Map created");
+	
+	if (ascii) {
+	    /* also add new vector features */
+	    action_mode = MODE_ADD;
+	}
+    }
+    else { /* open selected vector file */
+	mapset = G_find_vector2 (params.map -> answer, G_mapset()); 
+	if ( mapset == NULL ) {
+	    G_fatal_error (_("Vector map <%s> not found in the current mapset"),
+			   params.map -> answer);
+	}
+	else if (action_mode == MODE_ADD) { /* write */
+	    ret = Vect_open_update (&Map, params.map -> answer, mapset); 
+	}
+	else { /* read-only -- select features */
+	    ret = Vect_open_old (&Map, params.map -> answer, mapset);
+	}
+	
+	if (ret < 2)
+	    G_fatal_error (_("Unable to open vector map <%s> at topological level %d"),
+			   params.map -> answer, 2);
+    }
+    
+    G_debug (1, "Map opened");
+
+    /* open backgroud maps */
+    if (params.bmaps->answer) {
+	i = 0;
+	char *bmap;
+	while (params.bmaps->answers[i]) {
+	    bmap = params.bmaps->answers[i];
+	    mapset = G_find_vector2 (bmap, ""); 
+	    if (mapset == NULL) {
+		G_fatal_error (_("Vector map <%s> not found"),
+			       bmap);
+	    }
+
+	    if (strcmp(G_fully_qualified_name((const char*) params.map -> answer, (const char*) G_mapset()),
+		       G_fully_qualified_name((const char*) bmap, (const char*) mapset)) == 0) {
+		G_fatal_error (_("Unable to open vector map <%s> as the backround map. "
+				 "It is given as vector map to be edited."),
+			       bmap);
+	    }
+	    nbgmaps++;
+	    BgMap = (struct Map_info**) G_realloc ((void *) BgMap, nbgmaps * sizeof(struct Map_info*));
+	    BgMap[nbgmaps-1] = (struct Map_info *) G_malloc (sizeof(struct Map_info));
+	    if (Vect_open_old(BgMap[nbgmaps-1], bmap, mapset) == -1) {
+		G_fatal_error (_("Unable to open vector map <%s>"),
+			       G_fully_qualified_name(bmap, mapset));
+	    }
+	    G_verbose_message(_("Background vector map <%s> registered"),
+			      G_fully_qualified_name(bmap, mapset));
+	    i++;
+	}
+    }
+
+    layer = atoi (params.fld -> answer);
+    if (params.query->answer) { /* allow negative threshold value (shorter / longer) */
+	thresh = atof (params.maxdist -> answer);
+    }
+    else {
+	thresh = max_distance(atof (params.maxdist -> answer));
+    }
+    move_first = params.move_first->answer ? 1 : 0;
+    snap = NO_SNAP;
+    if (strcmp(params.snap->answer, "node") == 0)
+	snap = SNAP;
+    else if (strcmp(params.snap->answer, "vertex") == 0)
+	snap = SNAPVERTEX;
+
+    if (action_mode != MODE_CREATE && action_mode != MODE_ADD) {
+	/* select lines */
+	List = Vect_new_list();
+	if (action_mode == MODE_COPY && BgMap && BgMap[0]) {
+	    List = select_lines(BgMap[0], action_mode,
+				&params,
+				List);
+	}
+	else {
+	    List = select_lines(&Map, action_mode,
+				&params,
+				List);
+	}
+    }
+
+    if ((action_mode != MODE_CREATE && action_mode != MODE_ADD &&
+	 action_mode != MODE_SELECT)) {
+	if (List -> n_values < 1) {
+	    G_warning (_("No features selected, nothing to edit"));
+	    action_mode = MODE_NONE;
+	    ret = 0;
+	}
+	else {
+	    /* reopen the map for updating */
+	    if (action_mode == MODE_ZBULK && !Vect_is_3d(&Map)) {
+		Vect_close(&Map);
+		G_fatal_error(_("Vector map <%s> is not 3D. Tool '%s' requires 3D vector map. "
+				"Please convert the vector map "
+				"to 3D using e.g. %s."),
+			      params.map->answer, params.tool->answer, "v.extrude");
+	    }
+	    Vect_close (&Map);
+
+	    Vect_open_update (&Map, params.map -> answer, G_mapset()); 
+	}
+    }
+
+    /* coords option -> array */
+    if (params.coord -> answers) {
+	coord = Vect_new_line_struct();
+	int i = 0;
+	double east, north;
+	while (params.coord -> answers[i]) {
+	    east = atof (params.coord -> answers[i]);
+	    north = atof (params.coord -> answers[i+1]);
+	    Vect_append_point(coord, east, north, 0.0);
+	    i+=2;
+	}
+    }
+
+    /* perform requested editation */
+    switch(action_mode) {
+    case MODE_CREATE:
+	print = 0; /* do not print id's */
+	break;
+    case MODE_ADD:
+	print = 0;
+	if (!params.header -> answer)
+	    read_head(ascii, &Map);
+	struct ilist *List_added;
+	List_added = Vect_new_list();
+	ret = asc_to_bin(ascii, &Map, List_added);
+	G_message(_("%d features added"), ret);
+	if (ret > 0) {
+	    if (snap != NO_SNAP) { /* apply snapping */
+		Vedit_snap_lines(&Map, BgMap, nbgmaps,
+				 List_added,
+				 thresh,
+				 snap == SNAP ? 0 : 1); /* snap to vertex ? */
+	    }
+	    if (params.close -> answer) { /* close boundaries */
+		int nclosed;
+		nclosed = close_lines(&Map, GV_BOUNDARY, thresh);
+		G_message (_("%d lines closed"), nclosed);
+	    }
+	}
+	Vect_destroy_list (List_added);
+	break;
+    case MODE_DEL:
+	ret = Vedit_delete_lines(&Map, List);
+	G_message(_("%d features deleted"), ret);
+	break;
+    case MODE_MOVE:
+	move_x = atof(params.move -> answers[0]);
+	move_y = atof(params.move -> answers[1]);
+	ret = Vedit_move_lines(&Map, BgMap, nbgmaps,
+			       List,
+			       move_x, move_y, 0.0, snap, thresh); /* TODO: 3D */
+	G_message(_("%d features moved"), ret);
+	break;
+    case MODE_VERTEX_MOVE:
+	move_x = atof(params.move -> answers[0]);
+	move_y = atof(params.move -> answers[1]);
+	ret = Vedit_move_vertex(&Map, BgMap, nbgmaps,
+				List,
+				coord, thresh,
+				move_x, move_y, 0.0, /* TODO: 3D */
+				move_first, snap);
+	G_message(_("%d vertices moved"), ret);
+	break;
+    case MODE_VERTEX_ADD:
+	ret = Vedit_add_vertex(&Map, List,
+			       coord, thresh);
+	G_message(_("%d vertices added"), ret);    
+	break;
+    case MODE_VERTEX_DELETE:
+	ret = Vedit_remove_vertex(&Map, List,
+				  coord, thresh);
+	G_message(_("%d vertices removed"), ret);
+	break;
+    case MODE_BREAK:
+	if (params.coord->answer) {
+	    ret = Vedit_split_lines(&Map, List,
+				    coord, thresh, NULL);
+	}
+	else {
+	    ret = Vect_break_lines_list(&Map, List,
+					GV_LINES, NULL, NULL);
+	}
+	G_message(_("%d lines broken"), ret);
+	break;
+    case MODE_CONNECT:
+	ret = Vedit_connect_lines(&Map, List,
+				  thresh);
+	G_message(_("%d lines connected"), ret);
+      	break;
+    case MODE_MERGE:
+	ret = Vedit_merge_lines(&Map, List);
+	G_message (_("%d lines merged"), ret);
+    	break;
+    case MODE_SELECT:
+	print = 1;
+	ret = print_selected(List);
+	break;
+    case MODE_CATADD:
+	ret = Vedit_modify_cats(&Map, List,
+				layer, 0, Clist);
+	G_message(_("%d features modified"), ret);
+    	break;
+    case MODE_CATDEL:
+	ret = Vedit_modify_cats(&Map, List,
+				layer, 1, Clist);
+	G_message(_("%d features modified"), ret);
+	break;
+    case MODE_COPY:
+	if (BgMap && BgMap[0]) {
+	    if (nbgmaps > 1) 
+		G_warning(_("Multiple background maps were given. "
+			    "Selected features will be copied only from "
+			    "vector map <%s>."),
+			  Vect_get_full_name(BgMap[0]));
+	    
+	    ret = Vedit_copy_lines(&Map, BgMap[0], List);
+	}
+	else {
+	    ret = Vedit_copy_lines(&Map, NULL, List);
+	}
+	G_message (_("%d features copied"), ret);
+	break;
+    case MODE_SNAP:
+	ret = snap_lines(&Map, List, thresh);
+	break;
+    case MODE_FLIP:
+	ret = Vedit_flip_lines(&Map, List);
+	G_message(_("%d lines flipped"), ret);
+	break;
+    case MODE_NONE:
+	print = 0;
+	break;
+    case MODE_ZBULK: {
+	double start, step;
+	double x1, y1, x2, y2;
+
+	start = atof(params.zbulk->answers[0]);
+	step  = atof(params.zbulk->answers[1]);
+
+	x1    = atof(params.bbox->answers[0]);
+	y1    = atof(params.bbox->answers[1]);
+	x2    = atof(params.bbox->answers[2]);
+	y2    = atof(params.bbox->answers[3]);
+
+	ret = Vedit_bulk_labeling (&Map, List,
+				   x1, y1, x2, y2,
+				   start, step);
+
+	G_message(_("%d lines labeled"), ret);
+	break;
+    }
+    case MODE_CHTYPE: {
+	int npoints, nlines, ncentroids, nboundaries;
+	ret = Vedit_chtype_lines(&Map, List,
+				 &npoints, &ncentroids,
+				 &nlines, &nboundaries);
+
+	if (ret > 0) {
+	    if (npoints > 0) {
+		G_message(_("%d points converted to centroids"),
+			  npoints);
+	    }
+	    if (ncentroids > 0) {
+		G_message(_("%d centroids converted to points"),
+			  ncentroids);
+	    }
+	    if (nlines > 0) {
+		G_message(_("%d lines converted to boundaries"),
+			  nlines);
+	    }
+	    if (nboundaries > 0) {
+		G_message(_("%d boundaries converted to lines"),
+			  nboundaries);
+	    }
+	}
+	else {
+	    G_message(_("No feature modified"));
+	}
+	break;
+    }
+    default:
+	G_warning(_("Operation not implemented"));
+	ret = -1;
+	break;
+    }
+
+    /*
+    if (print && ret > 0) {
+	for (i = 0; i < Vect_get_num_updated_lines(&Map); i++) {
+	    if (i > 0)
+		fprintf (stdout, ",");
+	    fprintf (stdout, "%d", Vect_get_updated_line(&Map, i));
+	}
+	if (Vect_get_num_updated_lines(&Map) > 0)
+	    fprintf (stdout, "\n");
+	fflush (stdout);
+    }
+    */
+
+    Vect_hist_command(&Map);
+    
+    /* build topology only if requested or if tool!=select */
+    if  (!(action_mode == MODE_SELECT || params.topo -> answer == 1 || !MODE_NONE)) {
+        Vect_build_partial(&Map, GV_BUILD_NONE, NULL);
+	if (G_verbose() > G_verbose_min())
+	    Vect_build (&Map, stderr);
+	else
+	    Vect_build (&Map, NULL);
+    }
+
+    if (List)
+	Vect_destroy_list(List);
+
+    Vect_close(&Map);
+    
+    G_debug(1, "Map closed");
+
+    /* close background maps */
+    for (i = 0; i < nbgmaps; i++) {
+	Vect_close(BgMap[i]);
+	G_free ((void *) BgMap[i]);
+    }
+    G_free ((void *) BgMap);
+
+    if (coord)
+	Vect_destroy_line_struct(coord);
+
+    if (Clist) 
+	Vect_destroy_cat_list(Clist);
+
+    G_done_msg (" ");
+
+    if (ret > -1) {
+	exit (EXIT_SUCCESS);
+    }
+    else {
+	exit (EXIT_FAILURE);
+    }
+}

Copied: grass/branches/releasebranch_6_3/vector/v.edit/max_distance.c (from rev 30279, grass/branches/releasebranch_6_3/vector/v.edit/cmd/max_distance.c)
===================================================================
--- grass/branches/releasebranch_6_3/vector/v.edit/max_distance.c	                        (rev 0)
+++ grass/branches/releasebranch_6_3/vector/v.edit/max_distance.c	2008-02-27 15:10:07 UTC (rev 30374)
@@ -0,0 +1,92 @@
+/****************************************************************
+ *
+ * MODULE:     v.edit
+ *
+ * PURPOSE:    Editing vector map.
+ *
+ * AUTHOR(S):  GRASS Development Team
+ *             Wolf Bergenheim, Jachym Cepicky, Martin Landa
+ *
+ * COPYRIGHT:  (C) 2006-2008 by the GRASS Development Team
+ *
+ *             This program is free software under the
+ *             GNU General Public License (>=v2).
+ *             Read the file COPYING that comes with GRASS
+ *             for details.
+ *
+ * TODO:       3D support
+ ****************************************************************/
+
+#include "global.h"
+
+/**
+   \brief Set distance based on the current resolution
+
+   This code comes from v.what/main.c
+ 
+   \param[in] maxdistance max distance
+
+   \return result max distance
+*/
+double max_distance(double maxdistance)
+{
+    struct Cell_head window;
+
+    double ew_dist1, ew_dist2, ns_dist1, ns_dist2;
+    double xres, yres, maxd;
+
+    if (maxdistance < 0.0) {
+        G_get_window (&window);
+
+        ew_dist1 = G_distance(window.east, window.north, window.west, window.north);
+        /* EW Dist at South Edge */
+        ew_dist2 = G_distance(window.east, window.south, window.west, window.south);
+        /* NS Dist at East edge */
+        ns_dist1 = G_distance(window.east, window.north, window.east, window.south);
+        /* NS Dist at West edge */
+        ns_dist2 = G_distance(window.west, window.north, window.west, window.south);
+
+        xres = ((ew_dist1 + ew_dist2) / 2) / window.cols;
+        yres = ((ns_dist1 + ns_dist2) / 2) / window.rows;
+
+        if (xres > yres)
+	    maxd = xres;
+	else
+	    maxd = yres;
+
+	G_important_message (_("Threshold distance set to %g map units (based on 2D resolution)"), maxd);
+    }
+    else {
+        maxd = maxdistance;
+    }
+
+    G_debug (3, "max_distance(): threshold is %g", maxd);
+
+    return maxd;
+}
+
+/**
+   \brief Creates bounding box (polygon)
+
+   Based on center point; size (2 * maxdist)
+
+   \param[in] east,north coordinates of center
+   \param[in] maxdist size of bounding box
+   \param[out] result bounding box
+
+   \return
+*/
+void coord2bbox (double east, double north, double maxdist,
+		struct line_pnts *box)
+{
+    /* TODO: 3D */
+    Vect_reset_line(box);
+    
+    Vect_append_point(box, east - maxdist, north - maxdist, 0);
+    Vect_append_point(box, east + maxdist, north - maxdist, 0);
+    Vect_append_point(box, east + maxdist, north + maxdist, 0);
+    Vect_append_point(box, east - maxdist, north + maxdist, 0);
+    Vect_append_point(box, box->x[0], box->y[0], box->z[0]);
+	
+    return;
+}

Copied: grass/branches/releasebranch_6_3/vector/v.edit/proto.h (from rev 30279, grass/branches/releasebranch_6_3/vector/v.edit/cmd/proto.h)
===================================================================
--- grass/branches/releasebranch_6_3/vector/v.edit/proto.h	                        (rev 0)
+++ grass/branches/releasebranch_6_3/vector/v.edit/proto.h	2008-02-27 15:10:07 UTC (rev 30374)
@@ -0,0 +1,51 @@
+#ifndef _V_EDIT_PROTO
+# define _V_EDIT_PROTO
+
+/* args.c */
+int parser(int, char* [], struct GParams *, enum mode *);
+
+/* a2b.c */
+int asc_to_bin(FILE *, struct Map_info *, struct ilist *);
+int read_head ( FILE *, struct Map_info *);
+int close_lines(struct Map_info *, int, double);
+
+/* select.c */
+int print_selected(struct ilist *);
+struct ilist* select_lines(struct Map_info *, enum mode,
+			   struct GParams *,
+			   struct ilist *);
+int sel_by_cat(struct Map_info *, struct cat_list*,
+	       int, int, char *,
+	       struct ilist *);
+int sel_by_coordinates(struct Map_info *,
+		       int, struct line_pnts *, double,
+		       struct ilist *);
+int sel_by_bbox(struct Map_info *,
+		int, double, double, double, double,
+		struct ilist *);
+int sel_by_polygon(struct Map_info *,
+		   int, struct line_pnts *,
+		   struct ilist *);
+int sel_by_id(struct Map_info *,
+	      int, char *,
+	      struct ilist *);
+int sel_by_where(struct Map_info *,
+		 int, int, char *,
+		 struct ilist *);
+int reverse_selection(struct Map_info *, int, struct ilist **);
+int sel_by_query(struct Map_info *,
+		 int, int, double, const char *,
+		 struct ilist*);
+
+/* snap.c */
+int snap_lines(struct Map_info *,
+	       struct ilist *, double);
+int snap_line(struct Map_info *,
+	      int, int, double);
+
+/* max_distance.c */
+double max_distance (double);
+void coord2bbox (double, double, double,
+		 struct line_pnts *);
+
+#endif /* _V_EDIT_PROTO */

Copied: grass/branches/releasebranch_6_3/vector/v.edit/select.c (from rev 30279, grass/branches/releasebranch_6_3/vector/v.edit/cmd/select.c)
===================================================================
--- grass/branches/releasebranch_6_3/vector/v.edit/select.c	                        (rev 0)
+++ grass/branches/releasebranch_6_3/vector/v.edit/select.c	2008-02-27 15:10:07 UTC (rev 30374)
@@ -0,0 +1,630 @@
+/****************************************************************
+ *
+ * MODULE:     v.edit
+ *
+ * PURPOSE:    Editing vector map.
+ *
+ * AUTHOR(S):  GRASS Development Team
+ *             Wolf Bergenheim, Jachym Cepicky, Martin Landa
+ *
+ * COPYRIGHT:  (C) 2006-2008 by the GRASS Development Team
+ *
+ *             This program is free software under the
+ *             GNU General Public License (>=v2).
+ *             Read the file COPYING that comes with GRASS
+ *             for details.
+ *
+ * TODO:       3D support
+ ****************************************************************/
+
+#include <grass/dbmi.h>
+#include "global.h"
+
+static char first_selection = 1;
+static int merge_lists (struct ilist*, struct ilist*);
+
+/**
+   \brief Select vector features
+
+   \param[in] Map vector map
+   \param[in] action_mode tool
+   \param[in] params GRASS parameters
+   \param[in] List list of selected features
+   
+   \return list of newly selected features
+*/
+struct ilist *select_lines(struct Map_info *Map, enum mode action_mode,
+			   struct GParams *params,
+			   struct ilist *List)
+{
+    int layer, type;
+    double thresh;
+
+    layer  = atoi (params -> fld -> answer);
+    type   = Vect_option_to_types (params -> type);
+    thresh = atof (params -> maxdist -> answer);
+
+    /* select by id's */
+    if (params -> id -> answer != NULL) {
+	sel_by_id(Map,
+		  type, params -> id -> answer,
+		  List);
+    }
+
+    /* select by category (ignore tools catdel and catadd) */
+    if((action_mode != MODE_CATADD && action_mode != MODE_CATDEL) &&
+       params -> cat -> answer != NULL) {
+	sel_by_cat(Map, NULL,
+		   layer, type, params -> cat -> answer,
+		   List);
+    }
+    
+    /* select by coordinates (+threshold) */
+    if (params -> coord -> answer != NULL) {
+	int i;
+	double east, north;
+	struct line_pnts *coords;
+
+	coords = Vect_new_line_struct();
+	i = 0;
+	while (params->coord->answers[i]) {
+	    east = atof(params->coord->answers[i]);
+	    north = atof(params->coord->answers[i+1]);
+	    Vect_append_point(coords, east, north, 0.0);
+	    i += 2;
+	}
+
+        sel_by_coordinates(Map,
+			   type, coords, thresh,
+			   List);
+
+	Vect_destroy_line_struct(coords);
+    }
+    
+    /* select by bbox */
+    if (params -> bbox -> answer != NULL) {
+	struct line_pnts *bbox;
+	double x1, y1, x2, y2;
+
+	bbox = Vect_new_line_struct();
+
+	x1 = atof(params->bbox->answers[0]);
+	y1 = atof(params->bbox->answers[1]);
+	x2 = atof(params->bbox->answers[2]);
+	y2 = atof(params->bbox->answers[3]);
+
+	Vect_append_point(bbox, x1, y1, -PORT_DOUBLE_MAX);
+	Vect_append_point(bbox, x2, y1, PORT_DOUBLE_MAX);
+	Vect_append_point(bbox, x2, y2, -PORT_DOUBLE_MAX);
+	Vect_append_point(bbox, x1, y2, PORT_DOUBLE_MAX);
+	Vect_append_point(bbox, x1, y1, -PORT_DOUBLE_MAX);
+
+	/* sel_by_bbox not used */
+	/*
+	sel_by_bbox(Map,
+		    type, x1, y1, x2, y2,
+		    List);
+	*/ 
+        sel_by_polygon(Map,
+		       type, bbox,
+		       List);
+
+	Vect_destroy_line_struct(bbox);
+    }
+    
+    /* select by polygon  */
+    if (params -> poly -> answer != NULL) {
+	int i;
+	struct line_pnts *Polygon;
+
+	Polygon = Vect_new_line_struct();
+    
+	for (i = 0; params -> poly -> answers[i]; i+=2){
+	    Vect_append_point(Polygon,
+			      atof(params -> poly -> answers[i]),
+			      atof(params -> poly -> answers[i+1]),
+			      0.0);
+	}
+    
+	/* if first and last point of polygon does not match */
+	if (atof(params -> poly -> answers[i-1]) != atof(params -> poly -> answers[0])) {
+	    Vect_append_point(Polygon,
+			      atof(params -> poly -> answers[0]),
+			      atof(params -> poly -> answers[1]),
+			      0.0);
+	}
+
+        sel_by_polygon(Map,
+		       type, Polygon,
+		       List);
+	
+	Vect_destroy_line_struct(Polygon);
+    }
+    
+    /* select by where statement */
+    if (params -> where -> answer != NULL) {
+        sel_by_where(Map,
+		     layer, type, params -> where -> answer,
+		     List);
+    }
+
+    /* selecy by query */
+    if (params -> query -> answer != NULL) {
+	int query_type;
+	struct ilist *List_tmp;
+	if (first_selection) {
+	    List_tmp = List;
+	    first_selection = 0;
+	}
+	else {
+	    List_tmp = Vect_new_list();
+	}
+
+	query_type = QUERY_UNKNOWN;
+	if (strcmp(params->query->answer, "length") == 0) {
+	    query_type = QUERY_LENGTH;
+	}
+	else if (strcmp(params->query->answer, "dangle") == 0) {
+	    query_type = QUERY_DANGLE;
+	}
+
+	Vedit_select_by_query(Map,
+			      type, layer, thresh, query_type,
+			      List_tmp);
+
+	/* merge lists (only duplicate items) */
+	if (List_tmp != List) {
+	    merge_lists (List, List_tmp);
+	    Vect_destroy_list (List_tmp);
+	}
+    }
+
+    if (params -> reverse -> answer) {
+	reverse_selection(Map, type, &List);
+    }
+
+    G_message (_("%d of %d features selected from vector map <%s>"),
+	       List -> n_values,
+	       Vect_get_num_lines (Map),
+	       Vect_get_full_name(Map));
+
+    return List;
+}
+
+/**
+   \brief Print selected vector features
+ 
+   \param[in] List list of selected features
+
+   \return number of selected features
+   \return -1 on error
+*/
+int print_selected(struct ilist *List)
+{
+    int i;
+
+    /* print the result */
+    for (i = 0; i < List->n_values; i++) {
+	fprintf(stdout, "%d%s",
+		List -> value[i],
+		i < List->n_values -1 ? "," : "");
+    }
+    if (List->n_values > 0) {
+	fprintf(stdout, "\n");
+    }
+    fflush(stdout);
+
+    return List -> n_values;
+}
+
+/**
+   \brief Select features by category
+ 
+   \param[in] Map vector map
+   \param[in] cl_orig original list of categories (previously selected)
+   \param[in] layer layer number
+   \param[in] type feature type
+   \param[in] cat category string
+   \param[in,out] List list of selected features
+
+   \return number of selected lines
+*/
+int sel_by_cat(struct Map_info *Map, struct cat_list *cl_orig,
+	       int layer, int type, char *cats,
+	       struct ilist* List)
+{
+    struct ilist *List_tmp, *List_tmp1;
+    struct cat_list *cl;
+
+    int i, cat;
+
+    if (first_selection || cl_orig) {
+	List_tmp = List;
+	first_selection = 0;
+    }
+    else {
+	List_tmp = Vect_new_list();
+    }
+
+    List_tmp1 = Vect_new_list();
+
+    if (cl_orig == NULL) {
+	cl = Vect_new_cat_list();
+
+	Vect_str_to_cat_list (cats, cl);
+    }
+    else {	
+	cl = cl_orig;
+    }
+
+    for(i = 0; i < cl -> n_ranges; i++) {
+        for(cat = cl->min[i]; cat <= cl->max[i]; cat++) {
+            Vect_cidx_find_all (Map, layer, type, cat, List_tmp1);
+	    Vect_list_append_list (List_tmp, List_tmp1);
+        }
+    }
+
+    G_debug (1, "  %d lines selected (by category)", List_tmp -> n_values);
+
+    /* merge lists (only duplicate items) */
+    if (List_tmp != List) {
+	merge_lists (List, List_tmp);
+	Vect_destroy_list (List_tmp);
+    }
+
+    Vect_destroy_list (List_tmp1);
+
+    return List -> n_values;
+}
+
+/**
+   \brief Select features by coordinates
+ 
+   \param[in] Map vector map
+   \param[in] type feature type
+   \param[in] coords coordinates GRASS parameters
+   \param[in] thresh threshold value for searching
+   \param[in,out] List list of selected features
+
+   \return number of selected lines
+*/
+int sel_by_coordinates(struct Map_info *Map,
+		       int type, struct line_pnts *coords, double thresh,
+		       struct ilist* List)
+{
+    int i;
+    double east, north, maxdist;
+
+    struct ilist* List_tmp, *List_in_box;
+    struct line_pnts *box;
+
+    if (first_selection) {
+	List_tmp = List;
+	first_selection = 0;
+    }
+    else {
+	List_tmp = Vect_new_list();
+    }
+    
+    box = Vect_new_line_struct();
+    List_in_box = Vect_new_list();
+
+    if (thresh < 0)
+	maxdist = max_distance (thresh);
+    else
+	maxdist = thresh;
+
+    for (i = 0; i < coords -> n_points; i++) {
+	east  = coords->x[i];
+        north = coords->y[i];
+
+	coord2bbox (east, north, maxdist, box);
+
+	Vect_select_lines_by_polygon(Map, box, 0, NULL, type, List_in_box);
+	
+	if (List_in_box -> n_values > 0) 
+	    Vect_list_append_list (List_tmp, List_in_box);
+    }
+
+    G_debug (1, "  %d lines selected (by coordinates)", List_tmp -> n_values);
+
+    /* merge lists (only duplicate items) */
+    if (List_tmp != List) {
+	merge_lists (List, List_tmp);
+	Vect_destroy_list (List_tmp);
+    }
+    
+    Vect_destroy_line_struct (box);
+    Vect_destroy_list (List_in_box);
+
+    return List -> n_values;
+}
+
+/**
+   \brief Select features by bbox
+   
+   \param[in] Map vector map
+   \param[in] type feature type
+   \param[in] bbox_opt bounding boxes
+   \param[in,out] List list of selected features
+
+   \return number of selected lines
+*/
+int sel_by_bbox(struct Map_info *Map,
+		int type, double x1, double y1, double x2, double y2,
+		struct ilist* List)
+{
+    BOUND_BOX bbox;
+
+    struct ilist* List_tmp;
+
+    if (first_selection) {
+	List_tmp = List;
+	first_selection = 0;
+    }
+    else {
+	List_tmp = Vect_new_list();
+    }
+    
+    /* bounding box */
+    bbox.N = y1 < y2 ? y2 : y1;
+    bbox.S = y1 < y2 ? y1 : y2;
+    bbox.W = x1 < x2 ? x1 : x2;
+    bbox.E = x1 < x2 ? x2 : x1;
+    bbox.T  = PORT_DOUBLE_MAX;
+    bbox.B  = -PORT_DOUBLE_MAX;
+
+    Vect_select_lines_by_box (Map, &bbox, type, List_tmp);
+
+    G_debug (1, "  %d lines selected (by bbox)", List_tmp -> n_values);
+
+    /* merge lists (only duplicate items) */
+    if (List_tmp != List) {
+	merge_lists (List, List_tmp);
+	Vect_destroy_list (List_tmp);
+    }
+    
+    return List -> n_values;
+}
+
+/**
+   \brief Select features by polygon
+
+   \param[in] Map vector map
+   \param[in] type feature type
+   \param[in] poly polygon coordinates
+   \param[in,out] List list of selected features
+   
+   \return number of selected lines
+*/
+int sel_by_polygon(struct Map_info *Map,
+		   int type, struct line_pnts *Polygon,
+		   struct ilist* List)
+{
+    struct ilist *List_tmp;
+    
+    if (first_selection) {
+	List_tmp = List;
+	first_selection = 0;
+    }
+    else {
+	List_tmp = Vect_new_list();
+    }
+
+    /* no isles */
+    Vect_select_lines_by_polygon (Map, Polygon, 0, NULL, type, List_tmp);
+
+    G_debug (1, "  %d lines selected (by polygon)", List_tmp -> n_values);
+
+    /* merge lists (only duplicate items) */
+    if (List_tmp != List) {
+	merge_lists (List, List_tmp);
+	Vect_destroy_list (List_tmp);
+    }
+
+    return List -> n_values;
+}
+
+/**
+   \brief Select features by id
+
+   \param[in] Map vector map
+   \param[in] type feature type
+   \param[in] ids ids list
+   \param[in,out] List list of selected features
+ 
+   \return number of selected lines
+*/
+int sel_by_id(struct Map_info *Map,
+	      int type, char *ids,
+	      struct ilist* List)
+{
+    int i;
+    int num, id;
+    struct cat_list *il; /* NOTE: this is not cat list, but list of id's */
+    struct ilist *List_tmp;
+
+    if (first_selection) {
+	List_tmp = List;
+	first_selection = 0;
+    }
+    else {
+	List_tmp = Vect_new_list();
+    }
+
+    il = Vect_new_cat_list();
+    Vect_str_to_cat_list (ids, il);
+
+    num = Vect_get_num_lines (Map);
+
+    for(i = 0; i < il -> n_ranges; i++) {
+	for (id = 1; id <= num; id++) {
+	    if (!(Vect_read_line(Map, NULL, NULL, id) & type)) {
+		continue;
+	    }
+	    if (id >= il -> min[i] && id <= il -> max[i]) {
+		Vect_list_append (List_tmp, id);
+	    }
+	}
+    }
+    
+    G_debug (1, "  %d lines selected (by id)", List_tmp -> n_values);
+
+    /* merge lists (only duplicate items) */
+    if (List_tmp != List) {
+	merge_lists (List, List_tmp);
+	Vect_destroy_list (List_tmp);
+    }
+
+    Vect_destroy_cat_list (il);
+
+    return List -> n_values; 
+}
+
+/**
+   \brief Select features according to SQL where statement
+
+   \param[in] Map vector map
+   \param[in] layer layer number
+   \param[in] type feature type
+   \param[in] where 'where' statement
+   \param[in,out] List list of selected features
+ 
+   \return number of selected lines
+*/
+int sel_by_where (struct Map_info *Map,
+		  int layer, int type, char *where,
+		  struct ilist* List)
+{
+    struct cat_list *cat_list;
+    struct ilist *List_tmp;
+    struct field_info* Fi;
+    dbDriver* driver;
+    dbHandle handle;
+
+    int *cats, ncats;
+
+    if (first_selection) {
+	List_tmp = List;
+	first_selection = 0;
+    }
+    else {
+	List_tmp = Vect_new_list();
+    }
+
+    cat_list = Vect_new_cat_list();
+
+    if (layer < 1) {
+	G_fatal_error (_("Layer must be > 0 for 'where'"));
+    }
+
+    Fi = Vect_get_field (Map, layer);
+
+    if (!Fi) {
+      G_fatal_error (_("Database connection not defined for layer %d"),
+		     layer);
+    }
+
+    driver = db_start_driver (Fi -> driver);
+
+    if (!driver)
+	G_fatal_error(_("Unable to start driver <%s>"),
+		      Fi->driver) ;
+    
+    db_init_handle (&handle);
+
+    db_set_handle (&handle, Fi -> database, NULL);
+
+    if (db_open_database(driver, &handle) != DB_OK)
+	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
+		      Fi->database, Fi->driver);
+    
+    ncats = db_select_int (driver, Fi -> table, Fi -> key,
+			   where, &cats);
+
+    db_close_database(driver);
+    db_shutdown_driver(driver);
+
+    Vect_array_to_cat_list (cats, ncats, cat_list);
+    
+    /* free array of cats */
+    if (ncats >= 0)
+	G_free (cats);
+    
+    sel_by_cat (Map, cat_list,
+		layer, type, NULL,
+		List_tmp);
+
+    G_debug (1, "  %d lines selected (by where)", List_tmp -> n_values);
+
+    /* merge lists (only duplicate items) */
+    if (List_tmp != List) {
+	merge_lists (List, List_tmp);
+	Vect_destroy_list (List_tmp);
+    }
+
+    Vect_destroy_cat_list (cat_list);
+
+    return List -> n_values;
+}
+
+/**
+   \brief merge two list, i.e. store only duplicate items
+
+   \param[in] alist,blist list to be merged
+
+   \return result number of items
+*/
+static int merge_lists (struct ilist* alist, struct ilist* blist)
+{
+    int i;
+
+    struct ilist* list_del;
+    
+    list_del = Vect_new_list();
+
+    for (i = 0; i < alist -> n_values; i++) {
+	if (!Vect_val_in_list (blist, alist -> value[i]))
+	    Vect_list_append (list_del, alist -> value[i]);
+    }
+
+    Vect_list_delete_list (alist, list_del);
+
+    Vect_destroy_list (list_del);
+
+    return alist -> n_values;
+} 
+
+/**
+   \brief Reverse list selection
+   
+   \param[in] Map vector map
+   \param[in] type feature type
+   \param[in,out] reversed list
+
+   \return 1
+*/
+int reverse_selection (struct Map_info *Map, int type, struct ilist** List) {
+
+    struct ilist* list_reverse;
+    int line, nlines, ltype;
+
+    list_reverse = Vect_new_list();
+
+    nlines = Vect_get_num_lines(Map);
+
+    for (line = 1; line <= nlines; line++) {
+	ltype = Vect_read_line(Map, NULL, NULL, line);
+
+	if (!(ltype & type))
+	    continue;
+
+	if (!Vect_val_in_list (*List, line))
+	    Vect_list_append (list_reverse, line);
+    }
+
+    Vect_destroy_list (*List);
+    *List = list_reverse;
+
+    return 1;
+}

Copied: grass/branches/releasebranch_6_3/vector/v.edit/snap.c (from rev 30279, grass/branches/releasebranch_6_3/vector/v.edit/cmd/snap.c)
===================================================================
--- grass/branches/releasebranch_6_3/vector/v.edit/snap.c	                        (rev 0)
+++ grass/branches/releasebranch_6_3/vector/v.edit/snap.c	2008-02-27 15:10:07 UTC (rev 30374)
@@ -0,0 +1,132 @@
+/****************************************************************
+ *
+ * MODULE:     v.edit
+ *
+ * PURPOSE:    Editing vector map.
+ *
+ * AUTHOR(S):  GRASS Development Team
+ *             Wolf Bergenheim, Jachym Cepicky, Martin Landa
+ *
+ * COPYRIGHT:  (C) 2006-2008 by the GRASS Development Team
+ *
+ *             This program is free software under the
+ *             GNU General Public License (>=v2).
+ *             Read the file COPYING that comes with GRASS
+ *             for details.
+ *
+ * TODO:       3D support
+ ****************************************************************/
+
+#include "global.h"
+
+/**
+   \brief Global snapping function based on snapping library function.
+
+   \param[in] Map vector map
+   \param[in] List list of lines to be snapped
+   \param[in] thresh threshold distance for snapping
+
+   \return 1
+ */
+int snap_lines(struct Map_info *Map,
+	       struct ilist *List, double thresh) {
+    
+    FILE * output;
+
+    if (G_verbose() > G_verbose_min()) {
+      G_important_message (SEP);
+	output = stderr;
+    }
+    else
+	output = NULL;
+
+    Vect_snap_lines_list (Map, List, thresh, NULL, output);
+
+    if (G_verbose() > G_verbose_min()) {
+      G_important_message (SEP);
+    }
+
+    return 1;
+}
+
+/**
+   \brief Snap two selected lines
+
+   \param[in] Map vector map
+   \param[in] line1 reference line
+   \param[in] line2 line to be snapped (to be modified)
+   \param[in] thresh threshold distance for snapping (-1 for no limit)
+
+   \return id of snapped line
+   \return 0 lines not snapped
+   \return -1 on error
+*/
+int snap_line2(struct Map_info *Map,
+	       int line1, int line2, double thresh)
+{
+    struct line_pnts *Points1, *Points2;
+    struct line_cats *Cats2;
+    int type1, type2;
+    int newline;
+    double mindist;
+    int mindistidx;
+    
+    Points1 = Vect_new_line_struct();
+    Points2 = Vect_new_line_struct();
+    Cats2 = Vect_new_cats_struct();
+
+    type1 = Vect_read_line(Map, Points1, NULL, line1);
+    type2 = Vect_read_line(Map, Points2, Cats2, line2);
+
+    /* find mininal distance and its indexes */
+    mindist = Vedit_get_min_distance(Points1, Points2, 0, /* TODO 3D */
+				     &mindistidx);
+
+    if (thresh > 0.0 && mindist > thresh) {
+	Vect_destroy_line_struct(Points1);
+	Vect_destroy_line_struct(Points2);
+	Vect_destroy_cats_struct(Cats2);
+	return 0;
+    }
+
+    switch(mindistidx) {
+    case 0: 
+	Points2->x[0] = Points1->x[0];
+	Points2->y[0] = Points1->y[0];
+	Points2->z[0] = Points1->z[0];
+	break;
+    case 1: 
+	Points2->x[Points2->n_points-1] = Points1->x[0];
+	Points2->y[Points2->n_points-1] = Points1->y[0];
+	Points2->z[Points2->n_points-1] = Points1->z[0];
+	break;
+    case 2: 
+	Points2->x[0] = Points1->x[Points1->n_points-1];
+	Points2->y[0] = Points1->y[Points1->n_points-1];
+	Points2->z[0] = Points1->z[Points1->n_points-1];
+	break;
+    case 3: 
+	Points2->x[Points2->n_points-1] = Points1->x[Points1->n_points-1];
+	Points2->y[Points2->n_points-1] = Points1->y[Points1->n_points-1];
+	Points2->z[Points2->n_points-1] = Points1->z[Points1->n_points-1];
+	break;
+    default:
+	break;
+    }
+
+    newline = Vect_rewrite_line (Map, line2, type2, Points2, Cats2);
+    if (newline < 0) {
+	G_warning(_("Unable to rewrite line %d"), line2);
+        return -1;
+    }
+
+    /*
+    G_message(_("Line %d snapped to line %d"),
+	      line2, line1);
+    */
+    Vect_destroy_line_struct(Points1);
+    Vect_destroy_line_struct(Points2);
+    Vect_destroy_cats_struct(Cats2);
+    
+    return newline;
+}



More information about the grass-commit mailing list