瀏覽代碼

vlib(pg): add_line_to_topo_pg() and delete_line_from_topo_pg() added
various minor improvements in PostGIS Topology support
(work in progress)


git-svn-id: https://svn.osgeo.org/grass/grass/trunk@55706 15284696-431f-4ddb-bdfa-cd5b030d7da7

Martin Landa 12 年之前
父節點
當前提交
6161703763
共有 5 個文件被更改,包括 208 次插入105 次删除
  1. 11 16
      lib/vector/Vlib/break_polygons.c
  2. 7 3
      lib/vector/Vlib/level_two.c
  3. 8 3
      lib/vector/Vlib/read_pg.c
  4. 171 79
      lib/vector/Vlib/write_pg.c
  5. 11 4
      lib/vector/diglib/plus_line.c

+ 11 - 16
lib/vector/Vlib/break_polygons.c

@@ -7,10 +7,8 @@
 
 
    (C) 2001-2009 by the GRASS Development Team
    (C) 2001-2009 by the GRASS Development Team
 
 
-   This program is free software under the 
-   GNU General Public License (>=v2). 
-   Read the file COPYING that comes with GRASS
-   for details.
+   This program is free software under the GNU General Public License
+   (>=v2).  Read the file COPYING that comes with GRASS for details.
 
 
    \author Radim Blazek
    \author Radim Blazek
    \author Update for GRASS 7 Markus Metz
    \author Update for GRASS 7 Markus Metz
@@ -651,27 +649,24 @@ void Vect_break_polygons_mem(struct Map_info *Map, int type, struct Map_info *Er
 }
 }
 
 
 /*!
 /*!
-   \brief Break polygons in vector map.
+   \brief Break polygons in vector map
 
 
    Breaks lines specified by type in vector map. Points at
    Breaks lines specified by type in vector map. Points at
-   intersections may be optionally written to error map. Input map
-   must be opened on level 2 for update at least on GV_BUILD_BASE.
+   intersections may be optionally written to error map. Input vector
+   map must be opened on level 2 for update at least on GV_BUILD_BASE.
 
 
-   Function is optimized for closed polygons rigs (e.g. imported from
+   Function is optimized for closed polygons rings (e.g. imported from
    OGR) but with clean geometry - adjacent polygons mostly have
    OGR) but with clean geometry - adjacent polygons mostly have
    identical boundary. Function creates database of ALL points in the
    identical boundary. Function creates database of ALL points in the
-   map, and then is looking for those where polygons should be broken.
-   Lines may be broken only at points existing in input map!
+   vector map, and then is looking for those where polygons should be
+   broken.  Lines may be broken only at points existing in input
+   vector map!
 
 
    \param Map input map where polygons will be broken
    \param Map input map where polygons will be broken
-   \param type type of line to be broken
+   \param type type of line to be broken (GV_LINE or GV_BOUNDARY)
    \param Err vector map where points at intersections will be written or NULL
    \param Err vector map where points at intersections will be written or NULL
-
-   \return
  */
  */
-
-void
-Vect_break_polygons(struct Map_info *Map, int type, struct Map_info *Err)
+void Vect_break_polygons(struct Map_info *Map, int type, struct Map_info *Err)
 {
 {
     if (getenv("GRASS_VECTOR_LOWMEM"))
     if (getenv("GRASS_VECTOR_LOWMEM"))
 	return Vect_break_polygons_file(Map, type, Err);
 	return Vect_break_polygons_file(Map, type, Err);

+ 7 - 3
lib/vector/Vlib/level_two.c

@@ -226,17 +226,21 @@ int Vect_get_num_updated_nodes(const struct Map_info *Map)
 }
 }
 
 
 /*!
 /*!
-   \brief Get updated node by index
+   \brief Get updated (modified) node by index
 
 
    Note: Vect_set_updated() must be called to maintain list of updated
    Note: Vect_set_updated() must be called to maintain list of updated
    features
    features
 
 
-   Negative id indicates deleted node.
+   Negative id:
+    - if Node[id] is not NULL then the node was added
+    - if Node[id] is NULL then the node was deleted
+   Positive id:
+    - node was updated
 
 
    \param Map pointer to Map_info struct
    \param Map pointer to Map_info struct
    \param idx index
    \param idx index
 
 
-   \return updated node
+   \return id of modified node
  */
  */
 int Vect_get_updated_node(const struct Map_info *Map, int idx)
 int Vect_get_updated_node(const struct Map_info *Map, int idx)
 {
 {

+ 8 - 3
lib/vector/Vlib/read_pg.c

@@ -8,7 +8,12 @@
    \todo Currently only points, linestrings and polygons are supported,
    \todo Currently only points, linestrings and polygons are supported,
    implement also other types
    implement also other types
 
 
-   (C) 2011-2012 by the GRASS Development Team
+   \todo Support multigeometries
+
+   \todo PostGIS Topology - fix category handling (read categories
+   from feature table)
+
+   (C) 2011-2013 by the GRASS Development Team
 
 
    This program is free software under the GNU General Public License
    This program is free software under the GNU General Public License
    (>=v2). Read the file COPYING that comes with GRASS for details.
    (>=v2). Read the file COPYING that comes with GRASS for details.
@@ -324,7 +329,7 @@ int V2_read_line_pg(struct Map_info *Map, struct line_pnts *line_p,
         return 0;
         return 0;
     }
     }
     
     
-    G_debug(4, "V2_read_line_pg() line = %d type = %d offset = %lu",
+    G_debug(4, "V2_read_line_pg() line = %d type = %d offset = %"PRI_OFF_T,
             line, Line->type, Line->offset);
             line, Line->type, Line->offset);
     
     
     if (!line_p && !line_c)
     if (!line_p && !line_c)
@@ -335,7 +340,7 @@ int V2_read_line_pg(struct Map_info *Map, struct line_pnts *line_p,
     if (line_c != NULL)
     if (line_c != NULL)
         Vect_reset_cats(line_c);
         Vect_reset_cats(line_c);
 
 
-    if (line_c)
+    if (line_c) 
         Vect_cat_set(line_c, 1, (int) Line->offset);
         Vect_cat_set(line_c, 1, (int) Line->offset);
     
     
     if (Line->type == GV_CENTROID && !pg_info->toposchema_name) {
     if (Line->type == GV_CENTROID && !pg_info->toposchema_name) {

+ 171 - 79
lib/vector/Vlib/write_pg.c

@@ -7,11 +7,9 @@
 
 
    Write subroutine inspired by OGR PostgreSQL driver.
    Write subroutine inspired by OGR PostgreSQL driver.
 
 
-   \todo PostGIS version of V2__add_line_to_topo_nat()
-   \todo OGR version of V2__delete_area_cats_from_cidx_nat()
+   \todo PostGIS version of V2__delete_area_cats_from_cidx_nat()
    \todo function to delete corresponding entry in fidx
    \todo function to delete corresponding entry in fidx
-   \todo OGR version of V2__add_area_cats_to_cidx_nat
-   \todo OGR version of V2__add_line_to_topo_nat
+   \todo PostGIS version of V2__add_area_cats_to_cidx_nat
 
 
    (C) 2012-2013 by Martin Landa, and the GRASS Development Team
    (C) 2012-2013 by Martin Landa, and the GRASS Development Team
 
 
@@ -68,6 +66,8 @@ static int update_next_edge(struct Map_info*, int, int);
 static int delete_face(const struct Map_info *, int);
 static int delete_face(const struct Map_info *, int);
 static int update_topo_edge(struct Map_info *, int);
 static int update_topo_edge(struct Map_info *, int);
 static int update_topo_face(struct Map_info *, int);
 static int update_topo_face(struct Map_info *, int);
+static int add_line_to_topo_pg(struct Map_info *, off_t, int, const struct line_pnts *);
+static int delete_line_from_topo_pg(struct Map_info *, int, int, const struct line_pnts *);
 #endif
 #endif
 
 
 static struct line_pnts *Points;
 static struct line_pnts *Points;
@@ -214,7 +214,7 @@ off_t V1_rewrite_line_pg(struct Map_info * Map,
   \return -1 on error
   \return -1 on error
 */
 */
 off_t V2_rewrite_line_pg(struct Map_info *Map, int line, int type, off_t old_offset,
 off_t V2_rewrite_line_pg(struct Map_info *Map, int line, int type, off_t old_offset,
-			  const struct line_pnts *points, const struct line_cats *cats)
+                         const struct line_pnts *points, const struct line_cats *cats)
 {
 {
     G_debug(3, "V2_rewrite_line_pg(): line=%d type=%d offset=%"PRI_OFF_T,
     G_debug(3, "V2_rewrite_line_pg(): line=%d type=%d offset=%"PRI_OFF_T,
             line, type, old_offset);
             line, type, old_offset);
@@ -249,7 +249,7 @@ off_t V2_rewrite_line_pg(struct Map_info *Map, int line, int type, off_t old_off
     }
     }
 
 
     /* remove line from topology */
     /* remove line from topology */
-    if (0 != V2__delete_line_from_topo_nat(Map, line, type, Points, NULL))
+    if (0 != delete_line_from_topo_pg(Map, line, type, Points))
         return -1;
         return -1;
 
 
     if (pg_info->toposchema_name) { /* PostGIS Topology */
     if (pg_info->toposchema_name) { /* PostGIS Topology */
@@ -281,7 +281,7 @@ off_t V2_rewrite_line_pg(struct Map_info *Map, int line, int type, off_t old_off
 
 
     /* update topology
     /* update topology
        note: offset is not changed */
        note: offset is not changed */
-    return V2__add_line_to_topo_nat(Map, old_offset, type, points, cats, -1, NULL);
+    return add_line_to_topo_pg(Map, old_offset, type, points);
 #else
 #else
     G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
     G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
     return -1;
     return -1;
@@ -377,7 +377,7 @@ int V2_delete_line_pg(struct Map_info *Map, int line)
         return V2_delete_line_sfa(Map, line);
         return V2_delete_line_sfa(Map, line);
     }
     }
     else {                          /* PostGIS topology */
     else {                          /* PostGIS topology */
-        int type, n_nodes;
+        int type;
         char stmt[DB_SQL_MAX];
         char stmt[DB_SQL_MAX];
         const char *table_name, *keycolumn;
         const char *table_name, *keycolumn;
         
         
@@ -441,34 +441,7 @@ int V2_delete_line_pg(struct Map_info *Map, int line)
         }
         }
         
         
         /* update topology */
         /* update topology */
-        Vect_reset_updated(Map);
-        if (0 != V2__delete_line_from_topo_nat(Map, line, type, Points, NULL))
-            return -1;
-     
-        /* delete nodes from 'nodes' table */
-        n_nodes = Vect_get_num_updated_nodes(Map);
-        if (n_nodes > 0) {
-            int i, node;
-            
-            for (i = 0; i < n_nodes; i++) {
-                node = Vect_get_updated_node(Map, i);
-                if (node > 0)
-                    continue; /* node was updated, not deleted */
-                
-                node = abs(node);
-                G_debug(3, "delete node %d from 'node' table", node);
-                
-                sprintf(stmt, "DELETE FROM \"%s\".\"node\" WHERE node_id = %d",
-                        pg_info->toposchema_name, node);
-                if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
-                    G_warning(_("Unable to delete node %d"), node);
-                    Vect__execute_pg(pg_info->conn, "ROLLBACK");
-                    return -1;
-                }
-            }
-        }
-        
-        return 0;
+        return delete_line_from_topo_pg(Map, line, type, Points);
     }
     }
 #else
 #else
     G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
     G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
@@ -1234,7 +1207,6 @@ off_t write_line_tp(struct Map_info *Map, int type, int is_node,
         dig_add_node(plus, points->x[0], points->y[0], points->z[0]);
         dig_add_node(plus, points->x[0], points->y[0], points->z[0]);
     }
     }
     else {
     else {
-        int n_nodes;
         off_t offset;
         off_t offset;
         
         
         /* better is probably to check nextval directly */
         /* better is probably to check nextval directly */
@@ -1246,31 +1218,7 @@ off_t write_line_tp(struct Map_info *Map, int type, int is_node,
             offset = Vect_get_num_primitives(Map, GV_LINES) + 1; /* next */
             offset = Vect_get_num_primitives(Map, GV_LINES) + 1; /* next */
         }
         }
         
         
-        Vect_reset_updated(Map);
-        line = V2__add_line_to_topo_nat(Map, offset, type, points, NULL, /* TODO: handle categories */
-                                        -1, NULL);
-        
-        /* insert new nodes into 'nodes' table */
-        n_nodes = Vect_get_num_updated_nodes(Map);
-        if (n_nodes > 0) {
-            int i, node;
-            double x, y, z;
-            
-            if (!Points)
-                Points = Vect_new_line_struct();
-            
-            for (i = 0; i < n_nodes; i++) {
-                node = Vect_get_updated_node(Map, i);
-                G_debug(3, "  new node: %d", node);
-
-                Vect_get_node_coor(Map, node, &x, &y, &z);
-                Vect_reset_line(Points);
-                Vect_append_point(Points, x, y, z);
-                
-                write_feature(Map, -1, GV_POINT, (const struct line_pnts **) &Points, 1,
-                              -1, NULL);
-            }
-        }
+        line = add_line_to_topo_pg(Map, offset, type, points);
     }
     }
     
     
     /* write new feature to PostGIS
     /* write new feature to PostGIS
@@ -1922,25 +1870,53 @@ char *build_insert_stmt(const struct Format_info_pg *pg_info,
 /*!
 /*!
   \brief Insert topological element into 'node' or 'edge' table
   \brief Insert topological element into 'node' or 'edge' table
 
 
+  Negative id for nodes.
+  
   \param Map pointer to Map_info struct
   \param Map pointer to Map_info struct
-  \param line feature id (-1 for nodes/points)
+  \param id feature id (-1 for nodes/points)
   \param type feature type (GV_POINT, GV_LINE, ...)
   \param type feature type (GV_POINT, GV_LINE, ...)
   \param geom_data geometry in wkb
   \param geom_data geometry in wkb
 
 
   \return 0 on success
   \return 0 on success
   \return -1 on error
   \return -1 on error
 */
 */
-int insert_topo_element(struct Map_info *Map, int line, int type,
+int insert_topo_element(struct Map_info *Map, int id, int type,
                         const char *geom_data)
                         const char *geom_data)
 {
 {
+    int ret;
     char *stmt;
     char *stmt;
     struct Format_info_pg *pg_info;
     struct Format_info_pg *pg_info;
     struct P_line *Line;
     struct P_line *Line;
-    
+    struct P_node *Node;
+
     pg_info = &(Map->fInfo.pg);
     pg_info = &(Map->fInfo.pg);
-    
-    if (line > 0)
+
+    Line = NULL;
+    Node = NULL;
+    if (id > 0) {
+        int line;
+
+        line = id;
+        if (line > Map->plus.n_lines) {
+            G_warning(_("Invalid line %d (%d)"), line, Map->plus.n_lines);
+            return -1;
+        }
         Line = Map->plus.Line[line];
         Line = Map->plus.Line[line];
+    }
+    else {
+        int node;
+        
+        node = abs(id);
+        if (type != GV_POINT) {
+            G_warning(_("Invalid feature type (%d) for node"), type);
+            return -1;
+        }
+        if (node > Map->plus.n_nodes) {
+            G_warning(_("Invalid node %d (%d)"), node, Map->plus.n_nodes);
+            return -1;
+        }
+        Node = Map->plus.Node[node];
+    }
 
 
     stmt = NULL;
     stmt = NULL;
     switch(type) {
     switch(type) {
@@ -1949,8 +1925,8 @@ int insert_topo_element(struct Map_info *Map, int line, int type,
         G_asprintf(&stmt, "SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
         G_asprintf(&stmt, "SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
                    pg_info->toposchema_name, geom_data);
                    pg_info->toposchema_name, geom_data);
 #else
 #else
-        G_asprintf(&stmt, "INSERT INTO \"%s\".node (geom) VALUES ('%s'::GEOMETRY)",
-                   pg_info->toposchema_name, geom_data);
+        G_asprintf(&stmt, "INSERT INTO \"%s\".node (node_id, geom) VALUES (%d, '%s'::GEOMETRY)",
+                   pg_info->toposchema_name, abs(id), geom_data);
 #endif
 #endif
         break;
         break;
     }
     }
@@ -1976,12 +1952,12 @@ int insert_topo_element(struct Map_info *Map, int line, int type,
         G_debug(3, "new edge: id=%d next_left_edge=%d next_right_edge=%d",
         G_debug(3, "new edge: id=%d next_left_edge=%d next_right_edge=%d",
                 (int)Line->offset, nle, nre);
                 (int)Line->offset, nle, nre);
         
         
-        G_asprintf(&stmt, "INSERT INTO \"%s\".edge_data (geom, start_node, end_node, "
+        G_asprintf(&stmt, "INSERT INTO \"%s\".edge_data (edge_id, start_node, end_node, "
                    "next_left_edge, abs_next_left_edge, next_right_edge, abs_next_right_edge, "
                    "next_left_edge, abs_next_left_edge, next_right_edge, abs_next_right_edge, "
-                   "left_face, right_face) "
-                   "VALUES ('%s'::GEOMETRY, %d, %d, %d, %d, %d, %d, 0, 0)",
-                   pg_info->toposchema_name, geom_data, topo->N1, topo->N2, nle, abs(nle),
-                   nre, abs(nre));
+                   "left_face, right_face, geom) "
+                   "VALUES (%d, %d, %d, %d, %d, %d, %d, 0, 0, '%s'::GEOMETRY)",
+                   pg_info->toposchema_name, (int) Line->offset, topo->N1, topo->N2,
+                   nle, abs(nle), nre, abs(nre), geom_data);
 #endif
 #endif
         break;
         break;
     }
     }
@@ -2007,9 +1983,9 @@ int insert_topo_element(struct Map_info *Map, int line, int type,
             return NULL;
             return NULL;
         }
         }
         */
         */
-        G_asprintf(&stmt, "INSERT INTO \"%s\".node (containing_face, geom) "
-                   "VALUES (%d, '%s'::GEOMETRY)",
-                   pg_info->toposchema_name, topo->area, geom_data);
+        G_asprintf(&stmt, "INSERT INTO \"%s\".node (node_id, containing_face, geom) "
+                   "VALUES (%d, %d, '%s'::GEOMETRY)",
+                   pg_info->toposchema_name, (int)Line->offset, topo->area, geom_data);
 #endif
 #endif
         break;
         break;
     }
     }
@@ -2018,7 +1994,10 @@ int insert_topo_element(struct Map_info *Map, int line, int type,
         break;
         break;
     }
     }
     
     
-    if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
+    ret = Vect__execute_pg(pg_info->conn, stmt);
+    G_free(stmt);
+    
+    if (ret == -1) {
         /* rollback transaction */
         /* rollback transaction */
         Vect__execute_pg(pg_info->conn, "ROLLBACK");
         Vect__execute_pg(pg_info->conn, "ROLLBACK");
         return -1;
         return -1;
@@ -2174,7 +2153,7 @@ int Vect__insert_face_pg(struct Map_info *Map, int area)
 }
 }
 
 
 /*!
 /*!
-  \brief Delete existing face
+  \brief Delete existing face (currently unused)
 
 
   \todo Set foreign keys as DEFERRABLE INITIALLY DEFERRED and use SET
   \todo Set foreign keys as DEFERRABLE INITIALLY DEFERRED and use SET
   CONSTRAINTS ALL DEFERRED
   CONSTRAINTS ALL DEFERRED
@@ -2429,4 +2408,117 @@ int update_topo_face(struct Map_info *Map, int line)
     
     
     return 0;
     return 0;
 }
 }
+
+/*!
+  \brief Add line to native and PostGIS topology
+
+  \param Map vector map
+  \param line feature id to remove from topo
+  \param type feature type
+  \param Points feature vertices
+
+  \return feature id
+  \return -1 on error
+*/
+int add_line_to_topo_pg(struct Map_info *Map, off_t offset, int type,
+                          const struct line_pnts *points)
+{
+    int line, n_nodes;
+    
+    struct Plus_head *plus;
+
+    plus    = &(Map->plus);
+
+    Vect_reset_updated(Map);
+    line = V2__add_line_to_topo_nat(Map, offset, type, points, NULL, 
+                                    -1, NULL);
+    
+    /* insert new nodes into 'node' table */
+    n_nodes = Vect_get_num_updated_nodes(Map);
+    if (n_nodes > 0) {
+        int i, node;
+        double x, y, z;
+        
+        if (!Points)
+            Points = Vect_new_line_struct();
+        
+        for (i = 0; i < n_nodes; i++) {
+            node = Vect_get_updated_node(Map, i);
+            /* skip updated and deleted nodes */
+            if (node > 0 || plus->Node[abs(node)] == NULL)
+                continue;
+            
+            G_debug(3, "  new node: %d", node);
+            
+            Vect_get_node_coor(Map, abs(node), &x, &y, &z);
+            Vect_reset_line(Points);
+            Vect_append_point(Points, x, y, z);
+            
+            write_feature(Map, node, GV_POINT, (const struct line_pnts **) &Points, 1,
+                          -1, NULL);
+        }
+    }
+
+    return line;
+}
+
+/*!
+  \brief Delete line from native and PostGIS topology
+
+  \todo Implement deleting nodes on request
+  
+  \param Map vector map
+  \param line feature id to remove from topo
+  \param type feature type
+  \param Points feature vertices
+
+  \return 0 on success
+  \return -1 on error
+*/
+int delete_line_from_topo_pg(struct Map_info *Map, int line, int type,
+                             const struct line_pnts *Points)
+{
+    int n_nodes;
+    char stmt[DB_SQL_MAX];
+    
+    struct Format_info_pg *pg_info;
+    struct Plus_head *plus;
+
+    pg_info = &(Map->fInfo.pg);
+    plus    = &(Map->plus);
+    
+    Vect_reset_updated(Map);
+    if (0 != V2__delete_line_from_topo_nat(Map, line, type, Points, NULL))
+        return -1;
+    
+    /* disabled: remove isolated nodes when closing the map
+       note: node id cannot be used as node_id
+       
+       delete nodes from 'node' table
+    n_nodes = Vect_get_num_updated_nodes(Map);
+    if (n_nodes > 0) {
+        int i, node;
+        
+        for (i = 0; i < n_nodes; i++) {
+            node = Vect_get_updated_node(Map, i);
+            if (node > 0 || plus->Node[abs(node)] != NULL)
+                continue; 
+            
+            node = abs(node);
+            G_debug(3, "delete node %d from 'node' table", node);
+            
+            sprintf(stmt, "DELETE FROM \"%s\".\"node\" WHERE node_id = %d",
+                    pg_info->toposchema_name, node);
+            if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+                G_warning(_("Unable to delete node %d"), node);
+                Vect__execute_pg(pg_info->conn, "ROLLBACK");
+                return -1;
+            }
+        }
+    }
+    */
+
+    return 0;
+}
+
 #endif
 #endif

+ 11 - 4
lib/vector/diglib/plus_line.c

@@ -21,7 +21,7 @@
 static int add_line(struct Plus_head *plus, int lineid, int type, const struct line_pnts *Points,
 static int add_line(struct Plus_head *plus, int lineid, int type, const struct line_pnts *Points,
 		    const struct bound_box *box, off_t offset)
 		    const struct bound_box *box, off_t offset)
 {
 {
-    int node, lp;
+    int node, lp, node_new;
     struct P_line *line;
     struct P_line *line;
 
 
     plus->Line[lineid] = dig_alloc_line();
     plus->Line[lineid] = dig_alloc_line();
@@ -54,15 +54,19 @@ static int add_line(struct Plus_head *plus, int lineid, int type, const struct l
     G_debug(3, "Register node: type = %d,  %f,%f", type, Points->x[0],
     G_debug(3, "Register node: type = %d,  %f,%f", type, Points->x[0],
 	    Points->y[0]);
 	    Points->y[0]);
 
 
+    /* Start node */
     node = dig_find_node(plus, Points->x[0], Points->y[0], Points->z[0]);
     node = dig_find_node(plus, Points->x[0], Points->y[0], Points->z[0]);
     G_debug(3, "node = %d", node);
     G_debug(3, "node = %d", node);
     if (node == 0) {
     if (node == 0) {
 	node = dig_add_node(plus, Points->x[0], Points->y[0], Points->z[0]);
 	node = dig_add_node(plus, Points->x[0], Points->y[0], Points->z[0]);
 	G_debug(3, "Add new node: %d", node);
 	G_debug(3, "Add new node: %d", node);
+        node_new = TRUE;
     }
     }
     else {
     else {
-	G_debug(3, "Old node found: %d", node);
+        G_debug(3, "Old node found: %d", node);
+        node_new = FALSE;
     }
     }
+    
     if (type == GV_LINE) {
     if (type == GV_LINE) {
 	struct P_topo_l *topo = (struct P_topo_l *)line->topo;
 	struct P_topo_l *topo = (struct P_topo_l *)line->topo;
 
 
@@ -80,8 +84,9 @@ static int add_line(struct Plus_head *plus, int lineid, int type, const struct l
 
 
     dig_node_add_line(plus, node, lineid, Points, type);
     dig_node_add_line(plus, node, lineid, Points, type);
     if (plus->uplist.do_uplist)
     if (plus->uplist.do_uplist)
-	dig_node_add_updated(plus, node);
+	dig_node_add_updated(plus, node_new ? -node : node);
 
 
+    /* End node */
     lp = Points->n_points - 1;
     lp = Points->n_points - 1;
     G_debug(3, "Register node %f,%f", Points->x[lp], Points->y[lp]);
     G_debug(3, "Register node %f,%f", Points->x[lp], Points->y[lp]);
     node = dig_find_node(plus, Points->x[lp], Points->y[lp],
     node = dig_find_node(plus, Points->x[lp], Points->y[lp],
@@ -91,9 +96,11 @@ static int add_line(struct Plus_head *plus, int lineid, int type, const struct l
 	node = dig_add_node(plus, Points->x[lp], Points->y[lp],
 	node = dig_add_node(plus, Points->x[lp], Points->y[lp],
 			    Points->z[lp]);
 			    Points->z[lp]);
 	G_debug(3, "Add new node: %d", node);
 	G_debug(3, "Add new node: %d", node);
+        node_new = TRUE;
     }
     }
     else {
     else {
 	G_debug(3, "Old node found: %d", node);
 	G_debug(3, "Old node found: %d", node);
+        node_new = FALSE;
     }
     }
     if (type == GV_LINE) {
     if (type == GV_LINE) {
 	struct P_topo_l *topo = (struct P_topo_l *)line->topo;
 	struct P_topo_l *topo = (struct P_topo_l *)line->topo;
@@ -108,7 +115,7 @@ static int add_line(struct Plus_head *plus, int lineid, int type, const struct l
 
 
     dig_node_add_line(plus, node, -lineid, Points, type);
     dig_node_add_line(plus, node, -lineid, Points, type);
     if (plus->uplist.do_uplist)
     if (plus->uplist.do_uplist)
-	dig_node_add_updated(plus, node);
+	dig_node_add_updated(plus, node_new ? -node : node);
 
 
     return (lineid);
     return (lineid);
 }
 }