浏览代码

vlib: implement V2__write_area_ogr() + V2__write_area_sfa()
update V2__write_area_pg()
fix off_t formatting issues


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

Martin Landa 12 年之前
父节点
当前提交
1de4c17e37
共有 6 个文件被更改,包括 315 次插入223 次删除
  1. 31 36
      lib/vector/Vlib/copy.c
  2. 10 0
      lib/vector/Vlib/local_proto.h
  3. 2 3
      lib/vector/Vlib/pg_local_proto.h
  4. 170 104
      lib/vector/Vlib/write_ogr.c
  5. 55 77
      lib/vector/Vlib/write_pg.c
  6. 47 3
      lib/vector/Vlib/write_sfa.c

+ 31 - 36
lib/vector/Vlib/copy.c

@@ -18,6 +18,8 @@
 #include <grass/vector.h>
 #include <grass/vector.h>
 #include <grass/glocale.h>
 #include <grass/glocale.h>
 
 
+#include "local_proto.h"
+
 /*!
 /*!
   \brief Copy topological elements
   \brief Copy topological elements
 
 
@@ -60,8 +62,6 @@ int Vect_copy_map_lines(struct Map_info *In, struct Map_info *Out)
 
 
    Note: Try to copy on level 2 otherwise level 1 is used.
    Note: Try to copy on level 2 otherwise level 1 is used.
    
    
-   \todo Implement V2__write_area_ogr()
-   
    \param In input vector map
    \param In input vector map
    \param field layer number (-1 for all layers)
    \param field layer number (-1 for all layers)
    \param[out] Out output vector map
    \param[out] Out output vector map
@@ -317,6 +317,9 @@ int copy_nodes(const struct Map_info *In, struct Map_info *Out)
             G_warning(_("Writing node %d failed"), node);
             G_warning(_("Writing node %d failed"), node);
             return 1;
             return 1;
         }
         }
+#else
+        G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
+        return 1;
 #endif
 #endif
     }
     }
 
 
@@ -376,19 +379,20 @@ int is_isle(const struct Map_info *Map, int area)
 */
 */
 int copy_areas(const struct Map_info *In, int field, struct Map_info *Out)
 int copy_areas(const struct Map_info *In, int field, struct Map_info *Out)
 {
 {
-    int i, area, nareas, cat, isle, nisles, nisles_alloc;
+    int i, area, nareas, cat, isle, nisles, nparts_alloc;
     int ogr;
     int ogr;
-    struct line_pnts *Points, **IPoints;
+    struct line_pnts **Points;
     struct line_cats *Cats;
     struct line_cats *Cats;
     
     
     ogr = Vect_maptype(Out) == (GV_FORMAT_OGR || GV_FORMAT_OGR_DIRECT);
     ogr = Vect_maptype(Out) == (GV_FORMAT_OGR || GV_FORMAT_OGR_DIRECT);
     
     
-    IPoints = NULL;
-    nisles_alloc = 0;
-    Points  = Vect_new_line_struct();
-    Cats    = Vect_new_cats_struct();
+    /* allocate points & cats */
+    Points    = (struct line_pnts **) G_malloc(sizeof(struct line_pnts *));
+    Points[0] = Vect_new_line_struct();
+    nparts_alloc = 1;
+    Cats      = Vect_new_cats_struct();
 
 
-    /* copy areas/polygons */
+    /* copy areas */
     nareas = Vect_get_num_areas(In);
     nareas = Vect_get_num_areas(In);
     G_message(_("Exporting areas..."));
     G_message(_("Exporting areas..."));
     for (area = 1; area <= nareas; area++) {
     for (area = 1; area <= nareas; area++) {
@@ -406,49 +410,40 @@ int copy_areas(const struct Map_info *In, int field, struct Map_info *Out)
             continue;
             continue;
         }
         }
         
         
-        /* get outer ring (area) geometry */
-        Vect_get_area_points(In, area, Points);
+        /* get outer ring (area) */
+        Vect_get_area_points(In, area, Points[0]);
 
 
+        /* get category */
         Vect_reset_cats(Cats);
         Vect_reset_cats(Cats);
         Vect_cat_set(Cats, field, cat);
         Vect_cat_set(Cats, field, cat);
         
         
-        /* get inner rings (isles) geometry */
+        /* get inner rings (isles) */
         nisles = Vect_get_area_num_isles(In, area);
         nisles = Vect_get_area_num_isles(In, area);
-        if (nisles > nisles_alloc) {
+        if (nisles + 1 > nparts_alloc) {
             /* reallocate space for isles */
             /* reallocate space for isles */
-            IPoints = (struct line_pnts **) G_realloc(IPoints,
-                                                      nisles *
-                                                      sizeof(struct line_pnts *));
-            for (i = nisles_alloc; i < nisles; i++)
-                IPoints[i] = Vect_new_line_struct();
-            nisles_alloc = nisles;
+            Points = (struct line_pnts **) G_realloc(Points,
+                                                     (nisles + 1) *
+                                                     sizeof(struct line_pnts *));
+            for (i = nparts_alloc; i < nisles + 1; i++)
+                Points[i] = Vect_new_line_struct();
+            nparts_alloc = nisles + 1;
         }
         }
         G_debug(3, "\tcat=%d, nisles=%d", cat, nisles);
         G_debug(3, "\tcat=%d, nisles=%d", cat, nisles);
         for (i = 0; i < nisles; i++) {
         for (i = 0; i < nisles; i++) {
             isle = Vect_get_area_isle(In, area, i);
             isle = Vect_get_area_isle(In, area, i);
-            Vect_get_isle_points(In, isle, IPoints[i]);
+            Vect_get_isle_points(In, isle, Points[i + 1]);
         }
         }
         
         
-        if (ogr)
-            Vect_write_line(Out, GV_BOUNDARY, Points, Cats);
-        else {
-#if HAVE_POSTGRES
-            if (-1 == V2__write_area_pg(Out, Points, Cats,
-                                        (const struct line_pnts **) IPoints, nisles)) {
-                G_warning(_("Writing area %d failed"), area);
-                return 1;
-            }
-#else
-            G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
-#endif
+        if (0 > V2__write_area_sfa(Out, (const struct line_pnts **) Points,
+                                   nisles + 1, Cats)) {
+            G_warning(_("Writing area %d failed"), area);
+            return -1;
         }
         }
     }
     }
     
     
     /* free allocated space for isles */
     /* free allocated space for isles */
-    for (i = 0; i < nisles_alloc; i++)
-        Vect_destroy_line_struct(IPoints[i]);
-
-    Vect_destroy_line_struct(Points);
+    for (i = 0; i < nparts_alloc; i++)
+        Vect_destroy_line_struct(Points[i]);
     Vect_destroy_cats_struct(Cats);
     Vect_destroy_cats_struct(Cats);
 
 
     return 0;
     return 0;

+ 10 - 0
lib/vector/Vlib/local_proto.h

@@ -22,4 +22,14 @@ int V2__add_line_to_topo_nat(struct Map_info *, off_t, int,
 int V2__delete_line_from_topo_nat(struct Map_info *, int, int,
 int V2__delete_line_from_topo_nat(struct Map_info *, int, int,
                                   const struct line_pnts *, const struct line_cats *);
                                   const struct line_pnts *, const struct line_cats *);
 
 
+/* write_sfa.c */
+off_t V2__write_area_sfa(struct Map_info *, const struct line_pnts **, int,
+                         const struct line_cats *);
+
+/* write_ogr.c */
+#ifdef HAVE_OGR
+off_t V2__write_area_ogr(struct Map_info *, const struct line_pnts **, int,
+                         const struct line_cats *);
+#endif /* HAVE_OGR */
+
 #endif /* PG_LOCAL_PROTO_H__ */
 #endif /* PG_LOCAL_PROTO_H__ */

+ 2 - 3
lib/vector/Vlib/pg_local_proto.h

@@ -63,9 +63,8 @@ int Vect__set_initial_query_pg(struct Format_info_pg *, int);
 int Vect__load_plus_pg(struct Map_info *, int);
 int Vect__load_plus_pg(struct Map_info *, int);
 
 
 off_t V2__write_node_pg(struct Map_info *, const struct line_pnts *);
 off_t V2__write_node_pg(struct Map_info *, const struct line_pnts *);
-off_t V2__write_area_pg(struct Map_info *, const struct line_pnts *,
-                        const struct line_cats *,
-                        const struct line_pnts **, int);
+off_t V2__write_area_pg(struct Map_info *, const struct line_pnts **, int,
+                        const struct line_cats *);
 
 
 int Vect__insert_face_pg(struct Map_info *, int);
 int Vect__insert_face_pg(struct Map_info *, int);
 
 

+ 170 - 104
lib/vector/Vlib/write_ogr.c

@@ -9,7 +9,7 @@
 
 
    \todo How to deal with OGRNullFID
    \todo How to deal with OGRNullFID
    
    
-   (C) 2009-2011, 2012 by Martin Landa, and the GRASS Development Team
+   (C) 2009-2013 by Martin Landa, and 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.
@@ -24,9 +24,11 @@
 #ifdef HAVE_OGR
 #ifdef HAVE_OGR
 #include <ogr_api.h>
 #include <ogr_api.h>
 
 
-static int sqltype_to_ogrtype(int);
+static off_t write_feature(struct Map_info *, int, const struct line_pnts **, int,
+                           const struct line_cats *);
 static int write_attributes(dbDriver *, int, const struct field_info *,
 static int write_attributes(dbDriver *, int, const struct field_info *,
 			    OGRLayerH, OGRFeatureH);
 			    OGRLayerH, OGRFeatureH);
+static int sqltype_to_ogrtype(int);
 #endif
 #endif
 
 
 /*!
 /*!
@@ -58,9 +60,130 @@ off_t V1_write_line_ogr(struct Map_info *Map, int type,
 			const struct line_cats *cats)
 			const struct line_cats *cats)
 {
 {
 #ifdef HAVE_OGR
 #ifdef HAVE_OGR
+    return write_feature(Map, type, &points, 1, cats);
+#else
+    G_fatal_error(_("GRASS is not compiled with OGR support"));
+    return -1;
+#endif
+}
+
+/*!
+  \brief Rewrites feature at the given offset on level 1 (OGR interface)
+  
+  This function simply calls V1_delete_line_ogr() and V1_write_line_ogr().
+  
+  \param Map pointer to Map_info structure
+  \param offset feature offset
+  \param type feature type (see V1_write_line_ogr() for supported types)
+  \param points pointer to line_pnts structure (feature geometry)
+  \param cats pointer to line_cats structure (feature categories)
+  
+  \return feature offset (rewriten feature)
+  \return -1 on error
+*/
+off_t V1_rewrite_line_ogr(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_ogr(): line=%d type=%d offset=%"PRI_OFF_T,
+	    line, type, offset);
+#ifdef HAVE_OGR
+    if (type != V1_read_line_ogr(Map, NULL, NULL, offset)) {
+	G_warning(_("Unable to rewrite feature (incompatible feature types)"));
+	return -1;
+    }
+
+    /* delete old */
+    V1_delete_line_ogr(Map, offset);
+
+    return V1_write_line_ogr(Map, type, points, cats);
+#else
+    G_fatal_error(_("GRASS is not compiled with OGR support"));
+    return -1;
+#endif
+}
+
+/*!
+  \brief Deletes feature at the given offset on level 1 (OGR interface)
+  
+  \param Map pointer Map_info structure
+  \param offset offset of feature to be deleted
+  
+  \return  0 on success
+  \return -1 on error
+*/
+int V1_delete_line_ogr(struct Map_info *Map, off_t offset)
+{
+#ifdef HAVE_OGR
+    struct Format_info_ogr *ogr_info;
+    
+    G_debug(3, "V1_delete_line_ogr(), offset = %lu", (unsigned long) offset);
+
+    ogr_info = &(Map->fInfo.ogr);
+    
+    if (!ogr_info->layer) {
+	G_warning(_("OGR layer not defined"));
+	return -1;
+    }
+    
+    if (offset >= ogr_info->offset.array_num) {
+	G_warning(_("Invalid offset (%d)"), offset);
+	return -1;
+    }
+    
+    if (OGR_L_DeleteFeature(ogr_info->layer,
+			    ogr_info->offset.array[offset]) != OGRERR_NONE)
+	G_warning(_("Unable to delete feature"));
+	return -1;
+    
+    return 0;
+#else
+    G_fatal_error(_("GRASS is not compiled with OGR support"));
+    return -1;
+#endif
+}
+
+#ifdef HAVE_OGR
+/*!
+   \brief Writes area on topological level (OGR Simple Features
+   interface, internal use only)
+
+   \param Map pointer to Map_info structure
+   \param points feature geometry (exterior + interior rings)
+   \param nparts number of parts including exterior ring
+   \param cats feature categories
+   
+   \return feature offset
+   \return -1 on error
+*/
+off_t V2__write_area_ogr(struct Map_info *Map,
+                         const struct line_pnts **points, int nparts,
+                         const struct line_cats *cats)
+{
+    return write_feature(Map, GV_BOUNDARY, points, nparts, cats);
+}
+
+/*!
+  \brief Write OGR feature
+
+   \param Map pointer to Map_info structure
+   \param type feature type (GV_POINT, GV_LINE, ...)
+   \param bpoints feature geometry
+   \param cats feature categories
+   \param ipoints isle geometry for polygons on NULL
+   \param nisles number of isles
+   
+   \return feature offset into file
+   \return -1 on error
+*/
+off_t write_feature(struct Map_info *Map, int type,
+                    const struct line_pnts **p_points, int nparts,
+                    const struct line_cats *cats)
+{
     int i, cat, ret;
     int i, cat, ret;
 
 
     struct field_info *Fi;
     struct field_info *Fi;
+    const struct line_pnts *points;
     struct Format_info_ogr *ogr_info;
     struct Format_info_ogr *ogr_info;
     struct Format_info_offset *offset_info;
     struct Format_info_offset *offset_info;
     
     
@@ -74,6 +197,11 @@ off_t V1_write_line_ogr(struct Map_info *Map, int type,
     ogr_info = &(Map->fInfo.ogr);
     ogr_info = &(Map->fInfo.ogr);
     offset_info = &(ogr_info->offset);
     offset_info = &(ogr_info->offset);
     
     
+    if (nparts < 1)
+        return -1;
+    
+    points = p_points[0]; /* feature geometry */
+    
     if (!ogr_info->layer) {
     if (!ogr_info->layer) {
 	/* create OGR layer if doesn't exist */
 	/* create OGR layer if doesn't exist */
 	if (V2_open_new_ogr(Map, type) < 0)
 	if (V2_open_new_ogr(Map, type) < 0)
@@ -137,43 +265,48 @@ off_t V1_write_line_ogr(struct Map_info *Map, int type,
     G_debug(3, "V1_write_line_ogr(): type = %d", type);
     G_debug(3, "V1_write_line_ogr(): type = %d", type);
 
 
     if (Ogr_geom_type == wkbPolygon || Ogr_geom_type == wkbPolygon25D) {
     if (Ogr_geom_type == wkbPolygon || Ogr_geom_type == wkbPolygon25D) {
-	/* create exterior ring */
-	OGRGeometryH Ogr_ring;
-	int npoints;
+	int iring, npoints;
 	
 	
-	npoints = points->n_points - 1;
-	Ogr_ring = OGR_G_CreateGeometry(wkbLinearRing);
-	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;
-	}
+        /* add rings (first is exterior ring) */
+        for (iring = 0; iring < nparts; iring++) {
+            OGRGeometryH Ogr_ring;
+            
+            points = p_points[iring];
+            npoints = points->n_points - 1;
+            Ogr_ring = OGR_G_CreateGeometry(wkbLinearRing);
+            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. Feature skipped."));
+                return -1;
+            }
 	
 	
-	/* add points */
-	for (i = 0; i < points->n_points; i++) {
-	    OGR_G_AddPoint(Ogr_ring, points->x[i], points->y[i],
-			   points->z[i]);
-	}
-	OGR_G_AddGeometry(Ogr_geometry, Ogr_ring);
+            /* add points */
+            for (i = 0; i < npoints; i++) {
+                OGR_G_AddPoint(Ogr_ring, points->x[i], points->y[i],
+                               points->z[i]);
+            }
+            G_debug(4, "   ring(%d): n_points = %d", iring, npoints);
+            OGR_G_AddGeometry(Ogr_geometry, Ogr_ring);
+        }
     }
     }
     else {
     else {
 	for (i = 0; i < points->n_points; i++) {
 	for (i = 0; i < points->n_points; i++) {
 	    OGR_G_AddPoint(Ogr_geometry, points->x[i], points->y[i],
 	    OGR_G_AddPoint(Ogr_geometry, points->x[i], points->y[i],
 			   points->z[i]);
 			   points->z[i]);
 	}
 	}
+        G_debug(4, "   n_points = %d", points->n_points);
     }
     }
     
     
-    G_debug(4, "   n_points = %d", points->n_points);
-
     /* create feature & set geometry */
     /* create feature & set geometry */
     Ogr_feature = OGR_F_Create(Ogr_featuredefn);
     Ogr_feature = OGR_F_Create(Ogr_featuredefn);
     OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
     OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
 
 
     /* write attributes */
     /* write attributes */
     if (cat > -1 && ogr_info->dbdriver) {
     if (cat > -1 && ogr_info->dbdriver) {
-	write_attributes(ogr_info->dbdriver,
-			 cat, Fi, ogr_info->layer, Ogr_feature);
+	if (0 > write_attributes(ogr_info->dbdriver,
+                                 cat, Fi, ogr_info->layer, Ogr_feature))
+            G_warning(_("Unable to writes feature attributes"));
 	G_free(Fi);
 	G_free(Fi);
     }
     }
     /* write feature into layer */
     /* write feature into layer */
@@ -202,93 +335,24 @@ off_t V1_write_line_ogr(struct Map_info *Map, int type,
     if (ret != OGRERR_NONE)
     if (ret != OGRERR_NONE)
 	return -1;
 	return -1;
     
     
-    G_debug(3, "V1_write_line_ogr(): -> offset = %lu offset_num = %d cat = %d",
+    G_debug(3, "write_feature(): -> offset = %lu offset_num = %d cat = %d",
 	    (unsigned long) offset, offset_info->array_num, cat);
 	    (unsigned long) offset, offset_info->array_num, cat);
 
 
     return offset;
     return offset;
-#else
-    G_fatal_error(_("GRASS is not compiled with OGR support"));
-    return -1;
-#endif
 }
 }
 
 
 /*!
 /*!
-  \brief Rewrites feature at the given offset on level 1 (OGR interface)
-  
-  This function simply calls V1_delete_line_ogr() and V1_write_line_ogr().
-  
-  \param Map pointer to Map_info structure
-  \param offset feature offset
-  \param type feature type (see V1_write_line_ogr() for supported types)
-  \param points pointer to line_pnts structure (feature geometry)
-  \param cats pointer to line_cats structure (feature categories)
-  
-  \return feature offset (rewriten feature)
-  \return -1 on error
-*/
-off_t V1_rewrite_line_ogr(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_ogr(): line=%d type=%d offset=%lu",
-	    line, type, offset);
-#ifdef HAVE_OGR
-    if (type != V1_read_line_ogr(Map, NULL, NULL, offset)) {
-	G_warning(_("Unable to rewrite feature (incompatible feature types)"));
-	return -1;
-    }
+  \brief Writes attributes
 
 
-    /* delete old */
-    V1_delete_line_ogr(Map, offset);
+  \param driver pointer to dbDriver
+  \param Fi pointer to field_info struct
+  \param[in,out] Ogr_layer OGR layer
+  \param[in,out] Ogr_feature OGR feature to modify
 
 
-    return V1_write_line_ogr(Map, type, points, cats);
-#else
-    G_fatal_error(_("GRASS is not compiled with OGR support"));
-    return -1;
-#endif
-}
-
-/*!
-  \brief Deletes feature at the given offset on level 1 (OGR interface)
-  
-  \param Map pointer Map_info structure
-  \param offset offset of feature to be deleted
-  
-  \return  0 on success
+  \return 1 on success
+  \return 0 no attributes
   \return -1 on error
   \return -1 on error
 */
 */
-int V1_delete_line_ogr(struct Map_info *Map, off_t offset)
-{
-#ifdef HAVE_OGR
-    struct Format_info_ogr *ogr_info;
-    
-    G_debug(3, "V1_delete_line_ogr(), offset = %lu", (unsigned long) offset);
-
-    ogr_info = &(Map->fInfo.ogr);
-    
-    if (!ogr_info->layer) {
-	G_warning(_("OGR layer not defined"));
-	return -1;
-    }
-    
-    if (offset >= ogr_info->offset.array_num) {
-	G_warning(_("Invalid offset (%d)"), offset);
-	return -1;
-    }
-    
-    if (OGR_L_DeleteFeature(ogr_info->layer,
-			    ogr_info->offset.array[offset]) != OGRERR_NONE)
-	G_warning(_("Unable to delete feature"));
-	return -1;
-    
-    return 0;
-#else
-    G_fatal_error(_("GRASS is not compiled with OGR support"));
-    return -1;
-#endif
-}
-
-#ifdef HAVE_OGR
 int write_attributes(dbDriver *driver, int cat, const struct field_info *Fi,
 int write_attributes(dbDriver *driver, int cat, const struct field_info *Fi,
 		     OGRLayerH Ogr_layer, OGRFeatureH Ogr_feature)
 		     OGRLayerH Ogr_layer, OGRFeatureH Ogr_feature)
 {
 {
@@ -321,13 +385,15 @@ int write_attributes(dbDriver *driver, int cat, const struct field_info *Fi,
 
 
     /* select data */
     /* select data */
     if (db_open_select_cursor(driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
     if (db_open_select_cursor(driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
-	G_fatal_error(_("Unable to select attributes for category %d"),
-		      cat);
+        G_warning(_("Unable to select attributes for category %d"),
+                  cat);
+        return -1;
     }
     }
     
     
     if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
     if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
-	G_fatal_error(_("Unable to fetch data from table <%s>"),
-		      Fi->table);
+	G_warning(_("Unable to fetch data from table <%s>"),
+                  Fi->table);
+        return -1;
     }
     }
     
     
     if (!more) {
     if (!more) {

+ 55 - 77
lib/vector/Vlib/write_pg.c

@@ -168,7 +168,7 @@ off_t V1_rewrite_line_pg(struct Map_info * Map,
                          const struct line_pnts * points,
                          const struct line_pnts * points,
                          const struct line_cats * cats)
                          const struct line_cats * cats)
 {
 {
-    G_debug(3, "V1_rewrite_line_pg(): line=%d type=%d offset=%lu",
+    G_debug(3, "V1_rewrite_line_pg(): line=%d type=%d offset=%"PRI_OFF_T,
             line, type, offset);
             line, type, offset);
 #ifdef HAVE_POSTGRES
 #ifdef HAVE_POSTGRES
     if (type != V1_read_line_pg(Map, NULL, NULL, offset)) {
     if (type != V1_read_line_pg(Map, NULL, NULL, offset)) {
@@ -206,7 +206,7 @@ off_t V1_rewrite_line_pg(struct Map_info * Map,
 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=%lu",
+    G_debug(3, "V2_rewrite_line_pg(): line=%d type=%d offset=%"PRI_OFF_T,
             line, type, old_offset);
             line, type, old_offset);
 #ifdef HAVE_POSTGRES
 #ifdef HAVE_POSTGRES
     const char *schema_name, *table_name, *keycolumn;
     const char *schema_name, *table_name, *keycolumn;
@@ -378,8 +378,8 @@ int V2_delete_line_pg(struct Map_info *Map, int line)
             /* first remove references to this edge */
             /* first remove references to this edge */
             /* (1) left next edge */
             /* (1) left next edge */
             sprintf(stmt, "UPDATE \"%s\".\"%s\" SET abs_next_left_edge = edge_id, "
             sprintf(stmt, "UPDATE \"%s\".\"%s\" SET abs_next_left_edge = edge_id, "
-                    "next_left_edge = -edge_id WHERE abs_next_left_edge = %ld",
-                    pg_info->toposchema_name, table_name, Line->offset);
+                    "next_left_edge = -edge_id WHERE abs_next_left_edge = %d",
+                    pg_info->toposchema_name, table_name, (int)Line->offset);
             if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
             if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
                 Vect__execute_pg(pg_info->conn, "ROLLBACK");
                 Vect__execute_pg(pg_info->conn, "ROLLBACK");
                 return -1;
                 return -1;
@@ -387,8 +387,8 @@ int V2_delete_line_pg(struct Map_info *Map, int line)
 
 
             /* (2) right next edge */
             /* (2) right next edge */
             sprintf(stmt, "UPDATE \"%s\".\"%s\" SET abs_next_right_edge = edge_id, "
             sprintf(stmt, "UPDATE \"%s\".\"%s\" SET abs_next_right_edge = edge_id, "
-                    "next_right_edge = edge_id WHERE abs_next_right_edge = %ld",
-                    pg_info->toposchema_name, table_name, Line->offset);
+                    "next_right_edge = edge_id WHERE abs_next_right_edge = %d",
+                    pg_info->toposchema_name, table_name, (int)Line->offset);
             if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
             if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
                 Vect__execute_pg(pg_info->conn, "ROLLBACK");
                 Vect__execute_pg(pg_info->conn, "ROLLBACK");
                 return -1;
                 return -1;
@@ -405,8 +405,8 @@ int V2_delete_line_pg(struct Map_info *Map, int line)
             return -1;
             return -1;
 
 
         /* delete record from topology table */
         /* delete record from topology table */
-        sprintf(stmt, "DELETE FROM \"%s\".\"%s\" WHERE %s_id = %ld",
-                pg_info->toposchema_name, table_name, keycolumn, Line->offset);
+        sprintf(stmt, "DELETE FROM \"%s\".\"%s\" WHERE %s_id = %d",
+                pg_info->toposchema_name, table_name, keycolumn, (int)Line->offset);
         if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
         if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
             G_warning(_("Unable to delete feature (%s) %d"), keycolumn,
             G_warning(_("Unable to delete feature (%s) %d"), keycolumn,
                       line);
                       line);
@@ -450,6 +450,7 @@ int V2_delete_line_pg(struct Map_info *Map, int line)
 #endif
 #endif
 }
 }
 
 
+#ifdef HAVE_POSTGRES
 /*!
 /*!
    \brief Writes node on topological level (PostGIS Topology interface, internal use only)
    \brief Writes node on topological level (PostGIS Topology interface, internal use only)
 
 
@@ -461,7 +462,6 @@ int V2_delete_line_pg(struct Map_info *Map, int line)
 */
 */
 off_t V2__write_node_pg(struct Map_info *Map, const struct line_pnts *points)
 off_t V2__write_node_pg(struct Map_info *Map, const struct line_pnts *points)
 {
 {
-#ifdef HAVE_POSTGRES
     struct Format_info_pg *pg_info;
     struct Format_info_pg *pg_info;
 
 
     pg_info = &(Map->fInfo.pg);
     pg_info = &(Map->fInfo.pg);
@@ -470,63 +470,38 @@ off_t V2__write_node_pg(struct Map_info *Map, const struct line_pnts *points)
         return -1; /* PostGIS Topology required */
         return -1; /* PostGIS Topology required */
     
     
     return write_line_tp(Map, GV_POINT, TRUE, points, NULL);
     return write_line_tp(Map, GV_POINT, TRUE, points, NULL);
-#else
-    G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
-    return -1;
-#endif
 }
 }
 
 
 /*!
 /*!
-   \brief Writes area on topological level (PostGIS Simple Features interface, internal use only)
+   \brief Writes area on topological level (PostGIS Simple Features
+   interface, internal use only)
 
 
    \param Map pointer to Map_info structure
    \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
+   \param points feature geometry (exterior + interior rings)
+   \param nparts number of parts including exterior ring
+   \param cats feature categories
    
    
-   \return feature offset into file
+   \return feature offset
    \return -1 on error
    \return -1 on error
 */
 */
 off_t V2__write_area_pg(struct Map_info *Map, 
 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)
+                        const struct line_pnts **points, int nparts,
+                        const struct line_cats *cats)
 {
 {
-#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
+    return write_line_sf(Map, GV_BOUNDARY, points, nparts, cats);
 }
 }
 
 
-#ifdef HAVE_POSTGRES
 /*!
 /*!
   \brief Write vector features as PostGIS simple feature element
   \brief Write vector features as PostGIS simple feature element
   
   
-  \return 0 on success
-  \return -1 on error
+   \param Map pointer to Map_info structure
+   \param type feature type (GV_POINT, GV_LINE, ...)
+   \param points feature geometry (exterior + interior rings for polygonsx)
+   \param nparts number of parts
+   \param cats feature categories
+
+   \return feature offset
+   \return -1 on error
 */
 */
 off_t write_line_sf(struct Map_info *Map, int type,
 off_t write_line_sf(struct Map_info *Map, int type,
                     const struct line_pnts **points, int nparts,
                     const struct line_pnts **points, int nparts,
@@ -544,6 +519,9 @@ off_t write_line_sf(struct Map_info *Map, int type,
     pg_info = &(Map->fInfo.pg);
     pg_info = &(Map->fInfo.pg);
     offset_info = &(pg_info->offset);
     offset_info = &(pg_info->offset);
 
 
+    if (nparts < 1)
+        return -1;
+    
     /* check required PG settings */
     /* check required PG settings */
     if (!pg_info->conn) {
     if (!pg_info->conn) {
         G_warning(_("No connection defined"));
         G_warning(_("No connection defined"));
@@ -1472,8 +1450,8 @@ int insert_topo_element(struct Map_info *Map, int line, int type,
         nle = -Line->offset;
         nle = -Line->offset;
         nre = Line->offset;
         nre = Line->offset;
         
         
-        G_debug(3, "new edge: id=%lu next_left_edge=%d next_right_edge=%d",
-                Line->offset, nle, nre);
+        G_debug(3, "new edge: id=%d next_left_edge=%d next_right_edge=%d",
+                (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 (geom, 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, "
@@ -1579,15 +1557,15 @@ int update_next_edge(struct Map_info* Map, int nlines, int line)
     
     
     if (next_line < 0) {
     if (next_line < 0) {
         sprintf(stmt, "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
         sprintf(stmt, "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
-                "abs_next_left_edge = %d WHERE edge_id = %lu AND abs_next_left_edge = %lu",
-                pg_info->toposchema_name, edge, abs(edge), Line_next->offset,  Line_next->offset);
-        G_debug(3, "update edge=%lu next_left_edge=%d (?)", Line_next->offset, edge);
+                "abs_next_left_edge = %d WHERE edge_id = %d AND abs_next_left_edge = %d",
+                pg_info->toposchema_name, edge, abs(edge), (int)Line_next->offset, (int)Line_next->offset);
+        G_debug(3, "update edge=%d next_left_edge=%d (?)", (int)Line_next->offset, edge);
     }
     }
     else {
     else {
         sprintf(stmt, "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
         sprintf(stmt, "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
-                "abs_next_right_edge = %d WHERE edge_id = %lu AND abs_next_right_edge = %lu",
-                pg_info->toposchema_name, edge, abs(edge), Line_next->offset, Line_next->offset);
-        G_debug(3, "update edge=%lu next_right_edge=%d (?)", Line_next->offset, edge);
+                "abs_next_right_edge = %d WHERE edge_id = %d AND abs_next_right_edge = %d",
+                pg_info->toposchema_name, edge, abs(edge), (int)Line_next->offset, (int)Line_next->offset);
+        G_debug(3, "update edge=%d next_right_edge=%d (?)", (int)Line_next->offset, edge);
     }
     }
     
     
     if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
     if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
@@ -1606,15 +1584,15 @@ int update_next_edge(struct Map_info* Map, int nlines, int line)
         
         
         if (next_line < 0) {
         if (next_line < 0) {
             sprintf(stmt, "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
             sprintf(stmt, "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
-                    "abs_next_left_edge = %d WHERE edge_id = %lu",
-                    pg_info->toposchema_name, edge, abs(edge), Line_next->offset);
-            G_debug(3, "update edge=%lu next_left_edge=%d", Line_next->offset, edge);
+                    "abs_next_left_edge = %d WHERE edge_id = %d",
+                    pg_info->toposchema_name, edge, abs(edge), (int)Line_next->offset);
+            G_debug(3, "update edge=%d next_left_edge=%d", (int)Line_next->offset, edge);
         }
         }
         else {
         else {
             sprintf(stmt, "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
             sprintf(stmt, "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
-                    "abs_next_right_edge = %d WHERE edge_id = %lu",
-                    pg_info->toposchema_name, edge, abs(edge), Line_next->offset);
-            G_debug(3, "update edge=%lu next_right_edge=%d", Line_next->offset, edge);
+                    "abs_next_right_edge = %d WHERE edge_id = %d",
+                    pg_info->toposchema_name, edge, abs(edge), (int)Line_next->offset);
+            G_debug(3, "update edge=%d next_right_edge=%d", (int)Line_next->offset, edge);
         }
         }
      
      
         if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
         if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
@@ -1807,25 +1785,25 @@ int update_topo_edge(struct Map_info *Map, int line)
         sprintf(stmt, "UPDATE \"%s\".edge_data SET "
         sprintf(stmt, "UPDATE \"%s\".edge_data SET "
                 "next_left_edge = %d, abs_next_left_edge = %d, "
                 "next_left_edge = %d, abs_next_left_edge = %d, "
                 "next_right_edge = %d, abs_next_right_edge = %d "
                 "next_right_edge = %d, abs_next_right_edge = %d "
-                "WHERE edge_id = %lu", pg_info->toposchema_name,
-                nle, abs(nle), nre, abs(nre), Line->offset);
+                "WHERE edge_id = %d", pg_info->toposchema_name,
+                nle, abs(nle), nre, abs(nre), (int)Line->offset);
     }
     }
     else if (nle != 0) {
     else if (nle != 0) {
         /* update next left edge only */
         /* update next left edge only */
         sprintf(stmt, "UPDATE \"%s\".edge_data SET "
         sprintf(stmt, "UPDATE \"%s\".edge_data SET "
                 "next_left_edge = %d, abs_next_left_edge = %d "
                 "next_left_edge = %d, abs_next_left_edge = %d "
-                "WHERE edge_id = %lu", pg_info->toposchema_name,
-                nle, abs(nle), Line->offset);
+                "WHERE edge_id = %d", pg_info->toposchema_name,
+                nle, abs(nle), (int)Line->offset);
     }
     }
     else {
     else {
         /* update next right edge only */
         /* update next right edge only */
         sprintf(stmt, "UPDATE \"%s\".edge_data SET "
         sprintf(stmt, "UPDATE \"%s\".edge_data SET "
                 "next_right_edge = %d, abs_next_right_edge = %d "
                 "next_right_edge = %d, abs_next_right_edge = %d "
-                "WHERE edge_id = %lu", pg_info->toposchema_name,
-                nre, abs(nre), Line->offset);
+                "WHERE edge_id = %d", pg_info->toposchema_name,
+                nre, abs(nre), (int)Line->offset);
     }
     }
-    G_debug(3, "update edge=%lu next_left_edge=%d next_right_edge=%d",
-            Line->offset, nle, nre);
+    G_debug(3, "update edge=%d next_left_edge=%d next_right_edge=%d",
+            (int)Line->offset, nle, nre);
     
     
     if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
     if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
         /* rollback transaction */
         /* rollback transaction */
@@ -1898,10 +1876,10 @@ int update_topo_face(struct Map_info *Map, int line)
             
             
             sprintf(stmt, "UPDATE \"%s\".edge_data SET "
             sprintf(stmt, "UPDATE \"%s\".edge_data SET "
                     "left_face = %d, right_face = %d "
                     "left_face = %d, right_face = %d "
-                    "WHERE edge_id = %lu", pg_info->toposchema_name,
+                    "WHERE edge_id = %d", pg_info->toposchema_name,
                     topo_i->left > 0 ? topo_i->left : 0,
                     topo_i->left > 0 ? topo_i->left : 0,
                     topo_i->right > 0 ? topo_i->right : 0,
                     topo_i->right > 0 ? topo_i->right : 0,
-                    Line_i->offset);
+                    (int) Line_i->offset);
             G_debug(2, "SQL: %s", stmt);
             G_debug(2, "SQL: %s", stmt);
             
             
             if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
             if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
@@ -1914,8 +1892,8 @@ int update_topo_face(struct Map_info *Map, int line)
         if (Area->centroid > 0) {
         if (Area->centroid > 0) {
             Line_i = Map->plus.Line[Area->centroid];
             Line_i = Map->plus.Line[Area->centroid];
             sprintf(stmt, "UPDATE \"%s\".node SET containing_face = %d "
             sprintf(stmt, "UPDATE \"%s\".node SET containing_face = %d "
-                    "WHERE node_id = %lu", pg_info->toposchema_name,
-                    face[s], Line_i->offset);
+                    "WHERE node_id = %d", pg_info->toposchema_name,
+                    face[s], (int)Line_i->offset);
             G_debug(2, "SQL: %s", stmt);
             G_debug(2, "SQL: %s", stmt);
             
             
             if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
             if(Vect__execute_pg(pg_info->conn, stmt) == -1) {

+ 47 - 3
lib/vector/Vlib/write_sfa.c

@@ -24,9 +24,15 @@
 #include <grass/vector.h>
 #include <grass/vector.h>
 #include <grass/glocale.h>
 #include <grass/glocale.h>
 
 
+#include "local_proto.h"
+
+#ifdef HAVE_POSTGRES
+#include "pg_local_proto.h"
+#endif
+
 #if defined HAVE_OGR || defined HAVE_POSTGRES
 #if defined HAVE_OGR || defined HAVE_POSTGRES
-void V2__add_line_to_topo_sfa(struct Map_info *, int, const struct line_pnts *,
-			      const struct line_cats *);
+static void V2__add_line_to_topo_sfa(struct Map_info *, int, const struct line_pnts *,
+                                     const struct line_cats *);
 #endif
 #endif
 
 
 /*!
 /*!
@@ -142,7 +148,7 @@ off_t V2_write_line_sfa(struct Map_info *Map, int type,
 off_t V2_rewrite_line_sfa(struct Map_info *Map, int line, int type, off_t offset,
 off_t V2_rewrite_line_sfa(struct Map_info *Map, int line, int type, off_t 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_sfa(): line=%d type=%d offset=%lu",
+    G_debug(3, "V2_rewrite_line_sfa(): line=%d type=%d offset=%"PRI_OFF_T,
 	    line, type, offset);
 	    line, type, offset);
 
 
     if (line < 1 || line > Map->plus.n_lines) {
     if (line < 1 || line > Map->plus.n_lines) {
@@ -262,6 +268,44 @@ int V2_delete_line_sfa(struct Map_info *Map, int line)
 #endif
 #endif
 }
 }
 
 
+/*!
+   \brief Writes area on topological level (Simple Features interface,
+   internal use only)
+
+   \param Map pointer to Map_info structure
+   \param points feature geometry (exterior + interior rings)
+   \param nparts number of parts including exterior ring
+   \param cats feature categories
+   
+   \return feature offset
+   \return -1 on error
+*/
+off_t V2__write_area_sfa(struct Map_info *Map, 
+                         const struct line_pnts **points, int nparts,
+                         const struct line_cats *cats)
+{
+    if (Map->format == GV_FORMAT_OGR) {
+#ifdef HAVE_OGR
+        return V2__write_area_ogr(Map, points, nparts, cats);
+#else
+        G_fatal_error(_("GRASS is not compiled with OGR support"));
+        return -1;
+#endif
+    }
+    else if (Map->format == GV_FORMAT_POSTGIS) {
+#ifdef HAVE_POSTGRES
+        return V2__write_area_pg(Map, points, nparts, cats);
+#else
+        G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
+        return -1;
+#endif
+    }
+    else {
+        G_warning(_("Unsupported vector map format (%d)"), Map->format);
+    }
+    return -1;
+}
+
 #if defined HAVE_OGR || defined HAVE_POSTGRES
 #if defined HAVE_OGR || defined HAVE_POSTGRES
 /*!
 /*!
   \brief Add feature to topo file (internal use only)
   \brief Add feature to topo file (internal use only)