[GRASS-SVN] r40206 - in grass/trunk: include lib/vector/Vlib vector/v.edit

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Jan 3 08:08:20 EST 2010


Author: martinl
Date: 2010-01-03 08:08:19 -0500 (Sun, 03 Jan 2010)
New Revision: 40206

Modified:
   grass/trunk/include/vector.h
   grass/trunk/lib/vector/Vlib/write.c
   grass/trunk/lib/vector/Vlib/write_nat.c
   grass/trunk/lib/vector/Vlib/write_ogr.c
   grass/trunk/vector/v.edit/main.c
Log:
libvect: implement V1/2_write_line_ogr
	 update v.edit to add new features


Modified: grass/trunk/include/vector.h
===================================================================
--- grass/trunk/include/vector.h	2010-01-03 11:47:59 UTC (rev 40205)
+++ grass/trunk/include/vector.h	2010-01-03 13:08:19 UTC (rev 40206)
@@ -438,7 +438,13 @@
 void Vect__init_head(struct Map_info *);
 void Vect__delete_area_cats_from_cidx(struct Map_info *, int);
 void Vect__add_area_cats_to_cidx(struct Map_info *, int);
-int V2__delete_line(struct Map_info *, int, int (*fn) (struct Map_info *, off_t));
+int V2__delete_line(struct Map_info *, int, int (*delete_fn) (struct Map_info *, off_t));
+void Vect__add_line_to_topo(struct Map_info *, int, const struct line_pnts *,
+			    const struct line_cats *);
+off_t V2__write_line(struct Map_info *, int, const struct line_pnts *,
+		     const struct line_cats *,
+		     off_t (*write_fn) (struct Map_info *, int, const struct line_pnts *,
+					const struct line_cats *));
 
 /* Open/close/rewind map */
 int Vect_coor_info(const struct Map_info *, struct Coor_info *);
@@ -489,10 +495,12 @@
 int V2_restore_line_nat(struct Map_info *, int, off_t);
 off_t V1_write_line_nat(struct Map_info *, int, const struct line_pnts *,
 			const struct line_cats *);
+off_t V1_write_line_ogr(struct Map_info *, int, const struct line_pnts *,
+			const struct line_cats *);
 off_t V2_write_line_nat(struct Map_info *, int, const struct line_pnts *,
 			const struct line_cats *);
-int V1_write_line_ogr(struct Map_info *, int, const struct line_pnts *,
-		      const struct line_cats *);
+off_t V2_write_line_ogr(struct Map_info *, int, const struct line_pnts *,
+			const struct line_cats *);
 off_t V1_rewrite_line_nat(struct Map_info *, off_t, int,
 			  const struct line_pnts *, const struct line_cats *);
 int V2_rewrite_line_nat(struct Map_info *, int, int,

Modified: grass/trunk/lib/vector/Vlib/write.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write.c	2010-01-03 11:47:59 UTC (rev 40205)
+++ grass/trunk/lib/vector/Vlib/write.c	2010-01-03 13:08:19 UTC (rev 40206)
@@ -66,9 +66,9 @@
     write_dummy, V1_write_line_nat, V2_write_line_nat}
 #ifdef HAVE_OGR
     , {
-    write_dummy, V1_write_line_ogr, write_dummy}
+    write_dummy, V1_write_line_ogr, V2_write_line_ogr}
     , {
-    write_dummy, V1_write_line_ogr, write_dummy}
+    write_dummy, V1_write_line_ogr, V2_write_line_ogr}
 #else
     , {
     write_dummy, format_l, format_l}
@@ -396,6 +396,260 @@
 }
 
 /*!
+  \brief Add line to topo file
+
+  Update areas. Areas are modified if: 
+   
+  1) first or/and last point are existing nodes ->
+   - drop areas/islands whose boundaries are neighbour to this boundary at these nodes
+   - try build areas and islands for this boundary and neighbour boundaries going through these nodes
+
+   Question: may be by adding line created new area/isle which doesn't go through nodes of this line
+
+   <pre>
+             old         new line 
+         +----+----+                    +----+----+                 +----+----+ 
+         | A1 | A2 |  +      /      ->  | A1 |   /|   or +   \   -> | A1 | A2 | \
+         |    |    |                    |    |    |                 |    |    |
+         +----+----+                    +----+----+                 +----+----+
+           I1   I1                        I1   I1                      
+   </pre>        
+ 
+   - reattache all centroids/isles inside new area(s)
+   - attach new isle to area outside
+
+  2) line is closed ring (node at the end is new, so it is not case above)
+    - build new area/isle
+    - check if it is island or contains island(s)
+    - re-attach all centroids/isles inside new area(s)
+    - attach new isle to area outside
+    
+    Note that 1) and 2) is done by the same code.
+*/
+void Vect__add_line_to_topo(struct Map_info *Map, int line,
+			    const struct line_pnts *points, const struct line_cats *cats)
+{
+    int first, s, n, i;
+    int type, node, next_line, area, side, sel_area, new_area[2];
+
+    struct Plus_head *plus;
+    struct P_line *Line, *NLine;
+    struct P_node *Node;
+    struct P_area *Area;
+    
+    struct bound_box box, abox;
+    
+    plus = &(Map->plus);
+    Line = plus->Line[line];
+    type = Line->type;
+
+    if (plus->built >= GV_BUILD_AREAS) {
+	if (type == GV_BOUNDARY) {
+	    /* Delete neighbour areas/isles */
+	    first = 1;
+	    for (s = 1; s < 3; s++) {	/* for each node */
+		if (s == 1)
+		    node = Line->N1;	/* Node 1 */
+		else
+		    node = Line->N2;
+		G_debug(3,
+			"  delete neighbour areas/iseles: side = %d node = %d",
+			s, node);
+		Node = plus->Node[node];
+		n = 0;
+		for (i = 0; i < Node->n_lines; i++) {
+		    NLine = plus->Line[abs(Node->lines[i])];
+		    if (NLine->type == GV_BOUNDARY)
+			n++;
+		}
+
+		G_debug(3, "  number of boundaries at node = %d", n);
+		if (n > 2) {	/* more than 2 boundaries at node ( >= 2 old + 1 new ) */
+		    /* Line above (to the right), it is enough to check to the right, because if area/isle
+		     *  exists it is the same to the left */
+		    if (s == 1)
+			next_line =
+			    dig_angle_next_line(plus, line, GV_RIGHT,
+						GV_BOUNDARY);
+		    else
+			next_line =
+			    dig_angle_next_line(plus, -line, GV_RIGHT,
+						GV_BOUNDARY);
+
+		    if (next_line != 0) {	/* there is a boundary to the right */
+			NLine = plus->Line[abs(next_line)];
+			if (next_line > 0)	/* the boundary is connected by 1. node */
+			    area = NLine->right;	/* we are interested just in this side (close to our line) */
+			else if (next_line < 0)	/* the boundary is connected by 2. node */
+			    area = NLine->left;
+
+			G_debug(3, "  next_line = %d area = %d", next_line,
+				area);
+			if (area > 0) {	/* is area */
+			    Vect_get_area_box(Map, area, &box);
+			    if (first) {
+				Vect_box_copy(&abox, &box);
+				first = 0;
+			    }
+			    else
+				Vect_box_extend(&abox, &box);
+
+			    if (plus->update_cidx) {
+				Vect__delete_area_cats_from_cidx(Map, area);
+			    }
+			    dig_del_area(plus, area);
+			}
+			else if (area < 0) {	/* is isle */
+			    dig_del_isle(plus, -area);
+			}
+		    }
+		}
+	    }
+	    /* Build new areas/isles. Thas true that we deleted also adjacent areas/isles, but if
+	     *  they form new one our boundary must participate, so we need to build areas/isles
+	     *  just for our boundary */
+	    for (s = 1; s < 3; s++) {
+		if (s == 1)
+		    side = GV_LEFT;
+		else
+		    side = GV_RIGHT;
+		G_debug(3, "  build area/isle on side = %d", side);
+
+		G_debug(3, "Build area for line = %d, side = %d", line, side);
+		area = Vect_build_line_area(Map, line, side);
+		G_debug(3, "Build area for line = %d, side = %d", line, side);
+		if (area > 0) {	/* area */
+		    Vect_get_area_box(Map, area, &box);
+		    if (first) {
+			Vect_box_copy(&abox, &box);
+			first = 0;
+		    }
+		    else
+			Vect_box_extend(&abox, &box);
+		}
+		else if (area < 0) {
+		    /* isle -> must be attached -> add to abox */
+		    Vect_get_isle_box(Map, -area, &box);
+		    if (first) {
+			Vect_box_copy(&abox, &box);
+			first = 0;
+		    }
+		    else
+			Vect_box_extend(&abox, &box);
+		}
+		new_area[s - 1] = area;
+	    }
+	    /* Reattach all centroids/isles in deleted areas + new area.
+	     *  Because isles are selected by box it covers also possible new isle created above */
+	    if (!first) {	/* i.e. old area/isle was deleted or new one created */
+		/* Reattache isles */
+		if (plus->built >= GV_BUILD_ATTACH_ISLES)
+		    Vect_attach_isles(Map, &abox);
+
+		/* Reattach centroids */
+		if (plus->built >= GV_BUILD_CENTROIDS)
+		    Vect_attach_centroids(Map, &abox);
+	    }
+	    /* Add to category index */
+	    if (plus->update_cidx) {
+		for (s = 1; s < 3; s++) {
+		    if (new_area[s - 1] > 0) {
+			Vect__add_area_cats_to_cidx(Map, new_area[s - 1]);
+		    }
+		}
+	    }
+	}
+    }
+
+    /* Attach centroid */
+    if (plus->built >= GV_BUILD_CENTROIDS) {
+	if (type == GV_CENTROID) {
+	    sel_area = Vect_find_area(Map, points->x[0], points->y[0]);
+	    G_debug(3, "  new centroid %d is in area %d", line, sel_area);
+	    if (sel_area > 0) {
+		Area = plus->Area[sel_area];
+		Line = plus->Line[line];
+		if (Area->centroid == 0) {	/* first centroid */
+		    G_debug(3, "  first centroid -> attach to area");
+		    Area->centroid = line;
+		    Line->left = sel_area;
+		    if (plus->update_cidx) {
+			Vect__add_area_cats_to_cidx(Map, sel_area);
+		    }
+		}
+		else {		/* duplicate centroid */
+		    G_debug(3,
+			    "  duplicate centroid -> do not attach to area");
+		    Line->left = -sel_area;
+		}
+	    }
+	}
+    }
+
+    /* Add cetegory index */
+    for (i = 0; i < cats->n_cats; i++) {
+	dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
+				type);
+    }
+
+    return;
+}
+
+/*!
+  \brief Writes feature to 'coor' file (topology level) - internal use only
+  
+  \param Map pointer to Map_info structure
+  \param type feature type
+  \param points feature geometry
+  \param cats feature categories
+  
+  \return new feature id
+  \return -1 on error
+*/
+off_t V2__write_line(struct Map_info *Map,
+		     int type, const struct line_pnts *points, const struct line_cats *cats,
+		     off_t (*write_fn) (struct Map_info *, int, const struct line_pnts *,
+					const struct line_cats *))
+{
+    int line;
+    off_t offset;
+    struct Plus_head *plus;
+    struct bound_box box;
+
+    line = 0;
+    
+    G_debug(3, "V2__write_line()");
+    offset = write_fn(Map, type, points, cats);
+    if (offset < 0)
+	return -1;
+
+    /* Update topology */
+    plus = &(Map->plus);
+    /* Add line */
+    if (plus->built >= GV_BUILD_BASE) {
+	line = dig_add_line(plus, type, points, offset);
+	G_debug(3, "  line added to topo with id = %d", line);
+	dig_line_box(points, &box);
+	dig_line_set_box(plus, line, &box);
+	if (line == 1)
+	    Vect_box_copy(&(plus->box), &box);
+	else
+	    Vect_box_extend(&(plus->box), &box);
+    }
+
+    Vect__add_line_to_topo(Map,
+			   line, points, cats);
+
+    G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
+	    plus->n_upnodes);
+
+    /* returns int line, but is defined as off_t for compatibility with
+     * Write_line_array in write.c */
+    
+    return line;
+}
+
+/*!
    \brief Writes new feature to the end of file
 
    The function calls G_fatal_error() on error.

Modified: grass/trunk/lib/vector/Vlib/write_nat.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_nat.c	2010-01-03 11:47:59 UTC (rev 40205)
+++ grass/trunk/lib/vector/Vlib/write_nat.c	2010-01-03 13:08:19 UTC (rev 40206)
@@ -30,211 +30,11 @@
 #include <grass/vector.h>
 #include <grass/glocale.h>
 
-/*!
-  \brief Add line to topo file
+static off_t rewrite_line_nat(struct Map_info *, off_t, int,
+			      const struct line_pnts *, const struct line_cats *);
 
-  Update areas. Areas are modified if: 
-   
-  1) first or/and last point are existing nodes ->
-   - drop areas/islands whose boundaries are neighbour to this boundary at these nodes
-   - try build areas and islands for this boundary and neighbour boundaries going through these nodes
-
-   Question: may be by adding line created new area/isle which doesn't go through nodes of this line
-
-   <pre>
-             old         new line 
-         +----+----+                    +----+----+                 +----+----+ 
-         | A1 | A2 |  +      /      ->  | A1 |   /|   or +   \   -> | A1 | A2 | \
-         |    |    |                    |    |    |                 |    |    |
-         +----+----+                    +----+----+                 +----+----+
-           I1   I1                        I1   I1                      
-   </pre>        
- 
-   - reattache all centroids/isles inside new area(s)
-   - attach new isle to area outside
-
-  2) line is closed ring (node at the end is new, so it is not case above)
-    - build new area/isle
-    - check if it is island or contains island(s)
-    - re-attach all centroids/isles inside new area(s)
-    - attach new isle to area outside
-    
-    Note that 1) and 2) is done by the same code.
-*/
-static void add_line_to_topo(struct Map_info *Map, int line,
-			     const struct line_pnts *points, const struct line_cats *cats)
-{
-    int first, s, n, i;
-    int type, node, next_line, area, side, sel_area, new_area[2];
-
-    struct Plus_head *plus;
-    struct P_line *Line, *NLine;
-    struct P_node *Node;
-    struct P_area *Area;
-    
-    struct bound_box box, abox;
-    
-    plus = &(Map->plus);
-    Line = plus->Line[line];
-    type = Line->type;
-
-    if (plus->built >= GV_BUILD_AREAS) {
-	if (type == GV_BOUNDARY) {
-	    /* Delete neighbour areas/isles */
-	    first = 1;
-	    for (s = 1; s < 3; s++) {	/* for each node */
-		if (s == 1)
-		    node = Line->N1;	/* Node 1 */
-		else
-		    node = Line->N2;
-		G_debug(3,
-			"  delete neighbour areas/iseles: side = %d node = %d",
-			s, node);
-		Node = plus->Node[node];
-		n = 0;
-		for (i = 0; i < Node->n_lines; i++) {
-		    NLine = plus->Line[abs(Node->lines[i])];
-		    if (NLine->type == GV_BOUNDARY)
-			n++;
-		}
-
-		G_debug(3, "  number of boundaries at node = %d", n);
-		if (n > 2) {	/* more than 2 boundaries at node ( >= 2 old + 1 new ) */
-		    /* Line above (to the right), it is enough to check to the right, because if area/isle
-		     *  exists it is the same to the left */
-		    if (s == 1)
-			next_line =
-			    dig_angle_next_line(plus, line, GV_RIGHT,
-						GV_BOUNDARY);
-		    else
-			next_line =
-			    dig_angle_next_line(plus, -line, GV_RIGHT,
-						GV_BOUNDARY);
-
-		    if (next_line != 0) {	/* there is a boundary to the right */
-			NLine = plus->Line[abs(next_line)];
-			if (next_line > 0)	/* the boundary is connected by 1. node */
-			    area = NLine->right;	/* we are interested just in this side (close to our line) */
-			else if (next_line < 0)	/* the boundary is connected by 2. node */
-			    area = NLine->left;
-
-			G_debug(3, "  next_line = %d area = %d", next_line,
-				area);
-			if (area > 0) {	/* is area */
-			    Vect_get_area_box(Map, area, &box);
-			    if (first) {
-				Vect_box_copy(&abox, &box);
-				first = 0;
-			    }
-			    else
-				Vect_box_extend(&abox, &box);
-
-			    if (plus->update_cidx) {
-				Vect__delete_area_cats_from_cidx(Map, area);
-			    }
-			    dig_del_area(plus, area);
-			}
-			else if (area < 0) {	/* is isle */
-			    dig_del_isle(plus, -area);
-			}
-		    }
-		}
-	    }
-	    /* Build new areas/isles. Thas true that we deleted also adjacent areas/isles, but if
-	     *  they form new one our boundary must participate, so we need to build areas/isles
-	     *  just for our boundary */
-	    for (s = 1; s < 3; s++) {
-		if (s == 1)
-		    side = GV_LEFT;
-		else
-		    side = GV_RIGHT;
-		G_debug(3, "  build area/isle on side = %d", side);
-
-		G_debug(3, "Build area for line = %d, side = %d", line, side);
-		area = Vect_build_line_area(Map, line, side);
-		G_debug(3, "Build area for line = %d, side = %d", line, side);
-		if (area > 0) {	/* area */
-		    Vect_get_area_box(Map, area, &box);
-		    if (first) {
-			Vect_box_copy(&abox, &box);
-			first = 0;
-		    }
-		    else
-			Vect_box_extend(&abox, &box);
-		}
-		else if (area < 0) {
-		    /* isle -> must be attached -> add to abox */
-		    Vect_get_isle_box(Map, -area, &box);
-		    if (first) {
-			Vect_box_copy(&abox, &box);
-			first = 0;
-		    }
-		    else
-			Vect_box_extend(&abox, &box);
-		}
-		new_area[s - 1] = area;
-	    }
-	    /* Reattach all centroids/isles in deleted areas + new area.
-	     *  Because isles are selected by box it covers also possible new isle created above */
-	    if (!first) {	/* i.e. old area/isle was deleted or new one created */
-		/* Reattache isles */
-		if (plus->built >= GV_BUILD_ATTACH_ISLES)
-		    Vect_attach_isles(Map, &abox);
-
-		/* Reattach centroids */
-		if (plus->built >= GV_BUILD_CENTROIDS)
-		    Vect_attach_centroids(Map, &abox);
-	    }
-	    /* Add to category index */
-	    if (plus->update_cidx) {
-		for (s = 1; s < 3; s++) {
-		    if (new_area[s - 1] > 0) {
-			Vect__add_area_cats_to_cidx(Map, new_area[s - 1]);
-		    }
-		}
-	    }
-	}
-    }
-
-    /* Attach centroid */
-    if (plus->built >= GV_BUILD_CENTROIDS) {
-	if (type == GV_CENTROID) {
-	    sel_area = Vect_find_area(Map, points->x[0], points->y[0]);
-	    G_debug(3, "  new centroid %d is in area %d", line, sel_area);
-	    if (sel_area > 0) {
-		Area = plus->Area[sel_area];
-		Line = plus->Line[line];
-		if (Area->centroid == 0) {	/* first centroid */
-		    G_debug(3, "  first centroid -> attach to area");
-		    Area->centroid = line;
-		    Line->left = sel_area;
-		    if (plus->update_cidx) {
-			Vect__add_area_cats_to_cidx(Map, sel_area);
-		    }
-		}
-		else {		/* duplicate centroid */
-		    G_debug(3,
-			    "  duplicate centroid -> do not attach to area");
-		    Line->left = -sel_area;
-		}
-	    }
-	}
-    }
-
-    /* Add cetegory index */
-    for (i = 0; i < cats->n_cats; i++) {
-	dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
-				type);
-    }
-
-    return;
-}
-
-static off_t V1__rewrite_line_nat(struct Map_info *Map, off_t offset, int type,
-				  const struct line_pnts *points, const struct line_cats *cats);
-
 /*!
-  \brief Writes feature to 'coor' file
+  \brief Writes feature to 'coor' file (level 1)
   
   \param Map pointer to Map_info structure
   \param type feature type
@@ -256,7 +56,7 @@
     if (offset == -1)
 	return -1;
 
-    return V1__rewrite_line_nat(Map, offset, type, points, cats);
+    return rewrite_line_nat(Map, offset, type, points, cats);
 }
 
 /*!
@@ -273,41 +73,7 @@
 off_t V2_write_line_nat(struct Map_info *Map,
 			int type, const struct line_pnts *points, const struct line_cats *cats)
 {
-    int line;
-    off_t offset;
-    struct Plus_head *plus;
-    struct bound_box box;
-
-    line = 0;
-    
-    G_debug(3, "V2_write_line_nat()");
-    offset = V1_write_line_nat(Map, type, points, cats);
-    if (offset < 0)
-	return -1;
-
-    /* Update topology */
-    plus = &(Map->plus);
-    /* Add line */
-    if (plus->built >= GV_BUILD_BASE) {
-	line = dig_add_line(plus, type, points, offset);
-	G_debug(3, "  line added to topo with id = %d", line);
-	dig_line_box(points, &box);
-	dig_line_set_box(plus, line, &box);
-	if (line == 1)
-	    Vect_box_copy(&(plus->box), &box);
-	else
-	    Vect_box_extend(&(plus->box), &box);
-    }
-
-    add_line_to_topo(Map,
-		     line, points, cats);
-
-    G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
-	    plus->n_upnodes);
-
-    /* returns int line, but is defined as off_t for compatibility with
-     * Write_line_array in write.c */
-    return line;
+    return V2__write_line(Map, type, points, cats, V1_write_line_nat);
 }
 
 /*!
@@ -356,7 +122,7 @@
 	    || ((type & GV_LINES) && (old_type & GV_LINES)))) {
 
 	/* equal -> overwrite the old */
-	return V1__rewrite_line_nat(Map, offset, type, points, cats);
+	return rewrite_line_nat(Map, offset, type, points, cats);
     }
     else {
 	/* differ -> delete the old and append new */
@@ -371,7 +137,7 @@
 	if (new_offset == -1)
 	    return -1;
 
-	return V1__rewrite_line_nat(Map, new_offset, type, points, cats);
+	return rewrite_line_nat(Map, new_offset, type, points, cats);
     }
 }
 
@@ -417,10 +183,10 @@
   \return feature offset
   \return -1 on error
 */
-off_t V1__rewrite_line_nat(struct Map_info *Map,
-			   off_t offset,
-			   int type,
-			   const struct line_pnts *points, const struct line_cats *cats)
+off_t rewrite_line_nat(struct Map_info *Map,
+		       off_t offset,
+		       int type,
+		       const struct line_pnts *points, const struct line_cats *cats)
 {
     int i, n_points;
     char rhead, nc;
@@ -672,7 +438,7 @@
 	Vect_box_extend(&(plus->box), &box);
     }
     
-    add_line_to_topo(Map,
+    Vect__add_line_to_topo(Map,
 		     line, points, cats);
 
     G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,

Modified: grass/trunk/lib/vector/Vlib/write_ogr.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_ogr.c	2010-01-03 11:47:59 UTC (rev 40205)
+++ grass/trunk/lib/vector/Vlib/write_ogr.c	2010-01-03 13:08:19 UTC (rev 40206)
@@ -24,7 +24,7 @@
 #include <ogr_api.h>
 
 static int write_attributes(int, const struct field_info *,
-			    OGRFeatureH);
+			    OGRLayerH, OGRFeatureH);
 
 /*!
   \brief Writes feature on level 1 (OGR format)
@@ -34,13 +34,13 @@
   \param points pointer to line_pnts structure (feature geometry) 
   \param cats pointer to line_cats structure (feature categories)
   
-  \return 0 on success
+  \return feature offset into file
   \return -1 on error
 */
-int V1_write_line_ogr(struct Map_info *Map,
-		      int type, const struct line_pnts *points, const struct line_cats *cats)
+off_t V1_write_line_ogr(struct Map_info *Map,
+			int type, const struct line_pnts *points, const struct line_cats *cats)
 {
-    int i, cat;
+    int i, cat, ret;
 
     struct field_info *Fi;
     
@@ -97,28 +97,90 @@
 	    G_fatal_error(_("Database connection not defined for layer %d"),
 			  cats->field[0]);
 	}
-	write_attributes(cat, Fi, Ogr_feature);
+	write_attributes(cat, Fi, Map->fInfo.ogr.layer, Ogr_feature);
     }
     else { /* no attributes */
 	G_warning(_("Feature has no categories"));
     }
     
     /* write feature into layer */
-    OGR_L_CreateFeature(Map->fInfo.ogr.layer, Ogr_feature);
+    ret = OGR_L_CreateFeature(Map->fInfo.ogr.layer, Ogr_feature);
 
     /* destroy */
     OGR_G_DestroyGeometry(Ogr_geometry);
     OGR_F_Destroy(Ogr_feature);
     
+    if (ret != OGRERR_NONE)
+	return -1;
+    
+    return Map->fInfo.ogr.offset_num++;
+}
+
+/*!
+  \brief Writes feature to 'coor' file (topology level)
+  
+  \param Map pointer to Map_info structure
+  \param type feature type
+  \param points feature geometry
+  \param cats feature categories
+  
+  \return new feature id
+  \return -1 on error
+*/
+off_t V2_write_line_ogr(struct Map_info *Map,
+			int type, const struct line_pnts *points, const struct line_cats *cats)
+{
+    return V2__write_line(Map, type, points, cats, V1_write_line_ogr);
+}
+
+/*!
+  \brief Deletes feature at the given offset (level 1)
+  
+  \param Map pointer Map_info structure
+  \param offset feature offset
+  
+  \return  0 on success
+  \return -1 on error
+*/
+int V1_delete_line_ogr(struct Map_info *Map, off_t offset)
+{
+    G_debug(3, "V1_delete_line_ogr(), offset = %lu", (unsigned long) offset);
+
+    if (!Map->fInfo.ogr.layer) {
+	G_warning(_("OGR layer not defined"));
+	return -1;
+    }
+    
+    if (offset >= Map->fInfo.ogr.offset_num)
+	return -1;
+    
+    if (OGR_L_DeleteFeature(Map->fInfo.ogr.layer, Map->fInfo.ogr.offset[offset]) != OGRERR_NONE)
+	return -1;
+    
     return 0;
 }
 
+/*!
+  \brief Deletes feature (topology level).
+  
+  \param Map pointer to Map_info structure
+  \param line feature id
+  
+  \return 0 on success
+  \return -1 on error
+*/
+int V2_delete_line_ogr(struct Map_info *Map, int line)
+{
+    return V2__delete_line(Map, line, V1_delete_line_ogr);
+}
+
 int write_attributes(int cat, const struct field_info *Fi,
-		     OGRFeatureH Ogr_feature)
+		     OGRLayerH Ogr_layer, OGRFeatureH Ogr_feature)
 {
     int j, ogrfieldnum;
     char buf[2000];
     int ncol, colsqltype, colctype, more;
+    char *fidcol;
     dbDriver *Driver;
     dbTable *Table;
     dbString dbstring;
@@ -142,7 +204,10 @@
     db_set_string(&dbstring, buf);
 
     /* open driver & select data */
-    Driver = db_start_driver(Fi->driver);
+    Driver = db_start_driver_open_database(Fi->driver, Fi->database);
+    if (!Driver)
+	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
+		      Fi->database, Fi->driver);
     if (db_open_select_cursor(Driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
 	G_fatal_error(_("Unable to select attributes for category %d"),
 		      cat);
@@ -159,10 +224,16 @@
 	return -1;
     }
 
+    fidcol = OGR_L_GetFIDColumn(Ogr_layer); 
+
     Table = db_get_cursor_table(&cursor);
     ncol = db_get_table_number_of_columns(Table);
     for (j = 0; j < ncol; j++) {
 	Column = db_get_table_column(Table, j);
+	if (fidcol && strcmp(db_get_column_name(Column), fidcol) == 0) {
+	    /* skip fid column */
+	    continue;
+	}
 	Value = db_get_column_value(Column);
 	db_convert_column_value_to_string(Column, &dbstring);	/* for debug only */
 	G_debug(2, "col %d : val = %s", j,
@@ -174,7 +245,11 @@
 	
 	ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature,
 					  db_get_column_name(Column));
-	
+	if (ogrfieldnum < 0) {
+	    G_warning(_("Uknown column <%s>"),
+		      db_get_column_name(Column));
+	    continue;
+	}
 	/* Reset */
 	OGR_F_UnsetField(Ogr_feature, ogrfieldnum);
 	
@@ -212,45 +287,4 @@
     return 1;
 }
 
-/*!
-  \brief Deletes feature at the given offset (level 1)
-  
-  \param Map pointer Map_info structure
-  \param offset feature offset
-  
-  \return  0 on success
-  \return -1 on error
-*/
-int V1_delete_line_ogr(struct Map_info *Map, off_t offset)
-{
-    G_debug(3, "V1_delete_line_ogr(), offset = %lu", (unsigned long) offset);
-
-    if (!Map->fInfo.ogr.layer) {
-	G_warning(_("OGR layer not defined"));
-	return -1;
-    }
-    
-    if (offset >= Map->fInfo.ogr.offset_num)
-	return -1;
-    
-    if (OGR_L_DeleteFeature(Map->fInfo.ogr.layer, Map->fInfo.ogr.offset[offset]) != OGRERR_NONE)
-	return -1;
-    
-    return 0;
-}
-
-/*!
-  \brief Deletes feature (topology level).
-  
-  \param Map pointer to Map_info structure
-  \param line feature id
-  
-  \return 0 on success
-  \return -1 on error
-*/
-int V2_delete_line_ogr(struct Map_info *Map, int line)
-{
-    return V2__delete_line(Map, line, V1_delete_line_ogr);
-}
-
 #endif /* HAVE_OGR */

Modified: grass/trunk/vector/v.edit/main.c
===================================================================
--- grass/trunk/vector/v.edit/main.c	2010-01-03 11:47:59 UTC (rev 40205)
+++ grass/trunk/vector/v.edit/main.c	2010-01-03 13:08:19 UTC (rev 40206)
@@ -105,7 +105,7 @@
     }
     else {			/* open selected vector file */
 	if (action_mode == MODE_ADD)	/* write */
-	    ret = Vect_open_update(&Map, params.map->answer, G_mapset());
+	    ret = Vect_open_update2(&Map, params.map->answer, G_mapset(), params.fld->answer);
 	else			/* read-only -- select features */
 	    ret = Vect_open_old2(&Map, params.map->answer, G_mapset(), params.fld->answer);
 



More information about the grass-commit mailing list