[GRASS-SVN] r42079 - in grass/trunk: include lib/vector/Vlib

svn_grass at osgeo.org svn_grass at osgeo.org
Mon May 3 04:06:53 EDT 2010


Author: mmetz
Date: 2010-05-03 04:06:52 -0400 (Mon, 03 May 2010)
New Revision: 42079

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
Log:
next step on OGR vector write access

Modified: grass/trunk/include/vector.h
===================================================================
--- grass/trunk/include/vector.h	2010-05-02 17:34:38 UTC (rev 42078)
+++ grass/trunk/include/vector.h	2010-05-03 08:06:52 UTC (rev 42079)
@@ -247,7 +247,7 @@
 /* Level 2 only */
 int Vect_read_line(const struct Map_info *, struct line_pnts *, struct line_cats *,
 		   int);
-int Vect_rewrite_line(struct Map_info *, int, int, const struct line_pnts *,
+off_t Vect_rewrite_line(struct Map_info *, int, int, const struct line_pnts *,
 		      const struct line_cats *);
 int Vect_delete_line(struct Map_info *, int);
 int Vect_restore_line(struct Map_info *, int, off_t);
@@ -436,15 +436,6 @@
  */
 int Vect_print_header(const struct Map_info *);
 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 (*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 *);
@@ -490,27 +481,27 @@
 int V2_read_next_line_ogr(struct Map_info *, struct line_pnts *,
 			  struct line_cats *);
 int V1_delete_line_nat(struct Map_info *, off_t);
+int V2_delete_line_nat(struct Map_info *, off_t);
 int V1_delete_line_ogr(struct Map_info *, off_t);
-int V2_delete_line_nat(struct Map_info *, int);
-int V2_delete_line_ogr(struct Map_info *, int);
+int V2_delete_line_ogr(struct Map_info *, off_t);
 int V1_restore_line_nat(struct Map_info *, off_t);
 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 *);
+off_t 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,
+off_t V1_rewrite_line_nat(struct Map_info *, int, int, off_t,
 			  const struct line_pnts *, const struct line_cats *);
-off_t V1_rewrite_line_ogr(struct Map_info *, off_t, int,
+off_t V2_rewrite_line_nat(struct Map_info *, int, int, off_t,
 			  const struct line_pnts *, const struct line_cats *);
-int V2_rewrite_line_nat(struct Map_info *, int, int,
-			const struct line_pnts *, const struct line_cats *);
-int V2_rewrite_line_ogr(struct Map_info *, int, int,
-			const struct line_pnts *, const struct line_cats *);
+off_t V1_rewrite_line_ogr(struct Map_info *, int, int, off_t,
+			  const struct line_pnts *, const struct line_cats *);
+off_t V2_rewrite_line_ogr(struct Map_info *, int, int, off_t,
+			  const struct line_pnts *, const struct line_cats *);
 
     /* Build topology */
 int Vect_build_nat(struct Map_info *, int);

Modified: grass/trunk/lib/vector/Vlib/write.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write.c	2010-05-02 17:34:38 UTC (rev 42078)
+++ grass/trunk/lib/vector/Vlib/write.c	2010-05-03 08:06:52 UTC (rev 42079)
@@ -26,7 +26,7 @@
 	      _("for this format/level not supported"));
     return -1;
 }
-static int rewrite_dummy()
+static off_t rewrite_dummy()
 {
     G_warning("Vect_rewrite_line() %s",
 	      _("for this format/level not supported"));
@@ -61,7 +61,7 @@
 
 #endif
 
-static off_t (*Write_line_array[][3]) () = {
+static off_t (*Vect_write_line_array[][3]) () = {
     {
     write_dummy, V1_write_line_nat, V2_write_line_nat}
 #ifdef HAVE_OGR
@@ -77,7 +77,7 @@
 #endif
 };
 
-static int (*Vect_rewrite_line_array[][3]) () = {
+static off_t (*Vect_rewrite_line_array[][3]) () = {
     {
     rewrite_dummy, V1_rewrite_line_nat, V2_rewrite_line_nat}
 #ifdef HAVE_OGR
@@ -98,9 +98,9 @@
     delete_dummy, V1_delete_line_nat, V2_delete_line_nat}
 #ifdef HAVE_OGR
     , {
-    delete_dummy, V1_delete_line_ogr, V2_delete_line_ogr}
+    delete_dummy, V1_delete_line_ogr, V2_delete_line_nat}
     , {
-    delete_dummy, V1_delete_line_ogr, V2_delete_line_ogr}
+    delete_dummy, V1_delete_line_ogr, V2_delete_line_nat}
 #else
     , {
     delete_dummy, format, format}
@@ -125,533 +125,11 @@
 #endif
 };
 
-/*! 
-  \brief Deletes area (i.e. centroid) categories from category
-  index (internal use only)
-
-  \param Map pointer to Map_info structure
-  \param area area id
-*/
-void Vect__delete_area_cats_from_cidx(struct Map_info *Map, int area)
-{
-    int i;
-    struct P_area *Area;
-    static struct line_cats *Cats = NULL;
-
-    G_debug(3, "Vect__delete_area_cats_from_cidx() area = %d", area);
-
-    Area = Map->plus.Area[area];
-    if (!Area)
-	G_fatal_error(_("%s: Area %d does not exist"),
-		      "delete_area_cats_from_cidx()", area);
-    
-    if (Area->centroid == 0) /* no centroid found */
-	return;
-
-    if (!Cats)
-	Cats = Vect_new_cats_struct();
-
-    V2_read_line_nat(Map, NULL, Cats, Area->centroid);
-
-    for (i = 0; i < Cats->n_cats; i++) {
-	dig_cidx_del_cat(&(Map->plus), Cats->field[i], Cats->cat[i], area,
-			 GV_AREA);
-    }
-}
-
-/*! 
-  \brief Adds area (i.e. centroid) categories from category index
-  (internal use only)
-
-  \param Map pointer to Map_info structure
-  \param area area id
-*/
-void Vect__add_area_cats_to_cidx(struct Map_info *Map, int area)
-{
-    int i;
-    struct P_area *Area;
-    static struct line_cats *Cats = NULL;
-
-    G_debug(3, "Vect__add_area_cats_to_cidx() area = %d", area);
-
-    Area = Map->plus.Area[area];
-    if (!Area)
-	G_fatal_error(_("%s: Area %d does not exist"),
-		      "add_area_cats_to_cidx():", area);
-
-    if (Area->centroid == 0) /* no centroid found */
-	return;
-
-    if (!Cats)
-	Cats = Vect_new_cats_struct();
-
-    V2_read_line_nat(Map, NULL, Cats, Area->centroid);
-
-    for (i = 0; i < Cats->n_cats; i++) {
-	dig_cidx_add_cat_sorted(&(Map->plus), Cats->field[i], Cats->cat[i],
-				area, GV_AREA);
-    }
-}
-
 /*!
-  \brief Deletes feature (topology level) -- internal use only
-  
-  \param pointer to Map_info structure
-  \param line feature id
-  \param fn function to delete feature (native or ogr)
-  
-  \return 0 on success
-  \return -1 on error
-*/
-int V2__delete_line(struct Map_info *Map, int line, int (*fn_delete) (struct Map_info *, off_t))
-{
-    int ret, i, side, type, first, next_line, area;
-    struct P_line *Line;
-    struct P_area *Area;
-    struct Plus_head *plus;
-    struct bound_box box, abox;
-    int adjacent[4], n_adjacent;
-    static struct line_cats *Cats = NULL;
-
-    G_debug(3, "V2__delete_line(), line = %d", line);
-
-    type = first = n_adjacent = 0;
-    Line = NULL;
-    plus = &(Map->plus);
-
-    if (plus->built >= GV_BUILD_BASE) {
-	Line = Map->plus.Line[line];
-
-	if (Line == NULL)
-	    G_fatal_error(_("Attempt to delete dead feature"));
-	type = Line->type;
-    }
-
-    if (!Cats) {
-	Cats = Vect_new_cats_struct();
-    }
-
-    /* Update category index */
-    if (plus->update_cidx) {
-	type = V2_read_line_nat(Map, NULL, Cats, line);
-
-	for (i = 0; i < Cats->n_cats; i++) {
-	    dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
-	}
-    }
-
-    /* delete the line from coor */
-    ret = fn_delete(Map, Line->offset);
-
-    if (ret == -1) {
-	return ret;
-    }
-
-    /* Update topology */
-    if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
-	/* Store adjacent boundaries at nodes (will be used to rebuild area/isle) */
-	/* Adjacent are stored: > 0 - we want right side; < 0 - we want left side */
-	n_adjacent = 0;
-
-	next_line = dig_angle_next_line(plus, line, GV_RIGHT, GV_BOUNDARY);
-	if (next_line != 0 && abs(next_line) != line) {
-	    /* N1, to the right -> we want the right side for > 0  and left for < 0 */
-	    adjacent[n_adjacent] = next_line;
-	    n_adjacent++;
-	}
-	next_line = dig_angle_next_line(plus, line, GV_LEFT, GV_BOUNDARY);
-	if (next_line != 0 && abs(next_line) != line) {
-	    /* N1, to the left -> we want the left side for > 0  and right for < 0 */
-	    adjacent[n_adjacent] = -next_line;
-	    n_adjacent++;
-	}
-	next_line = dig_angle_next_line(plus, -line, GV_RIGHT, GV_BOUNDARY);
-	if (next_line != 0 && abs(next_line) != line) {
-	    /* N2, to the right -> we want the right side for > 0  and left for < 0 */
-	    adjacent[n_adjacent] = next_line;
-	    n_adjacent++;
-	}
-	next_line = dig_angle_next_line(plus, -line, GV_LEFT, GV_BOUNDARY);
-	if (next_line != 0 && abs(next_line) != line) {
-	    /* N2, to the left -> we want the left side for > 0  and right for < 0 */
-	    adjacent[n_adjacent] = -next_line;
-	    n_adjacent++;
-	}
-
-	/* Delete area(s) and islands this line forms */
-	first = 1;
-	if (Line->left > 0) {	/* delete area */
-	    Vect_get_area_box(Map, Line->left, &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, Line->left);
-	    }
-	    dig_del_area(plus, Line->left);
-	}
-	else if (Line->left < 0) {	/* delete isle */
-	    dig_del_isle(plus, -Line->left);
-	}
-	if (Line->right > 0) {	/* delete area */
-	    Vect_get_area_box(Map, Line->right, &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, Line->right);
-	    }
-	    dig_del_area(plus, Line->right);
-	}
-	else if (Line->right < 0) {	/* delete isle */
-	    dig_del_isle(plus, -Line->right);
-	}
-    }
-
-    /* Delete reference from area */
-    if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
-	if (Line->left > 0) {
-	    G_debug(3, "Remove centroid %d from area %d", line, Line->left);
-	    if (plus->update_cidx) {
-		Vect__delete_area_cats_from_cidx(Map, Line->left);
-	    }
-	    Area = Map->plus.Area[Line->left];
-	    Area->centroid = 0;
-	}
-    }
-
-    /* delete the line from topo */
-    dig_del_line(plus, line);
-
-    /* Rebuild areas/isles and attach centroids and isles */
-    if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
-	int *new_areas, nnew_areas;
-
-	nnew_areas = 0;
-	new_areas = (int *)G_malloc(2 * n_adjacent * sizeof(int));
-	/* Rebuild areas/isles */
-	for (i = 0; i < n_adjacent; i++) {
-	    if (adjacent[i] > 0)
-		side = GV_RIGHT;
-	    else
-		side = GV_LEFT;
-
-	    G_debug(3, "Build area for line = %d, side = %d", adjacent[i],
-		    side);
-
-	    area = Vect_build_line_area(Map, abs(adjacent[i]), 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);
-
-		new_areas[nnew_areas] = area;
-		nnew_areas++;
-	    }
-	    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);
-	    }
-	}
-	/* 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);
-	}
-
-	if (plus->update_cidx) {
-	    for (i = 0; i < nnew_areas; i++) {
-		Vect__add_area_cats_to_cidx(Map, new_areas[i]);
-	    }
-	}
-    }
-
-    G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
-	    plus->n_upnodes);
-    return ret;
-}
-
-/*!
-  \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
 
+   Vector map topology is not required.
+
    The function calls G_fatal_error() on error.
 
    \param Map pointer to vector map
@@ -681,7 +159,7 @@
     }
 
     offset =
-	(*Write_line_array[Map->format][Map->level]) (Map, type, points,
+	(*Vect_write_line_array[Map->format][Map->level]) (Map, type, points,
 						      cats);
 
     if (offset == -1)
@@ -691,10 +169,11 @@
     return offset;
 }
 
-
 /*!
    \brief Rewrites feature info at the given offset.
 
+   Vector map must be opened with full topology (level 2).
+
    The number of points or cats or type may change. If necessary, the
    old feature is deleted and new is written.
 
@@ -706,15 +185,15 @@
    \param points feature geometry
    \param cats feature categories
 
-   \return new feature id
+   \return feature offset
    \return -1 on error
  */
-int
+off_t
 Vect_rewrite_line(struct Map_info *Map,
 		  int line,
 		  int type, const struct line_pnts *points, const struct line_cats *cats)
 {
-    long ret;
+    off_t ret, offset;
 
     G_debug(3, "Vect_rewrite_line(): name = %s, line = %d", Map->name, line);
 
@@ -727,8 +206,9 @@
 	Map->plus.cidx_up_to_date = 0;
     }
 
+    offset = Map->plus.Line[line]->offset;
     ret =
-	(*Vect_rewrite_line_array[Map->format][Map->level]) (Map, line, type,
+	(*Vect_rewrite_line_array[Map->format][Map->level]) (Map, offset, line, type,
 							     points, cats);
 
     if (ret == -1)
@@ -740,7 +220,7 @@
 /*!
    \brief Delete feature
 
-   Vector map must be opened on topo level 2.
+   Vector map must be opened with full topology (level 2).
 
    This function calls G_fatal_error() on error.
 
@@ -786,12 +266,12 @@
 /*!
    \brief Restore previously deleted feature
 
-   Vector map must be opened on topo level 2.
+   Vector map must be opened with full topology (level 2).
 
    This function calls G_fatal_error() on error.
 
    \param Map pointer to vector map
-   \param line feature id to be deleted
+   \param line feature id to be restored
 
    \return 0 on success
    \return -1 on error

Modified: grass/trunk/lib/vector/Vlib/write_nat.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_nat.c	2010-05-02 17:34:38 UTC (rev 42078)
+++ grass/trunk/lib/vector/Vlib/write_nat.c	2010-05-03 08:06:52 UTC (rev 42079)
@@ -30,10 +30,281 @@
 #include <grass/vector.h>
 #include <grass/glocale.h>
 
-static off_t rewrite_line_nat(struct Map_info *, off_t, int,
+static off_t V1__rewrite_line_nat(struct Map_info *, off_t, int,
 			      const struct line_pnts *, const struct line_cats *);
 
+
+/*! 
+  \brief Deletes area (i.e. centroid) categories from category
+  index (internal use only)
+
+  \param Map pointer to Map_info structure
+  \param area area id
+*/
+static void V2__delete_area_cats_from_cidx_nat(struct Map_info *Map, int area)
+{
+    int i;
+    struct P_area *Area;
+    static struct line_cats *Cats = NULL;
+
+    G_debug(3, "V2__delete_area_cats_from_cidx_nat(), area = %d", area);
+
+    Area = Map->plus.Area[area];
+    if (!Area)
+	G_fatal_error(_("%s: Area %d does not exist"),
+		      "delete_area_cats_from_cidx()", area);
+    
+    if (Area->centroid == 0) /* no centroid found */
+	return;
+
+    if (!Cats)
+	Cats = Vect_new_cats_struct();
+
+    V2_read_line_nat(Map, NULL, Cats, Area->centroid);
+
+    for (i = 0; i < Cats->n_cats; i++) {
+	dig_cidx_del_cat(&(Map->plus), Cats->field[i], Cats->cat[i], area,
+			 GV_AREA);
+    }
+}
+
+/*! 
+  \brief Adds area (i.e. centroid) categories from category index
+  (internal use only)
+
+  \param Map pointer to Map_info structure
+  \param area area id
+*/
+static void V2__add_area_cats_to_cidx_nat(struct Map_info *Map, int area)
+{
+    int i;
+    struct P_area *Area;
+    static struct line_cats *Cats = NULL;
+
+    G_debug(3, "V2__add_area_cats_to_cidx_nat(), area = %d", area);
+
+    Area = Map->plus.Area[area];
+    if (!Area)
+	G_fatal_error(_("%s: Area %d does not exist"),
+		      "add_area_cats_to_cidx():", area);
+
+    if (Area->centroid == 0) /* no centroid found */
+	return;
+
+    if (!Cats)
+	Cats = Vect_new_cats_struct();
+
+    V2_read_line_nat(Map, NULL, Cats, Area->centroid);
+
+    for (i = 0; i < Cats->n_cats; i++) {
+	dig_cidx_add_cat_sorted(&(Map->plus), Cats->field[i], Cats->cat[i],
+				area, GV_AREA);
+    }
+}
+
 /*!
+  \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.
+*/
+static void V2__add_line_to_topo_nat(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;
+    
+    G_debug(3, "V2__add_line_to_topo_nat(), line = %d", line);
+
+    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) {
+				V2__delete_area_cats_from_cidx_nat(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) {
+			V2__add_area_cats_to_cidx_nat(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) {
+			V2__add_area_cats_to_cidx_nat(Map, sel_area);
+		    }
+		}
+		else {		/* duplicate centroid */
+		    G_debug(3,
+			    "  duplicate centroid -> do not attach to area");
+		    Line->left = -sel_area;
+		}
+	    }
+	}
+    }
+
+    /* Add category 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 (level 1)
   
   \param Map pointer to Map_info structure
@@ -56,11 +327,11 @@
     if (offset == -1)
 	return -1;
 
-    return rewrite_line_nat(Map, offset, type, points, cats);
+    return V1__rewrite_line_nat(Map, offset, type, points, cats);
 }
 
 /*!
-  \brief Writes feature to 'coor' file (topology level)
+  \brief Writes feature to 'coor' file (topology level) - internal use only
   
   \param Map pointer to Map_info structure
   \param type feature type
@@ -70,10 +341,44 @@
   \return new feature id
   \return -1 on error
 */
-off_t V2_write_line_nat(struct Map_info *Map,
-			int type, const struct line_pnts *points, const struct line_cats *cats)
+off_t V2_write_line_nat(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_nat);
+    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);
+    }
+
+    V2__add_line_to_topo_nat(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
+     * Vect_write_line_array in write.c */
+    
+    return line;
 }
 
 /*!
@@ -95,9 +400,7 @@
   \return feature offset (rewriten feature)
   \return -1 on error
 */
-off_t V1_rewrite_line_nat(struct Map_info *Map,
-			  off_t offset,
-			  int type,
+off_t V1_rewrite_line_nat(struct Map_info *Map, int line, int type, off_t offset,
 			  const struct line_pnts *points, const struct line_cats *cats)
 {
     int old_type;
@@ -105,6 +408,8 @@
     struct line_cats *old_cats;
     off_t new_offset;
     
+    G_debug(3, "V1_rewrite_line_nat(), offset = %lu", (unsigned long) offset);
+
     /* TODO: enable points and cats == NULL  */
 
     /* First compare numbers of points and cats with tha old one */
@@ -122,7 +427,7 @@
 	    || ((type & GV_LINES) && (old_type & GV_LINES)))) {
 
 	/* equal -> overwrite the old */
-	return rewrite_line_nat(Map, offset, type, points, cats);
+	return V1__rewrite_line_nat(Map, offset, type, points, cats);
     }
     else {
 	/* differ -> delete the old and append new */
@@ -137,28 +442,24 @@
 	if (new_offset == -1)
 	    return -1;
 
-	return rewrite_line_nat(Map, new_offset, type, points, cats);
+	return V1__rewrite_line_nat(Map, new_offset, type, points, cats);
     }
 }
 
 /*!
-  \brief Rewrites feature (topology level)
-   
-  Old feature is deleted (marked as dead), new feature written.
+  \brief Rewrites feature to 'coor' file (topology level) - internal use only
   
   \param Map pointer to Map_info structure
+  \param type feature type
   \param line feature id
-  \param type feature type
   \param points feature geometry
-  \param cats feature category
+  \param cats feature categories
   
-  \return new feature id
+  \return offset where line was rewritten
   \return -1 on error
 */
-int V2_rewrite_line_nat(struct Map_info *Map,
-			int line,
-			int type,
-			const struct line_pnts *points, const struct line_cats *cats)
+off_t V2_rewrite_line_nat(struct Map_info *Map, int line, int type, off_t old_offset,
+			  const struct line_pnts *points, const struct line_cats *cats)
 {
     /* TODO: this is just quick shortcut because we have already V2_delete_nat()
      *        and V2_write_nat() this function first deletes old line
@@ -166,9 +467,40 @@
      *        and cats was not changed or topology is not changed (nodes not moved,
      *        angles not changed etc.) */
 
+    off_t offset;
+    struct Plus_head *plus;
+    struct bound_box box;
+
     V2_delete_line_nat(Map, line);
+    
+    G_debug(3, "V2_write_line_nat(), line = %d", line);
+    offset = V1_rewrite_line_nat(Map, line, type, old_offset, points, cats);
+    if (offset < 0)
+	return -1;
 
-    return (V2_write_line_nat(Map, type, points, cats));
+    /* 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);
+    }
+
+    V2__add_line_to_topo_nat(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
+     * Vect_rewrite_line_array in write.c */
+    
+    return line;
 }
 
 /*!
@@ -183,7 +515,7 @@
   \return feature offset
   \return -1 on error
 */
-off_t rewrite_line_nat(struct Map_info *Map,
+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)
@@ -312,7 +644,7 @@
 }
 
 /*!
-  \brief Deletes feature (topology level).
+  \brief Deletes feature (topology level) -- internal use only
   
   \param pointer to Map_info structure
   \param line feature id
@@ -320,9 +652,196 @@
   \return 0 on success
   \return -1 on error
 */
-int V2_delete_line_nat(struct Map_info *Map, int line)
+int V2_delete_line_nat(struct Map_info *Map, off_t line)
 {
-    return V2__delete_line(Map, line, V1_delete_line_nat);
+    int ret, i, side, type, first, next_line, area;
+    struct P_line *Line;
+    struct P_area *Area;
+    struct Plus_head *plus;
+    struct bound_box box, abox;
+    int adjacent[4], n_adjacent;
+    static struct line_cats *Cats = NULL;
+
+    G_debug(3, "V2_delete_line_nat(), line = %lu", (unsigned long) line);
+
+    type = first = n_adjacent = 0;
+    Line = NULL;
+    plus = &(Map->plus);
+
+    if (plus->built >= GV_BUILD_BASE) {
+	Line = Map->plus.Line[line];
+
+	if (Line == NULL)
+	    G_fatal_error(_("Attempt to delete dead feature"));
+	type = Line->type;
+    }
+
+    if (!Cats) {
+	Cats = Vect_new_cats_struct();
+    }
+
+    /* Update category index */
+    if (plus->update_cidx) {
+	type = V2_read_line_nat(Map, NULL, Cats, line);
+
+	for (i = 0; i < Cats->n_cats; i++) {
+	    dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
+	}
+    }
+
+    /* delete the line from coor */
+    ret = V1_delete_line_nat(Map, Line->offset);
+
+    if (ret == -1) {
+	return ret;
+    }
+
+    /* Update topology */
+    if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
+	/* Store adjacent boundaries at nodes (will be used to rebuild area/isle) */
+	/* Adjacent are stored: > 0 - we want right side; < 0 - we want left side */
+	n_adjacent = 0;
+
+	next_line = dig_angle_next_line(plus, line, GV_RIGHT, GV_BOUNDARY);
+	if (next_line != 0 && abs(next_line) != line) {
+	    /* N1, to the right -> we want the right side for > 0  and left for < 0 */
+	    adjacent[n_adjacent] = next_line;
+	    n_adjacent++;
+	}
+	next_line = dig_angle_next_line(plus, line, GV_LEFT, GV_BOUNDARY);
+	if (next_line != 0 && abs(next_line) != line) {
+	    /* N1, to the left -> we want the left side for > 0  and right for < 0 */
+	    adjacent[n_adjacent] = -next_line;
+	    n_adjacent++;
+	}
+	next_line = dig_angle_next_line(plus, -line, GV_RIGHT, GV_BOUNDARY);
+	if (next_line != 0 && abs(next_line) != line) {
+	    /* N2, to the right -> we want the right side for > 0  and left for < 0 */
+	    adjacent[n_adjacent] = next_line;
+	    n_adjacent++;
+	}
+	next_line = dig_angle_next_line(plus, -line, GV_LEFT, GV_BOUNDARY);
+	if (next_line != 0 && abs(next_line) != line) {
+	    /* N2, to the left -> we want the left side for > 0  and right for < 0 */
+	    adjacent[n_adjacent] = -next_line;
+	    n_adjacent++;
+	}
+
+	/* Delete area(s) and islands this line forms */
+	first = 1;
+	if (Line->left > 0) {	/* delete area */
+	    Vect_get_area_box(Map, Line->left, &box);
+	    if (first) {
+		Vect_box_copy(&abox, &box);
+		first = 0;
+	    }
+	    else
+		Vect_box_extend(&abox, &box);
+
+	    if (plus->update_cidx) {
+		V2__delete_area_cats_from_cidx_nat(Map, Line->left);
+	    }
+	    dig_del_area(plus, Line->left);
+	}
+	else if (Line->left < 0) {	/* delete isle */
+	    dig_del_isle(plus, -Line->left);
+	}
+	if (Line->right > 0) {	/* delete area */
+	    Vect_get_area_box(Map, Line->right, &box);
+	    if (first) {
+		Vect_box_copy(&abox, &box);
+		first = 0;
+	    }
+	    else
+		Vect_box_extend(&abox, &box);
+
+	    if (plus->update_cidx) {
+		V2__delete_area_cats_from_cidx_nat(Map, Line->right);
+	    }
+	    dig_del_area(plus, Line->right);
+	}
+	else if (Line->right < 0) {	/* delete isle */
+	    dig_del_isle(plus, -Line->right);
+	}
+    }
+
+    /* Delete reference from area */
+    if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
+	if (Line->left > 0) {
+	    G_debug(3, "Remove centroid %d from area %d", (int) line, Line->left);
+	    if (plus->update_cidx) {
+		V2__delete_area_cats_from_cidx_nat(Map, Line->left);
+	    }
+	    Area = Map->plus.Area[Line->left];
+	    Area->centroid = 0;
+	}
+    }
+
+    /* delete the line from topo */
+    dig_del_line(plus, line);
+
+    /* Rebuild areas/isles and attach centroids and isles */
+    if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
+	int *new_areas, nnew_areas;
+
+	nnew_areas = 0;
+	new_areas = (int *)G_malloc(2 * n_adjacent * sizeof(int));
+	/* Rebuild areas/isles */
+	for (i = 0; i < n_adjacent; i++) {
+	    if (adjacent[i] > 0)
+		side = GV_RIGHT;
+	    else
+		side = GV_LEFT;
+
+	    G_debug(3, "Build area for line = %d, side = %d", adjacent[i],
+		    side);
+
+	    area = Vect_build_line_area(Map, abs(adjacent[i]), 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);
+
+		new_areas[nnew_areas] = area;
+		nnew_areas++;
+	    }
+	    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);
+	    }
+	}
+	/* 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);
+	}
+
+	if (plus->update_cidx) {
+	    for (i = 0; i < nnew_areas; i++) {
+		V2__add_area_cats_to_cidx_nat(Map, new_areas[i]);
+	    }
+	}
+    }
+
+    G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
+	    plus->n_upnodes);
+    return ret;
 }
 
 /*!
@@ -438,12 +957,11 @@
 	Vect_box_extend(&(plus->box), &box);
     }
     
-    Vect__add_line_to_topo(Map,
+    V2__add_line_to_topo_nat(Map,
 		     line, points, cats);
 
     G_debug(3, "updated lines : %d , updated nodes : %d", plus->n_uplines,
 	    plus->n_upnodes);
-    
 
     return ret;
 }

Modified: grass/trunk/lib/vector/Vlib/write_ogr.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_ogr.c	2010-05-02 17:34:38 UTC (rev 42078)
+++ grass/trunk/lib/vector/Vlib/write_ogr.c	2010-05-03 08:06:52 UTC (rev 42079)
@@ -26,6 +26,22 @@
 static int write_attributes(int, const struct field_info *,
 			    OGRLayerH, OGRFeatureH);
 
+/* TODO:
+ * OGR version of V2__delete_area_cats_from_cidx_nat()
+ * function to delete corresponding entry in fidx
+ * OGR version of V2__add_area_cats_to_cidx_nat
+ * OGR version of V2__add_line_to_topo_nat
+ */
+
+void V2__add_line_to_topo_ogr(struct Map_info *Map, int line,
+			    const struct line_pnts *points, const struct line_cats *cats)
+{
+   /* recycle code from build_ogr */
+    G_warning("feature not yet implemented, coming soon...");
+
+    return;
+}
+
 /*!
   \brief Writes feature on level 1
 
@@ -53,11 +69,16 @@
 	return -1;
     }
 
-    /* determine feature's geometry */
-    if (type & (GV_POINTS | GV_KERNEL)) {
+    /* determine matching OGR feature geometry type */
+    /* NOTE: centroids are not supported in OGR,
+     *       pseudotopo holds virtual centroids */
+    /* NOTE: boundaries are not supported in OGR,
+     *       pseudotopo treats polygons as boundaries */
+    
+    if (type & (GV_POINT | GV_KERNEL)) {
 	Ogr_geometry = OGR_G_CreateGeometry(wkbPoint);
     }
-    else if (type & GV_LINES) {
+    else if (type & GV_LINE) {
 	Ogr_geometry = OGR_G_CreateGeometry(wkbLineString);
     }
     else if (type & GV_FACE) {
@@ -116,24 +137,97 @@
     return Map->fInfo.ogr.offset_num++;
 }
 
+off_t V2_write_line_ogr(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_ogr(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);
+
+	V2__add_line_to_topo_ogr(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 feature (topology level)
+  \brief Rewrites feature at the given offset (level 1)
   
   \param Map pointer to Map_info structure
+  \param offset feature offset
   \param type feature type
   \param points feature geometry
   \param cats feature categories
   
-  \return new feature id
+  \return feature offset (rewriten feature)
   \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)
+off_t V1_rewrite_line_ogr(struct Map_info *Map,
+			  int line,
+			  int type,
+			  off_t offset,
+			  const struct line_pnts *points, const struct line_cats *cats)
 {
-    return V2__write_line(Map, type, points, cats, V1_write_line_ogr);
+    if (type != V1_read_line_ogr(Map, NULL, NULL, offset)) {
+	G_warning(_("Unable to rewrite feature (incompatible feature types)"));
+	return -1;
+    }
+
+    /* delete old */
+    V1_delete_line_ogr(Map, offset);
+
+    return V1_write_line_ogr(Map, type, points, cats);
 }
 
 /*!
+  \brief Rewrites feature to 'coor' file (topology level) - internal use only
+  
+  \param Map pointer to Map_info structure
+  \param type feature type
+  \param line feature id
+  \param points feature geometry
+  \param cats feature categories
+  
+  \return offset where line was rewritten
+  \return -1 on error
+*/
+off_t V2_rewrite_line_ogr(struct Map_info *Map, int line, int type, off_t offset,
+			  const struct line_pnts *points, const struct line_cats *cats)
+{
+    V2_delete_line_ogr(Map, line);
+
+    return (V2_write_line_ogr(Map, type, points, cats));
+}
+
+/*!
   \brief Deletes feature at the given offset (level 1)
   
   \param Map pointer Map_info structure
@@ -161,68 +255,77 @@
 }
 
 /*!
-  \brief Deletes feature (topology level).
+  \brief Deletes feature (topology level) -- internal use only
   
-  \param Map pointer to Map_info structure
+  \param 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)
+int V2_delete_line_ogr(struct Map_info *Map, off_t line)
 {
-    return V2__delete_line(Map, line, V1_delete_line_ogr);
-}
+    int ret, i, side, type, first, next_line, area;
+    struct P_line *Line;
+    struct P_area *Area;
+    struct Plus_head *plus;
+    struct bound_box box, abox;
+    int adjacent[4], n_adjacent;
+    static struct line_cats *Cats = NULL;
 
-/*!
-  \brief Rewrites feature at the given offset (level 1)
-  
-  \param Map pointer to Map_info structure
-  \param offset feature offset
-  \param type feature type
-  \param points feature geometry
-  \param cats feature categories
-  
-  \return feature offset (rewriten feature)
-  \return -1 on error
-*/
-off_t V1_rewrite_line_ogr(struct Map_info *Map,
-			  off_t offset,
-			  int type,
-			  const struct line_pnts *points, const struct line_cats *cats)
-{
-    if (type != V1_read_line_ogr(Map, NULL, NULL, offset)) {
-	G_warning(_("Unable to rewrite feature (incompatible feature types)"));
-	return -1;
+    G_debug(3, "V2_delete_line_nat(), line = %d", (int) line);
+
+    type = first = n_adjacent = 0;
+    Line = NULL;
+    plus = &(Map->plus);
+
+    if (plus->built >= GV_BUILD_BASE) {
+	Line = Map->plus.Line[line];
+
+	if (Line == NULL)
+	    G_fatal_error(_("Attempt to delete dead feature"));
+	type = Line->type;
     }
 
-    /* delete old */
-    V1_delete_line_ogr(Map, offset);
+    if (!Cats) {
+	Cats = Vect_new_cats_struct();
+    }
 
-    return V1_write_line_ogr(Map, type, points, cats);
-}
+    /* Update category index */
+    if (plus->update_cidx) {
+	type = V2_read_line_ogr(Map, NULL, Cats, line);
 
-/*!
-  \brief Rewrites feature (topology level)
-  
-  \param Map pointer to Map_info structure
-  \param line feature id
-  \param type feature type
-  \param points feature geometry
-  \param cats feature categories
-  
-  \return feature offset (rewriten feature)
-  \return -1 on error
-*/
-int V2_rewrite_line_ogr(struct Map_info *Map,
-			int line,
-			int type,
-			const struct line_pnts *points, const struct line_cats *cats)
-{
-    /* delete old */
-    V2_delete_line_ogr(Map, line);
+	for (i = 0; i < Cats->n_cats; i++) {
+	    dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
+	}
+    }
+    /* Update fidx */
 
-    return V2_write_line_ogr(Map, type, points, cats);
+    /* delete the line from coor */
+    ret = V1_delete_line_ogr(Map, Line->offset);
+
+    if (ret == -1) {
+	return ret;
+    }
+
+    /* Update topology */
+    if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
+	/* TODO */
+	/* remove centroid together with boundary (is really an OGR polygon) */
+    }
+    /* Delete reference from area */
+    if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
+	/* for OGR mapsets, virtual centroid will be removed when polygon is removed */
+    }
+
+    /* delete the line from topo */
+    dig_del_line(plus, line);
+
+    /* Rebuild areas/isles and attach centroids and isles */
+    if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
+	/* maybe not needed VERIFY */
+    }
+    return ret;
 }
 
 int write_attributes(int cat, const struct field_info *Fi,



More information about the grass-commit mailing list