|
@@ -30,9 +30,280 @@
|
|
|
#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)
|
|
|
|
|
@@ -56,11 +327,11 @@ off_t V1_write_line_nat(struct Map_info *Map,
|
|
|
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 @@ off_t V1_write_line_nat(struct Map_info *Map,
|
|
|
\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 @@ off_t V2_write_line_nat(struct Map_info *Map,
|
|
|
\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 @@ off_t V1_rewrite_line_nat(struct Map_info *Map,
|
|
|
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 @@ off_t V1_rewrite_line_nat(struct Map_info *Map,
|
|
|
|| ((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 @@ off_t V1_rewrite_line_nat(struct Map_info *Map,
|
|
|
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 line feature id
|
|
|
\param type feature type
|
|
|
+ \param line feature id
|
|
|
\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 @@ int V2_rewrite_line_nat(struct Map_info *Map,
|
|
|
* 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;
|
|
|
+
|
|
|
+ /* 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);
|
|
|
|
|
|
- return (V2_write_line_nat(Map, type, points, cats));
|
|
|
+ /* 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 @@ int V2_rewrite_line_nat(struct Map_info *Map,
|
|
|
\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 @@ int V1_delete_line_nat(struct Map_info *Map, off_t offset)
|
|
|
}
|
|
|
|
|
|
/*!
|
|
|
- \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 @@ int V1_delete_line_nat(struct Map_info *Map, off_t offset)
|
|
|
\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 @@ int V2_restore_line_nat(struct Map_info *Map, int line, off_t offset)
|
|
|
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;
|
|
|
}
|