--
--
-/*#define POSTGIS_TOPOLOGY_DEBUG 1*/
+/* #define POSTGIS_TOPOLOGY_DEBUG 1 */
--={ ----------------------------------------------------------------
-- SQL/MM block
$$
DECLARE
rec RECORD;
+ rng_info RECORD; -- movement range info
oldedge RECORD;
range GEOMETRY; -- movement range
tmp1 GEOMETRY;
- tmp2 GEOMETRY;
snode_info RECORD;
enode_info RECORD;
sql TEXT;
|| '.node WHERE geom && '
|| quote_literal(acurve::text)
|| '::geometry'
+ -- TODO: skip start_node and end_node !
LOOP
IF ST_RelateMatch(rec.relate, 'T********') THEN
RAISE EXCEPTION 'SQL/MM Spatial exception - geometry crosses a node';
-- Check that the "motion range" doesn't include any node
--{
- tmp1 := ST_MakeLine(ST_EndPoint(oldedge.geom), ST_StartPoint(oldedge.geom));
+ sql := 'SELECT ST_Collect(geom) as nodes, '
+ || 'null::geometry as r1, null::geometry as r2 FROM '
+ || quote_ident(atopology)
+ || '.node WHERE geom && '
+ || quote_literal(ST_Collect(ST_Envelope(oldedge.geom),
+ ST_Envelope(acurve))::text)
+ || '::geometry AND node_id NOT IN ( '
+ || oldedge.start_node || ',' || oldedge.end_node || ')';
#ifdef POSTGIS_TOPOLOGY_DEBUG
- RAISE DEBUG 'end-to-start: %', ST_AsText(tmp1);
+ RAISE DEBUG '%', sql;
#endif
+ EXECUTE sql INTO rng_info;
+
+ -- There's no collision if there's no nodes in the combined
+ -- bbox of old and new edges.
+ --
+ IF NOT ST_IsEmpty(rng_info.nodes) THEN -- {
- tmp2 := ST_MakeLine(oldedge.geom, tmp1);
- IF ST_NumPoints(tmp2) < 4 THEN
- tmp2 := ST_AddPoint(tmp2, ST_StartPoint(oldedge.geom));
- END IF;
#ifdef POSTGIS_TOPOLOGY_DEBUG
- RAISE DEBUG 'Old-ring: %', ST_AsText(tmp2);
+ RAISE DEBUG '% nodes in the edge movement range bbox: %',
+ ST_NumGeometries(rng_info.nodes),
+ ST_AsText(rng_info.nodes)
+ ;
#endif
- tmp2 := ST_CollectionExtract(ST_MakeValid(ST_MakePolygon(tmp2)), 3);
+
+ tmp1 := ST_MakeLine(ST_EndPoint(oldedge.geom), ST_StartPoint(oldedge.geom));
#ifdef POSTGIS_TOPOLOGY_DEBUG
- RAISE DEBUG 'Old-ring (poly): %', ST_AsText(tmp2);
+ RAISE DEBUG 'end-to-start: %', ST_AsText(tmp1);
#endif
- range := ST_MakeLine(acurve, tmp1);
- IF ST_NumPoints(range) < 4 THEN
- range := ST_AddPoint(range, ST_StartPoint(oldedge.geom));
- END IF;
+ rng_info.r1 := ST_MakeLine(oldedge.geom, tmp1);
+ IF ST_NumPoints(rng_info.r1) < 4 THEN
+ rng_info.r1 := ST_AddPoint(rng_info.r1, ST_StartPoint(oldedge.geom));
+ END IF;
#ifdef POSTGIS_TOPOLOGY_DEBUG
- RAISE DEBUG 'New-ring: %', ST_AsText(range);
+ RAISE DEBUG 'Old-ring: %', ST_AsText(rng_info.r1);
#endif
- range := ST_CollectionExtract(ST_MakeValid(ST_MakePolygon(range)), 3);
+ rng_info.r1 := ST_CollectionExtract(
+ ST_MakeValid(ST_MakePolygon(rng_info.r1)), 3);
#ifdef POSTGIS_TOPOLOGY_DEBUG
- RAISE DEBUG 'New-ring (poly): %', ST_AsText(range);
+ RAISE DEBUG 'Old-ring (poly): %', ST_AsText(rng_info.r1);
#endif
- range := ST_SymDifference(range, tmp2);
+ rng_info.r2 := ST_MakeLine(acurve, tmp1);
+ IF ST_NumPoints(rng_info.r2) < 4 THEN
+ rng_info.r2 := ST_AddPoint(rng_info.r2, ST_StartPoint(oldedge.geom));
+ END IF;
#ifdef POSTGIS_TOPOLOGY_DEBUG
- RAISE DEBUG 'Range motion: %', ST_AsText(range);
+ RAISE DEBUG 'New-ring: %', ST_AsText(rng_info.r2);
#endif
-
- sql := 'SELECT node_id, geom FROM '
- || quote_ident(atopology)
- || '.node WHERE ST_Contains('
- || quote_literal(range::text)
- || '::geometry, geom) LIMIT 1';
+ rng_info.r2 := ST_CollectionExtract(
+ ST_MakeValid(ST_MakePolygon(rng_info.r2)), 3);
#ifdef POSTGIS_TOPOLOGY_DEBUG
- RAISE DEBUG '%', sql;
+ RAISE DEBUG 'New-ring (poly): %', ST_AsText(rng_info.r2);
#endif
- FOR rec IN EXECUTE sql LOOP -- {
- RAISE EXCEPTION 'Edge motion collision at %', ST_AsText(rec.geom);
- END LOOP; -- }
+
+ tmp1 := ST_CollectionExtract(ST_Intersection(rng_info.nodes, rng_info.r1), 1);
+ range := ST_CollectionExtract(ST_Intersection(rng_info.nodes, rng_info.r2), 1);
+ IF ST_IsEmpty(tmp1) != ST_IsEmpty(range) OR NOT ST_Equals(tmp1, range)
+ THEN
+ RAISE EXCEPTION 'Edge motion collision at %',
+ ST_AsText(ST_GeometryN(ST_Union(tmp1, range), 1));
+ END IF;
+
+ END IF; -- }
--} motion range checking end
SELECT 'T12.1', ST_AddIsoNode('city_data', 8, 'POINT(49 10)');
SELECT 'T12', ST_ChangeEdgeGeom('city_data', 16, 'LINESTRING(47 6, 47 14)');
+-- See http://trac.osgeo.org/postgis/ticket/2176
+SELECT 'T13.1', TopoGeo_AddLineString('city_data', '01020000001D000000E42CEC69873FF2BF9E98F56228E347400EDB16653648F2BF4985B18520E34740E92B4833164DF2BF3A1E335019E34740A94D9CDCEF50F2BF33F9669B1BE347407DAEB6627F59F2BF2CF180B229E34740758E01D9EB5DF2BFD0D556EC2FE34740533F6F2A5261F2BFD717096D39E34740F4893C49BA66F2BFC8073D9B55E34740B8239C16BC68F2BF33A7CB6262E34740AA2B9FE57970F2BF4165FCFB8CE347406DC5FEB27B72F2BFBA4E232D95E34740978BF84ECC7AF2BF24EEB1F4A1E34740E527D53E1D8FF2BF8F8D40BCAEE3474036CD3B4ED191F2BF649291B3B0E34740841266DAFE95F2BF1DE6CB0BB0E34740E3361AC05BA0F2BFB2632310AFE347405C5A0D897BACF2BF72F90FE9B7E3474031D3F6AFACB4F2BF4F232D95B7E347402B137EA99FB7F2BFD656EC2FBBE347402D431CEBE2B6F2BF551344DD07E4474011E4A08499B6F2BF15E3FC4D28E447406519E25817B7F2BF63EE5A423EE447409DD7D825AAB7F2BFE3FC4D2844E447405969520ABABDF2BF2384471B47E44740A31EA2D11DC4F2BFB1F9B83654E447400473F4F8BDCDF2BFEA5BE67459E447405070B1A206D3F2BFF19D98F562E4474062670A9DD7D8F2BF0E4FAF9465E447407FF6234564D8F2BFF1BA7EC16EE44740' );
+SELECT 'T13.2', ST_ChangeEdgeGeom('city_data', 29, '010200000008000000E42CEC69873FF2BF9E98F56228E34740E92B4833164DF2BF3B1E335019E34740768E01D9EB5DF2BFD0D556EC2FE347406EC5FEB27B72F2BFBA4E232D95E34740988BF84ECC7AF2BF25EEB1F4A1E347402C137EA99FB7F2BFD656EC2FBBE347409DD7D825AAB7F2BFE4FC4D2844E447407FF6234564D8F2BFF1BA7EC16EE44740' );
+-- Now add an obstacle and try to change back (should fail)
+SELECT 'T13.3', TopoGeo_AddPoint('city_data', 'POINT(-1.1697 47.7825)'::geometry);
+SELECT 'T13.4', ST_ChangeEdgeGeom('city_data', 29, '01020000001D000000E42CEC69873FF2BF9E98F56228E347400EDB16653648F2BF4985B18520E34740E92B4833164DF2BF3A1E335019E34740A94D9CDCEF50F2BF33F9669B1BE347407DAEB6627F59F2BF2CF180B229E34740758E01D9EB5DF2BFD0D556EC2FE34740533F6F2A5261F2BFD717096D39E34740F4893C49BA66F2BFC8073D9B55E34740B8239C16BC68F2BF33A7CB6262E34740AA2B9FE57970F2BF4165FCFB8CE347406DC5FEB27B72F2BFBA4E232D95E34740978BF84ECC7AF2BF24EEB1F4A1E34740E527D53E1D8FF2BF8F8D40BCAEE3474036CD3B4ED191F2BF649291B3B0E34740841266DAFE95F2BF1DE6CB0BB0E34740E3361AC05BA0F2BFB2632310AFE347405C5A0D897BACF2BF72F90FE9B7E3474031D3F6AFACB4F2BF4F232D95B7E347402B137EA99FB7F2BFD656EC2FBBE347402D431CEBE2B6F2BF551344DD07E4474011E4A08499B6F2BF15E3FC4D28E447406519E25817B7F2BF63EE5A423EE447409DD7D825AAB7F2BFE3FC4D2844E447405969520ABABDF2BF2384471B47E44740A31EA2D11DC4F2BFB1F9B83654E447400473F4F8BDCDF2BFEA5BE67459E447405070B1A206D3F2BFF19D98F562E4474062670A9DD7D8F2BF0E4FAF9465E447407FF6234564D8F2BFF1BA7EC16EE44740' );
+
-- TODO: test changing some clockwise closed edges..
SELECT topology.DropTopology('city_data');
+