[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