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

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Mar 10 15:07:05 EST 2012


Author: martinl
Date: 2012-03-10 12:07:05 -0800 (Sat, 10 Mar 2012)
New Revision: 51027

Added:
   grass/trunk/lib/vector/Vlib/write_pg.c
   grass/trunk/lib/vector/Vlib/write_sfa.c
Modified:
   grass/trunk/include/defs/vector.h
   grass/trunk/include/vect/dig_structs.h
   grass/trunk/lib/vector/Vlib/build.c
   grass/trunk/lib/vector/Vlib/open.c
   grass/trunk/lib/vector/Vlib/open_pg.c
   grass/trunk/lib/vector/Vlib/pg_local_proto.h
   grass/trunk/lib/vector/Vlib/read.c
   grass/trunk/lib/vector/Vlib/read_pg.c
   grass/trunk/lib/vector/Vlib/write.c
   grass/trunk/lib/vector/Vlib/write_nat.c
   grass/trunk/lib/vector/Vlib/write_ogr.c
Log:
vlib(pg): implement V1_write_line_pg() and V2_write_line_sfa()


Modified: grass/trunk/include/defs/vector.h
===================================================================
--- grass/trunk/include/defs/vector.h	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/include/defs/vector.h	2012-03-10 20:07:05 UTC (rev 51027)
@@ -523,7 +523,9 @@
 			const struct line_cats *);
 off_t V1_write_line_ogr(struct Map_info *, int, const struct line_pnts *,
 			const struct line_cats *);
-off_t V2_write_line_ogr(struct Map_info *, int, const struct line_pnts *,
+off_t V1_write_line_pg(struct Map_info *, int, const struct line_pnts *,
+		       const struct line_cats *);
+off_t V2_write_line_sfa(struct Map_info *, int, const struct line_pnts *,
 			const struct line_cats *);
 off_t V1_rewrite_line_nat(struct Map_info *, int, int, off_t,
 			  const struct line_pnts *, const struct line_cats *);

Modified: grass/trunk/include/vect/dig_structs.h
===================================================================
--- grass/trunk/include/vect/dig_structs.h	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/include/vect/dig_structs.h	2012-03-10 20:07:05 UTC (rev 51027)
@@ -604,7 +604,19 @@
     /*!
       \brief Geometry column
     */
-    char    *geom_column;       
+    char    *geom_column;
+    /*!
+      \brief Feature type
+    */
+    SF_FeatureType feature_type;
+    /*!
+      \brief Coordinates dimension
+    */
+    int      coor_dim;
+    /*!
+      \brief SRS ID
+    */
+    int      srid;
 #ifdef HAVE_POSTGRES
     /*!
       \brief PGconn object (generated by PQconnectdb)

Modified: grass/trunk/lib/vector/Vlib/build.c
===================================================================
--- grass/trunk/lib/vector/Vlib/build.c	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/lib/vector/Vlib/build.c	2012-03-10 20:07:05 UTC (rev 51027)
@@ -22,12 +22,6 @@
 
 #define SEP "-----------------------------------\n"
 
-static int build_dummy()
-{
-    G_warning(_("Not implemented"));
-    return -1;
-}
-
 #if !defined HAVE_OGR || !defined HAVE_POSTGRES
 static int format()
 {
@@ -704,11 +698,12 @@
 
     G_debug(3, "Vect_build(): build = %d", build);
 
-    /* If topology is already build (map on level2), set level to 1 so that lines will
-     *  be read by V1_read_ (all lines) */
-    Map->level = 1;		/* may be not needed, because  V1_read is used directly by Vect_build_ */
+    /* If topology is already build (map on level2), set level to 1 so
+     * that lines will be read by V1_read_ (all lines) */
+    Map->level = 1; /* may be not needed, because V1_read is used
+		       directly by Vect_build_ */
     if (Map->format != GV_FORMAT_OGR_DIRECT)
-	Map->support_updated = 1;
+	Map->support_updated = TRUE;
 
     if (Map->plus.Spidx_built == FALSE)
 	Vect_open_sidx(Map, 2);

Modified: grass/trunk/lib/vector/Vlib/open.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open.c	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/lib/vector/Vlib/open.c	2012-03-10 20:07:05 UTC (rev 51027)
@@ -368,7 +368,8 @@
     }
 
     /* open level 1 files / sources (format specific) */
-    if (!head_only || ogr_mapset) {		/* no need to open coordinates */
+    if (!head_only || ogr_mapset || format == GV_FORMAT_POSTGIS) {
+	/* no need to open coordinates */
 	if (0 != (*Open_old_array[format][1]) (Map, update)) {	/* cannot open */
 	    if (level == 2) {	/* support files opened */
 		dig_free_plus(&(Map->plus));
@@ -470,21 +471,27 @@
     
     /* delete support files if native format was opened for update (not head_only) */
     if (update && !head_only) {
-	char file_path[2000];
+	char file_path[GPATH_MAX];
 
 	sprintf(buf, "%s/%s", GV_DIRECTORY, name);
 
 	G_file_name(file_path, buf, GV_TOPO_ELEMENT, G_mapset());
-	if (access(file_path, F_OK) == 0)	/* file exists? */
+	if (access(file_path, F_OK) == 0)	/* topo file exists? */
 	    unlink(file_path);
 
 	G_file_name(file_path, buf, GV_SIDX_ELEMENT, G_mapset());
-	if (access(file_path, F_OK) == 0)	/* file exists? */
+	if (access(file_path, F_OK) == 0)	/* sidx file exists? */
 	    unlink(file_path);
 
 	G_file_name(file_path, buf, GV_CIDX_ELEMENT, G_mapset());
-	if (access(file_path, F_OK) == 0)	/* file exists? */
+	if (access(file_path, F_OK) == 0)	/* cidx file exists? */
 	    unlink(file_path);
+
+	if (format == GV_FORMAT_OGR || format == GV_FORMAT_POSTGIS) {
+	    G_file_name(file_path, buf, GV_FIDX_ELEMENT, G_mapset());
+	    if (access(file_path, F_OK) == 0)	/* fidx file exists? */
+		unlink(file_path);
+	}
     }
 
     return level;

Modified: grass/trunk/lib/vector/Vlib/open_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open_pg.c	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/lib/vector/Vlib/open_pg.c	2012-03-10 20:07:05 UTC (rev 51027)
@@ -58,6 +58,32 @@
 
     return key_column;
 }
+
+static SF_FeatureType ftype_from_string(const char *type)
+{
+    SF_FeatureType sf_type;
+
+    if (G_strcasecmp(type, "POINT") == 0)
+	return SF_POINT;
+    else if (G_strcasecmp(type, "LINESTRING") == 0)
+	return SF_LINESTRING;
+    else if (G_strcasecmp(type, "POLYGON") == 0)
+	return SF_POLYGON;
+    else if (G_strcasecmp(type, "MULTIPOINT") == 0)
+	return SF_MULTIPOINT;
+    else if (G_strcasecmp(type, "MULTILINESTRING") == 0)
+	return SF_MULTILINESTRING;
+    else if (G_strcasecmp(type, "MULTIPOLYGON") == 0)
+	return SF_MULTIPOLYGON;
+    else if (G_strcasecmp(type, "GEOMETRYCOLLECTION") == 0)
+	return SF_GEOMETRYCOLLECTION;
+    
+    return SF_UNKNOWN;
+    
+    G_debug(3, "ftype_from_string(): type='%s' -> %d", type, sf_type);
+    
+    return sf_type;
+}
 #endif
 
 /*!
@@ -113,7 +139,8 @@
     }
     
     /* get fid and geometry column */
-    db_set_string(&stmt, "SELECT f_table_name, f_geometry_column "
+    db_set_string(&stmt, "SELECT f_table_name, f_geometry_column,"
+		  "coord_dimension,srid,type "
 		  "FROM geometry_columns");
     G_debug(2, "SQL: %s", db_get_string(&stmt));
     
@@ -127,10 +154,18 @@
     found = FALSE;
     for (i = 0; i < ntables; i++) {
 	if (strcmp(PQgetvalue(res, i, 0), pg_info->table_name) == 0) {
+	    /* geometry column */
 	    pg_info->geom_column = G_store(PQgetvalue(res, i, 1));
 	    G_debug(3, "\t-> table = %s column = %s", pg_info->table_name,
 		    pg_info->geom_column);
+	    /* fid column */
 	    pg_info->fid_column = get_key_column(pg_info);
+	    /* coordinates dimension */
+	    pg_info->coor_dim = atoi(PQgetvalue(res, i, 2));
+	    /* SRS ID */
+	    pg_info->srid = atoi(PQgetvalue(res, i, 3));
+	    /* feature type */
+	    pg_info->feature_type = ftype_from_string(PQgetvalue(res, i, 4));
 	    found = TRUE;
 	    break;
 	}

Modified: grass/trunk/lib/vector/Vlib/pg_local_proto.h
===================================================================
--- grass/trunk/lib/vector/Vlib/pg_local_proto.h	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/lib/vector/Vlib/pg_local_proto.h	2012-03-10 20:07:05 UTC (rev 51027)
@@ -1,9 +1,41 @@
 #ifndef __PG_LOCAL_PROTO_H__
 #define __PG_LOCAL_PROTO_H__
 
+#include <grass/vector.h>
+
 #ifdef HAVE_POSTGRES
 #include <libpq-fe.h>
 
+#define CURSOR_PAGE 500
+
+#define SWAP32(x) \
+        ((unsigned int)( \
+            (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
+            (((unsigned int)(x) & (unsigned int)0x0000ff00UL) <<  8) | \
+            (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >>  8) | \
+            (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
+
+#define SWAPDOUBLE(x) \
+{                                                                 \
+    unsigned char temp, *data = (unsigned char *) (x);            \
+                                                                  \
+    temp = data[0];                                               \
+    data[0] = data[7];                                            \
+    data[7] = temp;                                               \
+    temp = data[1];                                               \
+    data[1] = data[6];                                            \
+    data[6] = temp;                                               \
+    temp = data[2];                                               \
+    data[2] = data[5];                                            \
+    data[5] = temp;                                               \
+    temp = data[3];                                               \
+    data[3] = data[4];                                            \
+    data[4] = temp;                                               \
+}                                                                    
+
+#define LSBWORD32(x)      (x)
+#define MSBWORD32(x)      SWAP32(x)
+
 /* used for building pseudo-topology (requires some extra information
  * about lines in cache) */
 struct feat_parts

Modified: grass/trunk/lib/vector/Vlib/read.c
===================================================================
--- grass/trunk/lib/vector/Vlib/read.c	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/lib/vector/Vlib/read.c	2012-03-10 20:07:05 UTC (rev 51027)
@@ -21,6 +21,8 @@
 
 static int read_dummy()
 {
+    G_warning("Vect_read_line() %s",
+	      _("for this format/level not supported"));
     return -1;
 }
 

Modified: grass/trunk/lib/vector/Vlib/read_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/read_pg.c	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/lib/vector/Vlib/read_pg.c	2012-03-10 20:07:05 UTC (rev 51027)
@@ -27,33 +27,6 @@
 #ifdef HAVE_POSTGRES
 #include "pg_local_proto.h"
 
-#define CURSOR_PAGE 500
-
-#define SWAP32(x) \
-        ((unsigned int)( \
-            (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
-            (((unsigned int)(x) & (unsigned int)0x0000ff00UL) <<  8) | \
-            (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >>  8) | \
-            (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
-
-#define SWAPDOUBLE(x) \
-{                                                                 \
-    unsigned char temp, *data = (unsigned char *) (x);            \
-                                                                  \
-    temp = data[0];                                               \
-    data[0] = data[7];                                            \
-    data[7] = temp;                                               \
-    temp = data[1];                                               \
-    data[1] = data[6];                                            \
-    data[6] = temp;                                               \
-    temp = data[2];                                               \
-    data[2] = data[5];                                            \
-    data[5] = temp;                                               \
-    temp = data[3];                                               \
-    data[3] = data[4];                                            \
-    data[4] = temp;                                               \
-}                                                                    
-
 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);

Modified: grass/trunk/lib/vector/Vlib/write.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write.c	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/lib/vector/Vlib/write.c	2012-03-10 20:07:05 UTC (rev 51027)
@@ -5,13 +5,20 @@
 
    Higher level functions for reading/writing/manipulating vectors.
 
-   (C) 2001-2010 by the GRASS Development Team
+   Operations:
+    - Add feature
+    - Rewrite feature
+    - Delete feature
+    - Restore feature
 
+   (C) 2001-2010, 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.
 
    \author Radim Blazek
-   \author Updated by Martin Landa <landa.martin gmail.com> (restore lines, OGR support)
+   \author Updated by Martin Landa <landa.martin gmail.com>
+   (restore lines, OGR & PostGIS support)
  */
 
 #include <sys/types.h>
@@ -44,7 +51,7 @@
     return -1;
 }
 
-#ifndef HAVE_OGR
+#if !defined HAVE_OGR || !defined HAVE_POSTGRES
 static int format()
 {
     G_fatal_error(_("Requested format is not compiled in this version"));
@@ -56,55 +63,75 @@
     G_fatal_error(_("Requested format is not compiled in this version"));
     return 0;
 }
-
 #endif
 
 static off_t (*Vect_write_line_array[][3]) () = {
     {
-    write_dummy, V1_write_line_nat, V2_write_line_nat}
+	write_dummy, V1_write_line_nat, V2_write_line_nat}
 #ifdef HAVE_OGR
     , {
-    write_dummy, V1_write_line_ogr, V2_write_line_ogr}
+	write_dummy, V1_write_line_ogr, V2_write_line_sfa}
     , {
-    write_dummy, V1_write_line_ogr, V2_write_line_ogr}
+	write_dummy, V1_write_line_ogr, V2_write_line_sfa}
 #else
     , {
-    write_dummy, format_l, format_l}
+	write_dummy, format_l, format_l}
     , {
-    write_dummy, format_l, format_l}
+	write_dummy, format_l, format_l}
 #endif
+#ifdef HAVE_POSTGRES
+    , {
+	write_dummy, V1_write_line_pg, V2_write_line_sfa}
+#else
+    , {
+	write_dummy, format_l, format_l}
+#endif
 };
 
 static off_t (*Vect_rewrite_line_array[][3]) () = {
     {
-    rewrite_dummy, V1_rewrite_line_nat, V2_rewrite_line_nat}
+	rewrite_dummy, V1_rewrite_line_nat, V2_rewrite_line_nat}
 #ifdef HAVE_OGR
     , {
-    rewrite_dummy, V1_rewrite_line_ogr, V2_rewrite_line_ogr}
+	rewrite_dummy, V1_rewrite_line_ogr, V2_rewrite_line_ogr}
     , {
-    rewrite_dummy, V1_rewrite_line_ogr, V2_rewrite_line_ogr}
+	rewrite_dummy, V1_rewrite_line_ogr, V2_rewrite_line_ogr}
 #else
     , {
-    rewrite_dummy, format, format}
+	rewrite_dummy, format_l, format_l}
     , {
-    rewrite_dummy, format, format}
+	rewrite_dummy, format_l, format_l}
 #endif
+#ifdef HAVE_POSTGRES
+    , {
+	rewrite_dummy, rewrite_dummy, rewrite_dummy}
+#else
+    , {
+	rewrite_dummy, format_l, format_l}
+#endif
 };
 
 static int (*Vect_delete_line_array[][3]) () = {
     {
-    delete_dummy, V1_delete_line_nat, V2_delete_line_nat}
+	delete_dummy, V1_delete_line_nat, V2_delete_line_nat}
 #ifdef HAVE_OGR
     , {
-    delete_dummy, V1_delete_line_ogr, V2_delete_line_ogr}
+	delete_dummy, V1_delete_line_ogr, V2_delete_line_ogr}
     , {
-    delete_dummy, V1_delete_line_ogr, V2_delete_line_ogr}
+	delete_dummy, V1_delete_line_ogr, V2_delete_line_ogr}
 #else
     , {
-    delete_dummy, format, format}
+	delete_dummy, format, format}
     , {
-    delete_dummy, format, format}
+	delete_dummy, format, format}
 #endif
+#ifdef HAVE_POSTGRES
+    , {
+	delete_dummy, delete_dummy, delete_dummy}
+#else
+    , {
+	delete_dummy, format, format}
+#endif
 };
 
 static int (*Vect_restore_line_array[][3]) () = {
@@ -112,15 +139,22 @@
     restore_dummy, restore_dummy, V2_restore_line_nat}
 #ifdef HAVE_OGR
     , {
-    restore_dummy, restore_dummy, restore_dummy}
+	restore_dummy, restore_dummy, restore_dummy}
     , {
-    restore_dummy, restore_dummy, restore_dummy}
+	restore_dummy, restore_dummy, restore_dummy}
 #else
     , {
-    restore_dummy, format, format}
+	restore_dummy, format, format}
     , {
-    restore_dummy, format, format}
+	restore_dummy, format, format}
 #endif
+#ifdef HAVE_POSTGRES
+    , {
+	restore_dummy, restore_dummy, restore_dummy}
+#else
+    , {
+	restore_dummy, format, format}
+#endif
 };
 
 /*!
@@ -130,8 +164,8 @@
 
    The function calls G_fatal_error() on error.
 
-   \param Map pointer to vector map
-   \param type feature type
+   \param Map pointer to Map_info structure
+   \param type feature type (GV_POINT, GV_LINE, ...)
    \param points feature geometry
    \param cats feature categories
 
@@ -153,9 +187,9 @@
 	Map->plus.cidx_up_to_date = 0;
     }
 
-    offset =
+    offset = 
 	(*Vect_write_line_array[Map->format][Map->level]) (Map, type, points,
-						      cats);
+							   cats);
 
     if (offset == -1)
 	G_fatal_error(_("Unable to write feature (negative offset)"));
@@ -174,9 +208,9 @@
 
    This function calls G_fatal_error() on error.
 
-   \param Map pointer to vector map
+   \param Map pointer to Map_info structure
    \param line feature id
-   \param type feature type
+   \param type feature type (GV_POINT, GV_LINE, ...)
    \param points feature geometry
    \param cats feature categories
 
@@ -216,7 +250,7 @@
 
    This function calls G_fatal_error() on error.
 
-   \param Map pointer to vector map
+   \param Map pointer to Map_info structure
    \param line feature id
 
    \return 0 on success
@@ -260,7 +294,7 @@
 
    This function calls G_fatal_error() on error.
 
-   \param Map pointer to vector map
+   \param Map pointer to Map_info structure
    \param line feature id to be restored
 
    \return 0 on success

Modified: grass/trunk/lib/vector/Vlib/write_nat.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_nat.c	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/lib/vector/Vlib/write_nat.c	2012-03-10 20:07:05 UTC (rev 51027)
@@ -5,14 +5,8 @@
 
    Higher level functions for reading/writing/manipulating vectors.
 
-   Operations:
-    - Add feature
-    - Rewrite feature
-    - Delete feature
-    - Restore feature
+   (C) 2001-2010, 2012 by the GRASS Development Team
 
-   (C) 2001-2010 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.
 
@@ -29,13 +23,14 @@
 #include <grass/glocale.h>
 
 static off_t V1__rewrite_line_nat(struct Map_info *, off_t, int,
-			      const struct line_pnts *, const struct line_cats *);
+				  const struct line_pnts *, const struct line_cats *);
 
-
 /*! 
   \brief Deletes area (i.e. centroid) categories from category
   index (internal use only)
 
+  Call G_fatal_error() when area do not exits.
+  
   \param Map pointer to Map_info structure
   \param area area id
 */
@@ -70,6 +65,8 @@
   \brief Adds area (i.e. centroid) categories from category index
   (internal use only)
 
+  Call G_fatal_error() when area do not exits.
+  
   \param Map pointer to Map_info structure
   \param area area id
 */
@@ -101,7 +98,7 @@
 }
 
 /*!
-  \brief Add line to topo file (internal use only)
+  \brief Add feature (line) to topo file (internal use only)
 
   Update areas. Areas are modified if: 
    
@@ -132,7 +129,7 @@
     Note that 1) and 2) is done by the same code.
 
     \param Map pointer to Map_info structure
-    \param line line id
+    \param line feature id
     \param points pointer to line_pnts structure (feature's geometry)
     \param cats pointer to line_cats structure (feature's categories)
 */
@@ -312,7 +309,7 @@
   \brief Writes feature to 'coor' file (level 1)
   
   \param Map pointer to Map_info structure
-  \param type feature type
+  \param type feature type (GV_POINT, GV_LINE, ...)
   \param points feature geometry
   \param cats feature categories
   
@@ -338,7 +335,7 @@
   \brief Writes feature to 'coor' file (topology level) - internal use only
   
   \param Map pointer to Map_info structure
-  \param type feature type
+  \param type feature type (GV_POINT, GV_LINE, ...)
   \param points feature geometry
   \param cats feature categories
   
@@ -346,7 +343,7 @@
   \return -1 on error
 */
 off_t V2_write_line_nat(struct Map_info *Map, int type,
-             const struct line_pnts *points, const struct line_cats *cats)
+			const struct line_pnts *points, const struct line_cats *cats)
 {
     int line;
     off_t offset;
@@ -396,7 +393,7 @@
   
   \param Map pointer to Map_info structure
   \param offset feature offset
-  \param type feature type
+  \param type feature type (GV_POINT, GV_LINE, ...)
   \param points feature geometry
   \param cats feature categories
   
@@ -411,7 +408,8 @@
     struct line_cats *old_cats;
     off_t new_offset;
     
-    G_debug(3, "V1_rewrite_line_nat(), offset = %lu", (unsigned long) offset);
+    G_debug(3, "V1_rewrite_line_nat(): line = %d offset = %lu",
+	    line, (unsigned long) offset);
 
     /* TODO: enable points and cats == NULL  */
 
@@ -453,7 +451,7 @@
   \brief Rewrites feature to 'coor' file (topology level) - internal use only
   
   \param Map pointer to Map_info structure
-  \param type feature type
+  \param type feature type  (GV_POINT, GV_LINE, ...)
   \param line feature id
   \param points feature geometry
   \param cats feature categories
@@ -510,7 +508,7 @@
   
   \param Map pointer to Map_info structure
   \param offset feature offset
-  \param type feature type
+  \param type feature type  (GV_POINT, GV_LINE, ...)
   \param points feature geometry
   \param cats feature categories
   
@@ -518,9 +516,8 @@
   \return -1 on error
 */
 off_t V1__rewrite_line_nat(struct Map_info *Map,
-		       off_t offset,
-		       int type,
-		       const struct line_pnts *points, const struct line_cats *cats)
+			   off_t offset, int type,
+			   const struct line_pnts *points, const struct line_cats *cats)
 {
     int i, n_points;
     char rhead, nc;

Modified: grass/trunk/lib/vector/Vlib/write_ogr.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_ogr.c	2012-03-10 07:22:01 UTC (rev 51026)
+++ grass/trunk/lib/vector/Vlib/write_ogr.c	2012-03-10 20:07:05 UTC (rev 51027)
@@ -7,13 +7,8 @@
 
    Inspired by v.out.ogr's code.
 
-   \todo OGR version of V2__delete_area_cats_from_cidx_nat()
-   \todo function to delete corresponding entry in fidx
-   \todo OGR version of V2__add_area_cats_to_cidx_nat
-   \todo OGR version of V2__add_line_to_topo_nat
+   (C) 2009-2011, 2012 by Martin Landa, and the GRASS Development Team
 
-   (C) 2009-2011 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.
 
@@ -30,77 +25,6 @@
 static int sqltype_to_ogrtype(int);
 static int write_attributes(dbDriver *, int, const struct field_info *,
 			    OGRLayerH, OGRFeatureH);
-
-static void V2__add_line_to_topo_ogr(struct Map_info *Map, int line,
-				     const struct line_pnts *points,
-				     const struct line_cats *cats)
-{
-    int first, s, i;
-    int type, area, side;
-
-    struct Plus_head *plus;
-    struct P_line *Line;
-    
-    struct bound_box box, abox;
-    
-    G_debug(3, "V2__add_line_to_topo_ogr(): line = %d npoints = %d", line,
-	    points->n_points);
-
-    plus = &(Map->plus);
-    Line = plus->Line[line];
-    type = Line->type;
-
-    if (plus->built >= GV_BUILD_AREAS &&
-	type == GV_BOUNDARY) {	
-	struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
-	
-	if (topo->N1 != topo->N2) {
-	    G_warning(_("Boundary is not closed. Skipping."));
-	    return;
-	}
-	
-	/* Build new areas/isles */
-	for (s = 0; s < 2; s++) {
-	    side = (s == 0 ? GV_LEFT : GV_RIGHT);
-	    area = Vect_build_line_area(Map, line, side);
-	    if (area > 0) {	/* area */
-		Vect_get_area_box(Map, area, &box);
-		if (first) {
-		    Vect_box_copy(&abox, &box);
-		    first = FALSE;
-		}
-		else
-		    Vect_box_extend(&abox, &box);
-	    }
-	    else if (area < 0) {
-		/* isle -> must be attached -> add to abox */
-		Vect_get_isle_box(Map, -area, &box);
-		if (first) {
-		    Vect_box_copy(&abox, &box);
-		    first = FALSE;
-		}
-		else
-		    Vect_box_extend(&abox, &box);
-	    }
-	    G_debug(4, "Vect_build_line_area(): -> area = %d", area);
-	}
-
-	/* Attach centroid/isle to the new area */
-	if (plus->built >= GV_BUILD_ATTACH_ISLES)
-	    Vect_attach_isles(Map, &abox);
-	if (plus->built >= GV_BUILD_CENTROIDS)
-	    Vect_attach_centroids(Map, &abox);
-    }
-    
-    /* Add category index */
-    for (i = 0; i < cats->n_cats; i++) {
-	dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
-				type);
-    }
-    
-    return;
-}
-
 #endif
 
 /*!
@@ -115,7 +39,7 @@
   \todo How to deal with OGRNullFID ?
   
   \param Map pointer to Map_info structure
-  \param type feature type
+  \param type feature type (GV_POINT, GV_LINE, ...)
   \param points pointer to line_pnts structure (feature geometry) 
   \param cats pointer to line_cats structure (feature categories)
   
@@ -130,7 +54,8 @@
     int i, cat, ret;
 
     struct field_info *Fi;
-    struct Format_info_ogr *fInfo;
+    struct Format_info_ogr *ogr_info;
+    struct Format_info_offset *offset_info;
     
     off_t offset;
     
@@ -139,7 +64,10 @@
     OGRFeatureDefnH    Ogr_featuredefn;
     OGRwkbGeometryType Ogr_geom_type;
 
-    if (!Map->fInfo.ogr.layer) {
+    ogr_info = &(Map->fInfo.ogr);
+    offset_info = &(ogr_info->offset);
+    
+    if (!ogr_info->layer) {
 	/* create OGR layer if doesn't exist */
 	if (V2_open_new_ogr(Map, type) < 0)
 	    return -1;
@@ -160,8 +88,7 @@
 	}
     }
     
-    fInfo = &(Map->fInfo.ogr);
-    Ogr_featuredefn = OGR_L_GetLayerDefn(fInfo->layer);
+    Ogr_featuredefn = OGR_L_GetLayerDefn(ogr_info->layer);
     Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);
     
     /* determine matching OGR feature geometry type */
@@ -237,28 +164,28 @@
     OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
 
     /* write attributes */
-    if (cat > -1 && fInfo->dbdriver) {
-	write_attributes(fInfo->dbdriver,
-			 cat, Fi, fInfo->layer, Ogr_feature);
+    if (cat > -1 && ogr_info->dbdriver) {
+	write_attributes(ogr_info->dbdriver,
+			 cat, Fi, ogr_info->layer, Ogr_feature);
 	G_free(Fi);
     }
     /* write feature into layer */
-    ret = OGR_L_CreateFeature(fInfo->layer, Ogr_feature);
+    ret = OGR_L_CreateFeature(ogr_info->layer, Ogr_feature);
 
     /* update offset array */
-    if (fInfo->offset.array_num >= fInfo->offset.array_alloc) {
-	fInfo->offset.array_alloc += 1000;
-	fInfo->offset.array = (int *) G_realloc(fInfo->offset.array,
-						fInfo->offset.array_alloc *
+    if (offset_info->array_num >= offset_info->array_alloc) {
+	offset_info->array_alloc += 1000;
+	offset_info->array = (int *) G_realloc(offset_info->array,
+						offset_info->array_alloc *
 						sizeof(int));
     }
 
-    offset = fInfo->offset.array_num;
+    offset = offset_info->array_num;
     
-    fInfo->offset.array[fInfo->offset.array_num++] = (int) OGR_F_GetFID(Ogr_feature);
+    offset_info->array[offset_info->array_num++] = (int) OGR_F_GetFID(Ogr_feature);
     if (Ogr_geom_type == wkbPolygon || Ogr_geom_type == wkbPolygon25D) {
 	/* register exterior ring in offset array */
-	fInfo->offset.array[fInfo->offset.array_num++] = 0; 
+	offset_info->array[offset_info->array_num++] = 0; 
     }
       
     /* destroy */
@@ -278,97 +205,11 @@
 }
 
 /*!
-  \brief Writes feature on level 2
-
-  \param Map pointer to Map_info structure
-  \param type feature type
-  \param points pointer to line_pnts structure (feature geometry) 
-  \param cats pointer to line_cats structure (feature categories)
+  \brief Rewrites feature at the given offset (level 1) (OGR interface)
   
-  \return feature offset into file
-  \return -1 on error
-*/
-off_t V2_write_line_ogr(struct Map_info *Map, int type,
-			const struct line_pnts *points, const struct line_cats *cats)
-{
-#ifdef HAVE_OGR
-    int line;
-    off_t offset;
-    struct Plus_head *plus;
-    struct bound_box box;
-
-    line = 0;
-    plus = &(Map->plus);
-    
-    G_debug(3, "V2_write_line_ogr()");
-    
-    offset = V1_write_line_ogr(Map, type, points, cats);
-    if (offset < 0)
-	return -1;
-    
-    /* Update topology */
-    if (plus->built >= GV_BUILD_BASE) {
-	dig_line_box(points, &box);
-	line = dig_add_line(plus, type, points, &box, offset);
-	G_debug(3, "\tline added to topo with line = %d", line);
-	if (line == 1)
-	    Vect_box_copy(&(plus->box), &box);
-	else
-	    Vect_box_extend(&(plus->box), &box);
-
-	if (type == GV_BOUNDARY) {
-	    int ret, cline;
-	    long FID;
-	    double x, y;
-	    
-	    struct bound_box box;
-	    struct line_pnts *CPoints;
-
-	    /* add virtual centroid to pseudo-topology */
-	    ret = Vect_get_point_in_poly(points, &x, &y);
-	    if (ret == 0) {
-		CPoints = Vect_new_line_struct();
-		Vect_append_point(CPoints, x, y, 0.0);
-		
-		FID = Map->fInfo.ogr.offset.array[offset];
-
-		dig_line_box(CPoints, &box);
-		cline = dig_add_line(plus, GV_CENTROID,
-				     CPoints, &box, FID);
-		G_debug(4, "\tCentroid: x = %f, y = %f, cat = %lu, line = %d",
-			x, y, FID, cline);	  
-		dig_cidx_add_cat(plus, 1, (int) FID,
-				 cline, GV_CENTROID);
-		
-		Vect_destroy_line_struct(CPoints);
-	    }
-	    else {
-		G_warning(_("Unable to calculate centroid for area"));
-	    }
-	}
-	V2__add_line_to_topo_ogr(Map, line, points, cats);
-    }
-
-
-    G_debug(3, "updated lines : %d , updated nodes : %d", plus->uplist.n_uplines,
-	    plus->uplist.n_upnodes);
-
-    /* returns int line, but is defined as off_t for compatibility with
-     * Write_line_array in write.c */
-    
-    return line;
-#else
-    G_fatal_error(_("GRASS is not compiled with OGR support"));
-    return -1;
-#endif
-}
-
-/*!
-  \brief Rewrites feature at the given offset (level 1)
-  
   \param Map pointer to Map_info structure
   \param offset feature offset
-  \param type feature type
+  \param type feature type (GV_POINT, GV_LINE, ...)
   \param points feature geometry
   \param cats feature categories
   
@@ -376,9 +217,7 @@
   \return -1 on error
 */
 off_t V1_rewrite_line_ogr(struct Map_info *Map,
-			  int line,
-			  int type,
-			  off_t offset,
+			  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=%llu",
@@ -404,7 +243,7 @@
   
   \param Map pointer to Map_info structure
   \param line feature id
-  \param type feature type
+  \param type feature type (GV_POINT, GV_LINE, ...)
   \param offset unused
   \param points feature geometry
   \param cats feature categories
@@ -426,7 +265,7 @@
 
     V2_delete_line_ogr(Map, line);
 
-    return V2_write_line_ogr(Map, type, points, cats);
+    return V2_write_line_sfa(Map, type, points, cats);
 #else
     G_fatal_error(_("GRASS is not compiled with OGR support"));
     return -1;
@@ -445,18 +284,22 @@
 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);
 
-    if (!Map->fInfo.ogr.layer) {
+    ogr_info = &(Map->fInfo.ogr);
+    
+    if (!ogr_info->layer) {
 	G_warning(_("OGR layer not defined"));
 	return -1;
     }
     
-    if (offset >= Map->fInfo.ogr.offset.array_num)
+    if (offset >= ogr_info->offset.array_num)
 	return -1;
     
-    if (OGR_L_DeleteFeature(Map->fInfo.ogr.layer,
-			    Map->fInfo.ogr.offset.array[offset]) != OGRERR_NONE)
+    if (OGR_L_DeleteFeature(ogr_info->layer,
+			    ogr_info->offset.array[offset]) != OGRERR_NONE)
 	return -1;
     
     return 0;

Added: grass/trunk/lib/vector/Vlib/write_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_pg.c	                        (rev 0)
+++ grass/trunk/lib/vector/Vlib/write_pg.c	2012-03-10 20:07:05 UTC (rev 51027)
@@ -0,0 +1,554 @@
+/*!
+   \file lib/vector/Vlib/write_pg.c
+
+   \brief Vector library - write vector feature (PostGIS format)
+
+   Higher level functions for reading/writing/manipulating vectors.
+
+   Inspired by OGR PostgreSQL driver.
+
+   \todo PostGIS version of V2__add_line_to_topo_nat()
+   \todo OGR version of V2__delete_area_cats_from_cidx_nat()
+   \todo function to delete corresponding entry in fidx
+   \todo OGR version of V2__add_area_cats_to_cidx_nat
+   \todo OGR version of V2__add_line_to_topo_nat
+
+   (C) 2012 by Martin Landa, and 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.
+
+   \author Martin Landa <landa.martin gmail.com>
+ */
+
+#include <grass/vector.h>
+#include <grass/glocale.h>
+
+#ifdef HAVE_POSTGRES
+#include "pg_local_proto.h"
+
+#define WKBSRIDFLAG 0x20000000
+
+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 *,
+				     int, int*);
+static int write_feature(const struct Format_info_pg *, 
+			 int, const struct line_pnts *, int, int);
+#endif
+
+/*!
+  \brief Writes feature on level 1 (PostGIS interface)
+
+  Note:
+   - centroids are not supported in PostGIS, pseudotopo holds virtual
+     centroids
+   - boundaries are not supported in PostGIS, pseudotopo treats polygons
+     as boundaries
+     
+  \param Map pointer to Map_info structure
+  \param type feature type (GV_POINT, GV_LINE, ...)
+  \param points pointer to line_pnts structure (feature geometry) 
+  \param cats pointer to line_cats structure (feature categories)
+  
+  \return feature offset into file
+  \return -1 on error
+*/
+off_t V1_write_line_pg(struct Map_info *Map, int type,
+		       const struct line_pnts *points,
+		       const struct line_cats *cats)
+{
+#ifdef HAVE_POSTGRES
+    int cat;
+    off_t offset;
+    
+    SF_FeatureType sf_type;
+
+    struct field_info *Fi;
+    struct Format_info_pg *pg_info;
+    struct Format_info_offset *offset_info;
+    
+    pg_info = &(Map->fInfo.pg);
+    offset_info = &(pg_info->offset);
+    
+    /* create PostGIS layer if doesn't exist ? */
+    
+    cat = -1; /* no attributes to be written */
+    if (cats->n_cats > 0 && Vect_get_num_dblinks(Map) > 0) {
+	/* check for attributes */
+	Fi = Vect_get_dblink(Map, 0);
+	if (Fi) {
+	    if (!Vect_cat_get(cats, Fi->number, &cat))
+		G_warning(_("No category defined for layer %d"), Fi->number);
+	    if (cats->n_cats > 1) {
+		G_warning(_("Feature has more categories, using "
+			    "category %d (from layer %d)"),
+			  cat, cats->field[0]);
+	    }
+	}
+    }
+
+    sf_type = pg_info->feature_type;
+    
+    /* determine matching PostGIS feature geometry type */
+    if (type & (GV_POINT | GV_KERNEL)) {
+	if (sf_type != SF_POINT &&
+	    sf_type != SF_POINT25D) {
+	    G_warning(_("Feature is not a point. Skipping."));
+	    return -1;
+	}
+    }
+    else if (type & GV_LINE) {
+	if (sf_type != SF_LINESTRING &&
+	    sf_type != SF_LINESTRING25D) {
+	    G_warning(_("Feature is not a line. Skipping."));
+	    return -1;
+	}
+    }
+    else if (type & GV_BOUNDARY) {
+	if (sf_type != SF_POLYGON) {
+	    G_warning(_("Feature is not a polygon. Skipping."));
+	    return -1;
+	}
+    }
+    else if (type & GV_FACE) {
+	if (sf_type != SF_POLYGON25D) {
+	    G_warning(_("Feature is not a face. Skipping."));
+	    return -1;
+	}
+    }
+    else {
+	G_warning(_("Unsupported feature type (%d)"), type);
+	return -1;
+    }
+
+    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;
+	
+	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;
+	}
+    }
+
+    if (execute(pg_info->conn, "BEGIN") == -1)
+	return -1;
+    
+    /* write feature's geometry and fid */
+    if (-1 == write_feature(pg_info, type, points,
+			    Vect_is_3d(Map) ? WITH_Z : WITHOUT_Z, cat))
+	return -1;
+
+    /* write attributes */
+    /* ? */
+    
+    if (execute(pg_info->conn, "COMMIT") == -1)
+	return -1;
+    
+    /* update offset array */
+    if (offset_info->array_num >= offset_info->array_alloc) {
+	offset_info->array_alloc += 1000;
+	offset_info->array = (int *) G_realloc(offset_info->array,
+					       offset_info->array_alloc *
+					       sizeof(int));
+    }
+
+    offset = offset_info->array_num;
+    
+    offset_info->array[offset_info->array_num++] = (int) cat;
+    if (sf_type == SF_POLYGON || sf_type == SF_POLYGON25D) {
+	/* register exterior ring in offset array */
+	offset_info->array[offset_info->array_num++] = 0; 
+    }
+    
+    G_debug(3, "V1_write_line_ogr(): -> offset = %lu", (unsigned long) offset);
+
+    return offset;
+#else
+    G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
+    return -1;
+#endif
+}
+
+#ifdef HAVE_POSTGRES
+/*!
+  \brief Binary data to HEX
+
+  Allocated buffer should be freed by G_free().
+  
+  \param nbytes number of bytes to allocate
+  \param wkb_data WKB data
+
+  \return allocated buffer with HEX data
+*/
+char *binary_to_hex(int nbytes, const unsigned char *wkb_data)
+{
+    char *hex_data;
+    int i, nlow, nhigh;
+    static const char ach_hex[] = "0123456789ABCDEF";
+
+    hex_data = (char *) G_malloc(nbytes * 2 + 1);
+    hex_data[nbytes * 2] = '\0';
+
+    for (i = 0; i < nbytes; i++) {
+        nlow  = wkb_data[i] & 0x0f;
+        nhigh = (wkb_data[i] & 0xf0) >> 4;
+
+        hex_data[i * 2]     = ach_hex[nhigh];
+        hex_data[i * 2 + 1] = ach_hex[nlow];
+    }
+
+    return hex_data;
+}
+
+/*!
+  \bried Write point into WKB buffer
+
+  See OGRPoint::exportToWkb from GDAL/OGR library
+
+  \param byte_order byte order (LITTLE_ENDIAN or BIG_ENDIAN)
+  \param points feature geometry
+  \param with_z WITH_Z for 3D data
+  \param[out] nsize buffer size
+  
+  \return allocated WKB buffer
+  \return NULL on error
+*/
+unsigned char *point_to_wkb(int byte_order,
+			    const struct line_pnts *points, int with_z,
+			    int *nsize)
+{
+    unsigned char *wkb_data;
+    unsigned int sf_type;
+    
+    if (points->n_points != 1)
+	return NULL;
+    
+    /* allocate buffer */
+    *nsize = with_z ? 29 : 21;
+    wkb_data = G_malloc(*nsize);
+    G_zero(wkb_data, *nsize);
+    
+    G_debug(5, "\t->point size=%d (with_z = %d)", *nsize, with_z);
+    
+    /* set the byte order */
+    if (byte_order == LITTLE_ENDIAN)
+	wkb_data[0] = '\001';
+    else
+	wkb_data[0] = '\000';
+    
+    /* set the geometry feature type */
+    sf_type = with_z ? SF_POINT25D : SF_POINT;
+    
+    if (byte_order == LITTLE_ENDIAN)
+	sf_type = LSBWORD32(sf_type);
+    else
+        sf_type = MSBWORD32(sf_type);
+    memcpy(wkb_data + 1, &sf_type, 4);
+    
+    /* copy in the raw data */
+    memcpy(wkb_data + 5, &(points->x[0]), 8);
+    memcpy(wkb_data + 5 + 8, &(points->y[0]), 8);
+
+    if (with_z) {
+        memcpy(wkb_data + 5 + 16, &(points->z[0]), 8);
+    }
+
+    /* swap if needed */
+    if (byte_order == ENDIAN_BIG) {
+	SWAPDOUBLE(wkb_data + 5);
+        SWAPDOUBLE(wkb_data + 5 + 8);
+	
+        if (with_z)
+            SWAPDOUBLE(wkb_data + 5 + 16);
+    }
+
+    return wkb_data;
+}
+
+/*!
+  \bried Write linestring into WKB buffer
+
+  See OGRLineString::exportToWkb from GDAL/OGR library
+
+  \param byte_order byte order (LITTLE_ENDIAN or BIG_ENDIAN)
+  \param points feature geometry
+  \param with_z WITH_Z for 3D data
+  \param[out] nsize buffer size
+  
+  \return allocated WKB buffer
+  \return NULL on error
+*/
+unsigned char *linestring_to_wkb(int byte_order,
+				 const struct line_pnts *points, int with_z,
+				 int *nsize)
+{
+    int i, point_size;
+    unsigned char *wkb_data;
+    unsigned int sf_type;
+
+    if (points->n_points < 1)
+	return NULL;
+
+    /* allocate buffer */
+    point_size = 8 * (with_z ? 3 : 2);
+    *nsize = 5 + 4 + points->n_points * point_size;
+    wkb_data = G_malloc(*nsize);
+    G_zero(wkb_data, *nsize);
+
+    G_debug(5, "\t->linestring size=%d (with_z = %d)", *nsize, with_z);
+
+    /* set the byte order */
+    if (byte_order == LITTLE_ENDIAN)
+	wkb_data[0] = '\001';
+    else
+	wkb_data[0] = '\000';
+
+    /* set the geometry feature type */
+    sf_type = with_z ? SF_LINESTRING25D : SF_LINESTRING;
+    
+    if (byte_order == LITTLE_ENDIAN)
+	sf_type = LSBWORD32(sf_type);
+    else
+        sf_type = MSBWORD32(sf_type);
+    memcpy(wkb_data + 1, &sf_type, 4);
+    
+    /* copy in the data count */
+    memcpy(wkb_data + 5, &(points->n_points), 4);
+    
+    /* copy in the raw data */
+    for (i = 0; i < points->n_points; i++) {
+	memcpy(wkb_data + 9 + point_size * i, &(points->x[i]), 8);
+	memcpy(wkb_data + 9 + 8 + point_size * i, &(points->y[i]), 8);
+	
+	if (with_z) {
+	    memcpy(wkb_data + 9 + 16 + point_size * i, &(points->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);
+        }
+    }
+
+    return wkb_data;
+}
+
+/*!
+  \bried Write polygon into WKB buffer
+
+  See OGRPolygon::exportToWkb from GDAL/OGR library
+
+  \param byte_order byte order (LITTLE_ENDIAN or BIG_ENDIAN)
+  \param points feature geometry
+  \param with_z WITH_Z for 3D data
+  \param[out] nsize buffer size
+  
+  \return allocated WKB buffer
+  \return NULL on error
+*/
+unsigned char *polygon_to_wkb(int byte_order,
+			      const struct line_pnts *points, int with_z,
+			      int *nsize)
+{
+    int i, point_size, nrings;
+    unsigned char *wkb_data;
+    unsigned int sf_type;
+
+    if (points->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);
+    wkb_data = G_malloc(*nsize);
+    G_zero(wkb_data, *nsize);
+
+    G_debug(5, "\t->polygon size=%d (with_z = %d)", *nsize, with_z);
+    
+    /* set the byte order */
+    if (byte_order == LITTLE_ENDIAN)
+	wkb_data[0] = '\001';
+    else
+	wkb_data[0] = '\000';
+
+    /* set the geometry feature type */
+    sf_type = with_z ? SF_POLYGON25D : SF_POLYGON;
+    
+    if (byte_order == LITTLE_ENDIAN)
+	sf_type = LSBWORD32(sf_type);
+    else
+        sf_type = MSBWORD32(sf_type);
+    memcpy(wkb_data + 1, &sf_type, 4);
+ 
+    /* copy in the raw data */
+    if (byte_order == ENDIAN_BIG) {
+        int ncount;
+	
+        ncount = CPL_SWAP32(nrings);
+        memcpy(wkb_data + 5, &ncount, 4);
+    }
+    else {
+        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);
+	}
+    }
+
+    /* 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++ )
+        {
+            CPL_SWAPDOUBLE(wkb_data + 9 + 4 + 8 * i);
+        }
+    }
+
+    return wkb_data;
+}
+/*!
+  \brief Insert feature into table
+
+  \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 with_z WITH_Z for 3D data
+  \param fid feature id
+
+  \return -1 on error
+  \retirn 0 on success
+*/
+int write_feature(const struct Format_info_pg *pg_info,
+		  int type, const struct line_pnts *points, int with_z,
+		  int fid)
+{
+    int   byte_order, nbytes, nsize;
+    unsigned int sf_type;
+    unsigned char *wkb_data;
+    char  *stmt, *text_data, *text_data_p, *hex_data;
+    
+    if (with_z && pg_info->coor_dim != 3) {
+	G_warning(_("Trying to insert 3D data into feature table "
+		    "which store 2D data only"));
+	return -1;
+    }
+    if (!with_z && pg_info->coor_dim != 2) {
+	G_warning(_("Trying to insert 2D data into feature table "
+		    "which store 3D data only"));
+	return -1;
+    }
+    
+    byte_order = LITTLE_ENDIAN; /* ? */
+    
+    /* get wkb data */
+    nbytes = -1;
+    wkb_data = NULL;
+    if (type == GV_POINT) 
+	wkb_data = point_to_wkb(byte_order, points, 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);
+    
+    if (!wkb_data || nbytes < 1) {
+	G_warning(_("Unsupported feature type %d"), type);
+	return -1;
+    }
+    
+    /* When converting to hex, each byte takes 2 hex characters. In
+       addition we add in 8 characters to represent the SRID integer
+       in hex, and one for a null terminator */
+    nsize = nbytes * 2 + 8 + 1;
+    text_data = text_data_p = (char *) G_malloc(nsize);
+    
+    /* convert the 1st byte, which is the endianess flag, to hex */
+    hex_data = binary_to_hex(1, wkb_data);
+    strcpy(text_data_p, hex_data);
+    G_free (hex_data);
+    text_data_p += 2;
+
+    /* get the geom type which is bytes 2 through 5 */
+    memcpy(&sf_type, wkb_data + 1, 4);
+
+    /* add the SRID flag if an SRID is provided */
+    if (pg_info->srid > 0) {
+	unsigned int srs_flag;
+	/* change the flag to little endianess */
+        srs_flag = LSBWORD32(WKBSRIDFLAG);
+        /* apply the flag */
+        sf_type = sf_type | srs_flag;
+    }
+
+    /* write the geom type which is 4 bytes */
+    hex_data = binary_to_hex(4, (unsigned char*) &sf_type);
+    strcpy(text_data_p, hex_data);
+    G_free(hex_data);
+    text_data_p += 8;
+
+    /* include SRID if provided */
+    if (pg_info->srid > 0) {
+	unsigned int srs_id;
+        /* force the srsid to little endianess */
+        srs_id = LSBWORD32(pg_info->srid);
+        hex_data = binary_to_hex(sizeof(srs_id), (unsigned char*) &srs_id);
+        strcpy(text_data_p, hex_data);
+        G_free(hex_data);
+        text_data_p += 8;
+    }
+
+    /* copy the rest of the data over - subtract 5 since we already
+       copied 5 bytes above */
+    hex_data = binary_to_hex(nbytes - 5, wkb_data + 5);
+    strcpy(text_data_p, hex_data);
+    G_free(hex_data);
+
+    /* build INSERT statement */
+    stmt = NULL;
+    G_asprintf(&stmt, "INSERT INTO %s (%s, %s) VALUES (%d, '%s'::GEOMETRY)",
+	       pg_info->table_name, pg_info->fid_column, pg_info->geom_column,
+	       fid, text_data);
+    G_debug(2, "SQL: %s", stmt);
+    
+    if (execute(pg_info->conn, stmt) == -1)
+	return -1;
+
+    G_free(wkb_data);
+    G_free(text_data);
+    G_free(stmt);
+    
+    return 0;
+}
+#endif


Property changes on: grass/trunk/lib/vector/Vlib/write_pg.c
___________________________________________________________________
Added: svn:mime-type
   + text/x-csrc
Added: svn:eol-style
   + native

Added: grass/trunk/lib/vector/Vlib/write_sfa.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_sfa.c	                        (rev 0)
+++ grass/trunk/lib/vector/Vlib/write_sfa.c	2012-03-10 20:07:05 UTC (rev 51027)
@@ -0,0 +1,204 @@
+/*!
+   \file lib/vector/Vlib/write_sfa.c
+
+   \brief Vector library - write vector feature - simple feature access
+
+   Higher level functions for reading/writing/manipulating vectors.
+
+   See write_ogr.c (OGR interface) and write_pg.c (PostGIS interface)
+   for imlementation issues.
+
+   \todo SFA version of V2__delete_area_cats_from_cidx_nat()
+   \todo function to delete corresponding entry in fidx
+   \todo SFA version of V2__add_area_cats_to_cidx_nat
+   \todo SFA version of V2__add_line_to_topo_nat
+
+   (C) 2011-2012 by Martin Landa, and 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.
+
+   \author Martin Landa <landa.martin gmail.com>
+ */
+
+#include <grass/vector.h>
+#include <grass/glocale.h>
+
+#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 *);
+#endif
+
+/*!
+  \brief Writes feature on level 2 (OGR/PostGIS interface)
+
+  \param Map pointer to Map_info structure
+  \param type feature type (GV_POINT, GV_LINE, ...)
+  \param points pointer to line_pnts structure (feature geometry) 
+  \param cats pointer to line_cats structure (feature categories)
+  
+  \return feature offset into file
+  \return -1 on error
+*/
+off_t V2_write_line_sfa(struct Map_info *Map, int type,
+			const struct line_pnts *points, const struct line_cats *cats)
+{
+#if defined HAVE_OGR || defined HAVE_POSTGRES
+    int line;
+    off_t offset;
+    struct Plus_head *plus;
+    struct bound_box box;
+    struct Format_info_offset *offset_info;
+    
+    line = 0;
+    plus = &(Map->plus);
+    
+    G_debug(3, "V2_write_line_sfa(): type = %d (format = %d)",
+	    type, Map->format);
+    
+    if (Map->format == GV_FORMAT_POSTGIS) {
+	offset_info = &(Map->fInfo.pg.offset);
+	offset = V1_write_line_pg(Map, type, points, cats);
+    }
+    else {
+	offset_info = &(Map->fInfo.pg.offset);
+	offset = V1_write_line_ogr(Map, type, points, cats);
+    }
+    if (offset < 0)
+	return -1;
+    
+    /* Update topology */
+    if (plus->built >= GV_BUILD_BASE) {
+	dig_line_box(points, &box);
+	line = dig_add_line(plus, type, points, &box, offset);
+	G_debug(3, "\tline added to topo with line = %d", line);
+	if (line == 1)
+	    Vect_box_copy(&(plus->box), &box);
+	else
+	    Vect_box_extend(&(plus->box), &box);
+
+	if (type == GV_BOUNDARY) {
+	    int ret, cline;
+	    long FID;
+	    double x, y;
+	    
+	    struct bound_box box;
+	    struct line_pnts *CPoints;
+
+	    /* add virtual centroid to pseudo-topology */
+	    ret = Vect_get_point_in_poly(points, &x, &y);
+	    if (ret == 0) {
+		CPoints = Vect_new_line_struct();
+		Vect_append_point(CPoints, x, y, 0.0);
+		
+		FID = offset_info->array[offset];
+
+		dig_line_box(CPoints, &box);
+		cline = dig_add_line(plus, GV_CENTROID,
+				     CPoints, &box, FID);
+		G_debug(4, "\tCentroid: x = %f, y = %f, cat = %lu, line = %d",
+			x, y, FID, cline);	  
+		dig_cidx_add_cat(plus, 1, (int) FID,
+				 cline, GV_CENTROID);
+		
+		Vect_destroy_line_struct(CPoints);
+	    }
+	    else {
+		G_warning(_("Unable to calculate centroid for area"));
+	    }
+	}
+	V2__add_line_to_topo_sfa(Map, line, points, cats);
+    }
+
+
+    G_debug(3, "updated lines : %d , updated nodes : %d", plus->uplist.n_uplines,
+	    plus->uplist.n_upnodes);
+
+    /* returns int line, but is defined as off_t for compatibility with
+     * Write_line_array in write.c */
+    return line;
+#else
+    G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
+    return -1;
+#endif
+}
+
+#if defined HAVE_OGR || defined HAVE_POSTGRES
+/*!
+  \brief Add feature to topo file (internal use only)
+
+  \param Map pointer to Map_info structure
+  \param line feature id
+  \param points pointer to line_pnts structure (feature's geometry)
+  \param cats pointer to line_cats structure (feature's categories)
+*/
+void V2__add_line_to_topo_sfa(struct Map_info *Map, int line,
+			      const struct line_pnts *points,
+			      const struct line_cats *cats)
+{
+    int first, s, i;
+    int type, area, side;
+
+    struct Plus_head *plus;
+    struct P_line *Line;
+    
+    struct bound_box box, abox;
+    
+    G_debug(3, "V2__add_line_to_topo_ogr(): line = %d npoints = %d", line,
+	    points->n_points);
+
+    plus = &(Map->plus);
+    Line = plus->Line[line];
+    type = Line->type;
+
+    if (plus->built >= GV_BUILD_AREAS &&
+	type == GV_BOUNDARY) {	
+	struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
+	
+	if (topo->N1 != topo->N2) {
+	    G_warning(_("Boundary is not closed. Skipping."));
+	    return;
+	}
+	
+	/* Build new areas/isles */
+	for (s = 0; s < 2; s++) {
+	    side = (s == 0 ? GV_LEFT : GV_RIGHT);
+	    area = Vect_build_line_area(Map, line, side);
+	    if (area > 0) {	/* area */
+		Vect_get_area_box(Map, area, &box);
+		if (first) {
+		    Vect_box_copy(&abox, &box);
+		    first = FALSE;
+		}
+		else
+		    Vect_box_extend(&abox, &box);
+	    }
+	    else if (area < 0) {
+		/* isle -> must be attached -> add to abox */
+		Vect_get_isle_box(Map, -area, &box);
+		if (first) {
+		    Vect_box_copy(&abox, &box);
+		    first = FALSE;
+		}
+		else
+		    Vect_box_extend(&abox, &box);
+	    }
+	    G_debug(4, "Vect_build_line_area(): -> area = %d", area);
+	}
+
+	/* Attach centroid/isle to the new area */
+	if (plus->built >= GV_BUILD_ATTACH_ISLES)
+	    Vect_attach_isles(Map, &abox);
+	if (plus->built >= GV_BUILD_CENTROIDS)
+	    Vect_attach_centroids(Map, &abox);
+    }
+    
+    /* Add category index */
+    for (i = 0; i < cats->n_cats; i++) {
+	dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
+				type);
+    }
+    
+    return;
+}
+#endif /* HAVE_OGR || HAVE_POSTGRES */


Property changes on: grass/trunk/lib/vector/Vlib/write_sfa.c
___________________________________________________________________
Added: svn:mime-type
   + text/x-csrc
Added: svn:eol-style
   + native



More information about the grass-commit mailing list