From 89cd0131bf185d1e67d757a8bc316184c3d666e1 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Wed, 25 Nov 2015 18:20:47 +0000 Subject: [PATCH] Add TopoGeom_{add,rem}Element functions Includes regression tests and documentation git-svn-id: http://svn.osgeo.org/postgis/trunk@14423 b70326c6-7e19-0410-871a-916f4a2858ee --- NEWS | 2 + doc/extras_topology.xml | 104 +++++++++++++++++- topology/Makefile.in | 24 +++- .../sql/topogeometry/topogeom_edit.sql.in | 95 ++++++++++++++++ topology/test/Makefile.in | 1 + topology/test/regress/topogeom_edit.sql | 24 ++++ topology/test/regress/topogeom_edit_expected | 8 ++ topology/topology.sql.in | 1 + 8 files changed, 255 insertions(+), 4 deletions(-) create mode 100644 topology/sql/topogeometry/topogeom_edit.sql.in create mode 100644 topology/test/regress/topogeom_edit.sql create mode 100644 topology/test/regress/topogeom_edit_expected diff --git a/NEWS b/NEWS index 8dcc3e2de..9324d6047 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PostGIS 2.3.0 * Deprecated signatures * * New Features * + - TopoGeom_addElement, TopoGeom_remElement (Sando Santilli) + PostGIS 2.2.0 2015/10/07 diff --git a/doc/extras_topology.xml b/doc/extras_topology.xml index 1524701a4..b81ea353c 100644 --- a/doc/extras_topology.xml +++ b/doc/extras_topology.xml @@ -185,7 +185,9 @@ ERROR: value for domain topology.topoelement violates check constraint "dimensi , , - + , + , + @@ -2939,6 +2941,97 @@ UPDATE nei_topo SET topo = ST_Buffer(clearTopoGeom(topo), -10); + + + TopoGeom_addElement + Add an element to the definition of a TopoGeometry + + + + + topogeometry TopoGeom_addElement + topogeometry tg + topoelement el + + + + + + Description + + +Adds a to the definition of a +TopoGeometry object. Does not error out if the element is already +part of the definition. + + + + Availability: 2.3 + + + Examples + +-- Add edge 5 to TopoGeometry tg +UPDATE mylayer SET tg = TopoGeom_addElement(tg, '{5,2}'); + + + + + + See Also + +, + + + + + + + + TopoGeom_remElement + + Remove an element from the definition of a TopoGeometry + + + + + + topogeometry TopoGeom_remElement + topogeometry tg + topoelement el + + + + + + Description + + +Removes a from the definition of a +TopoGeometry object. + + + + Availability: 2.3 + + + Examples + +-- Remove face 43 from TopoGeometry tg +UPDATE mylayer SET tg = TopoGeom_remElement(tg, '{43,3}'); + + + + + + See Also + +, + + + + + toTopoGeom @@ -3037,7 +3130,7 @@ Refer to tg_id is the topogeometry id of the topogeometry object in the topology in the layer denoted by layer_id in the topology.layer table. - Availability: 1.? + Availability: 2.0.0 @@ -3050,7 +3143,12 @@ Refer to See Also - , + + , + , + , + + diff --git a/topology/Makefile.in b/topology/Makefile.in index 8b5f1d7b3..8dcfe64fb 100644 --- a/topology/Makefile.in +++ b/topology/Makefile.in @@ -100,7 +100,29 @@ topology_upgrade.sql.in: topology.sql topology_upgrade.sql: topology_drop_before.sql topology_upgrade.sql.in topology_drop_after.sql cat $^ > $@ -topology.sql: sql/sqlmm.sql.in sql/populate.sql.in sql/polygonize.sql.in sql/export/gml.sql.in sql/export/TopoJSON.sql.in sql/query/getnodebypoint.sql.in sql/query/getedgebypoint.sql.in sql/query/getfacebypoint.sql.in sql/query/GetRingEdges.sql.in sql/query/GetNodeEdges.sql.in sql/manage/TopologySummary.sql.in sql/manage/CopyTopology.sql.in sql/manage/ManageHelper.sql.in sql/topoelement/topoelement_agg.sql.in sql/topogeometry/type.sql.in sql/topogeometry/totopogeom.sql.in sql/topogeometry/cleartopogeom.sql.in sql/topogeometry/simplify.sql.in sql/predicates.sql.in ../postgis/sqldefines.h ../postgis_svn_revision.h +topology.sql: \ + sql/sqlmm.sql.in \ + sql/populate.sql.in \ + sql/polygonize.sql.in \ + sql/export/gml.sql.in \ + sql/export/TopoJSON.sql.in \ + sql/query/getnodebypoint.sql.in \ + sql/query/getedgebypoint.sql.in \ + sql/query/getfacebypoint.sql.in \ + sql/query/GetRingEdges.sql.in \ + sql/query/GetNodeEdges.sql.in \ + sql/manage/TopologySummary.sql.in \ + sql/manage/CopyTopology.sql.in \ + sql/manage/ManageHelper.sql.in \ + sql/topoelement/topoelement_agg.sql.in \ + sql/topogeometry/type.sql.in \ + sql/topogeometry/totopogeom.sql.in \ + sql/topogeometry/cleartopogeom.sql.in \ + sql/topogeometry/topogeom_edit.sql.in \ + sql/topogeometry/simplify.sql.in \ + sql/predicates.sql.in \ + ../postgis/sqldefines.h \ + ../postgis_svn_revision.h uninstall_topology.sql: topology.sql ../utils/create_undef.pl $(PERL) ../utils/create_undef.pl $< $(POSTGIS_PGSQL_VERSION) > $@ diff --git a/topology/sql/topogeometry/topogeom_edit.sql.in b/topology/sql/topogeometry/topogeom_edit.sql.in new file mode 100644 index 000000000..4fd0d0e23 --- /dev/null +++ b/topology/sql/topogeometry/topogeom_edit.sql.in @@ -0,0 +1,95 @@ +-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-- +-- PostGIS - Spatial Types for PostgreSQL +-- http://postgis.net +-- +-- Copyright (C) 2015 Sandro Santilli +-- +-- This is free software; you can redistribute and/or modify it under +-- the terms of the GNU General Public Licence. See the COPYING file. +-- +-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +/* #define POSTGIS_TOPOLOGY_DEBUG 1 */ + +-- { +-- Add an element to a TopoGeometry definition +-- +-- }{ +CREATE OR REPLACE FUNCTION topology.TopoGeom_addElement(tg topology.TopoGeometry, el topology.TopoElement) + RETURNS topology.TopoGeometry +AS +$$ +DECLARE + toponame TEXT; + sql TEXT; +BEGIN + + -- Get topology name + BEGIN + SELECT name + FROM topology.topology + INTO STRICT toponame WHERE id = topology_id(tg); + EXCEPTION + WHEN NO_DATA_FOUND THEN + RAISE EXCEPTION 'No topology with name "%" in topology.topology', + atopology; + END; + + -- Insert new element + sql := format('INSERT INTO %s.relation' + '(topogeo_id,layer_id,element_id,element_type)' + ' VALUES($1,$2,$3,$4)', quote_ident(toponame)); + BEGIN + EXECUTE sql USING id(tg), layer_id(tg), el[1], el[2]; + EXCEPTION + WHEN unique_violation THEN + -- already present, let go + WHEN OTHERS THEN + RAISE EXCEPTION 'Got % (%)', SQLERRM, SQLSTATE; + END; + + RETURN tg; + +END +$$ +LANGUAGE 'plpgsql' VOLATILE STRICT; +-- } + +-- { +-- Remove an element from a TopoGeometry definition +-- +-- }{ +CREATE OR REPLACE FUNCTION topology.TopoGeom_remElement(tg topology.TopoGeometry, el topology.TopoElement) + RETURNS topology.TopoGeometry +AS +$$ +DECLARE + toponame TEXT; + sql TEXT; +BEGIN + + -- Get topology name + BEGIN + SELECT name + FROM topology.topology + INTO STRICT toponame WHERE id = topology_id(tg); + EXCEPTION + WHEN NO_DATA_FOUND THEN + RAISE EXCEPTION 'No topology with name "%" in topology.topology', + atopology; + END; + + -- Delete the element + sql := format('DELETE FROM %s.relation WHERE ' + 'topogeo_id = $1 AND layer_id = $2 AND ' + 'element_id = $3 AND element_type = $4', + quote_ident(toponame)); + EXECUTE sql USING id(tg), layer_id(tg), el[1], el[2]; + + RETURN tg; + +END +$$ +LANGUAGE 'plpgsql' VOLATILE STRICT; +-- } diff --git a/topology/test/Makefile.in b/topology/test/Makefile.in index 7274ec9e7..604f94a8b 100644 --- a/topology/test/Makefile.in +++ b/topology/test/Makefile.in @@ -51,6 +51,7 @@ TESTS = regress/legacy_validate.sql regress/legacy_predicate.sql \ regress/topogeo_addlinestring.sql \ regress/topogeo_addpoint.sql \ regress/topogeo_addpolygon.sql \ + regress/topogeom_edit.sql \ regress/topogeometry_type.sql \ regress/topojson.sql \ regress/topologysummary.sql \ diff --git a/topology/test/regress/topogeom_edit.sql b/topology/test/regress/topogeom_edit.sql new file mode 100644 index 000000000..fa83ef2b5 --- /dev/null +++ b/topology/test/regress/topogeom_edit.sql @@ -0,0 +1,24 @@ +\set VERBOSITY terse +set client_min_messages to ERROR; + +select 'create', createtopology('tt') > 0; + +-- Create a line layer (will be layer 1) +CREATE TABLE tt.f_line(id serial); +SELECT 'simple_line_layer', AddTopoGeometryColumn('tt', 'tt', 'f_line','g','LINE'); + +INSERT INTO tt.f_line (g) VALUES + ( toTopoGeom('LINESTRING(0 0, 10 0)'::geometry, 'tt', 1) ); +INSERT INTO tt.f_line (g) VALUES + ( toTopoGeom('LINESTRING(10 0, 30 0)'::geometry, 'tt', 1) ); + +-- Sane calls +SELECT id, 'start', id, ST_Length(g) FROM tt.f_line WHERE id = 1; +SELECT id, 'add', id, ST_Length(TopoGeom_addElement(g, '{2,2}')) FROM tt.f_line WHERE id = 1; +SELECT id, 'rem', id, ST_Length(TopoGeom_remElement(g, '{1,2}')) FROM tt.f_line WHERE id = 1; +SELECT id, 'dup', id, ST_Length(TopoGeom_addElement(g, '{2,2}')) FROM tt.f_line WHERE id = 1; +SELECT id, 'mis', id, ST_Length(TopoGeom_remElement(g, '{1,2}')) FROM tt.f_line WHERE id = 1; + + +DROP TABLE tt.f_line; +select droptopology('tt'); diff --git a/topology/test/regress/topogeom_edit_expected b/topology/test/regress/topogeom_edit_expected new file mode 100644 index 000000000..36c873a57 --- /dev/null +++ b/topology/test/regress/topogeom_edit_expected @@ -0,0 +1,8 @@ +create|t +simple_line_layer|1 +1|start|1|10 +1|add|1|30 +1|rem|1|20 +1|dup|1|20 +1|mis|1|20 +Topology 'tt' dropped diff --git a/topology/topology.sql.in b/topology/topology.sql.in index a0979abbb..92af06f34 100644 --- a/topology/topology.sql.in +++ b/topology/topology.sql.in @@ -1993,6 +1993,7 @@ LANGUAGE 'plpgsql' VOLATILE STRICT; #include "sql/topogeometry/cleartopogeom.sql.in" #include "sql/topogeometry/simplify.sql.in" #include "sql/topogeometry/totopogeom.sql.in" +#include "sql/topogeometry/topogeom_edit.sql.in" -- Exports #include "sql/export/gml.sql.in" -- 2.40.0