mirror of
https://git.osgeo.org/gitea/postgis/postgis
synced 2024-10-24 00:52:40 +00:00
Added ST_ModEdgesSplit function, cleaned up test files, added tests for
the new topology editing functions. git-svn-id: http://svn.osgeo.org/postgis/trunk@1971 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
parent
307df8801e
commit
e51b2fe6b6
|
@ -1,6 +1,8 @@
|
|||
DATABASE=postgis_topo_regress
|
||||
|
||||
all:
|
||||
@echo
|
||||
@echo "make test - create the database, run all tests except sqlmm"
|
||||
@echo
|
||||
@echo "make initdb - create the regress database"
|
||||
@echo "make inittopo - create topology routines"
|
||||
|
@ -10,6 +12,8 @@ all:
|
|||
@echo "make validate - validate 'city_data' loaded topology"
|
||||
@echo
|
||||
@echo "make hier - define some hierarchical TopoGeoms"
|
||||
@echo
|
||||
@echo "make edit - test sqlmm editing functions"
|
||||
@echo
|
||||
@echo "make cache - create geom caches for features tables"
|
||||
@echo "make topopred - run predicates on topogeoms"
|
||||
|
@ -19,6 +23,14 @@ all:
|
|||
@echo "make sqlmm - test SQL/MM functions (exceptions are expected)"
|
||||
@echo
|
||||
|
||||
pred:
|
||||
@make geompred | grep -v make > /tmp/geompred.out
|
||||
@make topopred | grep -v make > /tmp/topopred.out
|
||||
@diff /tmp/geompred.out /tmp/topopred.out
|
||||
@diff /tmp/geompred.out predicate.expected
|
||||
|
||||
test: inittopo load loadmore hier cache pred invalid edit
|
||||
|
||||
initdb:
|
||||
createdb $(DATABASE)
|
||||
createlang plpgsql $(DATABASE)
|
||||
|
@ -49,10 +61,10 @@ sqlmm:
|
|||
psql -f sqlmm_topology.sql $(DATABASE)
|
||||
|
||||
topopred: topo_predicates.sql
|
||||
psql -f topo_predicates.sql $(DATABASE)
|
||||
@psql -tf topo_predicates.sql $(DATABASE)
|
||||
|
||||
geompred: geom_predicates.sql
|
||||
psql -f geom_predicates.sql $(DATABASE)
|
||||
@psql -tf geom_predicates.sql $(DATABASE)
|
||||
|
||||
topo_predicates.sql: predicates.sql.in
|
||||
cpp -P -traditional-cpp predicates.sql.in | sed -e 's:@COLUMN@:feature:g;s:@SCHEMA@:topology.:g' > topo_predicates.sql
|
||||
|
@ -60,6 +72,8 @@ topo_predicates.sql: predicates.sql.in
|
|||
geom_predicates.sql: predicates.sql.in
|
||||
cpp -P -traditional-cpp predicates.sql.in | sed -e 's:@COLUMN@:the_geom:g;s:@SCHEMA@::g' > geom_predicates.sql
|
||||
|
||||
edit:
|
||||
psql -f edit_topology.sql
|
||||
|
||||
clean distclean:
|
||||
rm -f geom_predicates.sql topo_predicates.sql
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
-- created by load_topology.sql and stores there the SFS Geometry
|
||||
-- derived by the TopoGeometry column
|
||||
|
||||
ALTER TABLE features.city_streets ADD the_geom geometry;
|
||||
UPDATE features.city_streets set the_geom = topology.Geometry(feature);
|
||||
--ALTER TABLE features.city_streets ADD the_geom geometry;
|
||||
UPDATE features.city_streets set the_geom = multi(topology.Geometry(feature));
|
||||
|
||||
ALTER TABLE features.traffic_signs ADD the_geom geometry;
|
||||
UPDATE features.traffic_signs set the_geom = topology.Geometry(feature);
|
||||
--ALTER TABLE features.traffic_signs ADD the_geom geometry;
|
||||
UPDATE features.traffic_signs set the_geom = multi(topology.Geometry(feature));
|
||||
|
||||
ALTER TABLE features.land_parcels ADD the_geom geometry;
|
||||
UPDATE features.land_parcels set the_geom = topology.Geometry(feature);
|
||||
--ALTER TABLE features.land_parcels ADD the_geom geometry;
|
||||
UPDATE features.land_parcels set the_geom = multi(topology.Geometry(feature));
|
||||
|
||||
ALTER TABLE features.big_parcels ADD the_geom geometry;
|
||||
UPDATE features.big_parcels set the_geom = topology.Geometry(feature);
|
||||
--ALTER TABLE features.big_parcels ADD the_geom geometry;
|
||||
UPDATE features.big_parcels set the_geom = multi(topology.Geometry(feature));
|
||||
|
||||
ALTER TABLE features.big_signs ADD the_geom geometry;
|
||||
UPDATE features.big_signs set the_geom = topology.Geometry(feature);
|
||||
--ALTER TABLE features.big_signs ADD the_geom geometry;
|
||||
UPDATE features.big_signs set the_geom = multi(topology.Geometry(feature));
|
||||
|
|
3
topology/test/edit_topology.sql
Normal file
3
topology/test/edit_topology.sql
Normal file
|
@ -0,0 +1,3 @@
|
|||
select topology.ST_NewEdgesSplit('city_data',25,'POINT(10 35)');
|
||||
select topology.ST_ModEdgesSplit('city_data',27,'POINT(9.5 35)');
|
||||
select topology.ST_ModEdgesSplit('city_data',28,'POINT(11 35)');
|
|
@ -15,6 +15,8 @@ SELECT topology.AddTopoGeometryColumn('city_data', 'features',
|
|||
1 -- the land_parcles
|
||||
);
|
||||
|
||||
SELECT AddGeometryColumn('features','big_parcels','the_geom',-1,'MULTIPOLYGON',2);
|
||||
|
||||
INSERT INTO features.big_parcels VALUES ('P1P2', -- Feature name
|
||||
topology.CreateTopoGeom(
|
||||
'city_data', -- Topology name
|
||||
|
@ -36,13 +38,6 @@ INSERT INTO features.big_parcels VALUES ('F3F6', -- Feature name
|
|||
(SELECT layer_id FROM topology.layer WHERE table_name = 'big_parcels'),
|
||||
'{{6,1},{7,1}}')); -- F3 and F6
|
||||
|
||||
INSERT INTO features.big_parcels VALUES ('F3F6', -- Feature name
|
||||
topology.CreateTopoGeom(
|
||||
'city_data', -- Topology name
|
||||
3, -- Topology geometry type (polygon/multipolygon)
|
||||
(SELECT layer_id FROM topology.layer WHERE table_name = 'big_parcels'),
|
||||
'{{7,1},{6,1}}')); -- F3 and F6
|
||||
|
||||
SELECT feature_name, astext(topology.geometry(feature)) from features.big_parcels;
|
||||
|
||||
SELECT a.feature_name, b.feature_name
|
||||
|
@ -62,6 +57,8 @@ SELECT topology.AddTopoGeometryColumn('city_data', 'features',
|
|||
2 -- the traffic_signs
|
||||
);
|
||||
|
||||
SELECT AddGeometryColumn('features','big_signs','the_geom',-1,'MULTIPOINT',2);
|
||||
|
||||
INSERT INTO features.big_signs VALUES ('S1S2', -- Feature name
|
||||
topology.CreateTopoGeom(
|
||||
'city_data', -- Topology name
|
||||
|
|
|
@ -221,6 +221,12 @@ SELECT topology.AddTopoGeometryColumn('city_data', 'features', 'city_streets','f
|
|||
--NOTYET---- 5. Initialize topology metadata.
|
||||
--NOTYET--EXECUTE topology.INITIALIZE_METADATA('CITY_DATA');
|
||||
|
||||
-- 4bis. Add geometry columns, for caching Geometries from TopoGeometries
|
||||
|
||||
SELECT AddGeometryColumn('features','land_parcels','the_geom',-1,'MULTIPOLYGON',2);
|
||||
SELECT AddGeometryColumn('features','city_streets','the_geom',-1,'MULTILINESTRING',2);
|
||||
SELECT AddGeometryColumn('features','traffic_signs','the_geom',-1,'MULTIPOINT',2);
|
||||
|
||||
|
||||
|
||||
-- 6. Load feature tables using the CreateTopoGeom constructor.
|
||||
|
|
118
topology/test/predicate.expected
Normal file
118
topology/test/predicate.expected
Normal file
|
@ -0,0 +1,118 @@
|
|||
BEGIN
|
||||
POINT/POINT INTERSECTS
|
||||
|
||||
S1 | N1N6N14
|
||||
S3 | N1N6N14
|
||||
S4 | N3N4
|
||||
S4 | N4
|
||||
N1N2N3 | N1N6N14
|
||||
N1N2N3 | N3N4
|
||||
N3N4 | N4
|
||||
|
||||
POINT/LINE INTERSECTS
|
||||
|
||||
S1 | R1
|
||||
S1 | E20E19
|
||||
S1 | R1a
|
||||
S2 | R1
|
||||
S2 | R1a
|
||||
S3 | R2
|
||||
N1N2N3 | R4
|
||||
N1N6N14 | R1
|
||||
N1N6N14 | R2
|
||||
N1N6N14 | E20E19
|
||||
N1N6N14 | R1a
|
||||
N3N4 | R4
|
||||
|
||||
LINE/LINE INTERSECTS
|
||||
|
||||
R1 | E20E19
|
||||
R1 | R1a
|
||||
R3 | E25
|
||||
E7E8 | E20E19
|
||||
E20E19 | R1a
|
||||
|
||||
POINT/POLY INTERSECTS
|
||||
|
||||
S1 | P1
|
||||
S1 | P2
|
||||
S1 | F3
|
||||
S1 | F6
|
||||
S1 | F3F4
|
||||
S2 | P2
|
||||
S2 | P3
|
||||
S2 | F3F4
|
||||
S4 | P4
|
||||
N1N2N3 | P4
|
||||
N1N2N3 | P5
|
||||
N1N2N3 | F1
|
||||
N1N6N14 | P1
|
||||
N1N6N14 | P2
|
||||
N1N6N14 | P5
|
||||
N1N6N14 | F3
|
||||
N1N6N14 | F6
|
||||
N1N6N14 | F3F4
|
||||
N1N6N14 | F1
|
||||
N3N4 | P4
|
||||
N4 | P4
|
||||
|
||||
LINE/POLY INTERSECTS
|
||||
|
||||
R1 | P1
|
||||
R1 | P2
|
||||
R1 | P3
|
||||
R1 | F3
|
||||
R1 | F6
|
||||
R1 | F3F4
|
||||
R3 | P5
|
||||
R3 | F1
|
||||
R4 | P4
|
||||
E7E8 | P1
|
||||
E7E8 | P2
|
||||
E7E8 | P3
|
||||
E7E8 | F3
|
||||
E7E8 | F3F4
|
||||
E20E19 | P1
|
||||
E20E19 | P2
|
||||
E20E19 | F3
|
||||
E20E19 | F6
|
||||
E20E19 | F3F4
|
||||
E25 | P5
|
||||
E25 | F1
|
||||
R1a | P1
|
||||
R1a | P2
|
||||
R1a | P3
|
||||
R1a | F3
|
||||
R1a | F6
|
||||
R1a | F3F4
|
||||
|
||||
POLY/POLY INTERSECTS
|
||||
|
||||
P1 | P2
|
||||
P1 | F3
|
||||
P1 | F6
|
||||
P1 | F3F4
|
||||
P2 | P3
|
||||
P2 | F3
|
||||
P2 | F6
|
||||
P2 | F3F4
|
||||
P3 | F3F4
|
||||
P5 | F1
|
||||
F3 | F6
|
||||
F3 | F3F4
|
||||
F6 | F3F4
|
||||
|
||||
POINT/POINT EQUALS
|
||||
|
||||
S4 | N4
|
||||
|
||||
LINE/LINE EQUALS
|
||||
|
||||
R1 | R1a
|
||||
R3 | E25
|
||||
|
||||
POLYGON/POLYGON EQUALS
|
||||
|
||||
P5 | F1
|
||||
|
||||
COMMIT
|
|
@ -140,7 +140,12 @@
|
|||
-- Complete
|
||||
--
|
||||
-- ST_NewEdgesSplit
|
||||
-- Complete, exceptions untested
|
||||
-- Complete
|
||||
-- this also updates the Relation table
|
||||
-- TODO: add entries to the History table ?
|
||||
--
|
||||
-- ST_ModEdgesSplit
|
||||
-- Complete
|
||||
-- this also updates the Relation table
|
||||
-- TODO: add entries to the History table ?
|
||||
--
|
||||
|
@ -2880,7 +2885,7 @@ BEGIN
|
|||
|| '' AND abs(r.element_id) = '' || anedge
|
||||
|| '' AND r.element_type = 2''
|
||||
LOOP
|
||||
RAISE NOTICE ''TopoGeometry % in layer % contains the edge being split'', rec.topogeo_id, rec.layer_id;
|
||||
--RAISE NOTICE ''TopoGeometry % in layer % contains the edge being split'', rec.topogeo_id, rec.layer_id;
|
||||
|
||||
-- Delete old reference
|
||||
EXECUTE ''DELETE FROM '' || quote_ident(atopology)
|
||||
|
@ -2932,8 +2937,8 @@ BEGIN
|
|||
|
||||
END LOOP;
|
||||
|
||||
RAISE NOTICE ''Edge % split in edges % and % by node %'',
|
||||
anedge, edgeid1, edgeid2, nodeid;
|
||||
--RAISE NOTICE ''Edge % split in edges % and % by node %'',
|
||||
-- anedge, edgeid1, edgeid2, nodeid;
|
||||
|
||||
RETURN nodeid;
|
||||
END
|
||||
|
@ -2941,6 +2946,212 @@ END
|
|||
LANGUAGE 'plpgsql' _VOLATILE;
|
||||
--} ST_NewEdgesSplit
|
||||
|
||||
--{
|
||||
-- Topo-Geo and Topo-Net 3: Routine Details
|
||||
-- X.3.9
|
||||
--
|
||||
-- ST_ModEdgesSplit(atopology, anedge, apoint)
|
||||
--
|
||||
CREATEFUNCTION topology.ST_ModEdgesSplit(varchar, integer, geometry)
|
||||
RETURNS INTEGER AS
|
||||
'
|
||||
DECLARE
|
||||
atopology ALIAS FOR $1;
|
||||
anedge ALIAS FOR $2;
|
||||
apoint ALIAS FOR $3;
|
||||
oldedge RECORD;
|
||||
rec RECORD;
|
||||
tmp integer;
|
||||
topoid integer;
|
||||
nodeid integer;
|
||||
nodepos float8;
|
||||
newedgeid integer;
|
||||
newedge1 geometry;
|
||||
newedge2 geometry;
|
||||
query text;
|
||||
ok BOOL;
|
||||
BEGIN
|
||||
|
||||
--
|
||||
-- All args required
|
||||
--
|
||||
IF atopology IS NULL OR anedge IS NULL OR apoint IS NULL THEN
|
||||
RAISE EXCEPTION
|
||||
''SQL/MM Spatial exception - null argument'';
|
||||
END IF;
|
||||
|
||||
--
|
||||
-- Check node existance
|
||||
--
|
||||
ok = false;
|
||||
FOR oldedge IN EXECUTE ''SELECT * FROM ''
|
||||
|| quote_ident(atopology) || ''.edge_data '' ||
|
||||
'' WHERE edge_id = '' || anedge
|
||||
LOOP
|
||||
ok = true;
|
||||
END LOOP;
|
||||
IF NOT ok THEN
|
||||
RAISE EXCEPTION
|
||||
''SQL/MM Spatial exception - non-existent edge'';
|
||||
END IF;
|
||||
|
||||
--
|
||||
-- Check that given point is Within(anedge.geom)
|
||||
--
|
||||
IF NOT within(apoint, oldedge.geom) THEN
|
||||
RAISE EXCEPTION
|
||||
''SQL/MM Spatial exception - point not on edge'';
|
||||
END IF;
|
||||
|
||||
--
|
||||
-- Check if a coincident node already exists
|
||||
--
|
||||
FOR rec IN EXECUTE ''SELECT node_id FROM ''
|
||||
|| quote_ident(atopology) || ''.node '' ||
|
||||
''WHERE geom && '' || quote_literal(apoint) || ''::geometry''
|
||||
||'' AND x(geom) = x(''||quote_literal(apoint)||''::geometry)''
|
||||
||'' AND y(geom) = y(''||quote_literal(apoint)||''::geometry)''
|
||||
LOOP
|
||||
RAISE EXCEPTION
|
||||
''SQL/MM Spatial exception - coincident node'';
|
||||
END LOOP;
|
||||
|
||||
--
|
||||
-- Get new node id
|
||||
--
|
||||
FOR rec IN EXECUTE ''SELECT nextval('''''' ||
|
||||
atopology || ''.node_node_id_seq'''')''
|
||||
LOOP
|
||||
nodeid = rec.nextval;
|
||||
END LOOP;
|
||||
|
||||
--RAISE NOTICE ''Next node id = % '', nodeid;
|
||||
|
||||
--
|
||||
-- Add the new node
|
||||
--
|
||||
EXECUTE ''INSERT INTO '' || quote_ident(atopology)
|
||||
|| ''.node(node_id, geom)
|
||||
VALUES(''||nodeid||'',''||quote_literal(apoint)||
|
||||
'')'';
|
||||
|
||||
--
|
||||
-- Compute new edge
|
||||
--
|
||||
nodepos = line_locate_point(oldedge.geom, apoint);
|
||||
newedge1 = line_substring(oldedge.geom, 0, nodepos);
|
||||
newedge2 = line_substring(oldedge.geom, nodepos, 1);
|
||||
|
||||
|
||||
--
|
||||
-- Get ids for the new edge
|
||||
--
|
||||
FOR rec IN EXECUTE ''SELECT nextval('''''' ||
|
||||
atopology || ''.edge_data_edge_id_seq'''')''
|
||||
LOOP
|
||||
newedgeid = rec.nextval;
|
||||
END LOOP;
|
||||
|
||||
--
|
||||
-- Insert the new edge
|
||||
--
|
||||
EXECUTE ''INSERT INTO '' || quote_ident(atopology)
|
||||
|| ''.edge ''
|
||||
|| ''(edge_id, start_node, end_node,''
|
||||
|| ''next_left_edge, next_right_edge,''
|
||||
|| ''left_face, right_face, geom) ''
|
||||
|| ''VALUES(''
|
||||
||newedgeid||'',''||nodeid
|
||||
||'',''||oldedge.end_node
|
||||
||'',''||oldedge.next_left_edge
|
||||
||'',-''||anedge
|
||||
||'',''||oldedge.left_face
|
||||
||'',''||oldedge.right_face
|
||||
||'',''||quote_literal(newedge2)
|
||||
||'')'';
|
||||
|
||||
--
|
||||
-- Update the old edge
|
||||
--
|
||||
EXECUTE ''UPDATE '' || quote_ident(atopology) || ''.edge_data ''
|
||||
|| '' SET geom = '' || quote_literal(newedge1)
|
||||
|| '',''
|
||||
|| '' next_left_edge = '' || newedgeid
|
||||
|| '',''
|
||||
|| '' end_node = '' || nodeid
|
||||
|| '' WHERE edge_id = '' || anedge;
|
||||
|
||||
|
||||
--
|
||||
-- Update all next edge references to match new layout
|
||||
--
|
||||
|
||||
EXECUTE ''UPDATE '' || quote_ident(atopology)
|
||||
|| ''.edge_data SET next_right_edge = ''
|
||||
|| -newedgeid
|
||||
|| '',''
|
||||
|| '' abs_next_right_edge = '' || newedgeid
|
||||
|| '' WHERE next_right_edge = '' || -anedge;
|
||||
|
||||
EXECUTE ''UPDATE '' || quote_ident(atopology)
|
||||
|| ''.edge_data SET ''
|
||||
|| '' next_left_edge = '' || -newedgeid
|
||||
|| '',''
|
||||
|| '' abs_next_left_edge = '' || newedgeid
|
||||
|| '' WHERE next_left_edge = '' || -anedge;
|
||||
|
||||
-- Get topology id
|
||||
SELECT id FROM topology.topology into topoid
|
||||
WHERE name = atopology;
|
||||
|
||||
--
|
||||
-- Update references in the Relation table.
|
||||
-- We only take into considerations non-hierarchical
|
||||
-- TopoGeometry here, for obvious reasons.
|
||||
--
|
||||
FOR rec IN EXECUTE ''SELECT r.* FROM ''
|
||||
|| quote_ident(atopology)
|
||||
|| ''.relation r, topology.layer l ''
|
||||
|| '' WHERE ''
|
||||
|| '' l.topology_id = '' || topoid
|
||||
|| '' AND l.level = 0 ''
|
||||
|| '' AND l.layer_id = r.layer_id ''
|
||||
|| '' AND abs(r.element_id) = '' || anedge
|
||||
|| '' AND r.element_type = 2''
|
||||
LOOP
|
||||
--RAISE NOTICE ''TopoGeometry % in layer % contains the edge being split (%) - updating to add new edge %'', rec.topogeo_id, rec.layer_id, anedge, newedgeid;
|
||||
|
||||
-- Add new reference to edge1
|
||||
IF rec.element_id < 0 THEN
|
||||
tmp = -newedgeid;
|
||||
ELSE
|
||||
tmp = newedgeid;
|
||||
END IF;
|
||||
query = ''INSERT INTO '' || quote_ident(atopology)
|
||||
|| ''.relation ''
|
||||
|| '' VALUES( ''
|
||||
|| rec.topogeo_id
|
||||
|| '',''
|
||||
|| rec.layer_id
|
||||
|| '',''
|
||||
|| tmp
|
||||
|| '',''
|
||||
|| rec.element_type
|
||||
|| '')'';
|
||||
|
||||
--RAISE NOTICE ''%'', query;
|
||||
EXECUTE query;
|
||||
END LOOP;
|
||||
|
||||
--RAISE NOTICE ''Edge % split in edges % and % by node %'',
|
||||
-- anedge, anedge, newedgeid, nodeid;
|
||||
|
||||
RETURN nodeid;
|
||||
END
|
||||
'
|
||||
LANGUAGE 'plpgsql' _VOLATILE;
|
||||
--} ST_ModEdgesSplit
|
||||
|
||||
--{
|
||||
-- Topo-Geo and Topo-Net 3: Routine Details
|
||||
-- X.3.4
|
||||
|
|
Loading…
Reference in a new issue