瀏覽代碼

vlib/PostGIS Topo: implement deleting faces (work in progress)

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@54085 15284696-431f-4ddb-bdfa-cd5b030d7da7
Martin Landa 12 年之前
父節點
當前提交
491eed2fdf
共有 4 個文件被更改,包括 107 次插入29 次删除
  1. 3 5
      lib/vector/Vlib/build_nat.c
  2. 2 1
      lib/vector/Vlib/local_proto.h
  3. 10 6
      lib/vector/Vlib/write_nat.c
  4. 92 17
      lib/vector/Vlib/write_pg.c

+ 3 - 5
lib/vector/Vlib/build_nat.c

@@ -3,12 +3,10 @@
 
    \brief Vector library - Building topology for native format
 
-   (C) 2001-2009, 2011 by the GRASS Development Team
+   (C) 2001-2012 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 Original author CERL, probably Dave Gerdes or Mike Higgins.
    \author Update to GRASS 5.7 Radim Blazek and David D. Gray.

+ 2 - 1
lib/vector/Vlib/local_proto.h

@@ -4,6 +4,7 @@
 #include <grass/vector.h>
 
 void V2__add_line_to_topo_nat(struct Map_info *, int ,
-                              const struct line_pnts *, const struct line_cats *);
+                              const struct line_pnts *, const struct line_cats *,
+                              int (*external_routine) (const struct Map_info *, int));
 
 #endif /* PG_LOCAL_PROTO_H__ */

+ 10 - 6
lib/vector/Vlib/write_nat.c

@@ -5,7 +5,7 @@
 
    Higher level functions for reading/writing/manipulating vectors.
 
-   (C) 2001-2010, 2012 by the GRASS Development Team
+   (C) 2001-2012 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.
@@ -136,7 +136,8 @@ static void V2__add_area_cats_to_cidx_nat(struct Map_info *Map, int area)
     \param cats pointer to line_cats structure (feature's categories)
 */
 void V2__add_line_to_topo_nat(struct Map_info *Map, int line,
-                              const struct line_pnts *points, const struct line_cats *cats)
+                              const struct line_pnts *points, const struct line_cats *cats,
+                              int (*external_routine) (const struct Map_info *, int))
 {
     int first, s, n, i;
     int type, node, next_line, area, side, sel_area, new_area[2];
@@ -212,9 +213,13 @@ void V2__add_line_to_topo_nat(struct Map_info *Map, int line,
 			    V2__delete_area_cats_from_cidx_nat(Map, area);
 			}
 			dig_del_area(plus, area);
+                        if (external_routine) /* call external subroutine if defined */
+                            external_routine(Map, area);
 		    }
 		    else if (area < 0) {	/* is isle */
 			dig_del_isle(plus, -area);
+                        if (external_routine)  /* call external subroutine if defined */
+                            external_routine(Map, area);
 		    }
 		}
 	    }
@@ -374,7 +379,7 @@ off_t V2_write_line_nat(struct Map_info *Map, int type,
 	    Vect_box_extend(&(plus->box), &box);
     }
 
-    V2__add_line_to_topo_nat(Map, line, points, cats);
+    V2__add_line_to_topo_nat(Map, line, points, cats, NULL);
 
     G_debug(3, "updated lines : %d , updated nodes : %d", plus->uplist.n_uplines,
 	    plus->uplist.n_upnodes);
@@ -496,7 +501,7 @@ off_t V2_rewrite_line_nat(struct Map_info *Map, int line, int type, off_t old_of
 	    Vect_box_extend(&(plus->box), &box);
     }
 
-    V2__add_line_to_topo_nat(Map, line, points, cats);
+    V2__add_line_to_topo_nat(Map, line, points, cats, NULL);
 
     G_debug(3, "updated lines : %d , updated nodes : %d", plus->uplist.n_uplines,
 	    plus->uplist.n_upnodes);
@@ -966,8 +971,7 @@ int V2_restore_line_nat(struct Map_info *Map, int line, off_t offset)
 	Vect_box_extend(&(plus->box), &box);
     }
     
-    V2__add_line_to_topo_nat(Map,
-		     line, points, cats);
+    V2__add_line_to_topo_nat(Map, line, points, cats, NULL);
 
     G_debug(3, "updated lines : %d , updated nodes : %d", plus->uplist.n_uplines,
 	    plus->uplist.n_upnodes);

+ 92 - 17
lib/vector/Vlib/write_pg.c

@@ -58,6 +58,7 @@ static char *build_insert_stmt(const struct Format_info_pg *, const char *,
 static int insert_topo_element(struct Map_info *, int, int, const char *);
 static int update_next_edge(struct Map_info*, int, int);
 static int insert_face(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_face(struct Map_info *, int);
 #endif
@@ -970,7 +971,8 @@ int write_feature(struct Map_info *Map, int line, int type,
         
         /* update GRASS-like topo */
         if (line > 0) /* skip nodes */
-            V2__add_line_to_topo_nat(Map, line, points[0], NULL); /* TODO: cats */
+            V2__add_line_to_topo_nat(Map, line, points[0], NULL, /* TODO: cats */
+                                     delete_face);
         
         /* update PostGIS-line topo */
         if (type & GV_LINES)
@@ -1394,6 +1396,67 @@ int insert_face(struct Map_info *Map, int area)
     return area;
 }
 
+/*!
+  \brief Delete existing face
+
+  \todo Set foreign keys as DEFERRABLE INITIALLY DEFERRED and use SET
+  CONSTRAINTS ALL DEFERRED
+  
+  \param Map pointer to Map_info struct
+  \param area area id to delete
+
+  \return 0 on success
+  \return -1 on error
+*/
+int delete_face(const struct Map_info *Map, int area)
+{
+    char stmt[DB_SQL_MAX];
+
+    const struct Format_info_pg *pg_info;
+
+    pg_info = &(Map->fInfo.pg);
+    
+    /* update centroids first */
+    sprintf(stmt, "UPDATE \"%s\".node SET containing_face = 0 "
+            "WHERE containing_face = %d",
+            pg_info->toposchema_name, area);
+    G_debug(3, "SQL: %s", stmt);
+    if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+        Vect__execute_pg(pg_info->conn, "ROLLBACK");
+        return -1;
+    }
+
+    /* update also edges (left face) */
+    sprintf(stmt, "UPDATE \"%s\".edge_data SET left_face = 0 "
+            "WHERE left_face = %d",
+            pg_info->toposchema_name, area);
+    G_debug(3, "SQL: %s", stmt);
+    if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+        Vect__execute_pg(pg_info->conn, "ROLLBACK");
+        return -1;
+    }
+
+    /* update also edges (left face) */
+    sprintf(stmt, "UPDATE \"%s\".edge_data SET right_face = 0 "
+            "WHERE right_face = %d",
+            pg_info->toposchema_name, area);
+    G_debug(3, "SQL: %s", stmt);
+    if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+        Vect__execute_pg(pg_info->conn, "ROLLBACK");
+        return -1;
+    }
+
+    /* delete face */
+    sprintf(stmt, "DELETE FROM \"%s\".face WHERE face_id = %d",
+            pg_info->toposchema_name, area);
+    G_debug(3, "delete face id=%d", area);
+    if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+        Vect__execute_pg(pg_info->conn, "ROLLBACK");
+        return -1;
+    }
+
+    return 0;
+}
 
 /*!
   \brief Update lines (next left and right edges)
@@ -1511,13 +1574,13 @@ int update_topo_edge(struct Map_info *Map, int line)
 */  
 int update_topo_face(struct Map_info *Map, int line)
 {
-    int i, s, area, face;
+    int i, s, area, face[2];
     char stmt[DB_SQL_MAX];
     
     struct Format_info_pg *pg_info;
-    struct P_line *Line;
+    struct P_line *Line, *Line_i;
     struct P_area *Area;
-    struct P_topo_b *topo;
+    struct P_topo_b *topo, *topo_i;
     
     pg_info = &(Map->fInfo.pg);
     
@@ -1533,39 +1596,51 @@ int update_topo_face(struct Map_info *Map, int line)
     
     topo = (struct P_topo_b *)Line->topo;
     
+    /* for both side on the current boundary (line) */
+    /* create new faces */
     for (s = 0; s < 2; s++) { /* for each side */
         area = s == 0 ? topo->left : topo->right;
         if (area <= 0) /* no area - skip */
             continue;
-        Area = Map->plus.Area[area];
-        
-        face = insert_face(Map, area); /* TODO: update */
+
+        face[s] = insert_face(Map, area);
+        if (face[s] < 1) {
+            G_warning(_("Unable to create new face"));
+            return -1;
+        }
+    }
+    
+    /* update edges forming faces */
+    for (s = 0; s < 2; s++) { /* for each side */
+        area = s == 0 ? topo->left : topo->right;
+        if (area <= 0) /* no area - skip */
+          continue;
         
-        for (i = 0; i < Area->n_lines; i++) { /* update all boundaries */
-            Line = Map->plus.Line[abs(Area->lines[i])];
-            topo = (struct P_topo_b *)Line->topo;
+        Area = Map->plus.Area[area];
+        for (i = 0; i < Area->n_lines; i++) {
+            Line_i = Map->plus.Line[abs(Area->lines[i])];
+            topo_i = (struct P_topo_b *)Line_i->topo;
             
             sprintf(stmt, "UPDATE \"%s\".edge_data SET "
                     "left_face = %d, right_face = %d "
                     "WHERE edge_id = %lu", pg_info->toposchema_name,
-                    topo->left > 0 ? topo->left : 0,
-                    topo->right > 0 ? topo->right : 0,
-                    Line->offset);
+                    topo_i->left > 0 ? topo_i->left : 0,
+                    topo_i->right > 0 ? topo_i->right : 0,
+                    Line_i->offset);
             G_debug(2, "SQL: %s", stmt);
             
             if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
-                /* rollback transaction */
                 Vect__execute_pg(pg_info->conn, "ROLLBACK");
                 return -1;
             }
         }
         
-        /* update also centroids */
+        /* update also centroids (stored as nodes) */
         if (Area->centroid > 0) {
-            Line = Map->plus.Line[Area->centroid];
+            Line_i = Map->plus.Line[Area->centroid];
             sprintf(stmt, "UPDATE \"%s\".node SET containing_face = %d "
                     "WHERE node_id = %lu", pg_info->toposchema_name,
-                    face, Line->offset);
+                    face[s], Line_i->offset);
             G_debug(2, "SQL: %s", stmt);
             
             if(Vect__execute_pg(pg_info->conn, stmt) == -1) {