[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