[GRASS-SVN] r52563 - in grass/trunk: include/defs lib/vector/Vlib

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Aug 6 09:16:34 PDT 2012


Author: martinl
Date: 2012-08-06 09:16:34 -0700 (Mon, 06 Aug 2012)
New Revision: 52563

Modified:
   grass/trunk/include/defs/vector.h
   grass/trunk/lib/vector/Vlib/open.c
   grass/trunk/lib/vector/Vlib/open_pg.c
   grass/trunk/lib/vector/Vlib/write_pg.c
Log:
vlib: postgis topology support (work in progress)
      Vect_write_area_pg() introduced


Modified: grass/trunk/include/defs/vector.h
===================================================================
--- grass/trunk/include/defs/vector.h	2012-08-06 14:30:28 UTC (rev 52562)
+++ grass/trunk/include/defs/vector.h	2012-08-06 16:16:34 UTC (rev 52563)
@@ -548,6 +548,9 @@
                           const struct line_pnts *, const struct line_cats *);
 off_t V2_rewrite_line_sfa(struct Map_info *, int, int, off_t,
                           const struct line_pnts *, const struct line_cats *);
+off_t V2_write_area_pg(struct Map_info *, const struct line_pnts *,
+                       const struct line_cats *,
+                       const struct line_pnts **, int);
 
     /* Build topology */
 int Vect_build_nat(struct Map_info *, int);

Modified: grass/trunk/lib/vector/Vlib/open.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open.c	2012-08-06 14:30:28 UTC (rev 52562)
+++ grass/trunk/lib/vector/Vlib/open.c	2012-08-06 16:16:34 UTC (rev 52563)
@@ -730,7 +730,7 @@
     Map->mapset = G_store(G_mapset());
     Map->location = G_store(G_location());
     Map->gisdbase = G_store(G_gisdbase());
-
+    
     /* determine output format */
     if (strcmp(G_program_name(), "v.external") != 0)
         Map->format = map_format(Map);
@@ -1108,6 +1108,8 @@
 /* check for external formats definition */
 int map_format(struct Map_info *Map)
 {
+    char *def_file;
+    
     if (G_find_file2("", "OGR", G_mapset())) {
         /* OGR */
         FILE *fp;
@@ -1117,7 +1119,7 @@
         struct Format_info_ogr *ogr_info;
         
         G_debug(2, " using OGR format");
-        Map->format = GV_FORMAT_OGR;
+        Map->format = GV_FORMAT_OGR_DIRECT;
         fp = G_fopen_old("", "OGR", G_mapset());
         if (!fp) {
             G_fatal_error(_("Unable to open OGR file"));
@@ -1141,7 +1143,9 @@
         
         ogr_info->layer_name = G_store(Map->name);
     }
-    if (G_find_file2("", "PG", G_mapset())) {
+    
+    def_file = getenv("GRASS_VECTOR_PGFILE");
+    if (G_find_file2("", def_file ? def_file : "PG", G_mapset())) {
         /* PostGIS */
         if (Map->fInfo.ogr.driver_name) {
             G_warning(_("OGR output also detected, using OGR"));
@@ -1155,7 +1159,7 @@
             
             G_debug(2, " using PostGIS format");
             Map->format = GV_FORMAT_POSTGIS;
-            fp = G_fopen_old("", "PG", G_mapset());
+            fp = G_fopen_old("", def_file ? def_file : "PG", G_mapset());
             if (!fp) {
                 G_fatal_error(_("Unable to open PG file"));
             }
@@ -1178,30 +1182,30 @@
                 pg_info->schema_name = G_store("public");
             G_debug(1, "PG: schema_name = '%s'", pg_info->schema_name);
             
-            /* fid column (default: fid) */
+            /* fid column (default: ogc_fid) */
             p = G_find_key_value("fid", key_val);
             if (p)
                 pg_info->fid_column = G_store(p);
+            else
 #ifdef HAVE_POSTGRES
-            else
                 pg_info->fid_column = G_store(FID_COLUMN);
 #endif
             G_debug(1, "PG: fid_column = '%s'", pg_info->fid_column);
             
-            /* geometry column (default: geom) */
+            /* geometry column (default: wkb_geometry) */
             p = G_find_key_value("geometry_name", key_val);
             if (p)
                 pg_info->geom_column = G_store(p);
+            else
 #ifdef HAVE_POSTGRES
-            else
                 pg_info->geom_column = G_store(GEOMETRY_COLUMN);
 #endif
             G_debug(1, "PG: geom_column = '%s'", pg_info->geom_column);
             
             /* table name */
-            pg_info->table_name = G_store(Map->name);
+            Map->fInfo.pg.table_name = G_store(Map->name);
         }
     }
-
+    
     return Map->format;
 }

Modified: grass/trunk/lib/vector/Vlib/open_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open_pg.c	2012-08-06 14:30:28 UTC (rev 52562)
+++ grass/trunk/lib/vector/Vlib/open_pg.c	2012-08-06 16:16:34 UTC (rev 52563)
@@ -634,19 +634,21 @@
 {
     int spatial_index, primary_key;
     char stmt[DB_SQL_MAX];
-    char *geom_type;
+    char *geom_type, *def_file;
     
     PGresult *result;
 
+    def_file = getenv("GRASS_VECTOR_PGFILE");
+    
     /* by default create spatial index & add primary key */
     spatial_index = primary_key = TRUE;
-    if (G_find_file2("", "PG", G_mapset())) {
+    if (G_find_file2("", def_file ? def_file : "PG", G_mapset())) {
         FILE *fp;
         const char *p;
 
         struct Key_Value *key_val;
 
-        fp = G_fopen_old("", "PG", G_mapset());
+        fp = G_fopen_old("", def_file ? def_file : "PG", G_mapset());
         if (!fp) {
             G_fatal_error(_("Unable to open PG file"));
         }
@@ -862,18 +864,21 @@
 {
     double tolerance;
     char stmt[DB_SQL_MAX];
+    char *def_file;
     
     PGresult *result;
     
+    def_file = getenv("GRASS_VECTOR_PGFILE");
+    
     /* read default values from PG file*/
     tolerance = 0.;
-    if (G_find_file2("", "PG", G_mapset())) {
+    if (G_find_file2("", def_file ? def_file : "PG", G_mapset())) {
         FILE *fp;
         const char *p;
 
         struct Key_Value *key_val;
 
-        fp = G_fopen_old("", "PG", G_mapset());
+        fp = G_fopen_old("", def_file ? def_file : "PG", G_mapset());
         if (!fp) {
             G_fatal_error(_("Unable to open PG file"));
         }
@@ -899,7 +904,8 @@
     }
 
     /* create topology schema */
-    G_message(_("Creating topology schema <%s>..."), pg_info->toposchema_name);
+    G_verbose_message(_("Creating topology schema <%s>..."),
+                      pg_info->toposchema_name);
     sprintf(stmt, "SELECT topology.createtopology('%s', "
             "find_srid('%s', '%s', '%s'), %f, '%s')",
             pg_info->toposchema_name, pg_info->schema_name,
@@ -915,7 +921,8 @@
     }
     
     /* add topo column to the feature table */
-    G_message(_("Adding new topology column <%s>..."), pg_info->topogeom_column);
+    G_verbose_message(_("Adding new topology column <%s>..."),
+                      pg_info->topogeom_column);
     sprintf(stmt, "SELECT topology.AddTopoGeometryColumn('%s', '%s', '%s', "
             "'%s', '%s')", pg_info->toposchema_name, pg_info->schema_name,
             pg_info->table_name, pg_info->topogeom_column,

Modified: grass/trunk/lib/vector/Vlib/write_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_pg.c	2012-08-06 14:30:28 UTC (rev 52562)
+++ grass/trunk/lib/vector/Vlib/write_pg.c	2012-08-06 16:16:34 UTC (rev 52563)
@@ -31,18 +31,24 @@
 
 #define WKBSRIDFLAG 0x20000000
 
+static off_t write_line_sf(struct Map_info *, int,
+                           const struct line_pnts **, int,
+                           const struct line_cats *);
+static off_t write_line_tp(struct Map_info *, int,
+                           const struct line_pnts *);
 static char *binary_to_hex(int, const unsigned char *);
 static unsigned char *point_to_wkb(int, const struct line_pnts *, int, int *);
 static unsigned char *linestring_to_wkb(int, const struct line_pnts *,
                                         int, int *);
-static unsigned char *polygon_to_wkb(int, const struct line_pnts *,
+static unsigned char *polygon_to_wkb(int, const struct line_pnts **, int,
                                      int, int *);
 static int write_feature(struct Format_info_pg *,
-                         int, const struct line_pnts *, int,
+                         int, const struct line_pnts **, int, int,
                          int, const struct field_info *);
 static char *build_insert_stmt(const struct Format_info_pg *, const char *,
                                int, const struct field_info *);
-static char *build_topo_stmt(const struct Format_info_pg *, int, const char *);
+static char *build_topo_stmt(const struct Format_info_pg *, int,
+                             const struct P_line *, const char *);
 static char *build_topogeom_stmt(const struct Format_info_pg *, int, int, int);
 static int execute_topo(PGconn *, const char *);
 #endif
@@ -69,6 +75,159 @@
                        const struct line_cats *cats)
 {
 #ifdef HAVE_POSTGRES
+    if (!Map->fInfo.pg.toposchema_name)
+        return write_line_sf(Map, type, &points, 1, cats);
+    else
+        return write_line_tp(Map, type, points);
+#else
+    G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
+    return -1;
+#endif
+}
+
+/*!
+   \brief Rewrites feature at the given offset (level 1) (PostGIS interface)
+
+   \param Map pointer to Map_info structure
+   \param offset feature offset
+   \param type feature type (GV_POINT, GV_LINE, ...)
+   \param points feature geometry
+   \param cats feature categories
+
+   \return feature offset (rewriten feature)
+   \return -1 on error
+ */
+off_t V1_rewrite_line_pg(struct Map_info * Map,
+                         int line, int type, off_t offset,
+                         const struct line_pnts * points,
+                         const struct line_cats * cats)
+{
+    G_debug(3, "V1_rewrite_line_pg(): line=%d type=%d offset=%lu",
+            line, type, offset);
+#ifdef HAVE_POSTGRES
+    if (type != V1_read_line_pg(Map, NULL, NULL, offset)) {
+        G_warning(_("Unable to rewrite feature (incompatible feature types)"));
+        return -1;
+    }
+
+    /* delete old */
+    V1_delete_line_pg(Map, offset);
+
+    return V1_write_line_pg(Map, type, points, cats);
+#else
+    G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
+    return -1;
+#endif
+}
+
+/*!
+   \brief Deletes feature at the given offset (level 1)
+
+   \param Map pointer Map_info structure
+   \param offset feature offset
+
+   \return  0 on success
+   \return -1 on error
+ */
+int V1_delete_line_pg(struct Map_info *Map, off_t offset)
+{
+#ifdef HAVE_POSTGRES
+    long fid;
+    char stmt[DB_SQL_MAX];
+
+    struct Format_info_pg *pg_info;
+
+    pg_info = &(Map->fInfo.pg);
+
+    if (!pg_info->conn || !pg_info->table_name) {
+        G_warning(_("No connection defined"));
+        return -1;
+    }
+
+    if (offset >= pg_info->offset.array_num) {
+        G_warning(_("Invalid offset (%d)"), offset);
+        return -1;
+    }
+
+    fid = pg_info->offset.array[offset];
+
+    G_debug(3, "V1_delete_line_pg(), offset = %lu -> fid = %ld",
+            (unsigned long)offset, fid);
+
+    if (!pg_info->inTransaction) {
+        /* start transaction */
+        pg_info->inTransaction = TRUE;
+        if (execute(pg_info->conn, "BEGIN") == -1)
+            return -1;
+    }
+
+    sprintf(stmt, "DELETE FROM %s WHERE %s = %ld",
+            pg_info->table_name, pg_info->fid_column, fid);
+    G_debug(2, "SQL: %s", stmt);
+
+    if (execute(pg_info->conn, stmt) == -1) {
+        G_warning(_("Unable to delete feature"));
+        execute(pg_info->conn, "ROLLBACK");
+        return -1;
+    }
+
+    return 0;
+#else
+    G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
+    return -1;
+#endif
+}
+
+/*!
+   \brief Writes area on level 2 (PostGIS interface)
+
+   \param Map pointer to Map_info structure
+   \param type feature type (GV_POINT, GV_LINE, ...)
+   \param points pointer to line_pnts structure (boundary geometry) 
+   \param cats pointer to line_cats structure (feature categories)
+   \param ipoints pointer to line_pnts structure (isles geometry) 
+   \param nisles number of isles
+   
+   \return feature offset into file
+   \return -1 on error
+ */
+off_t V2_write_area_pg(struct Map_info *Map, 
+                       const struct line_pnts *bpoints,
+                       const struct line_cats *cats,
+                       const struct line_pnts **ipoints, int nisles)
+{
+#ifdef HAVE_POSTGRES
+    int i;
+    off_t ret;
+    const struct line_pnts **points;
+
+    if (nisles > 0) {
+        points = (const struct line_pnts **) G_calloc(nisles + 1, sizeof(struct line_pnts *));
+        points[0] = bpoints;
+        for (i = 0; i < nisles; i++)
+            points[i + 1] = ipoints[i];
+    }
+    else {
+        points = &bpoints;
+    }
+    
+    ret = write_line_sf(Map, GV_BOUNDARY, points, nisles + 1, cats);
+
+    if (nisles > 0)
+        G_free(points);
+
+    return ret;
+#else
+    G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
+    return -1;
+#endif
+}
+
+#ifdef HAVE_POSTGRES
+off_t write_line_sf(struct Map_info *Map, int type,
+                    const struct line_pnts **points, int nparts,
+                    const struct line_cats *cats)
+{
     int cat;
     off_t offset;
 
@@ -128,7 +287,7 @@
             return -1;
         }
     }
-    else if (type & GV_BOUNDARY) {
+    else if (type & GV_BOUNDARY || type & GV_CENTROID) {
         if (sf_type != SF_POLYGON) {
             G_warning(_("Feature is not a polygon. Skipping."));
             return -1;
@@ -144,24 +303,27 @@
         G_warning(_("Unsupported feature type (%d)"), type);
         return -1;
     }
+    
+    G_debug(3, "write_line_sf(): type = %d n_points = %d cat = %d",
+            type, points[0]->n_points, cat);
 
-    G_debug(3, "V1_write_line_pg(): type = %d n_points = %d cat = %d",
-            type, points->n_points, cat);
-
     if (sf_type == SF_POLYGON || sf_type == SF_POLYGON25D) {
-        int npoints;
+        /* skip this check when writing PostGIS topology */
+        int part, npoints;
 
-        npoints = points->n_points - 1;
-        if (points->x[0] != points->x[npoints] ||
-            points->y[0] != points->y[npoints] ||
-            points->z[0] != points->z[npoints]) {
-            G_warning(_("Boundary is not closed. Skipping."));
-            return -1;
+        for (part = 0; part < nparts; part++) { 
+            npoints = points[part]->n_points - 1;
+            if (points[part]->x[0] != points[part]->x[npoints] ||
+                points[part]->y[0] != points[part]->y[npoints] ||
+                points[part]->z[0] != points[part]->z[npoints]) {
+                G_warning(_("Boundary is not closed. Skipping."));
+                return -1;
+            }
         }
     }
 
     /* write feature's geometry and fid */
-    if (-1 == write_feature(pg_info, type, points,
+    if (-1 == write_feature(pg_info, type, points, nparts,
                             Vect_is_3d(Map) ? WITH_Z : WITHOUT_Z, cat, Fi)) {
         execute(pg_info->conn, "ROLLBACK");
         return -1;
@@ -182,110 +344,48 @@
         /* register first part in offset array */
         offset_info->array[offset_info->array_num++] = 0;
     }
-    G_debug(3, "V1_write_line_pg(): -> offset = %lu offset_num = %d cat = %d",
+    G_debug(3, "write_line_sf(): -> offset = %lu offset_num = %d cat = %d",
             (unsigned long)offset, offset_info->array_num, cat);
 
     return offset;
-#else
-    G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
-    return -1;
-#endif
 }
 
-/*!
-   \brief Rewrites feature at the given offset (level 1) (PostGIS interface)
-
-   \param Map pointer to Map_info structure
-   \param offset feature offset
-   \param type feature type (GV_POINT, GV_LINE, ...)
-   \param points feature geometry
-   \param cats feature categories
-
-   \return feature offset (rewriten feature)
-   \return -1 on error
- */
-off_t V1_rewrite_line_pg(struct Map_info * Map,
-                         int line, int type, off_t offset,
-                         const struct line_pnts * points,
-                         const struct line_cats * cats)
+off_t write_line_tp(struct Map_info *Map, int type,
+                    const struct line_pnts *points)
 {
-    G_debug(3, "V1_rewrite_line_pg(): line=%d type=%d offset=%lu",
-            line, type, offset);
-#ifdef HAVE_POSTGRES
-    if (type != V1_read_line_pg(Map, NULL, NULL, offset)) {
-        G_warning(_("Unable to rewrite feature (incompatible feature types)"));
-        return -1;
-    }
-
-    /* delete old */
-    V1_delete_line_pg(Map, offset);
-
-    return V1_write_line_pg(Map, type, points, cats);
-#else
-    G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
-    return -1;
-#endif
-}
-
-/*!
-   \brief Deletes feature at the given offset (level 1)
-
-   \param Map pointer Map_info structure
-   \param offset feature offset
-
-   \return  0 on success
-   \return -1 on error
- */
-int V1_delete_line_pg(struct Map_info *Map, off_t offset)
-{
-#ifdef HAVE_POSTGRES
-    long fid;
-    char stmt[DB_SQL_MAX];
-
     struct Format_info_pg *pg_info;
-
+    
     pg_info = &(Map->fInfo.pg);
 
-    if (!pg_info->conn || !pg_info->table_name) {
+    if (!pg_info->conn) {
         G_warning(_("No connection defined"));
         return -1;
     }
 
-    if (offset >= pg_info->offset.array_num) {
-        G_warning(_("Invalid offset (%d)"), offset);
+    if (!pg_info->table_name) {
+        G_warning(_("PostGIS feature table not defined"));
         return -1;
     }
 
-    fid = pg_info->offset.array[offset];
-
-    G_debug(3, "V1_delete_line_pg(), offset = %lu -> fid = %ld",
-            (unsigned long)offset, fid);
-
-    if (!pg_info->inTransaction) {
-        /* start transaction */
-        pg_info->inTransaction = TRUE;
-        if (execute(pg_info->conn, "BEGIN") == -1)
+    if (pg_info->feature_type == SF_UNKNOWN) {
+        /* create PostGIS table if doesn't exist */
+        if (V2_open_new_pg(Map, type) < 0)
             return -1;
     }
+    
+    G_debug(3, "write_line_pg(): type = %d n_points = %d",
+            type, points->n_points);
 
-    sprintf(stmt, "DELETE FROM %s WHERE %s = %ld",
-            pg_info->table_name, pg_info->fid_column, fid);
-    G_debug(2, "SQL: %s", stmt);
-
-    if (execute(pg_info->conn, stmt) == -1) {
-        G_warning(_("Unable to delete feature"));
+    /* write feature's geometry and fid */
+    if (-1 == write_feature(pg_info, type, &points, 1,
+                            Vect_is_3d(Map) ? WITH_Z : WITHOUT_Z, -1, NULL)) {
         execute(pg_info->conn, "ROLLBACK");
         return -1;
     }
 
     return 0;
-#else
-    G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
-    return -1;
-#endif
 }
 
-#ifdef HAVE_POSTGRES
 /*!
    \brief Binary data to HEX
 
@@ -463,7 +563,8 @@
    See OGRPolygon::exportToWkb from GDAL/OGR library
 
    \param byte_order byte order (ENDIAN_LITTLE or ENDIAN_BIG)
-   \param points feature geometry
+   \param ipoints list of ring geometries (first is outer ring)
+   \param nrings number of rings
    \param with_z WITH_Z for 3D data
    \param[out] nsize buffer size
 
@@ -471,21 +572,26 @@
    \return NULL on error
  */
 unsigned char *polygon_to_wkb(int byte_order,
-                              const struct line_pnts *points, int with_z,
-                              int *nsize)
+                              const struct line_pnts** points, int nrings,
+                              int with_z, int *nsize)
 {
-    int i, point_size, nrings;
+    int i, ring, point_size, offset;
     unsigned char *wkb_data;
     unsigned int sf_type;
 
-    if (points->n_points < 3)
+    /* check data validity */
+    if (nrings < 1)
         return NULL;
+    for (ring = 0; ring < nrings; ring++) {
+        if (points[ring]->n_points < 3)
+            return NULL;
+    }
 
     /* allocate buffer */
     point_size = 8 * (with_z ? 3 : 2);
-    /* one ring only */
-    nrings = 1;
-    *nsize = 9 + (4 + point_size * points->n_points);
+    *nsize = 9;
+    for (ring = 0; ring < nrings; ring++)
+        *nsize += 4 + point_size * points[ring]->n_points;
     wkb_data = G_malloc(*nsize);
     G_zero(wkb_data, *nsize);
 
@@ -517,31 +623,38 @@
         memcpy(wkb_data + 5, &nrings, 4);
     }
 
-    /* serialize ring */
-    memcpy(wkb_data + 9, &(points->n_points), 4);
-    for (i = 0; i < points->n_points; i++) {
-        memcpy(wkb_data + 9 + 4 + point_size * i, &(points->x[i]), 8);
-        memcpy(wkb_data + 9 + 4 + 8 + point_size * i, &(points->y[i]), 8);
-
-        if (with_z) {
-            memcpy(wkb_data + 9 + 4 + 16 + point_size * i, &(points->z[i]),
-                   8);
+    /* serialize rings */
+    offset = 9;
+    for (ring = 0; ring < nrings; ring++) {
+        memcpy(wkb_data + offset, &(points[ring]->n_points), 4);
+        for (i = 0; i < points[ring]->n_points; i++) {
+            memcpy(wkb_data + offset +
+                   4 + point_size * i, &(points[ring]->x[i]), 8);
+            memcpy(wkb_data + offset +
+                   4 + 8 + point_size * i, &(points[ring]->y[i]), 8);
+            
+            if (with_z) {
+                memcpy(wkb_data + offset +
+                       4 + 16 + point_size * i, &(points[ring]->z[i]), 8);
+            }
         }
-    }
-
-    /* swap if needed */
-    if (byte_order == ENDIAN_BIG) {
-        int npoints, nitems;
-
-        npoints = SWAP32(points->n_points);
-        memcpy(wkb_data + 5, &npoints, 4);
-
-        nitems = (with_z ? 3 : 2) * points->n_points;
-        for (i = 0; i < nitems; i++) {
-            SWAPDOUBLE(wkb_data + 9 + 4 + 8 * i);
+        
+        offset += 4 + point_size * points[ring]->n_points;
+        
+        /* swap if needed */
+        if (byte_order == ENDIAN_BIG) {
+            int npoints, nitems;
+            
+            npoints = SWAP32(points[ring]->n_points);
+            memcpy(wkb_data + 5, &npoints, 4);
+            
+            nitems = (with_z ? 3 : 2) * points[ring]->n_points;
+            for (i = 0; i < nitems; i++) {
+                SWAPDOUBLE(wkb_data + offset + 4 + 8 * i);
+            }
         }
     }
-
+    
     return wkb_data;
 }
 
@@ -551,6 +664,7 @@
    \param pg_info pointer to Format_info_pg struct
    \param type feature type (GV_POINT, GV_LINE, ...)
    \param points pointer to line_pnts struct
+   \param nparts number of parts (rings for polygon)
    \param with_z WITH_Z for 3D data
    \param cat category number (-1 for no category)
    \param Fi pointer to field_info (attributes to copy, NULL for no attributes)
@@ -558,9 +672,9 @@
    \return -1 on error
    \retirn 0 on success
  */
-int write_feature(struct Format_info_pg *pg_info,
-                  int type, const struct line_pnts *points, int with_z,
-                  int cat, const struct field_info *Fi)
+int write_feature(struct Format_info_pg *pg_info, int type,
+                  const struct line_pnts **points, int nparts,
+                  int with_z, int cat, const struct field_info *Fi)
 {
     int byte_order, nbytes, nsize;
     unsigned int sf_type;
@@ -583,13 +697,22 @@
     /* get wkb data */
     nbytes = -1;
     wkb_data = NULL;
-    if (type == GV_POINT)
-        wkb_data = point_to_wkb(byte_order, points, with_z, &nbytes);
+    if (type == GV_POINT || type == GV_CENTROID)
+        wkb_data = point_to_wkb(byte_order, points[0], with_z, &nbytes);
     else if (type == GV_LINE)
-        wkb_data = linestring_to_wkb(byte_order, points, with_z, &nbytes);
-    else if (type == GV_BOUNDARY)
-        wkb_data = polygon_to_wkb(byte_order, points, with_z, &nbytes);
-
+        wkb_data = linestring_to_wkb(byte_order, points[0], with_z, &nbytes);
+    else if (type == GV_BOUNDARY) {
+        if (!pg_info->toposchema_name) {
+            /* PostGIS simple feature access */
+            wkb_data = polygon_to_wkb(byte_order, points, nparts,
+                                      with_z, &nbytes);
+        }
+        else {
+            /* PostGIS topology access */
+            wkb_data = linestring_to_wkb(byte_order, points[0], with_z, &nbytes);
+        }
+    }
+    
     if (!wkb_data || nbytes < 1) {
         G_warning(_("Unsupported feature type %d"), type);
         return -1;
@@ -674,7 +797,7 @@
                                             to the feature table */
         
         /* insert feature into topology schema (node or edge) */
-        stmt = build_topo_stmt(pg_info, type, text_data);
+        stmt = build_topo_stmt(pg_info, type, NULL, text_data);
         id = execute_topo(pg_info->conn, stmt);
         if (id == -1) {
             /* rollback transaction */
@@ -686,7 +809,6 @@
         /* insert topoelement into feature table) */
         stmt = build_topogeom_stmt(pg_info, id, type, do_update);
         if (execute(pg_info->conn, stmt) == -1) {
-            /* rollback transaction */
             execute(pg_info->conn, "ROLLBACK");
             return -1;
         }
@@ -853,22 +975,59 @@
   topology schema
 
   \param pg_info so pointer to Format_info_pg
-  \param type feature type (GV_POINT, ...)
+  \param Line pointer to P_line struct (topo)
   \param geom_data geometry in wkb
 
   \return pointer to allocated string buffer with SQL statement
   \return NULL on error
 */
-char *build_topo_stmt(const struct Format_info_pg *pg_info,
-                      int type, const char *geom_data)
+char *build_topo_stmt(const struct Format_info_pg *pg_info, int type,
+                      const struct P_line *Line, const char *geom_data)
 {
     char *stmt;
     
     stmt = NULL;
-    if (type == GV_POINT) {
+    switch(type) {
+    case GV_POINT: {
+#if 0
+        G_asprintf(&stmt, "INSERT INTO \"%s\".node (geom) VALUES ('%s'::GEOMETRY)",
+                   pg_info->toposchema_name, geom_data);
+#else
+        G_asprintf(&stmt, "SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
+                   pg_info->toposchema_name, geom_data);
+#endif
+        break;
+    }
+    case GV_LINE: {
+        struct P_topo_l *topo;
+        
+        topo = (struct P_topo_l *) Line->topo;
+        G_asprintf(&stmt, "INSERT INTO \"%s\".edge_data (geom,"
+                   "start_node,end_node,"
+                   "next_left_edge,abs_next_left_edge,"
+                   "next_right_edge,abs_next_right_edge,"
+                   "left_face,right_face) "
+                   "VALUES ('%s'::GEOMETRY,%d,%d,0,0,0,0,0,0)",
+                   pg_info->toposchema_name, geom_data,
+                   topo->N1, topo->N2);
+        break;
+    }
+    case GV_CENTROID: {
+        /* TopoGeo_AddPoint ? */
         G_asprintf(&stmt, "SELECT AddNode('%s', '%s'::GEOMETRY)",
-                pg_info->toposchema_name, geom_data);
+                   pg_info->toposchema_name, geom_data);
+        break;
     }
+    case GV_BOUNDARY: {
+        /* TopoGeo_AddLineString ? */
+        G_asprintf(&stmt, "SELECT AddEdge('%s', '%s'::GEOMETRY)",
+                   pg_info->toposchema_name, geom_data);
+        break;
+    }
+    default:
+        G_warning(_("Unsupported feature type %d"), Line->type);
+        break;
+    }
     
     return stmt;
 }
@@ -897,7 +1056,7 @@
 
     if (type == GV_POINT)
         topogeom_type = 1;
-    else if (type == GV_LINES)
+    else if (type & GV_LINES)
         topogeom_type = 2;
     else {
         G_warning(_("Unsupported topo geometry type %d"), type);



More information about the grass-commit mailing list