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

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Jun 15 03:48:59 PDT 2012


Author: martinl
Date: 2012-06-15 03:48:58 -0700 (Fri, 15 Jun 2012)
New Revision: 52076

Modified:
   grass/trunk/lib/vector/Vlib/read_pg.c
Log:
vlib/pg: fix for polygons with more then 20 rings
         build centroids from spidx or postgis topo


Modified: grass/trunk/lib/vector/Vlib/read_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/read_pg.c	2012-06-15 10:20:33 UTC (rev 52075)
+++ grass/trunk/lib/vector/Vlib/read_pg.c	2012-06-15 10:48:58 UTC (rev 52076)
@@ -32,7 +32,7 @@
 
 static int read_next_line_pg(struct Map_info *,
                              struct line_pnts *, struct line_cats *, int);
-SF_FeatureType get_feature(struct Format_info_pg *, int, const char *);
+SF_FeatureType get_feature(struct Format_info_pg *, int, int);
 static unsigned char *hex_to_wkb(const char *, int *);
 static int point_from_wkb(const unsigned char *, int, int, int,
                           struct line_pnts *);
@@ -46,7 +46,8 @@
 static int error_corrupted_data(const char *);
 static void reallocate_cache(struct Format_info_cache *, int);
 static void add_fpart(struct feat_parts *, SF_FeatureType, int, int);
-static int read_centroid_pg(struct Format_info_pg *, int, struct line_pnts *);
+static int get_centroid_topo(struct Format_info_pg *, int, struct line_pnts *);
+static int get_centroid(struct Map_info *, int, struct line_pnts *);
 #endif
 
 /*!
@@ -249,7 +250,7 @@
 
         G_debug(3, "read (%s) feature (fid = %ld) to cache",
                 pg_info->table_name, fid);
-        get_feature(pg_info, fid, NULL);
+        get_feature(pg_info, fid, -1);
 
         if (pg_info->cache.sf_type == SF_NONE) {
             G_warning(_("Feature %d without geometry skipped"), fid);
@@ -287,8 +288,7 @@
                     struct line_cats *line_c, int line)
 {
 #ifdef HAVE_POSTGRES
-    int type;
-    char *topotable_name;
+    int type, fid;
     
     struct Format_info_pg *pg_info;
     struct P_line *Line;
@@ -314,20 +314,21 @@
     if (line_c)
         Vect_cat_set(line_c, 1, (int) Line->offset);
     
-    if (Line->type == GV_POINT)
-        topotable_name = "node";
-    else if (Line->type & GV_LINES)
-        topotable_name = "edge";
-    else if (Line->type == GV_CENTROID) {
-        return read_centroid_pg(pg_info, (int) Line->offset, line_p);
+    if (Line->type == GV_CENTROID) {
+        if (pg_info->toposchema_name)
+            return get_centroid_topo(pg_info, line, line_p);
+        else
+            return get_centroid(Map, line, line_p);
     }
-    else {
-        G_warning(_("Unsupported feature type %d"), Line->type);
-        return -1;
-    }
     
-    get_feature(pg_info, Line->offset, topotable_name);
+    /* get feature id */
+    if (pg_info->toposchema_name)
+        fid = Line->offset;
+    else
+        fid = pg_info->offset.array[Line->offset];
     
+    get_feature(pg_info, fid, Line->type);
+    
     if (pg_info->cache.sf_type == SF_NONE) {
         G_warning(_("Feature %d without geometry skipped"), Line->offset);
         return -1;
@@ -393,7 +394,7 @@
         /* read feature to cache if necessary */
         while (pg_info->cache.lines_next == pg_info->cache.lines_num) {
             /* cache feature -> line_p & line_c */
-            sf_type = get_feature(pg_info, -1, NULL);
+            sf_type = get_feature(pg_info, -1, -1);
 
             if (sf_type == SF_NONE) {
                 G_warning(_("Feature %d without geometry skipped"), line);
@@ -462,15 +463,14 @@
    \return simple feature type (SF_POINT, SF_LINESTRING, ...)
    \return -1 on error
  */
-SF_FeatureType get_feature(struct Format_info_pg *pg_info, int fid,
-                           const char *topotable_name)
+SF_FeatureType get_feature(struct Format_info_pg *pg_info, int fid, int type)
 {
     char *data;
     char stmt[DB_SQL_MAX];
     int left_face, right_face;
     
-    if (!topotable_name && !pg_info->geom_column) {
-        G_warning(_("No geometry column defined"));
+    if (!pg_info->geom_column && !pg_info->topogeom_column) {
+        G_warning(_("No geometry or topo geometry column defined"));
         return -1;
     }
     if (fid < 1) {
@@ -481,7 +481,7 @@
         }
     }
     else {
-        if (!topotable_name && !pg_info->fid_column) {
+        if (!pg_info->fid_column) {
             G_warning(_("Random access not supported. "
                         "Primary key not defined."));
             return -1;
@@ -490,7 +490,7 @@
         if (execute(pg_info->conn, "BEGIN") == -1)
             return -1;
 
-        if (!topotable_name) {
+        if (!pg_info->toposchema_name) {
             /* simple feature access */
             sprintf(stmt,
                     "DECLARE %s_%s%p CURSOR FOR SELECT %s FROM \"%s\".\"%s\" "
@@ -500,6 +500,18 @@
         }
         else {
             /* topological access */
+            char *topotable_name;
+            
+            if (type == GV_POINT)
+                topotable_name = "node";
+            else if (type & GV_LINES)
+                topotable_name = "edge";
+            else {
+                G_warning(_("Unsupported feature type %d"), type);
+                execute(pg_info->conn, "ROLLBACK");
+                return -1;
+            }
+            
             sprintf(stmt,
                     "DECLARE %s_%s%p CURSOR FOR SELECT geom,left_face,right_face "
                     " FROM \"%s\".\"%s\" "
@@ -1219,7 +1231,7 @@
         cache->lines_alloc = 1;
     }
     else {
-        cache->lines_alloc += 20;
+        cache->lines_alloc += num;
     }
 
     cache->lines = (struct line_pnts **)G_realloc(cache->lines,
@@ -1229,7 +1241,7 @@
                                           cache->lines_alloc * sizeof(int));
 
     if (cache->lines_alloc > 1) {
-        for (i = cache->lines_alloc - 20; i < cache->lines_alloc; i++) {
+        for (i = cache->lines_alloc - num; i < cache->lines_alloc; i++) {
             cache->lines[i] = Vect_new_line_struct();
             cache->lines_types[i] = -1;
         }
@@ -1250,7 +1262,7 @@
         if (fparts->a_parts == 0)
             fparts->a_parts = 1;
         else
-            fparts->a_parts += 20;
+            fparts->a_parts += fparts->n_parts;
 
         fparts->ftype = (SF_FeatureType *) G_realloc(fparts->ftype,
                                                      fparts->a_parts *
@@ -1268,8 +1280,18 @@
     fparts->n_parts++;
 }
 
-int read_centroid_pg(struct Format_info_pg *pg_info,
-                     int centroid, struct line_pnts *line_p)
+/*
+  \brief Get centroid from PostGIS topology
+  
+  \param pg_info pointer to Format_info_pg
+  \param centroid centroid id
+  \param[out] line_p output geometry
+
+  \return GV_CENTROID on success
+  \return -1 on error
+*/
+int get_centroid_topo(struct Format_info_pg *pg_info,
+                      int centroid, struct line_pnts *line_p)
 {
     char stmt[DB_SQL_MAX];
     char *data;
@@ -1300,4 +1322,51 @@
     
     return GV_CENTROID;
 }
+
+/*
+  \brief Get centroid
+  
+  \param pg_info pointer to Format_info_pg
+  \param centroid centroid id
+  \param[out] line_p output geometry
+
+  \return GV_CENTROID on success
+  \return -1 on error
+*/
+int get_centroid(struct Map_info *Map, int centroid,
+                 struct line_pnts *line_p)
+{
+    int i, found;
+    struct bound_box box;
+    struct boxlist list;
+    struct P_line *Line;
+    struct P_topo_c *topo;
+        
+    Line = Map->plus.Line[centroid];
+    topo = (struct P_topo_c *)Line->topo;
+    
+    /* get area bbox */
+    Vect_get_area_box(Map, topo->area, &box);
+    /* search in spatial index for centroid with area bbox */
+    dig_init_boxlist(&list, TRUE);
+    Vect_select_lines_by_box(Map, &box, Line->type, &list);
+    
+    found = -1;
+    for (i = 0; i < list.n_values; i++) {
+        if (list.id[i] == centroid) {
+            found = i;
+            break;
+        }
+    }
+    
+    if (found == -1)
+        return -1;
+    
+    if (line_p) {
+        Vect_reset_line(line_p);
+        Vect_append_point(line_p, list.box[found].E, list.box[found].N, 0.0);
+    }
+    
+    return GV_CENTROID;
+}
 #endif



More information about the grass-commit mailing list