[GRASS-SVN] r55706 - in grass/trunk/lib/vector: Vlib diglib
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Apr 11 11:22:46 PDT 2013
Author: martinl
Date: 2013-04-11 11:22:45 -0700 (Thu, 11 Apr 2013)
New Revision: 55706
Modified:
grass/trunk/lib/vector/Vlib/break_polygons.c
grass/trunk/lib/vector/Vlib/level_two.c
grass/trunk/lib/vector/Vlib/read_pg.c
grass/trunk/lib/vector/Vlib/write_pg.c
grass/trunk/lib/vector/diglib/plus_line.c
Log:
vlib(pg): add_line_to_topo_pg() and delete_line_from_topo_pg() added
various minor improvements in PostGIS Topology support
(work in progress)
Modified: grass/trunk/lib/vector/Vlib/break_polygons.c
===================================================================
--- grass/trunk/lib/vector/Vlib/break_polygons.c 2013-04-11 15:49:39 UTC (rev 55705)
+++ grass/trunk/lib/vector/Vlib/break_polygons.c 2013-04-11 18:22:45 UTC (rev 55706)
@@ -7,10 +7,8 @@
(C) 2001-2009 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.
+ 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 Update for GRASS 7 Markus Metz
@@ -651,27 +649,24 @@
}
/*!
- \brief Break polygons in vector map.
+ \brief Break polygons in vector map
Breaks lines specified by type in vector map. Points at
- intersections may be optionally written to error map. Input map
- must be opened on level 2 for update at least on GV_BUILD_BASE.
+ intersections may be optionally written to error map. Input vector
+ map must be opened on level 2 for update at least on GV_BUILD_BASE.
- Function is optimized for closed polygons rigs (e.g. imported from
+ Function is optimized for closed polygons rings (e.g. imported from
OGR) but with clean geometry - adjacent polygons mostly have
identical boundary. Function creates database of ALL points in the
- map, and then is looking for those where polygons should be broken.
- Lines may be broken only at points existing in input map!
+ vector map, and then is looking for those where polygons should be
+ broken. Lines may be broken only at points existing in input
+ vector map!
\param Map input map where polygons will be broken
- \param type type of line to be broken
+ \param type type of line to be broken (GV_LINE or GV_BOUNDARY)
\param Err vector map where points at intersections will be written or NULL
-
- \return
*/
-
-void
-Vect_break_polygons(struct Map_info *Map, int type, struct Map_info *Err)
+void Vect_break_polygons(struct Map_info *Map, int type, struct Map_info *Err)
{
if (getenv("GRASS_VECTOR_LOWMEM"))
return Vect_break_polygons_file(Map, type, Err);
Modified: grass/trunk/lib/vector/Vlib/level_two.c
===================================================================
--- grass/trunk/lib/vector/Vlib/level_two.c 2013-04-11 15:49:39 UTC (rev 55705)
+++ grass/trunk/lib/vector/Vlib/level_two.c 2013-04-11 18:22:45 UTC (rev 55706)
@@ -226,17 +226,21 @@
}
/*!
- \brief Get updated node by index
+ \brief Get updated (modified) node by index
Note: Vect_set_updated() must be called to maintain list of updated
features
- Negative id indicates deleted node.
+ Negative id:
+ - if Node[id] is not NULL then the node was added
+ - if Node[id] is NULL then the node was deleted
+ Positive id:
+ - node was updated
\param Map pointer to Map_info struct
\param idx index
- \return updated node
+ \return id of modified node
*/
int Vect_get_updated_node(const struct Map_info *Map, int idx)
{
Modified: grass/trunk/lib/vector/Vlib/read_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/read_pg.c 2013-04-11 15:49:39 UTC (rev 55705)
+++ grass/trunk/lib/vector/Vlib/read_pg.c 2013-04-11 18:22:45 UTC (rev 55706)
@@ -8,8 +8,13 @@
\todo Currently only points, linestrings and polygons are supported,
implement also other types
- (C) 2011-2012 by the GRASS Development Team
+ \todo Support multigeometries
+ \todo PostGIS Topology - fix category handling (read categories
+ from feature table)
+
+ (C) 2011-2013 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.
@@ -324,7 +329,7 @@
return 0;
}
- G_debug(4, "V2_read_line_pg() line = %d type = %d offset = %lu",
+ G_debug(4, "V2_read_line_pg() line = %d type = %d offset = %"PRI_OFF_T,
line, Line->type, Line->offset);
if (!line_p && !line_c)
@@ -335,7 +340,7 @@
if (line_c != NULL)
Vect_reset_cats(line_c);
- if (line_c)
+ if (line_c)
Vect_cat_set(line_c, 1, (int) Line->offset);
if (Line->type == GV_CENTROID && !pg_info->toposchema_name) {
Modified: grass/trunk/lib/vector/Vlib/write_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_pg.c 2013-04-11 15:49:39 UTC (rev 55705)
+++ grass/trunk/lib/vector/Vlib/write_pg.c 2013-04-11 18:22:45 UTC (rev 55706)
@@ -7,11 +7,9 @@
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()
+ \todo PostGIS 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
+ \todo PostGIS version of V2__add_area_cats_to_cidx_nat
(C) 2012-2013 by Martin Landa, and the GRASS Development Team
@@ -68,6 +66,8 @@
static int delete_face(const struct Map_info *, int);
static int update_topo_edge(struct Map_info *, int);
static int update_topo_face(struct Map_info *, int);
+static int add_line_to_topo_pg(struct Map_info *, off_t, int, const struct line_pnts *);
+static int delete_line_from_topo_pg(struct Map_info *, int, int, const struct line_pnts *);
#endif
static struct line_pnts *Points;
@@ -214,7 +214,7 @@
\return -1 on error
*/
off_t V2_rewrite_line_pg(struct Map_info *Map, int line, int type, off_t old_offset,
- const struct line_pnts *points, const struct line_cats *cats)
+ const struct line_pnts *points, const struct line_cats *cats)
{
G_debug(3, "V2_rewrite_line_pg(): line=%d type=%d offset=%"PRI_OFF_T,
line, type, old_offset);
@@ -249,7 +249,7 @@
}
/* remove line from topology */
- if (0 != V2__delete_line_from_topo_nat(Map, line, type, Points, NULL))
+ if (0 != delete_line_from_topo_pg(Map, line, type, Points))
return -1;
if (pg_info->toposchema_name) { /* PostGIS Topology */
@@ -281,7 +281,7 @@
/* update topology
note: offset is not changed */
- return V2__add_line_to_topo_nat(Map, old_offset, type, points, cats, -1, NULL);
+ return add_line_to_topo_pg(Map, old_offset, type, points);
#else
G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
return -1;
@@ -377,7 +377,7 @@
return V2_delete_line_sfa(Map, line);
}
else { /* PostGIS topology */
- int type, n_nodes;
+ int type;
char stmt[DB_SQL_MAX];
const char *table_name, *keycolumn;
@@ -441,34 +441,7 @@
}
/* update topology */
- Vect_reset_updated(Map);
- if (0 != V2__delete_line_from_topo_nat(Map, line, type, Points, NULL))
- return -1;
-
- /* delete nodes from 'nodes' table */
- n_nodes = Vect_get_num_updated_nodes(Map);
- if (n_nodes > 0) {
- int i, node;
-
- for (i = 0; i < n_nodes; i++) {
- node = Vect_get_updated_node(Map, i);
- if (node > 0)
- continue; /* node was updated, not deleted */
-
- node = abs(node);
- G_debug(3, "delete node %d from 'node' table", node);
-
- sprintf(stmt, "DELETE FROM \"%s\".\"node\" WHERE node_id = %d",
- pg_info->toposchema_name, node);
- if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
- G_warning(_("Unable to delete node %d"), node);
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
- return -1;
- }
- }
- }
-
- return 0;
+ return delete_line_from_topo_pg(Map, line, type, Points);
}
#else
G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
@@ -1234,7 +1207,6 @@
dig_add_node(plus, points->x[0], points->y[0], points->z[0]);
}
else {
- int n_nodes;
off_t offset;
/* better is probably to check nextval directly */
@@ -1246,31 +1218,7 @@
offset = Vect_get_num_primitives(Map, GV_LINES) + 1; /* next */
}
- Vect_reset_updated(Map);
- line = V2__add_line_to_topo_nat(Map, offset, type, points, NULL, /* TODO: handle categories */
- -1, NULL);
-
- /* insert new nodes into 'nodes' table */
- n_nodes = Vect_get_num_updated_nodes(Map);
- if (n_nodes > 0) {
- int i, node;
- double x, y, z;
-
- if (!Points)
- Points = Vect_new_line_struct();
-
- for (i = 0; i < n_nodes; i++) {
- node = Vect_get_updated_node(Map, i);
- G_debug(3, " new node: %d", node);
-
- Vect_get_node_coor(Map, node, &x, &y, &z);
- Vect_reset_line(Points);
- Vect_append_point(Points, x, y, z);
-
- write_feature(Map, -1, GV_POINT, (const struct line_pnts **) &Points, 1,
- -1, NULL);
- }
- }
+ line = add_line_to_topo_pg(Map, offset, type, points);
}
/* write new feature to PostGIS
@@ -1922,25 +1870,53 @@
/*!
\brief Insert topological element into 'node' or 'edge' table
+ Negative id for nodes.
+
\param Map pointer to Map_info struct
- \param line feature id (-1 for nodes/points)
+ \param id feature id (-1 for nodes/points)
\param type feature type (GV_POINT, GV_LINE, ...)
\param geom_data geometry in wkb
\return 0 on success
\return -1 on error
*/
-int insert_topo_element(struct Map_info *Map, int line, int type,
+int insert_topo_element(struct Map_info *Map, int id, int type,
const char *geom_data)
{
+ int ret;
char *stmt;
struct Format_info_pg *pg_info;
struct P_line *Line;
-
+ struct P_node *Node;
+
pg_info = &(Map->fInfo.pg);
-
- if (line > 0)
+
+ Line = NULL;
+ Node = NULL;
+ if (id > 0) {
+ int line;
+
+ line = id;
+ if (line > Map->plus.n_lines) {
+ G_warning(_("Invalid line %d (%d)"), line, Map->plus.n_lines);
+ return -1;
+ }
Line = Map->plus.Line[line];
+ }
+ else {
+ int node;
+
+ node = abs(id);
+ if (type != GV_POINT) {
+ G_warning(_("Invalid feature type (%d) for node"), type);
+ return -1;
+ }
+ if (node > Map->plus.n_nodes) {
+ G_warning(_("Invalid node %d (%d)"), node, Map->plus.n_nodes);
+ return -1;
+ }
+ Node = Map->plus.Node[node];
+ }
stmt = NULL;
switch(type) {
@@ -1949,8 +1925,8 @@
G_asprintf(&stmt, "SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
pg_info->toposchema_name, geom_data);
#else
- G_asprintf(&stmt, "INSERT INTO \"%s\".node (geom) VALUES ('%s'::GEOMETRY)",
- pg_info->toposchema_name, geom_data);
+ G_asprintf(&stmt, "INSERT INTO \"%s\".node (node_id, geom) VALUES (%d, '%s'::GEOMETRY)",
+ pg_info->toposchema_name, abs(id), geom_data);
#endif
break;
}
@@ -1976,12 +1952,12 @@
G_debug(3, "new edge: id=%d next_left_edge=%d next_right_edge=%d",
(int)Line->offset, nle, nre);
- G_asprintf(&stmt, "INSERT INTO \"%s\".edge_data (geom, start_node, end_node, "
+ G_asprintf(&stmt, "INSERT INTO \"%s\".edge_data (edge_id, start_node, end_node, "
"next_left_edge, abs_next_left_edge, next_right_edge, abs_next_right_edge, "
- "left_face, right_face) "
- "VALUES ('%s'::GEOMETRY, %d, %d, %d, %d, %d, %d, 0, 0)",
- pg_info->toposchema_name, geom_data, topo->N1, topo->N2, nle, abs(nle),
- nre, abs(nre));
+ "left_face, right_face, geom) "
+ "VALUES (%d, %d, %d, %d, %d, %d, %d, 0, 0, '%s'::GEOMETRY)",
+ pg_info->toposchema_name, (int) Line->offset, topo->N1, topo->N2,
+ nle, abs(nle), nre, abs(nre), geom_data);
#endif
break;
}
@@ -2007,9 +1983,9 @@
return NULL;
}
*/
- G_asprintf(&stmt, "INSERT INTO \"%s\".node (containing_face, geom) "
- "VALUES (%d, '%s'::GEOMETRY)",
- pg_info->toposchema_name, topo->area, geom_data);
+ G_asprintf(&stmt, "INSERT INTO \"%s\".node (node_id, containing_face, geom) "
+ "VALUES (%d, %d, '%s'::GEOMETRY)",
+ pg_info->toposchema_name, (int)Line->offset, topo->area, geom_data);
#endif
break;
}
@@ -2018,7 +1994,10 @@
break;
}
- if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ ret = Vect__execute_pg(pg_info->conn, stmt);
+ G_free(stmt);
+
+ if (ret == -1) {
/* rollback transaction */
Vect__execute_pg(pg_info->conn, "ROLLBACK");
return -1;
@@ -2174,7 +2153,7 @@
}
/*!
- \brief Delete existing face
+ \brief Delete existing face (currently unused)
\todo Set foreign keys as DEFERRABLE INITIALLY DEFERRED and use SET
CONSTRAINTS ALL DEFERRED
@@ -2429,4 +2408,117 @@
return 0;
}
+
+/*!
+ \brief Add line to native and PostGIS topology
+
+ \param Map vector map
+ \param line feature id to remove from topo
+ \param type feature type
+ \param Points feature vertices
+
+ \return feature id
+ \return -1 on error
+*/
+int add_line_to_topo_pg(struct Map_info *Map, off_t offset, int type,
+ const struct line_pnts *points)
+{
+ int line, n_nodes;
+
+ struct Plus_head *plus;
+
+ plus = &(Map->plus);
+
+ Vect_reset_updated(Map);
+ line = V2__add_line_to_topo_nat(Map, offset, type, points, NULL,
+ -1, NULL);
+
+ /* insert new nodes into 'node' table */
+ n_nodes = Vect_get_num_updated_nodes(Map);
+ if (n_nodes > 0) {
+ int i, node;
+ double x, y, z;
+
+ if (!Points)
+ Points = Vect_new_line_struct();
+
+ for (i = 0; i < n_nodes; i++) {
+ node = Vect_get_updated_node(Map, i);
+ /* skip updated and deleted nodes */
+ if (node > 0 || plus->Node[abs(node)] == NULL)
+ continue;
+
+ G_debug(3, " new node: %d", node);
+
+ Vect_get_node_coor(Map, abs(node), &x, &y, &z);
+ Vect_reset_line(Points);
+ Vect_append_point(Points, x, y, z);
+
+ write_feature(Map, node, GV_POINT, (const struct line_pnts **) &Points, 1,
+ -1, NULL);
+ }
+ }
+
+ return line;
+}
+
+/*!
+ \brief Delete line from native and PostGIS topology
+
+ \todo Implement deleting nodes on request
+
+ \param Map vector map
+ \param line feature id to remove from topo
+ \param type feature type
+ \param Points feature vertices
+
+ \return 0 on success
+ \return -1 on error
+*/
+int delete_line_from_topo_pg(struct Map_info *Map, int line, int type,
+ const struct line_pnts *Points)
+{
+ int n_nodes;
+ char stmt[DB_SQL_MAX];
+
+ struct Format_info_pg *pg_info;
+ struct Plus_head *plus;
+
+ pg_info = &(Map->fInfo.pg);
+ plus = &(Map->plus);
+
+ Vect_reset_updated(Map);
+ if (0 != V2__delete_line_from_topo_nat(Map, line, type, Points, NULL))
+ return -1;
+
+ /* disabled: remove isolated nodes when closing the map
+ note: node id cannot be used as node_id
+
+ delete nodes from 'node' table
+ n_nodes = Vect_get_num_updated_nodes(Map);
+ if (n_nodes > 0) {
+ int i, node;
+
+ for (i = 0; i < n_nodes; i++) {
+ node = Vect_get_updated_node(Map, i);
+ if (node > 0 || plus->Node[abs(node)] != NULL)
+ continue;
+
+ node = abs(node);
+ G_debug(3, "delete node %d from 'node' table", node);
+
+ sprintf(stmt, "DELETE FROM \"%s\".\"node\" WHERE node_id = %d",
+ pg_info->toposchema_name, node);
+ if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ G_warning(_("Unable to delete node %d"), node);
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+ }
+ }
+ */
+
+ return 0;
+}
+
#endif
Modified: grass/trunk/lib/vector/diglib/plus_line.c
===================================================================
--- grass/trunk/lib/vector/diglib/plus_line.c 2013-04-11 15:49:39 UTC (rev 55705)
+++ grass/trunk/lib/vector/diglib/plus_line.c 2013-04-11 18:22:45 UTC (rev 55706)
@@ -21,7 +21,7 @@
static int add_line(struct Plus_head *plus, int lineid, int type, const struct line_pnts *Points,
const struct bound_box *box, off_t offset)
{
- int node, lp;
+ int node, lp, node_new;
struct P_line *line;
plus->Line[lineid] = dig_alloc_line();
@@ -54,15 +54,19 @@
G_debug(3, "Register node: type = %d, %f,%f", type, Points->x[0],
Points->y[0]);
+ /* Start node */
node = dig_find_node(plus, Points->x[0], Points->y[0], Points->z[0]);
G_debug(3, "node = %d", node);
if (node == 0) {
node = dig_add_node(plus, Points->x[0], Points->y[0], Points->z[0]);
G_debug(3, "Add new node: %d", node);
+ node_new = TRUE;
}
else {
- G_debug(3, "Old node found: %d", node);
+ G_debug(3, "Old node found: %d", node);
+ node_new = FALSE;
}
+
if (type == GV_LINE) {
struct P_topo_l *topo = (struct P_topo_l *)line->topo;
@@ -80,8 +84,9 @@
dig_node_add_line(plus, node, lineid, Points, type);
if (plus->uplist.do_uplist)
- dig_node_add_updated(plus, node);
+ dig_node_add_updated(plus, node_new ? -node : node);
+ /* End node */
lp = Points->n_points - 1;
G_debug(3, "Register node %f,%f", Points->x[lp], Points->y[lp]);
node = dig_find_node(plus, Points->x[lp], Points->y[lp],
@@ -91,9 +96,11 @@
node = dig_add_node(plus, Points->x[lp], Points->y[lp],
Points->z[lp]);
G_debug(3, "Add new node: %d", node);
+ node_new = TRUE;
}
else {
G_debug(3, "Old node found: %d", node);
+ node_new = FALSE;
}
if (type == GV_LINE) {
struct P_topo_l *topo = (struct P_topo_l *)line->topo;
@@ -108,7 +115,7 @@
dig_node_add_line(plus, node, -lineid, Points, type);
if (plus->uplist.do_uplist)
- dig_node_add_updated(plus, node);
+ dig_node_add_updated(plus, node_new ? -node : node);
return (lineid);
}
More information about the grass-commit
mailing list