[GRASS-SVN] r52004 - grass/trunk/lib/vector/Vlib

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Jun 7 15:36:39 PDT 2012


Author: martinl
Date: 2012-06-07 15:36:38 -0700 (Thu, 07 Jun 2012)
New Revision: 52004

Modified:
   grass/trunk/lib/vector/Vlib/build.c
   grass/trunk/lib/vector/Vlib/build_pg.c
   grass/trunk/lib/vector/Vlib/open_pg.c
   grass/trunk/lib/vector/Vlib/pg_local_proto.h
Log:
vlib/pg: build isles for PostGIS Topology access


Modified: grass/trunk/lib/vector/Vlib/build.c
===================================================================
--- grass/trunk/lib/vector/Vlib/build.c	2012-06-07 19:19:42 UTC (rev 52003)
+++ grass/trunk/lib/vector/Vlib/build.c	2012-06-07 22:36:38 UTC (rev 52004)
@@ -56,15 +56,14 @@
    \param iline line id
    \param side side (GV_LEFT or GV_RIGHT)
 
-   \return > 0 number of area
-   \return < 0 number of isle
+   \return > 0 area id
+   \return < 0 isle id
    \return 0 not created (may also already exist)
  */
 int Vect_build_line_area(struct Map_info *Map, int iline, int side)
 {
     int j, area, isle, n_lines, line, direction;
-    static int first = 1;
-    off_t offset;
+    static int first = TRUE;
     struct Plus_head *plus;
     struct P_line *BLine;
     static struct line_pnts *Points, *APoints;
@@ -79,15 +78,15 @@
     if (first) {
 	Points = Vect_new_line_struct();
 	APoints = Vect_new_line_struct();
-	first = 0;
+	first = FALSE;
     }
 
     area = dig_line_get_area(plus, iline, side);
     if (area != 0) {
-	G_debug(3, "  area/isle = %d -> skip", area);
-	return 0;
+        G_debug(3, "  area/isle = %d -> skip", area);
+        return 0;
     }
-
+    
     n_lines = dig_build_area_with_line(plus, iline, side, &lines);
     G_debug(3, "  n_lines = %d", n_lines);
     if (n_lines < 1) {
@@ -99,9 +98,8 @@
     for (j = 0; j < n_lines; j++) {
 	line = abs(lines[j]);
 	BLine = plus->Line[line];
-	offset = BLine->offset;
 	G_debug(3, "  line[%d] = %d, offset = %lu", j, line,
-		(unsigned long)offset);
+		(unsigned long) BLine->offset);
 	Vect_read_line(Map, Points, NULL, line);
 	if (lines[j] > 0)
 	    direction = GV_FORWARD;

Modified: grass/trunk/lib/vector/Vlib/build_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/build_pg.c	2012-06-07 19:19:42 UTC (rev 52003)
+++ grass/trunk/lib/vector/Vlib/build_pg.c	2012-06-07 22:36:38 UTC (rev 52004)
@@ -5,8 +5,6 @@
 
    Higher level functions for reading/writing/manipulating vectors.
 
-   \todo Implement build_topo()
-
    Line offset is
    - centroids   : FID
    - other types : index of the first record (which is FID) in offset array.
@@ -108,7 +106,7 @@
 
 #ifdef HAVE_POSTGRES
 /*!
-  \brief Build based on PostGIS topology
+  \brief Build from PostGIS topology schema
 
   Currently only GV_BUILD_ALL is supported
 
@@ -120,10 +118,8 @@
 */
 int build_topo(struct Map_info *Map, int build)
 {
-    struct Format_info_pg *pg_info;
     struct Plus_head *plus;
     
-    pg_info = &(Map->fInfo.pg);
     plus = &(Map->plus);
     
     /* check if upgrade or downgrade */
@@ -140,7 +136,7 @@
     }
     
     if (plus->built < GV_BUILD_BASE) {
-        if (load_plus(pg_info, plus, FALSE) != 0)
+        if (load_plus(Map, FALSE) != 0)
             return 0;
     }
     

Modified: grass/trunk/lib/vector/Vlib/open_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open_pg.c	2012-06-07 19:19:42 UTC (rev 52003)
+++ grass/trunk/lib/vector/Vlib/open_pg.c	2012-06-07 22:36:38 UTC (rev 52004)
@@ -40,9 +40,8 @@
 static int check_topo(struct Format_info_pg *, struct Plus_head *);
 static int parse_bbox(const char *, struct bound_box *);
 static int num_of_records(const struct Format_info_pg *, const char *);
-static int read_p_node(struct Plus_head *, int, int, struct Format_info_pg *);
-static int read_p_line(struct Plus_head *, int, const struct edge_data *);
-static int read_p_area(struct Plus_head *, int, int, struct Format_info_pg *);
+static struct P_node *read_p_node(struct Plus_head *, int, int, struct Format_info_pg *);
+static struct P_line *read_p_line(struct Plus_head *, int, const struct edge_data *);
 static int load_plus_head(struct Format_info_pg *, struct Plus_head *);
 static void notice_processor(void *, const char *);
 #endif
@@ -401,6 +400,8 @@
     struct Plus_head *plus;
     struct Format_info_pg *pg_info;
     
+    Map->open = VECT_OPEN_CODE; /* needed by load_plus */
+
     plus = &(Map->plus);
     pg_info = &(Map->fInfo.pg);
     
@@ -411,7 +412,7 @@
     /* free and init plus structure */
     dig_init_plus(plus);
     
-    return load_plus(pg_info, plus, head_only);
+    return load_plus(Map, head_only);
 #else
     G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
     return -1;
@@ -956,11 +957,11 @@
   \param id node id (table "node")
   \param pg_info pointer to Format_info_pg sttucture
 
-  \return 0 on success
-  \return -1 on failure
+  \return pointer to new P_node struct
+  \return NULL on error
 */
-int read_p_node(struct Plus_head *plus, int n, int id,
-                struct Format_info_pg *pg_info)
+struct P_node *read_p_node(struct Plus_head *plus, int n, int id,
+                           struct Format_info_pg *pg_info)
 {
     int i, cnt;
     char stmt[DB_SQL_MAX];
@@ -986,13 +987,13 @@
         G_warning(_("Unable to read node %d"), id);
         if (res)
             PQclear(res);
-        return -1;
+        return NULL;
     }
     cnt = PQntuples(res);
     
     if (cnt == 0) { /* dead ??? */
         plus->Node[n] = NULL;
-        return 0;
+        return NULL;
     }
 
     node = dig_alloc_node();
@@ -1000,7 +1001,7 @@
     G_debug(4, "read_p_node(): id = %d, n_lines = %d", id, cnt);
     
     if (dig_node_alloc_line(node, node->n_lines) == -1)
-        return -1;
+        return NULL;
 
     /* lines / angles */
     for (i = 0; i < node->n_lines; i++) {
@@ -1037,7 +1038,7 @@
         G_warning(_("Unable to read node %d"), id);
         if (res)
             PQclear(res);
-        return -1;
+        return NULL;
     }
     node->x = atof(PQgetvalue(res, 0, 0));
     node->y = atof(PQgetvalue(res, 0, 1));
@@ -1049,7 +1050,7 @@
 
     plus->Node[n] = node;
     
-    return 0;
+    return node;
 }
 
 /*!
@@ -1067,11 +1068,11 @@
   \param data edge data (id, start/end node, left/right face, ...)
   \param pg_info pointer to Format_info_pg sttucture
 
-  \return 0 on success
-  \return -1 on failure
+  \return pointer to P_line struct
+  \return NULL on error
 */
-int read_p_line(struct Plus_head *plus, int n,
-                const struct edge_data *data)
+struct P_line *read_p_line(struct Plus_head *plus, int n,
+                           const struct edge_data *data)
 {
     int tp;
     struct P_line *line;
@@ -1091,7 +1092,7 @@
     
     if (tp == 0) { /* dead ??? */
         plus->Line[n] = NULL;
-        return 0;
+        return NULL;
     }
 
     line = dig_alloc_line();
@@ -1121,8 +1122,10 @@
             
             topo->N1    = data->start_node;
             topo->N2    = data->end_node;
-            topo->left  = data->left_face == 0 ? -1 : data->left_face;
-            topo->right = data->right_face == 0 ? -1 : data->right_face;
+
+            /* skip left/right area - will be detected when building
+               areas/isles */
+            topo->left = topo->right = 0;
         }
         /* centroids */
         else if (line->type == GV_CENTROID) {
@@ -1135,75 +1138,10 @@
 
     plus->Line[n] = line;
     
-    return 0;
+    return line;
 }
 
 /*!
-  \brief Read P_area structure
-  
-  See dig_Rd_P_area() for reference.
-  
-  \param plus pointer to Plus_head structure
-  \param n index (starts at 1)
-  \param face_id face id (see 'face' table)
-  \param pg_info pointer to Format_info_pg sttucture
-
-  \return 0 on success
-  \return -1 on failure
-*/
-int read_p_area(struct Plus_head *plus, int n, int face_id, struct Format_info_pg *pg_info)
-{
-    int i, cnt;
-    char stmt[DB_SQL_MAX];
-
-    PGresult *res;
-    struct P_area *area;
-
-    sprintf(stmt,
-            "SELECT edge from ST_GetFaceEdges('%s', %d)",
-            pg_info->toposchema_name, face_id);
-    G_debug(2, "SQL: %s", stmt);
-    res = PQexec(pg_info->conn, stmt);
-    if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
-        G_warning(_("Unable to read face %d"), face_id);
-        if (res)
-            PQclear(res);
-        return -1;
-    }
-    
-    cnt = PQntuples(res);
-    if (cnt == 0) { /* dead */
-        plus->Area[n] = NULL;
-        return 0;
-    }
-    
-    area = dig_alloc_area();
-
-    /* boundaries */
-    area->n_lines = cnt;
-    if (dig_area_alloc_line(area, area->n_lines) == -1)
-        return -1;
-    area->lines = (plus_t *)G_realloc(area->lines, sizeof(plus_t) * area->n_lines);
-    for (i = 0; i < area->n_lines; i++) {
-        /* GRASS   Topo model: lines in clockwise order
-           PosTGIS Topo model: lines in counter clockwise order */
-        area->lines[i] = -1 * atoi(PQgetvalue(res, i, 0));
-    }
-
-    /* isles */
-    /* TODO */
-
-    /* centroid */
-    area->centroid = plus->n_lines - plus->n_clines + i;
-    
-    plus->Area[n] = area;
-    
-    PQclear(res);
-    
-    return 0;
-}
-
-/*!
   \brief Read topo (from PostGIS topology schema) header info only
 
   \param[in,out] plus pointer to Plus_head struct
@@ -1256,12 +1194,13 @@
     /* + isolated nodes as points
        + centroids */
     plus->n_lines = num_of_records(pg_info, stmt); 
-    /* areas (faces in PostGIS Topology model) */
+    /* areas (faces in PostGIS Topology model)
     sprintf(stmt,
             "SELECT COUNT(*) FROM \"%s\".face WHERE mbr IS NOT NULL",
             pg_info->toposchema_name);
     plus->n_areas = num_of_records(pg_info, stmt);
     G_debug(3, "Vect_open_topo_pg(): n_areas=%d", plus->n_areas);
+    */
     /* TODO: n_isles | n_volumes | n_holes */
     
     /* number of features group by type */
@@ -1314,15 +1253,21 @@
   \return 0 on success
   \return -1 on error
 */
-int load_plus(struct Format_info_pg *pg_info, struct Plus_head *plus,
-              int head_only)
+int load_plus(struct Map_info *Map, int head_only)
 {
     int i, id, ntuples;
     char stmt[DB_SQL_MAX];
     struct edge_data line_data;
     
+    struct Format_info_pg *pg_info;
+    struct Plus_head *plus;
+    struct P_line *Line;
+    
     PGresult *res;
   
+    pg_info = &(Map->fInfo.pg);
+    plus = &(Map->plus);
+
     if (load_plus_head(pg_info, plus) != 0)
         return -1;
 
@@ -1364,7 +1309,9 @@
     G_debug(3, "load_plus(): n_lines = %d", plus->n_lines);
     dig_alloc_lines(plus, plus->n_lines); 
     
-    /* read PostGIS Topo standalone nodes */
+    /* read PostGIS Topo standalone nodes
+       -> points
+    */
     sprintf(stmt,
             "SELECT node_id FROM \"%s\".node WHERE node_id NOT IN "
             "(SELECT node FROM (SELECT start_node AS node FROM \"%s\".edge "
@@ -1391,7 +1338,10 @@
     }
     PQclear(res);
     
-    /* read PostGIS Topo edges */
+    /* read PostGIS Topo edges
+       -> lines
+       -> boundaries
+    */
     sprintf(stmt,
             "SELECT edge_id,start_node,end_node,left_face,right_face "
             "FROM \"%s\".edge",
@@ -1414,37 +1364,43 @@
         line_data.end_node   = atoi(PQgetvalue(res, i, 2));
         line_data.left_face  = atoi(PQgetvalue(res, i, 3));
         line_data.right_face = atoi(PQgetvalue(res, i, 4));
-        read_p_line(plus, plus->n_plines + i + 1, &line_data);
+        
+        id = plus->n_plines + i + 1; /* points already registered */
+        Line = read_p_line(plus, id, &line_data);
+        if (line_data.left_face != 0 || line_data.right_face != 0) {
+            /* boundary detected -> build area on left and right*/
+            
+            int s, side;
+            for (s = 0; s < 2; s++) {
+                if (s == 0)
+                    side = GV_LEFT;
+                else
+                    side = GV_RIGHT;
+                
+                G_debug(3, "Build area for line = %d, side = %d",
+                        id, side);
+                Vect_build_line_area(Map, id, side);
+            }
+        }
+        if (Line->type == GV_BOUNDARY) {
+            struct P_topo_b *topo;
+
+            if (line_data.left_face == 0)
+                line_data.left_face = -1;
+            if (line_data.right_face == 0)
+                line_data.right_face = -1;
+            
+            topo = (struct P_topo_b *)Line->topo;
+            if (topo->left != line_data.left_face)
+                G_warning(_("Left area detected as %d (should be %d"),
+                          topo->left, line_data.left_face);
+            if (topo->right != line_data.right_face)
+                G_warning(_("Right area detected as %d (should be %d"),
+                          topo->right, line_data.right_face);
+        }
     }
     PQclear(res);
     
-    /* read areas (GRASS Topo) */
-    sprintf(stmt,
-            "SELECT face_id from \"%s\".face WHERE mbr IS NOT NULL",
-            pg_info->toposchema_name);
-    G_debug(2, "SQL: %s", stmt);
-    res = PQexec(pg_info->conn, stmt);
-    if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
-        PQntuples(res) != plus->n_areas) {
-        G_warning(_("Unable to read areas"));
-        if (res)
-            PQclear(res);
-        return -1;
-    }
-    
-    G_debug(3, "load_plus(): n_areas = %d", plus->n_areas);
-    dig_alloc_areas(plus, plus->n_areas);
-    G_zero(&line_data, sizeof(struct edge_data));
-    for (i = 1; i <= plus->n_areas; i++) {
-        line_data.id = line_data.left_face = atoi(PQgetvalue(res, i - 1, 0));
-        read_p_area(plus, i, line_data.id, pg_info);
-        /* add centroids */
-        read_p_line(plus, plus->n_lines - plus->n_clines + i, &line_data);
-    }
-    PQclear(res);
-    
-    /* read isle (GRASS Topo) */
-
     return 0;
 }
 

Modified: grass/trunk/lib/vector/Vlib/pg_local_proto.h
===================================================================
--- grass/trunk/lib/vector/Vlib/pg_local_proto.h	2012-06-07 19:19:42 UTC (rev 52003)
+++ grass/trunk/lib/vector/Vlib/pg_local_proto.h	2012-06-07 22:36:38 UTC (rev 52004)
@@ -53,7 +53,7 @@
 			     struct Format_info_cache *,
 			     struct feat_parts *);
 int set_initial_query(struct Format_info_pg *, int);
-int load_plus(struct Format_info_pg *, struct Plus_head *, int);
+int load_plus(struct Map_info *, int);
 
 #endif /* HAVE_POSTGRES */
 



More information about the grass-commit mailing list