[GRASS-SVN] r54072 - in grass/trunk/lib/vector: Vlib diglib
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue Nov 27 02:00:54 PST 2012
Author: martinl
Date: 2012-11-27 02:00:53 -0800 (Tue, 27 Nov 2012)
New Revision: 54072
Modified:
grass/trunk/lib/vector/Vlib/copy.c
grass/trunk/lib/vector/Vlib/open_pg.c
grass/trunk/lib/vector/Vlib/pg_local_proto.h
grass/trunk/lib/vector/Vlib/read_pg.c
grass/trunk/lib/vector/Vlib/rewind_pg.c
grass/trunk/lib/vector/Vlib/write_nat.c
grass/trunk/lib/vector/Vlib/write_pg.c
grass/trunk/lib/vector/diglib/plus_area.c
Log:
vlib (PostGIS Topo): better support for areas/faces (work in progress)
Modified: grass/trunk/lib/vector/Vlib/copy.c
===================================================================
--- grass/trunk/lib/vector/Vlib/copy.c 2012-11-27 09:15:53 UTC (rev 54071)
+++ grass/trunk/lib/vector/Vlib/copy.c 2012-11-27 10:00:53 UTC (rev 54072)
@@ -18,6 +18,17 @@
#include <grass/vector.h>
#include <grass/glocale.h>
+/*!
+ \brief Copy topological elements
+
+ - simple features (None)
+ - native topo (GRASS)
+ - PostGIS Topo
+*/
+#define TOPO_NONE -1
+#define TOPO_NATIVE 1
+#define TOPO_POSTGIS 2
+
#ifdef HAVE_POSTGRES
#include "pg_local_proto.h"
#endif
@@ -60,37 +71,39 @@
int Vect_copy_map_lines_field(struct Map_info *In, int field,
struct Map_info *Out)
{
- int ret, native, pg_topo;
+ int ret, format, topo;
if (Vect_level(In) < 1)
G_fatal_error("Vect_copy_map_lines(): %s",
_("input vector map is not open"));
+
+ format = Vect_maptype(Out);
+ topo = TOPO_NONE;
+ if (format == GV_FORMAT_NATIVE)
+ topo = TOPO_NATIVE;
+ else if (format == GV_FORMAT_POSTGIS && Out->fInfo.pg.toposchema_name)
+ topo = TOPO_POSTGIS;
- /* check for external formats - copy areas/isles as polygons with holes */
- native = Vect_maptype(Out) == GV_FORMAT_NATIVE;
- /* check for PostGIS topology */
- pg_topo = Vect_maptype(Out) == GV_FORMAT_POSTGIS && Out->fInfo.pg.toposchema_name;
-
/* Note: sometimes is important to copy on level 2 (pseudotopo
- centroids) and sometimes on level 1 if build take too
- long time
+ centroids) and sometimes on level 1 if build take too long time
*/
if (Vect_level(In) >= 2) {
/* -> copy features on level 2 */
- if (pg_topo)
+ if (topo == TOPO_POSTGIS)
/* PostGIS topology - copy also nodes */
copy_nodes(In, Out);
/* copy features */
- ret = copy_lines_2(In, field, native, Out);
+ ret = copy_lines_2(In, field, topo, Out);
- if (!native) {
+ if (topo == TOPO_NONE) {
+ /* copy areas - external formats and simple features access only */
copy_areas(In, field, Out);
}
}
else {
/* -> copy features on level 1 */
- if (!native)
+ if (topo == TOPO_NONE)
G_warning(_("Vector map <%s> not open on topological level. "
"Areas will be skipped!"), Vect_get_full_name(In));
@@ -157,12 +170,13 @@
\param In input vector map
\param field layer number (-1 for all layers)
+ \param topo topo access (none, native, postgis)
\param Out output vector map
\return 0 on success
\return 1 on error
*/
-int copy_lines_2(struct Map_info *In, int field, int native, struct Map_info *Out)
+int copy_lines_2(struct Map_info *In, int field, int topo, struct Map_info *Out)
{
int i, type, nlines;
int ret, left, rite, centroid;
@@ -177,11 +191,11 @@
ret = 0;
nlines = Vect_get_num_lines(In);
- if (native)
- G_message(_("Copying features..."));
- else
+ if (topo == TOPO_NONE)
G_message(_("Copying features (%s)..."),
Vect_get_finfo_geometry_type(Out));
+ else
+ G_message(_("Copying features..."));
for (i = 1; i <= nlines; i++) {
if (!Vect_line_alive(In, i))
@@ -198,11 +212,13 @@
if (type == 0)
continue; /* dead line */
- if (!native && (type == GV_CENTROID || type == GV_BOUNDARY))
- /* OGR/PostGIS layers: centroids are stored in topo */
- /* polygon defined by areas (topo required) */
+ if (topo == TOPO_NONE && (type == GV_CENTROID || type == GV_BOUNDARY)) {
+ /* OGR/PostGIS layers (simple features): centroids are
+ stored in topo polygon defined by areas (topo required)
+ */
continue;
-
+ }
+
/* don't skips boundaries if field != -1 */
if (field != -1) {
if (type & GV_BOUNDARY) {
Modified: grass/trunk/lib/vector/Vlib/open_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open_pg.c 2012-11-27 09:15:53 UTC (rev 54071)
+++ grass/trunk/lib/vector/Vlib/open_pg.c 2012-11-27 10:00:53 UTC (rev 54072)
@@ -1410,7 +1410,8 @@
/* number of features group by type */
/* points */
sprintf(stmt,
- "SELECT COUNT(*) FROM \"%s\".node WHERE node_id NOT IN "
+ "SELECT COUNT(*) FROM \"%s\".node WHERE containing_face "
+ "IS NULL AND node_id NOT IN "
"(SELECT node FROM (SELECT start_node AS node FROM \"%s\".edge "
"GROUP BY start_node UNION ALL SELECT end_node AS node FROM "
"\"%s\".edge GROUP BY end_node) AS foo)",
@@ -1486,7 +1487,7 @@
"SELECT node_id,geom FROM \"%s\".node WHERE node_id IN "
"(SELECT node FROM (SELECT start_node AS node FROM \"%s\".edge "
"GROUP BY start_node UNION ALL SELECT end_node AS node FROM "
- "\"%s\".edge GROUP BY end_node) AS foo)",
+ "\"%s\".edge GROUP BY end_node) AS foo) ORDER BY node_id",
pg_info->toposchema_name, pg_info->toposchema_name,
pg_info->toposchema_name);
G_debug(2, "SQL: %s", stmt);
@@ -1522,7 +1523,7 @@
"SELECT node_id,geom FROM \"%s\".node WHERE node_id NOT IN "
"(SELECT node FROM (SELECT start_node AS node FROM \"%s\".edge "
"GROUP BY start_node UNION ALL SELECT end_node AS node FROM "
- "\"%s\".edge GROUP BY end_node) AS foo)",
+ "\"%s\".edge GROUP BY end_node) AS foo) ORDER BY node_id",
pg_info->toposchema_name, pg_info->toposchema_name,
pg_info->toposchema_name);
G_debug(2, "SQL: %s", stmt);
@@ -1551,7 +1552,7 @@
*/
sprintf(stmt,
"SELECT edge_id,start_node,end_node,left_face,right_face,geom "
- "FROM \"%s\".edge",
+ "FROM \"%s\".edge ORDER BY edge_id",
pg_info->toposchema_name);
G_debug(2, "SQL: %s", stmt);
res = PQexec(pg_info->conn, stmt);
@@ -1610,14 +1611,18 @@
}
PQclear(res);
- /* attach centroids */
+ /* read PostGIS Topo standalone nodes (containing_face is not null)
+ -> centroids
+ */
if (plus->n_areas > 0) {
sprintf(stmt,
- "SELECT ST_PointOnSurface(geom) AS geom FROM "
- "ST_GetFaceGeometry('%s',"
- "(SELECT face_id FROM \"%s\".face WHERE face_id > 0)) "
- "AS geom",
- pg_info->toposchema_name, pg_info->toposchema_name);
+ "SELECT node_id,geom FROM \"%s\".node WHERE containing_face "
+ "IS NOT NULL AND node_id NOT IN "
+ "(SELECT node FROM (SELECT start_node AS node FROM \"%s\".edge "
+ "GROUP BY start_node UNION ALL SELECT end_node AS node FROM "
+ "\"%s\".edge GROUP BY end_node) AS foo) ORDER BY node_id",
+ pg_info->toposchema_name, pg_info->toposchema_name,
+ pg_info->toposchema_name);
G_debug(2, "SQL: %s", stmt);
res = PQexec(pg_info->conn, stmt);
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
Modified: grass/trunk/lib/vector/Vlib/pg_local_proto.h
===================================================================
--- grass/trunk/lib/vector/Vlib/pg_local_proto.h 2012-11-27 09:15:53 UTC (rev 54071)
+++ grass/trunk/lib/vector/Vlib/pg_local_proto.h 2012-11-27 10:00:53 UTC (rev 54072)
@@ -59,6 +59,7 @@
/* functions used in *_pg.c files */
int Vect__execute_pg(PGconn *, const char *);
+int Vect__execute_get_value_pg(PGconn *, const char *);
SF_FeatureType Vect__cache_feature_pg(const char *, int, int,
struct Format_info_cache *,
struct feat_parts *);
Modified: grass/trunk/lib/vector/Vlib/read_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/read_pg.c 2012-11-27 09:15:53 UTC (rev 54071)
+++ grass/trunk/lib/vector/Vlib/read_pg.c 2012-11-27 10:00:53 UTC (rev 54072)
@@ -46,7 +46,6 @@
static int error_corrupted_data(const char *);
static void reallocate_cache(struct Format_info_cache *, int);
static void add_fpart(struct feat_parts *, SF_FeatureType, int, int);
-static int get_centroid_topo(struct Format_info_pg *, int, struct line_pnts *);
static int get_centroid(struct Map_info *, int, struct line_pnts *);
#endif
@@ -314,11 +313,9 @@
if (line_c)
Vect_cat_set(line_c, 1, (int) Line->offset);
- if (Line->type == GV_CENTROID) {
- if (pg_info->toposchema_name)
- return get_centroid_topo(pg_info, line, line_p);
- else
- return get_centroid(Map, line, line_p);
+ if (Line->type == GV_CENTROID && !pg_info->toposchema_name) {
+ /* simple features access: get centroid from sidx */
+ return get_centroid(Map, line, line_p);
}
/* get feature id */
@@ -370,7 +367,7 @@
struct line_pnts *line_p, struct line_cats *line_c,
int ignore_constraints)
{
- int line, itype;
+ int itype;
SF_FeatureType sf_type;
struct Format_info_pg *pg_info;
@@ -383,8 +380,6 @@
Vect_get_constraint_box(Map, &mbox);
while (TRUE) {
- line = Map->next_line++; /* level 2 only */
-
/* reset data structures */
if (line_p != NULL)
Vect_reset_line(line_p);
@@ -395,9 +390,9 @@
while (pg_info->cache.lines_next == pg_info->cache.lines_num) {
/* cache feature -> line_p & line_c */
sf_type = get_feature(pg_info, -1, -1);
-
+
if (sf_type == SF_NONE) {
- G_warning(_("Feature %d without geometry skipped"), line);
+ G_warning(_("Feature %d without geometry skipped"), pg_info->cache.fid);
return -1;
}
@@ -411,6 +406,8 @@
}
G_debug(4, "%d lines read to cache", pg_info->cache.lines_num);
+ /* store fid as offset to be used (used for topo access only */
+ Map->head.last_offset = pg_info->cache.fid;
}
/* get data from cache */
@@ -458,16 +455,16 @@
\param[in,out] pg_info pointer to Format_info_pg struct
\param fid feature id to be read (-1 for next)
- \param topotable_name table name for topological access (NULL for pseudo-topological access) - "node" or "edge"
-
+ \param type feature type (GV_POINT, GV_LINE, ...) - use only for topological access
+
\return simple feature type (SF_POINT, SF_LINESTRING, ...)
\return -1 on error
*/
SF_FeatureType get_feature(struct Format_info_pg *pg_info, int fid, int type)
{
+ int force_type; /* force type (GV_BOUNDARY or GV_CENTROID) for topo access only */
char *data;
char stmt[DB_SQL_MAX];
- int left_face, right_face;
if (!pg_info->geom_column && !pg_info->topogeom_column) {
G_warning(_("No geometry or topo geometry column defined"));
@@ -481,6 +478,7 @@
}
}
else {
+ /* random access */
if (!pg_info->fid_column) {
G_warning(_("Random access not supported. "
"Primary key not defined."));
@@ -495,31 +493,33 @@
sprintf(stmt,
"DECLARE %s_%s%p CURSOR FOR SELECT %s FROM \"%s\".\"%s\" "
"WHERE %s = %d", pg_info->schema_name, pg_info->table_name,
- pg_info->conn, pg_info->geom_column, pg_info->schema_name,
- pg_info->table_name, pg_info->fid_column, fid);
+ pg_info->conn, pg_info->geom_column,
+ pg_info->schema_name, pg_info->table_name,
+ pg_info->fid_column, fid);
}
else {
- /* topological access */
- char *topotable_name;
-
- if (type == GV_POINT)
- topotable_name = "node";
- else if (type & GV_LINES)
- topotable_name = "edge";
- else {
+ if (!(type & (GV_POINTS | GV_LINES))) {
G_warning(_("Unsupported feature type %d"), type);
Vect__execute_pg(pg_info->conn, "ROLLBACK");
return -1;
}
- sprintf(stmt,
- "DECLARE %s_%s%p CURSOR FOR SELECT geom,left_face,right_face "
- " FROM \"%s\".\"%s\" "
- "WHERE %s_id = %d", pg_info->schema_name, pg_info->table_name,
- pg_info->conn, pg_info->toposchema_name,
- topotable_name, topotable_name, fid);
+ if (type & GV_POINTS) {
+ sprintf(stmt,
+ "DECLARE %s_%s%p CURSOR FOR SELECT geom,containing_face "
+ " FROM \"%s\".node WHERE node_id = %d",
+ pg_info->schema_name, pg_info->table_name, pg_info->conn,
+ pg_info->toposchema_name, fid);
+ }
+ else {
+ sprintf(stmt,
+ "DECLARE %s_%s%p CURSOR FOR SELECT geom,left_face,right_face "
+ " FROM \"%s\".edge WHERE edge_id = %d",
+ pg_info->schema_name, pg_info->table_name, pg_info->conn,
+ pg_info->toposchema_name, fid);
+ }
}
-
+ G_debug(3, "SQL: %s", stmt);
if (Vect__execute_pg(pg_info->conn, stmt) == -1)
return -1;
@@ -570,22 +570,45 @@
}
return -2;
}
- data = (char *)PQgetvalue(pg_info->res, pg_info->next_line, 0);
- left_face = right_face = 0;
- if (pg_info->toposchema_name) { /* -> PostGIS topology access */
- if (fid < 0) { /* sequential access */
- left_face = atoi(PQgetvalue(pg_info->res, pg_info->next_line, 2));
- right_face = atoi(PQgetvalue(pg_info->res, pg_info->next_line, 3));
+
+ force_type = -1;
+ if (pg_info->toposchema_name) {
+ if (fid < 0) {
+ /* sequatial access */
+ if (strcmp(PQgetvalue(pg_info->res, pg_info->next_line, 2), "b") == 0)
+ force_type = GV_BOUNDARY;
+ else if (strcmp(PQgetvalue(pg_info->res, pg_info->next_line, 2), "c") == 0)
+ force_type = GV_CENTROID;
}
- else { /* random access */
- left_face = atoi(PQgetvalue(pg_info->res, pg_info->next_line, 1));
- right_face = atoi(PQgetvalue(pg_info->res, pg_info->next_line, 2));
+ else {
+ /* random access: check topological elemenent type consistency */
+ if (type & GV_POINTS) {
+ if (type == GV_POINT &&
+ strlen(PQgetvalue(pg_info->res, pg_info->next_line, 1)) != 0)
+ G_warning(_("Inconsistency in topology: detected centroid (should be point)"));
+ }
+ else {
+ int left_face, right_face;
+
+ left_face = atoi(PQgetvalue(pg_info->res, pg_info->next_line, 1));
+ right_face = atoi(PQgetvalue(pg_info->res, pg_info->next_line, 2));
+
+ if (type == GV_LINE &&
+ (left_face != 0 || right_face != 0))
+ G_warning(_("Inconsistency in topology: detected boundary (should be line)"));
+ }
}
}
- pg_info->cache.sf_type =
- Vect__cache_feature_pg(data, FALSE,
- left_face != 0 || right_face != 0 ? TRUE : FALSE,
- &(pg_info->cache), NULL);
+
+ /* get geometry data */
+ data = (char *)PQgetvalue(pg_info->res, pg_info->next_line, 0);
+
+ /* load feature to the cache */
+ pg_info->cache.sf_type = Vect__cache_feature_pg(data,
+ FALSE, force_type,
+ &(pg_info->cache), NULL);
+
+ /* set feature id */
if (fid < 0) {
pg_info->cache.fid =
atoi(PQgetvalue(pg_info->res, pg_info->next_line, 1));
@@ -607,7 +630,7 @@
if (Vect__execute_pg(pg_info->conn, "COMMIT") == -1)
return -1;
}
-
+
return pg_info->cache.sf_type;
}
@@ -659,7 +682,7 @@
\param data HEX data
\param skip_polygon skip polygons (level 1)
- \param force_boundary force GV_BOUNDARY feature type (for PostGIS topology)
+ \param force_type force GV_BOUNDARY or GV_CENTROID (used for PostGIS topology only)
\param[out] cache lines cache
\param[out] fparts used for building pseudo-topology (or NULL)
@@ -667,7 +690,7 @@
\return SF_UNKNOWN on error
*/
SF_FeatureType Vect__cache_feature_pg(const char *data, int skip_polygon,
- int force_boundary,
+ int force_type,
struct Format_info_cache *cache,
struct feat_parts * fparts)
{
@@ -759,17 +782,14 @@
ret = -1;
if (ftype == SF_POINT) {
cache->lines_num = 1;
- cache->lines_types[0] = GV_POINT;
+ cache->lines_types[0] = force_type == GV_CENTROID ? force_type : GV_POINT;
ret = point_from_wkb(wkb_data, nbytes, byte_order,
is3D, cache->lines[0]);
add_fpart(fparts, ftype, 0, 1);
}
else if (ftype == SF_LINESTRING) {
cache->lines_num = 1;
- if (force_boundary)
- cache->lines_types[0] = GV_BOUNDARY;
- else
- cache->lines_types[0] = GV_LINE;
+ cache->lines_types[0] = force_type == GV_BOUNDARY ? force_type : GV_LINE;
ret = linestring_from_wkb(wkb_data, nbytes, byte_order,
is3D, cache->lines[0], FALSE);
add_fpart(fparts, ftype, 0, 1);
@@ -1147,21 +1167,29 @@
}
else {
/* topology access */
+ /* TODO: optimize SQL statement (for points/centroids) */
sprintf(stmt,
"DECLARE %s_%s%p CURSOR FOR "
- "SELECT geom,fid,left_face,right_face FROM ("
- "SELECT node_id AS fid,geom,0 AS left_face,0 AS right_face FROM "
- "\"%s\".node WHERE node_id NOT IN "
+ "SELECT geom,fid,type FROM ("
+ "SELECT node_id AS fid,geom, 'p' AS type FROM \"%s\".node WHERE "
+ "containing_face IS NULL AND node_id NOT IN "
"(SELECT node FROM (SELECT start_node AS node FROM \"%s\".edge "
"GROUP BY start_node UNION ALL SELECT end_node AS node FROM "
- "\"%s\".edge GROUP BY end_node) AS foo) "
- "UNION ALL SELECT edge_id AS fid,geom,left_face,right_face FROM \"%s\".edge "
- "ORDER BY fid) AS foo",
+ "\"%s\".edge GROUP BY end_node) AS foo) UNION ALL SELECT "
+ "node_id AS fid,geom, 'c' AS type FROM \"%s\".node WHERE "
+ "containing_face IS NOT NULL AND node_id NOT IN "
+ "(SELECT node FROM (SELECT start_node AS node FROM \"%s\".edge "
+ "GROUP BY start_node UNION ALL SELECT end_node AS node FROM "
+ "\"topo_bridges\".edge GROUP BY end_node) AS foo) "
+ "UNION ALL SELECT edge_id AS fid, geom, 'l' AS type FROM \"%s\".edge WHERE "
+ "left_face = 0 AND right_face = 0 UNION ALL SELECT edge_id AS fid, geom, 'b' AS type FROM "
+ "\"%s\".edge WHERE left_face != 0 OR right_face != 0 ) AS foo ORDER BY fid, type",
pg_info->schema_name, pg_info->table_name, pg_info->conn,
pg_info->toposchema_name, pg_info->toposchema_name,
- pg_info->toposchema_name, pg_info->toposchema_name);
+ pg_info->toposchema_name, pg_info->toposchema_name,
+ pg_info->toposchema_name, pg_info->toposchema_name, pg_info->toposchema_name);
}
- G_debug(2, "SQL: %s", stmt);
+ G_debug(3, "SQL: %s", stmt);
if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
Vect__execute_pg(pg_info->conn, "ROLLBACK");
@@ -1216,6 +1244,38 @@
}
/*!
+ \brief Execute SQL statement and get value.
+
+ \param conn pointer to PGconn
+ \param stmt query
+
+ \return value on success
+ \return -1 on error
+ */
+int Vect__execute_get_value_pg(PGconn *conn, const char *stmt)
+{
+ int ret;
+ PGresult *result;
+
+ result = NULL;
+
+ G_debug(3, "Vect__execute_get_value_pg(): %s", stmt);
+ result = PQexec(conn, stmt);
+ if (!result || PQresultStatus(result) != PGRES_TUPLES_OK ||
+ PQntuples(result) != 1) {
+ PQclear(result);
+
+ G_warning(_("Execution failed: %s"), PQerrorMessage(conn));
+ return -1;
+ }
+
+ ret = atoi(PQgetvalue(result, 0, 0));
+ PQclear(result);
+
+ return ret;
+}
+
+/*!
\brief Reallocate lines cache
*/
void reallocate_cache(struct Format_info_cache *cache, int num)
@@ -1280,49 +1340,6 @@
}
/*
- \brief Get centroid from PostGIS topology
-
- \param pg_info pointer to Format_info_pg
- \param centroid centroid id
- \param[out] line_p output geometry
-
- \return GV_CENTROID on success
- \return -1 on error
-*/
-int get_centroid_topo(struct Format_info_pg *pg_info,
- int centroid, struct line_pnts *line_p)
-{
- char stmt[DB_SQL_MAX];
- char *data;
-
- PGresult *res;
-
- sprintf(stmt,
- "SELECT ST_PointOnSurface(geom) AS geom FROM "
- "ST_GetFaceGeometry('%s', %d) AS geom",
- pg_info->toposchema_name, centroid);
- res = PQexec(pg_info->conn, stmt);
- if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
- PQntuples(res) != 1) {
- G_warning(_("Unable to read centroid %d: %s"),
- centroid, PQerrorMessage(pg_info->conn));
- if (res)
- PQclear(res);
- return -1;
- }
-
- data = (char *)PQgetvalue(res, 0, 0);
- PQclear(res);
-
- if (GV_POINT != Vect__cache_feature_pg(data, FALSE, FALSE, &(pg_info->cache), NULL))
- return -1;
-
- Vect_append_points(line_p, pg_info->cache.lines[0], GV_FORWARD);
-
- return GV_CENTROID;
-}
-
-/*
\brief Get centroid
\param pg_info pointer to Format_info_pg
Modified: grass/trunk/lib/vector/Vlib/rewind_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/rewind_pg.c 2012-11-27 09:15:53 UTC (rev 54071)
+++ grass/trunk/lib/vector/Vlib/rewind_pg.c 2012-11-27 10:00:53 UTC (rev 54072)
@@ -81,8 +81,9 @@
{
G_debug(2, "V2_rewind_pg(): name = %s", Map->name);
#ifdef HAVE_POSTGRES
+ /* reset reading */
Map->next_line = 1;
-
+
V1_rewind_pg(Map);
return 0;
Modified: grass/trunk/lib/vector/Vlib/write_nat.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_nat.c 2012-11-27 09:15:53 UTC (rev 54071)
+++ grass/trunk/lib/vector/Vlib/write_nat.c 2012-11-27 10:00:53 UTC (rev 54072)
@@ -177,8 +177,8 @@
if (n > 2) {
/* more than 2 boundaries at node ( >= 2 old + 1 new ) */
/* Line above (to the right), it is enough to check to
- the right, because if area/isle
- exists it is the same to the left */
+ the right, because if area/isle exists it is the
+ same to the left */
if (!s)
next_line =
dig_angle_next_line(plus, line, GV_RIGHT,
Modified: grass/trunk/lib/vector/Vlib/write_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_pg.c 2012-11-27 09:15:53 UTC (rev 54071)
+++ grass/trunk/lib/vector/Vlib/write_pg.c 2012-11-27 10:00:53 UTC (rev 54072)
@@ -5,7 +5,7 @@
Higher level functions for reading/writing/manipulating vectors.
- Inspired by OGR PostgreSQL driver.
+ Write subroutine 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()
@@ -50,16 +50,16 @@
int, int *);
static unsigned char *polygon_to_wkb(int, const struct line_pnts **, int,
int, int *);
-static int write_feature(struct Map_info *,
- int, const struct line_pnts **, int, int,
- const struct P_line *,
+static int write_feature(struct Map_info *, int, int,
+ const struct line_pnts **, int, int,
int, const struct field_info *);
static char *build_insert_stmt(const struct Format_info_pg *, const char *,
- int, int, const struct field_info *);
-static char *build_topo_stmt(struct Map_info *, int,
- const struct P_line *, const char *);
-static int execute_topo(PGconn *, const char *);
-static int update_next_line(struct Map_info*, int, int, int*, int *);
+ int, const struct field_info *);
+static int insert_topo_element(struct Map_info *, int, int, const char *);
+static int update_next_edge(struct Map_info*, int, int, int*, int *);
+static int insert_face(struct Map_info *, int);
+static int update_topo_edge(struct Map_info *, int);
+static int update_topo_face(struct Map_info *, int);
#endif
/*!
@@ -131,7 +131,7 @@
}
else { /* PostGIS topology */
if (Map->plus.built < GV_BUILD_BASE)
- Map->plus.built = GV_BUILD_BASE;
+ Map->plus.built = GV_BUILD_ALL;
return write_line_tp(Map, type, FALSE, points, cats);
}
#else
@@ -387,7 +387,7 @@
}
}
else {
- G_warning(_("Unsupported feature type (%d)"), type);
+ G_warning(_("Unsupported feature type %d"), type);
return -1;
}
@@ -410,8 +410,8 @@
}
/* write feature's geometry and fid */
- if (-1 == write_feature(Map, type, points, nparts,
- Vect_is_3d(Map) ? WITH_Z : WITHOUT_Z, NULL, cat, Fi)) {
+ if (-1 == write_feature(Map, -1, type, points, nparts,
+ Vect_is_3d(Map) ? WITH_Z : WITHOUT_Z, cat, Fi)) {
Vect__execute_pg(pg_info->conn, "ROLLBACK");
return -1;
}
@@ -452,12 +452,11 @@
const struct line_pnts *points,
const struct line_cats *cats)
{
- int cat;
+ int line, cat;
struct field_info *Fi;
struct Format_info_pg *pg_info;
struct Plus_head *plus;
- struct P_line *Line;
pg_info = &(Map->fInfo.pg);
plus = &(Map->plus);
@@ -491,6 +490,8 @@
G_debug(3, "write_line_pg(): type = %d n_points = %d",
type, points->n_points);
+ line = -1; /* used only for topological access (lines, boundaries, and centroids) */
+
Fi = NULL; /* no attributes to be written */
cat = -1;
if (cats && cats->n_cats > 0) {
@@ -511,30 +512,38 @@
Vect_cat_get(cats, 1, &cat);
}
- /* update topology before writing feature */
- Line = NULL;
+ /* update GRASS-like topology before writing feature */
if (is_node) {
dig_add_node(plus, points->x[0], points->y[0], points->z[0]);
}
else {
- int line;
+ off_t offset;
struct bound_box box;
dig_line_box(points, &box);
- line = dig_add_line(plus, type, points, &box, 0); /* offset ? */
+ /* better is probably to check nextval directly */
+ if (type & GV_POINTS) {
+ offset = Vect_get_num_primitives(Map, GV_POINTS) + 1; /* next */
+ offset += Vect_get_num_nodes(Map); /* nodes are also stored in 'node' table */
+ }
+ else { /* LINES */
+ offset = Vect_get_num_primitives(Map, GV_LINES) + 1; /* next */
+ }
+ line = dig_add_line(plus, type, points, &box, offset);
G_debug(3, " line added to topo with id = %d", line);
+
if (line == 1)
Vect_box_copy(&(plus->box), &box);
else
Vect_box_extend(&(plus->box), &box);
- V2__add_line_to_topo_nat(Map, line, points, NULL); /* cats ? */
-
- Line = plus->Line[line];
}
- /* write feature geometry and fid */
- if (-1 == write_feature(Map, type, &points, 1,
- Vect_is_3d(Map) ? WITH_Z : WITHOUT_Z, Line,
+ /* write new feature to PostGIS
+ - feature table for simple features
+ - feature table and topo schema for topological access
+ */
+ if (-1 == write_feature(Map, line, type, &points, 1,
+ Vect_is_3d(Map) ? WITH_Z : WITHOUT_Z,
cat, Fi)) {
Vect__execute_pg(pg_info->conn, "ROLLBACK");
return -1;
@@ -819,6 +828,7 @@
\brief Insert feature into table
\param Map pointer to Map_info structure
+ \param line feature id (topo access only)
\param type feature type (GV_POINT, GV_LINE, ...)
\param points pointer to line_pnts struct
\param nparts number of parts (rings for polygon)
@@ -829,19 +839,17 @@
\return -1 on error
\retirn 0 on success
*/
-int write_feature(struct Map_info *Map, int type,
+int write_feature(struct Map_info *Map, int line, int type,
const struct line_pnts **points, int nparts, int with_z,
- const struct P_line *Line,
int cat, const struct field_info *Fi)
{
- int fid;
int byte_order, nbytes, nsize;
unsigned int sf_type;
unsigned char *wkb_data;
char *stmt, *text_data, *text_data_p, *hex_data;
struct Format_info_pg *pg_info;
-
+
pg_info = &(Map->fInfo.pg);
if (with_z && pg_info->coor_dim != 3) {
@@ -933,12 +941,7 @@
/* build INSERT statement
simple feature geometry + attributes
*/
- fid = -1;
- if (pg_info->toposchema_name) {
- /* use defined fid (=line) for topological access */
- fid = Vect_get_num_primitives(Map, type); /* write next fid */
- }
- stmt = build_insert_stmt(pg_info, text_data, fid, cat, Fi);
+ stmt = build_insert_stmt(pg_info, text_data, cat, Fi);
G_debug(2, "SQL: %s", stmt);
if (!pg_info->inTransaction) {
@@ -960,17 +963,20 @@
/* write feature in PostGIS topology schema if enabled */
if (pg_info->toposchema_name) {
/* insert feature into topology schema (node or edge) */
- stmt = build_topo_stmt(Map, type, Line, text_data);
-#if USE_TOPO_STMT
- if (stmt && execute_topo(pg_info->conn, stmt) == -1) {
-#else
- if (stmt && Vect__execute_pg(pg_info->conn, stmt) == -1) {
-#endif
- /* rollback transaction */
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ if (insert_topo_element(Map, line, type, text_data) != 0) {
+ G_warning(_("Unable to insert topological element into PostGIS Topology schema"));
return -1;
}
- G_free(stmt);
+
+ /* update GRASS-like topo */
+ if (line > 0) /* skip nodes */
+ V2__add_line_to_topo_nat(Map, line, points[0], NULL); /* TODO: cats */
+
+ /* update PostGIS-line topo */
+ if (type & GV_LINES)
+ update_topo_edge(Map, line);
+ if (type == GV_BOUNDARY)
+ update_topo_face(Map, line);
}
G_free(wkb_data);
@@ -987,14 +993,13 @@
\param pg_info pointer to Format_info_pg structure
\param geom_data geometry data
- \param fid feature id (=line)
\param cat category number (or -1 for no category)
\param Fi pointer to field_info structure (NULL for no attributes)
\return allocated string with INSERT statement
*/
char *build_insert_stmt(const struct Format_info_pg *pg_info,
- const char *geom_data, int fid,
+ const char *geom_data,
int cat, const struct field_info *Fi)
{
char *stmt, buf[DB_SQL_MAX];
@@ -1113,8 +1118,8 @@
else {
/* PostGIS topology access, write geometry in
* topology schema, skip geometry at this point */
- G_asprintf(&stmt, "%s,%s) VALUES (%s,%d)",
- buf, pg_info->fid_column, buf_val, fid);
+ G_asprintf(&stmt, "%s) VALUES (%s)",
+ buf, buf_val);
}
}
}
@@ -1130,33 +1135,37 @@
}
else if (cat > 0)
/* no attributes (topology elements) */
- G_asprintf(&stmt, "INSERT INTO \"%s\".\"%s\" (%s) VALUES (%d)",
+ G_asprintf(&stmt, "INSERT INTO \"%s\".\"%s\" (%s) VALUES (NULL)",
pg_info->schema_name, pg_info->table_name,
- pg_info->fid_column, fid);
+ pg_info->geom_column);
}
return stmt;
}
/*!
- \brief Build SELECT statement to insert new element into PostGIS
- topology schema
+ \brief Insert topological element into 'node' or 'edge' table
\param Map pointer to Map_info struct
- \param Line pointer to P_line struct (topo)
+ \param line feature id (-1 for nodes/points)
+ \param type feature type (GV_POINT, GV_LINE, ...)
\param geom_data geometry in wkb
- \return pointer to allocated string buffer with SQL statement
- \return NULL on error
+ \return 0 on success
+ \return -1 on error
*/
-char *build_topo_stmt(struct Map_info *Map, int type,
- const struct P_line *Line, const char *geom_data)
+int insert_topo_element(struct Map_info *Map, int line, int type,
+ const char *geom_data)
{
char *stmt;
struct Format_info_pg *pg_info;
-
+ struct P_line *Line;
+
pg_info = &(Map->fInfo.pg);
+ if (line > 0)
+ Line = Map->plus.Line[line];
+
stmt = NULL;
switch(type) {
case GV_POINT: {
@@ -1169,51 +1178,28 @@
#endif
break;
}
- case GV_LINE: {
- int line;
- int n1, n2;
- int nle, nre; /* next left | right edge */
+ case GV_LINE:
+ case GV_BOUNDARY: {
+#if USE_TOPO_STMT
+ G_asprintf(&stmt, "SELECT topology.AddEdge('%s', '%s'::GEOMETRY)",
+ pg_info->toposchema_name, geom_data);
+#else
+ int nle, nre;
- /*
- * isolated lines
- next left edge: -fid
- next right edge: fid
-
- * connected lines
- next left edge: next line or -fid
- next right edge: next line or fid
- */
if (!Line) {
G_warning(_("Topology not available. Unable to insert new edge."));
- return NULL;
+ return -1;
}
struct P_topo_l *topo = (struct P_topo_l *) Line->topo;
-
-#if USE_TOPO_STMT
- G_asprintf(&stmt, "SELECT topology.AddEdge('%s', '%s'::GEOMETRY)",
- pg_info->toposchema_name, geom_data);
-#else
- line = Vect_get_num_lines(Map);
- /* get number of lines for each node */
- n1 = Vect_get_node_n_lines(Map, topo->N1);
- n2 = Vect_get_node_n_lines(Map, topo->N2);
-
/* assuming isolated lines */
- nle = -line;
- nre = line;
+ nle = -Line->offset;
+ nre = Line->offset;
- /* check for line connection */
- if (n1 > 1) {
- update_next_line(Map, n1, line, &nle, &nre);
- }
- if (n2 > 1) {
- update_next_line(Map, n2, -line, &nle, &nre);
- }
+ G_debug(3, "new edge: id=%lu next_left_edge=%d next_right_edge=%d",
+ Line->offset, nle, nre);
- G_debug(3, "build_topo_stmt(): line=%d type=line nle=%d nre=%d", line, nle, nre);
-
G_asprintf(&stmt, "INSERT INTO \"%s\".edge_data (geom, start_node, end_node, "
"next_left_edge, abs_next_left_edge, next_right_edge, abs_next_right_edge, "
"left_face, right_face) "
@@ -1224,55 +1210,45 @@
break;
}
case GV_CENTROID: {
- /* TopoGeo_AddPoint ? */
- G_asprintf(&stmt, "SELECT AddNode('%s', '%s'::GEOMETRY)",
+#if USE_TOPO_STMT
+ G_asprintf(&stmt, "SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
pg_info->toposchema_name, geom_data);
+#else
+ if (!Line) {
+ G_warning(_("Topology not available. Unable to insert new node (centroid)"));
+ return -1;
+ }
+
+ struct P_topo_c *topo = (struct P_topo_c *) Line->topo;
+
+ /* get id - see write_line_tp()
+
+ sprintf(stmt_next, "SELECT nextval('\"%s\".node_node_id_seq')",
+ pg_info->toposchema_name);
+ Line->offset = Vect__execute_get_value_pg(pg_info->conn, stmt_next);
+ if (Line->offset < 1) {
+ G_warning(_("Invalid feature offset"));
+ return NULL;
+ }
+ */
+ G_asprintf(&stmt, "INSERT INTO \"%s\".node (containing_face, geom) "
+ "VALUES (%d, '%s'::GEOMETRY)",
+ pg_info->toposchema_name, topo->area, geom_data);
+#endif
break;
}
- case GV_BOUNDARY: {
- /* TopoGeo_AddLineString ? */
- G_asprintf(&stmt, "SELECT AddEdge('%s', '%s'::GEOMETRY)",
- pg_info->toposchema_name, geom_data);
- break;
- }
default:
G_warning(_("Unsupported feature type %d"), type);
break;
}
- return stmt;
-}
-
-/*!
- \brief Execute SQL topo select statement
-
- \param conn pointer to PGconn
- \param stmt query
-
- \return value on success
- \return -1 on error
- */
-int execute_topo(PGconn *conn, const char *stmt)
-{
- int ret;
- PGresult *result;
-
- result = NULL;
-
- G_debug(3, "execute_topo(): %s", stmt);
- result = PQexec(conn, stmt);
- if (!result || PQresultStatus(result) != PGRES_TUPLES_OK ||
- PQntuples(result) != 1) {
- PQclear(result);
-
- G_warning(_("Execution failed: %s"), PQerrorMessage(conn));
+ if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ /* rollback transaction */
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
return -1;
}
- ret = atoi(PQgetvalue(result, 0, 0));
- PQclear(result);
-
- return ret;
+ return 0;
}
/*!
@@ -1280,66 +1256,299 @@
\param Map pointer to Map_info struct
\param nlines number of lines
- \param line current line (negative for backward direction - ie. end node)
+ \param line current line
\param[out] left left line
\param[out] right right line
- \return line id (left or right)
-
+
\return 0 on success
\return -1 on failure
*/
-int update_next_line(struct Map_info* Map, int nlines, int line,
+int update_next_edge(struct Map_info* Map, int nlines, int line,
int *left, int *right)
{
- int next_line;
+ int next_line, edge;
char stmt[DB_SQL_MAX];
- struct Format_info_pg *pg_info;
+ const struct Format_info_pg *pg_info;
+ struct P_line *Line_next, *Line;
+ Line = Line_next = NULL;
+
pg_info = &(Map->fInfo.pg);
+
+ /* find next line
+ start node -> next on the left
+ end node -> next on the right
+ */
+ next_line = dig_angle_next_line(&(Map->plus), line, GV_LEFT, GV_LINES, NULL);
+ G_debug(3, "line=%d next_line=%d", line, next_line);
+ if (next_line == 0) {
+ G_warning(_("Invalid topology"));
+ return -1;
+ }
- /* update left line side */
- next_line = dig_angle_next_line(&(Map->plus), line,
- line < 0 ? GV_LEFT : GV_RIGHT, GV_LINE, NULL);
- if (line > 0)
- *right = next_line;
- else
- *left = next_line;
- sprintf(stmt, "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
- "abs_next_left_edge = %d WHERE edge_id = %d",
- pg_info->toposchema_name, line, abs(line), abs(next_line));
- G_debug(4, "build_topo_stmt(): line=%d nle=%d | line=%d nle=%d",
- line, next_line, abs(next_line), line);
+ Line = Map->plus.Line[abs(line)];
+ Line_next = Map->plus.Line[abs(next_line)];
+ if (!Line || !Line_next) {
+ G_warning(_("Invalid topology"));
+ return -1;
+ }
+ if (line > 0) {
+ edge = Line->offset;
+ *right = next_line > 0 ? Line_next->offset : -Line_next->offset;
+ }
+ else {
+ edge = -Line->offset;
+ *left = next_line > 0 ? Line_next->offset : -Line_next->offset;
+ }
+
+ if (next_line < 0) {
+ sprintf(stmt, "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
+ "abs_next_left_edge = %d WHERE edge_id = %lu",
+ pg_info->toposchema_name, edge, abs(edge), Line_next->offset);
+ G_debug(3, "update edge=%lu next_left_edge=%d", Line_next->offset, edge);
+ }
+ else {
+ sprintf(stmt, "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
+ "abs_next_right_edge = %d WHERE edge_id = %lu AND abs_next_right_edge = %lu",
+ pg_info->toposchema_name, edge, abs(edge), Line_next->offset, Line_next->offset);
+ G_debug(3, "update edge=%lu next_right_edge=%d (?)", Line_next->offset, edge);
+ }
+
if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
- /* rollback transaction */
Vect__execute_pg(pg_info->conn, "ROLLBACK");
return -1;
}
if (nlines > 2) {
- /* update right line side */
- next_line = dig_angle_next_line(&(Map->plus), line,
- line < 0 ? GV_RIGHT : GV_LEFT, GV_LINE, NULL);
- if (line > 0)
- *right = next_line;
- else
- *left = next_line;
- G_debug(4, "line=%d nre=%d", line, next_line);
- /*
- sprintf(stmt, "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
- "abs_next_right_edge = %d WHERE edge_id = %d",
- pg_info->toposchema_name, line, abs(line), abs(next_line));
- G_debug(0, "build_topo_stmt(): line=%d nre=%d", abs(next_line), line);
+ /* more lines connected to the node
+ start node -> next on the right
+ end node -> next on the left
+ */
+ next_line = dig_angle_next_line(&(Map->plus), line, GV_RIGHT, GV_LINES, NULL);
+ Line_next = Map->plus.Line[abs(next_line)];
+
+ if (next_line < 0) {
+ sprintf(stmt, "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
+ "abs_next_left_edge = %d WHERE edge_id = %lu",
+ pg_info->toposchema_name, edge, abs(edge), Line_next->offset);
+ G_debug(3, "update edge=%lu next_left_edge=%d", Line_next->offset, edge);
+ }
+ else {
+ sprintf(stmt, "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
+ "abs_next_right_edge = %d WHERE edge_id = %lu AND abs_next_right_edge = %lu",
+ pg_info->toposchema_name, edge, abs(edge), Line_next->offset, Line_next->offset);
+ G_debug(3, "update edge=%lu next_right_edge=%d (?)", Line_next->offset, edge);
+ }
+
if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
return -1;
}
- */
}
return 0;
}
+/*!
+ \brief Insert new face to the 'face' table (topo only)
+
+ \param Map pointer to Map_info struct
+ \param area area id
+
+ \return 0 on error
+ \return area id on success (>0)
+*/
+int insert_face(struct Map_info *Map, int area)
+{
+ char *stmt;
+
+ struct Format_info_pg *pg_info;
+ struct bound_box box;
+
+ if (area <= 0)
+ return 0; /* universal face has id '0' in PostGIS Topology */
+
+ stmt = NULL;
+ pg_info = &(Map->fInfo.pg);
+
+ /* check if face exists */
+
+ /* get mbr of the area */
+ Vect_get_area_box(Map, area, &box);
+
+ /* insert face if not exists */
+ G_asprintf(&stmt, "INSERT INTO \"%s\".face (face_id, mbr) VALUES "
+ "(%d, 'POLYGON((%.12f %.12f, %.12f %.12f, %.12f %.12f, %.12f %.12f, "
+ "%.12f %.12f))'::GEOMETRY)", pg_info->toposchema_name, area,
+ box.W, box.S, box.W, box.N, box.E, box.N,
+ box.E, box.S, box.W, box.S);
+ G_debug(3, "new face id=%d", area);
+ if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return 0;
+ }
+ G_free(stmt);
+
+ return area;
+}
+
+
+/*!
+ \brief Update lines (next left and right edges)
+
+ - isolated edges
+ next left edge: -edge
+ next right edge: edge
+
+ - connected edges
+ next left edge: next edge or -edge
+ next right edge: next edge or edge
+
+ \param Map pointer to Map_info struct
+ \param line feature id
+
+ \return 0 on success
+ \return -1 on error
+*/
+int update_topo_edge(struct Map_info *Map, int line)
+{
+ int n1, n2;
+ int nle, nre;
+ char stmt[DB_SQL_MAX];
+
+ struct Format_info_pg *pg_info;
+ struct P_line *Line;
+
+ pg_info = &(Map->fInfo.pg);
+
+ if (line < 1 || line > Vect_get_num_lines(Map)) {
+ G_warning(_("Inconsistency in topology detected"));
+ return -1;
+ }
+ Line = Map->plus.Line[line];
+ if (!Line) {
+ G_warning(_("Inconsistency in topology detected"));
+ return -1;
+ }
+
+ struct P_topo_l *topo = (struct P_topo_l *) Line->topo;
+
+ /* get number of lines for each node */
+ n1 = Vect_get_node_n_lines(Map, topo->N1);
+ n2 = Vect_get_node_n_lines(Map, topo->N2);
+
+ nre = nle = 0;
+
+ /* check for line connection */
+ if (n1 > 1) {
+ update_next_edge(Map, n1, line, &nle, &nre);
+ }
+ if (n2 > 1) {
+ update_next_edge(Map, n2, -line, &nle, &nre);
+ }
+
+ if (nle == 0 && nre == 0) /* nothing changed */
+ return 0;
+
+ sprintf(stmt, "UPDATE \"%s\".edge_data SET "
+ "next_left_edge = %d, abs_next_left_edge = %d, "
+ "next_right_edge = %d, abs_next_right_edge = %d "
+ "WHERE edge_id = %lu", pg_info->toposchema_name,
+ nle, abs(nle), nre, abs(nre), Line->offset);
+ G_debug(3, "update edge=%lu next_left_edge=%d next_right_edge=%d",
+ Line->offset, nle, nre);
+
+ if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ /* rollback transaction */
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*!
+ \brief Update lines (left and right faces)
+
+ TODO: handle isles
+
+ \param Map pointer to Map_info struct
+ \param line feature id
+
+ \return 0 on success
+ \return -1 on error
+*/
+int update_topo_face(struct Map_info *Map, int line)
+{
+ int i, s, area, face;
+ char stmt[DB_SQL_MAX];
+
+ struct Format_info_pg *pg_info;
+ struct P_line *Line;
+ struct P_area *Area;
+ struct P_topo_b *topo;
+
+ pg_info = &(Map->fInfo.pg);
+
+ if (line < 1 || line > Vect_get_num_lines(Map)) {
+ G_warning(_("Inconsistency in topology detected"));
+ return -1;
+ }
+ Line = Map->plus.Line[line];
+ if (!Line) {
+ G_warning(_("Inconsistency in topology detected"));
+ return -1;
+ }
+
+ topo = (struct P_topo_b *)Line->topo;
+
+ for (s = 0; s < 2; s++) { /* for each side */
+ area = s == 0 ? topo->left : topo->right;
+ if (area <= 0) /* no area - skip */
+ continue;
+ Area = Map->plus.Area[area];
+
+ face = insert_face(Map, area); /* TODO: update */
+
+ for (i = 0; i < Area->n_lines; i++) { /* update all boundaries */
+ Line = Map->plus.Line[abs(Area->lines[i])];
+ topo = (struct P_topo_b *)Line->topo;
+
+ sprintf(stmt, "UPDATE \"%s\".edge_data SET "
+ "left_face = %d, right_face = %d "
+ "WHERE edge_id = %lu", pg_info->toposchema_name,
+ topo->left > 0 ? topo->left : 0,
+ topo->right > 0 ? topo->right : 0,
+ Line->offset);
+ G_debug(2, "SQL: %s", stmt);
+
+ if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ /* rollback transaction */
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+ }
+
+ /* update also centroids */
+ if (Area->centroid > 0) {
+ Line = Map->plus.Line[Area->centroid];
+ sprintf(stmt, "UPDATE \"%s\".node SET containing_face = %d "
+ "WHERE node_id = %lu", pg_info->toposchema_name,
+ face, Line->offset);
+ G_debug(2, "SQL: %s", stmt);
+
+ if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ /* rollback transaction */
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
#endif
Modified: grass/trunk/lib/vector/diglib/plus_area.c
===================================================================
--- grass/trunk/lib/vector/diglib/plus_area.c 2012-11-27 09:15:53 UTC (rev 54071)
+++ grass/trunk/lib/vector/diglib/plus_area.c 2012-11-27 10:00:53 UTC (rev 54072)
@@ -457,12 +457,12 @@
* of points and degenerated lines are set to -9 (ignored).
*
* \param[in] plus pointer to Plus_head structure
- * \param[in] current_line current line id, negative if request for node 2
+ * \param[in] current_line current line id, negative if request for end node
* \param[in] side side GV_RIGHT or GV_LEFT
* \param[in] type line type (GV_LINE, GV_BOUNDARY or both)
* \param[in] angle
*
- * \return line number of next angle to follow an line (negative if connected by node2)
+ * \return line number of next angle to follow an line (negative if connected by end node)
* (number of current line may be return if dangle - this is used in build)
* \return 0 on error or not found
*/
More information about the grass-commit
mailing list