]> granicus.if.org Git - postgis/commitdiff
Added ST_ModEdgesSplit function, cleaned up test files, added tests for
authorSandro Santilli <strk@keybit.net>
Wed, 19 Oct 2005 10:04:15 +0000 (10:04 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 19 Oct 2005 10:04:15 +0000 (10:04 +0000)
the new topology editing functions.

git-svn-id: http://svn.osgeo.org/postgis/trunk@1971 b70326c6-7e19-0410-871a-916f4a2858ee

topology/test/Makefile
topology/test/cache_geometries.sql
topology/test/edit_topology.sql [new file with mode: 0644]
topology/test/hierarchy.sql
topology/test/load_topology.sql
topology/test/predicate.expected [new file with mode: 0644]
topology/topology.sql.in

index e72d6eba5467f136c89f586da348b8d8caf86148..2996eb7ad6249deaefd892c6100317614da40278 100644 (file)
@@ -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
index c42ffec6b212d7d0a7f39f5412af6e86b64fa2e8..20bdf1726bbb70b8d3fabb9fa8853c5bf034997a 100644 (file)
@@ -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)); 
diff --git a/topology/test/edit_topology.sql b/topology/test/edit_topology.sql
new file mode 100644 (file)
index 0000000..aef7c1c
--- /dev/null
@@ -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)');
index 0133bc8b97ef88158a2ac7809193fddbff2f09c5..382a15eb416d9784afb03b9ddbdd8c22dd9b94b0 100644 (file)
@@ -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
index 379146603b98d515bea798ed41ac65bb944fca18..049ec43f9ea9624255b47361bb5c807544a58d5b 100644 (file)
@@ -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.
diff --git a/topology/test/predicate.expected b/topology/test/predicate.expected
new file mode 100644 (file)
index 0000000..dc8c2e1
--- /dev/null
@@ -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
index 8a1538e3a70f04fde611a383fbb1efd81a6313a5..1380358bb8092270e08d56ba39c084673995b92a 100644 (file)
 --     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