]> granicus.if.org Git - postgis/commitdiff
Fix linking bugs with ST_NewEdgesSplit function (#1496)
authorSandro Santilli <strk@keybit.net>
Tue, 24 Jan 2012 14:03:26 +0000 (14:03 +0000)
committerSandro Santilli <strk@keybit.net>
Tue, 24 Jan 2012 14:03:26 +0000 (14:03 +0000)
Includes test coverage for this other function.

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

topology/sql/sqlmm.sql.in.c
topology/test/Makefile
topology/test/regress/st_newedgessplit.sql [new file with mode: 0644]
topology/test/regress/st_newedgessplit_expected [new file with mode: 0644]

index 408d2e19058903421575a313d0307def1e107cb2..d2a851a122d121a58f4a044d856bee2a88584e9b 100644 (file)
@@ -1943,29 +1943,52 @@ BEGIN
 
   --RAISE NOTICE 'EdgeId1 % EdgeId2 %', edgeid1, edgeid2;
 
+  --RAISE DEBUG 'oldedge.next_left_edge: %', oldedge.next_left_edge;
+  --RAISE DEBUG 'oldedge.next_right_edge: %', oldedge.next_right_edge;
+
   --
   -- Insert the two new edges
   --
   EXECUTE 'INSERT INTO ' || quote_ident(atopology)
     || '.edge VALUES('
-    ||edgeid1||','||oldedge.start_node
-    ||','||nodeid
-    ||','||edgeid2
-    ||','||oldedge.next_right_edge
-    ||','||oldedge.left_face
-    ||','||oldedge.right_face
-    ||','||quote_literal(edge1::text)
+    || edgeid1                                -- edge_id
+    || ',' || oldedge.start_node              -- start_node
+    || ',' || nodeid                          -- end_node
+    || ',' || edgeid2                         -- next_left_edge
+    || ',' || CASE                            -- next_right_edge
+               WHEN 
+                oldedge.next_right_edge = anedge
+               THEN edgeid1
+               WHEN
+                oldedge.next_right_edge = -anedge
+               THEN -edgeid2
+               ELSE oldedge.next_right_edge
+              END
+    || ',' || oldedge.left_face               -- left_face
+    || ',' || oldedge.right_face              -- right_face
+    || ',' || quote_literal(edge1::text)      -- geom
     ||')';
 
   EXECUTE 'INSERT INTO ' || quote_ident(atopology)
     || '.edge VALUES('
-    ||edgeid2||','||nodeid
-    ||','||oldedge.end_node
-    ||','||oldedge.next_left_edge
-    ||',-'||edgeid1
-    ||','||oldedge.left_face
-    ||','||oldedge.right_face
-    ||','||quote_literal(edge2::text)
+    || edgeid2                                -- edge_id
+    || ',' || nodeid                          -- start_node
+    || ',' || oldedge.end_node                -- end_node
+    || ',' || CASE                            -- next_left_edge
+               WHEN 
+                oldedge.next_left_edge =
+                -anedge
+               THEN -edgeid2
+               WHEN 
+                oldedge.next_left_edge =
+                anedge
+               THEN edgeid1
+               ELSE oldedge.next_left_edge
+              END
+    || ',' || -edgeid1                        -- next_right_edge
+    || ',' || oldedge.left_face               -- left_face
+    || ',' || oldedge.right_face              -- right_face
+    || ',' || quote_literal(edge2::text)      -- geom
     ||')';
 
   --
@@ -1977,26 +2000,34 @@ BEGIN
     || edgeid2
     || ','
     || ' abs_next_right_edge = ' || edgeid2
-    || ' WHERE next_right_edge = ' || anedge;
+    || ' WHERE next_right_edge = ' || anedge
+    || ' AND edge_id NOT IN (' || edgeid1 || ',' || edgeid2 || ')'
+    ;
   EXECUTE 'UPDATE ' || quote_ident(atopology)
     || '.edge_data SET next_right_edge = '
     || -edgeid1
     || ','
     || ' abs_next_right_edge = ' || edgeid1
-    || ' WHERE next_right_edge = ' || -anedge;
+    || ' WHERE next_right_edge = ' || -anedge
+    || ' AND edge_id NOT IN (' || edgeid1 || ',' || edgeid2 || ')'
+    ;
 
   EXECUTE 'UPDATE ' || quote_ident(atopology)
     || '.edge_data SET next_left_edge = '
     || edgeid1
     || ','
     || ' abs_next_left_edge = ' || edgeid1
-    || ' WHERE next_left_edge = ' || anedge;
+    || ' WHERE next_left_edge = ' || anedge
+    || ' AND edge_id NOT IN (' || edgeid1 || ',' || edgeid2 || ')'
+    ;
   EXECUTE 'UPDATE ' || quote_ident(atopology)
     || '.edge_data SET '
     || ' next_left_edge = ' || -edgeid2
     || ','
     || ' abs_next_left_edge = ' || edgeid2
-    || ' WHERE next_left_edge = ' || -anedge;
+    || ' WHERE next_left_edge = ' || -anedge
+    || ' AND edge_id NOT IN (' || edgeid1 || ',' || edgeid2 || ')'
+    ;
 
   -- Get topology id
         SELECT id FROM topology.topology into topoid
index 1c0de33f4474b7dbbbcadd03bd41d2da4fc57bd4..b679a7e7c84607c2e76757974a22d392f87b809c 100644 (file)
@@ -40,6 +40,7 @@ TESTS = regress/legacy_validate.sql regress/legacy_predicate.sql \
        regress/st_modedgeheal.sql \
        regress/st_modedgesplit.sql \
        regress/st_newedgeheal.sql \
+       regress/st_newedgessplit.sql \
        regress/st_remedgenewface.sql \
        regress/st_remedgemodface.sql \
        regress/topoelement.sql \
diff --git a/topology/test/regress/st_newedgessplit.sql b/topology/test/regress/st_newedgessplit.sql
new file mode 100644 (file)
index 0000000..3d24f96
--- /dev/null
@@ -0,0 +1,96 @@
+
+\set VERBOSITY terse
+set client_min_messages to ERROR;
+
+-- Import city_data
+\i load_topology.sql
+
+-- Save max node id
+select 'node'::text as what, max(node_id) INTO city_data.limits FROM city_data.node;
+INSERT INTO city_data.limits select 'edge'::text as what, max(edge_id) FROM city_data.edge;
+SELECT 'max',* from city_data.limits;
+
+-- Check changes since last saving, save more
+-- {
+CREATE OR REPLACE FUNCTION check_changes()
+RETURNS TABLE (o text)
+AS $$
+DECLARE
+  rec RECORD;
+  sql text;
+BEGIN
+  -- Check effect on nodes
+  sql := 'SELECT n.node_id, ''N|'' || n.node_id || ''|'' ||
+        COALESCE(n.containing_face::text,'''') || ''|'' ||
+        ST_AsText(ST_SnapToGrid(n.geom, 0.2))::text as xx
+       FROM city_data.node n WHERE n.node_id > (
+               SELECT max FROM city_data.limits WHERE what = ''node''::text )
+               ORDER BY n.node_id';
+
+  FOR rec IN EXECUTE sql LOOP
+    o := rec.xx;
+    RETURN NEXT;
+  END LOOP;
+  
+  -- Check effect on edges (there should be one split)
+  sql := '
+  WITH node_limits AS ( SELECT max FROM city_data.limits WHERE what = ''node''::text ),
+       edge_limits AS ( SELECT max FROM city_data.limits WHERE what = ''edge''::text )
+  SELECT ''E|'' || e.edge_id || ''|sn'' || e.start_node || ''|en'' || e.end_node 
+         || ''|nl'' || e.next_left_edge
+         || ''|nr'' || e.next_right_edge
+         || ''|lf'' || e.left_face
+         || ''|rf'' || e.right_face
+         :: text as xx
+   FROM city_data.edge e, node_limits nl, edge_limits el
+   WHERE e.start_node > nl.max
+      OR e.end_node > nl.max
+      OR e.edge_id > el.max
+  ORDER BY e.edge_id;
+  ';
+
+  FOR rec IN EXECUTE sql LOOP
+    o := rec.xx;
+    RETURN NEXT;
+  END LOOP;
+
+  UPDATE city_data.limits SET max = (SELECT max(n.node_id) FROM city_data.node n) WHERE what = 'node';
+  UPDATE city_data.limits SET max = (SELECT max(e.edge_id) FROM city_data.edge e) WHERE what = 'edge';
+
+END;
+$$ LANGUAGE 'plpgsql';
+-- }
+
+-- Invalid calls
+SELECT 'invalid', ST_NewEdgesSplit('city_data', 999, 'POINT(36 26, 38 30)');
+SELECT 'invalid', ST_NewEdgesSplit('city_data', 10, 'POINT(28 15)');
+SELECT 'invalid', ST_NewEdgesSplit('', 10, 'POINT(28 14)');
+SELECT 'invalid', ST_NewEdgesSplit(NULL, 10, 'POINT(28 14)');
+SELECT 'invalid', ST_NewEdgesSplit('city_data', NULL, 'POINT(28 14)');
+SELECT 'invalid', ST_NewEdgesSplit('city_data', 10, NULL);
+SELECT 'invalid', ST_NewEdgesSplit('fake', 10, 'POINT(28 14)');
+
+-- Non-isolated edge 
+SELECT 'noniso', ST_NewEdgesSplit('city_data', 10, 'POINT(28 14)');
+SELECT check_changes();
+
+-- Isolated edge
+SELECT 'iso', ST_NewEdgesSplit('city_data', 25, 'POINT(11 35)');
+SELECT check_changes();
+
+-- Dangling on end point 
+SELECT 'dangling_end', ST_NewEdgesSplit('city_data', 3, 'POINT(25 32)');
+SELECT check_changes();
+
+-- Dangling on start point 
+SELECT 'dangling_start', ST_NewEdgesSplit('city_data', 4, 'POINT(45 32)');
+SELECT check_changes();
+
+-- Splitting closed edge
+SELECT 'closed', ST_NewEdgesSplit('city_data', 1, 'POINT(3 38)');
+SELECT check_changes();
+
+
+
+DROP FUNCTION check_changes();
+SELECT DropTopology('city_data');
diff --git a/topology/test/regress/st_newedgessplit_expected b/topology/test/regress/st_newedgessplit_expected
new file mode 100644 (file)
index 0000000..bf41786
--- /dev/null
@@ -0,0 +1,36 @@
+BEGIN
+t
+9
+22
+26
+COMMIT
+max|node|22
+max|edge|26
+ERROR:  geometry has too many points at character 54
+ERROR:  SQL/MM Spatial exception - point not on edge
+ERROR:  zero-length delimited identifier at or near """" at character 15
+ERROR:  SQL/MM Spatial exception - null argument
+ERROR:  SQL/MM Spatial exception - null argument
+ERROR:  SQL/MM Spatial exception - null argument
+ERROR:  schema "fake" does not exist at character 15
+noniso|23
+N|23||POINT(28 14)
+E|27|sn13|en23|nl28|nr17|lf7|rf4
+E|28|sn23|en14|nl-20|nr-27|lf7|rf4
+iso|24
+N|24||POINT(11 35)
+E|29|sn21|en24|nl30|nr29|lf1|rf1
+E|30|sn24|en22|nl-30|nr-29|lf1|rf1
+dangling_end|25
+N|25||POINT(25 32)
+E|31|sn2|en25|nl32|nr2|lf2|rf2
+E|32|sn25|en3|nl-32|nr-31|lf2|rf2
+dangling_start|26
+N|26||POINT(45 32)
+E|33|sn5|en26|nl34|nr33|lf0|rf0
+E|34|sn26|en6|nl-5|nr-33|lf0|rf0
+closed|27
+N|27||POINT(3 38)
+E|35|sn1|en27|nl36|nr-36|lf1|rf0
+E|36|sn27|en1|nl35|nr-35|lf1|rf0
+Topology 'city_data' dropped