From: Sandro Santilli Date: Fri, 17 Feb 2012 18:29:50 +0000 (+0000) Subject: Check edge disposition around endnodes (#1571) X-Git-Tag: 2.0.0alpha6~36 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2ab2a79839bf180fb44f8eb524f16bc4487a3ea2;p=postgis Check edge disposition around endnodes (#1571) Includes a couple new testcases, for closed and non-closed edges changing disposition around their end nodes. git-svn-id: http://svn.osgeo.org/postgis/trunk@9228 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/topology/sql/sqlmm.sql.in.c b/topology/sql/sqlmm.sql.in.c index f78143e3e..de4e86084 100644 --- a/topology/sql/sqlmm.sql.in.c +++ b/topology/sql/sqlmm.sql.in.c @@ -2520,6 +2520,42 @@ $$ LANGUAGE 'plpgsql' VOLATILE; --} ST_AddIsoEdge +-- Internal function used by ST_ChangeEdgeGeom to compare +-- adjacent edges of an edge endpoint +-- +-- @param anode the node to use edge end star of +-- @param anedge the directed edge to get adjacents from +-- if positive `anode' is assumed to be its start node +-- if negative `anode' is assumed to be its end node +-- +-- { +CREATE OR REPLACE FUNCTION topology._ST_AdjacentEdges(atopology varchar, anode integer, anedge integer) +RETURNS integer[] AS +$$ +DECLARE + ret integer[]; +BEGIN + WITH edgestar AS ( + SELECT *, count(*) over () AS cnt + FROM GetNodeEdges(atopology, anode) + ) + SELECT ARRAY[ ( + SELECT p.edge AS prev FROM edgestar p + WHERE p.sequence = CASE WHEN m.sequence-1 < 1 THEN cnt + ELSE m.sequence-1 END + ), ( + SELECT p.edge AS prev FROM edgestar p WHERE p.sequence = ((m.sequence)%cnt)+1 + ) ] + FROM edgestar m + WHERE edge = anedge + INTO ret; + + RETURN ret; +END +$$ +LANGUAGE 'plpgsql' STABLE; +--} + --{ -- Topo-Geo and Topo-Net 3: Routine Details -- X.3.6 @@ -2540,6 +2576,8 @@ DECLARE range GEOMETRY; -- movement range tmp1 GEOMETRY; tmp2 GEOMETRY; + snode_info RECORD; + enode_info RECORD; sql TEXT; iscw BOOLEAN; BEGIN @@ -2674,6 +2712,10 @@ BEGIN -- Not in the specs: -- Check topological isomorphism -- + + -- Check that the "motion range" doesn't include any node + --{ + tmp1 := ST_MakeLine(ST_EndPoint(oldedge.geom), ST_StartPoint(oldedge.geom)); RAISE DEBUG 'end-to-start: %', ST_AsText(tmp1); @@ -2706,7 +2748,25 @@ BEGIN RAISE EXCEPTION 'Edge motion collision at %', ST_AsText(rec.geom); END LOOP; -- } - --RAISE EXCEPTION 'Not doing it'; + --} motion range checking end + + -- + -- Check edge adjacency before + --{ + + SELECT topology._ST_AdjacentEdges( + atopology, oldedge.start_node, anedge + ) as pre, NULL::integer[] as post + INTO STRICT snode_info; + RAISE DEBUG 'Bs:%', snode_info.pre; + + SELECT topology._ST_AdjacentEdges( + atopology, oldedge.end_node, -anedge + ) as pre, NULL::integer[] as post + INTO STRICT enode_info; + RAISE DEBUG 'Be:%', enode_info.pre; + + --} -- -- Update edge geometry @@ -2715,6 +2775,35 @@ BEGIN || ' SET geom = ' || quote_literal(acurve::text) || ' WHERE edge_id = ' || anedge; + -- + -- Check edge adjacency after + --{ + + snode_info.post := topology._ST_AdjacentEdges( + atopology, oldedge.start_node, anedge + ); + RAISE DEBUG 'As:%', snode_info.post; + + enode_info.post := topology._ST_AdjacentEdges( + atopology, oldedge.end_node, -anedge + ); + RAISE DEBUG 'Ae:%', enode_info.post; + + IF snode_info.pre != snode_info.post THEN + RAISE EXCEPTION 'Edge changed disposition around start node %', + oldedge.start_node; + END IF; + + IF enode_info.pre != enode_info.post THEN + RAISE EXCEPTION 'Edge changed disposition around end node %', + oldedge.end_node; + END IF; + + --} + + --RAISE EXCEPTION 'Not doing it'; + + RETURN 'Edge ' || anedge || ' changed'; END diff --git a/topology/test/regress/st_changeedgegeom.sql b/topology/test/regress/st_changeedgegeom.sql index f6cefdc2f..a9d68a74b 100644 --- a/topology/test/regress/st_changeedgegeom.sql +++ b/topology/test/regress/st_changeedgegeom.sql @@ -78,8 +78,18 @@ SELECT 'T8', topology.ST_ChangeEdgeGeom('city_data', 26, SELECT topology.ST_ChangeEdgeGeom('city_data', 13, 'LINESTRING(21 6, 21 2, 6 2, 6 25, 50 25, 50 2, 35 2, 35 6)'); +-- test moving closed edge into another face +SELECT 'T9', ST_AddEdgeModFace('city_data', 20, 20, + 'LINESTRING(4 31, 7 31, 4 34, 4 31)'); +SELECT ST_ChangeEdgeGeom('city_data', 26, -- should fail! + 'LINESTRING(4 31,5 31.5,4.6 32,4 31)'); + +-- TODO: test moving non-closed edge into another face +SELECT 'T10', ST_AddEdgeModFace('city_data', 17, 18, + 'LINESTRING(21 22, 28 27, 35 22)'); +SELECT ST_ChangeEdgeGeom('city_data', 28, -- should fail! + 'LINESTRING(21 22, 28 18, 35 22)'); --- TODO: test moving closed edge into another face -- TODO: test face mbr update SELECT topology.DropTopology('city_data'); diff --git a/topology/test/regress/st_changeedgegeom_expected b/topology/test/regress/st_changeedgegeom_expected index 74e1ce560..62c300768 100644 --- a/topology/test/regress/st_changeedgegeom_expected +++ b/topology/test/regress/st_changeedgegeom_expected @@ -23,4 +23,8 @@ T7.1|Edge 2 changed ERROR: Edge twist at node POINT(4 31) T8|Edge 26 changed ERROR: Edge motion collision at POINT(9 6) +T9|27 +ERROR: Edge changed disposition around start node 20 +T10|28 +ERROR: Edge changed disposition around start node 17 Topology 'city_data' dropped