From fd4aeeebb1238a611436cb96830946ffadb20870 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Sun, 22 Jan 2012 15:43:57 +0000 Subject: [PATCH] TopoGeo_addLineString: fix node crossing, reduce edges creations git-svn-id: http://svn.osgeo.org/postgis/trunk@8900 b70326c6-7e19-0410-871a-916f4a2858ee --- topology/sql/populate.sql.in.c | 79 ++++++++++++++++--- .../test/regress/topogeo_addlinestring.sql | 9 +++ .../regress/topogeo_addlinestring_expected | 11 ++- 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/topology/sql/populate.sql.in.c b/topology/sql/populate.sql.in.c index 830057c37..7dd1a7931 100644 --- a/topology/sql/populate.sql.in.c +++ b/topology/sql/populate.sql.in.c @@ -745,6 +745,8 @@ DECLARE start_node INTEGER; end_node INTEGER; id INTEGER; + inodes GEOMETRY; + iedges GEOMETRY; BEGIN -- 0. Check arguments @@ -758,37 +760,88 @@ BEGIN RAISE DEBUG 'Self-noded: %', ST_AsText(noded); #endif - -- 2. Node to edges and nodes falling within tolerance distance + -- 2. Node to edges falling within tolerance distance sql := 'WITH line AS ( SELECT ' - || quote_literal(aline::text) - || '::geometry as g ), nearby AS ( SELECT n.geom FROM ' - || quote_ident(atopology) - || '.node n, line l WHERE ST_DWithin(n.geom, l.g, ' - || tolerance || ') UNION ALL SELECT e.geom FROM ' + || quote_literal(noded::text) + || '::geometry as g ), nearby AS ( SELECT e.geom FROM ' || quote_ident(atopology) || '.edge e, line l WHERE ST_DWithin(e.geom, l.g, ' || tolerance || ') ) SELECT st_collect(geom) FROM nearby;'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - EXECUTE sql INTO set1; - IF set1 IS NOT NULL THEN - snapped := ST_Snap(noded, set1, tolerance); + EXECUTE sql INTO iedges; + IF iedges IS NOT NULL THEN + +#ifdef POSTGIS_TOPOLOGY_DEBUG + RAISE DEBUG 'Intersecting edges: %', ST_AsText(iedges); +#endif + + snapped := ST_Snap(noded, iedges, tolerance); #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG 'Snapped: %', ST_AsText(snapped); #endif - noded := ST_Difference(snapped, set1); + + noded := ST_Difference(snapped, iedges); #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG 'Difference: %', ST_AsText(noded); #endif - set2 := ST_Intersection(snapped, set1); + + set1 := ST_Intersection(snapped, iedges); #ifdef POSTGIS_TOPOLOGY_DEBUG - RAISE DEBUG 'Intersection: %', ST_AsText(set2); + RAISE DEBUG 'Intersection: %', ST_AsText(set1); #endif + + set2 := ST_LineMerge(set1); +#ifdef POSTGIS_TOPOLOGY_DEBUG + RAISE DEBUG 'LineMerged intersection: %', ST_AsText(set2); +#endif + noded := ST_Union(noded, set2); - -- TODO: linemerge ? +#ifdef POSTGIS_TOPOLOGY_DEBUG + RAISE DEBUG 'Unioned: %', ST_AsText(noded); +#endif + +-- -- Split by intersection points +-- set2 := ST_CollectionExtract(set1, 1); +--#ifdef POSTGIS_TOPOLOGY_DEBUG +-- RAISE DEBUG 'Intersection points: %', ST_AsText(set2); +--#endif +-- FOR rec IN SELECT (ST_Dump(set2)).geom LOOP +-- SELECT ST_Collect(geom) +-- FROM ST_Dump(ST_Split(noded, rec.geom)) +-- INTO STRICT noded; +-- END LOOP; +--#ifdef POSTGIS_TOPOLOGY_DEBUG +-- RAISE DEBUG 'Split by edge intersections: %', ST_AsText(noded); +--#endif + END IF; + -- 2.1. Node with existing nodes within tolerance + sql := 'WITH line AS ( SELECT ' + || quote_literal(noded::text) + || '::geometry as g ), nearby AS ( SELECT n.geom FROM ' + || quote_ident(atopology) + || '.node n, line l WHERE ST_DWithin(n.geom, l.g, ' + || tolerance || ') ) SELECT (st_dump(st_unaryunion(st_collect(geom)))).geom FROM nearby;'; +#ifdef POSTGIS_TOPOLOGY_DEBUG + RAISE DEBUG '%', sql; +#endif + FOR rec IN EXECUTE sql + LOOP + -- Use the node to split edges + SELECT ST_Collect(geom) + FROM ST_Dump(ST_Split(noded, rec.geom)) + INTO STRICT noded; +#ifdef POSTGIS_TOPOLOGY_DEBUG + RAISE DEBUG 'Split by %: %', ST_AsText(rec.geom), ST_AsText(noded); +#endif + END LOOP; +#ifdef POSTGIS_TOPOLOGY_DEBUG + RAISE DEBUG 'Split: %', ST_AsText(noded); +#endif + -- 3. For each (now-noded) segment, insert an edge FOR rec IN SELECT (ST_Dump(noded)).geom LOOP diff --git a/topology/test/regress/topogeo_addlinestring.sql b/topology/test/regress/topogeo_addlinestring.sql index dd4e5c514..623436147 100644 --- a/topology/test/regress/topogeo_addlinestring.sql +++ b/topology/test/regress/topogeo_addlinestring.sql @@ -111,5 +111,14 @@ SELECT check_changes(); SELECT 'contains', TopoGeo_addLineString('city_data', 'LINESTRING(14 34, 13 35, 10 35, 9 35, 7 36)') ORDER BY 2; SELECT check_changes(); +-- Crossing a node +SELECT 'nodecross', TopoGeo_addLineString('city_data', 'LINESTRING(18 37, 22 37)') ORDER BY 2; +SELECT check_changes(); + +-- Existing isolated edge with 2 segments +SELECT 'iso_ex_2segs', TopoGeo_addLineString('city_data', 'LINESTRING(37 20, 43 19, 41 16)'); +SELECT check_changes(); + + DROP FUNCTION check_changes(); SELECT DropTopology('city_data'); diff --git a/topology/test/regress/topogeo_addlinestring_expected b/topology/test/regress/topogeo_addlinestring_expected index c19b6cf3b..61fd16e39 100644 --- a/topology/test/regress/topogeo_addlinestring_expected +++ b/topology/test/regress/topogeo_addlinestring_expected @@ -84,12 +84,15 @@ crossover_again|46 contains|25 contains|47 contains|48 -contains|49 N|42||POINT(14 34) N|43||POINT(7 36) -N|44||POINT(10 35) -E|25|sn21|en44 E|47|sn42|en22 E|48|sn21|en43 -E|49|sn44|en22 +nodecross|49 +nodecross|50 +N|44||POINT(18 37) +N|45||POINT(22 37) +E|49|sn44|en4 +E|50|sn4|en45 +iso_ex_2segs|28 Topology 'city_data' dropped -- 2.50.1