]> granicus.if.org Git - postgis/commitdiff
TopoGeo_addLineString: fix node crossing, reduce edges creations
authorSandro Santilli <strk@keybit.net>
Sun, 22 Jan 2012 15:43:57 +0000 (15:43 +0000)
committerSandro Santilli <strk@keybit.net>
Sun, 22 Jan 2012 15:43:57 +0000 (15:43 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@8900 b70326c6-7e19-0410-871a-916f4a2858ee

topology/sql/populate.sql.in.c
topology/test/regress/topogeo_addlinestring.sql
topology/test/regress/topogeo_addlinestring_expected

index 830057c379408671edccc79aa9b881599402dbca..7dd1a7931615a30361fe567306f3bfad2c5eae80 100644 (file)
@@ -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
 
index dd4e5c514b3592ece7dafbd0c18d412648af3228..623436147afa49f453fcf8507c08831f2e09f721 100644 (file)
@@ -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');
index c19b6cf3be6a8cb054239c4f4bee35529dce6a3c..61fd16e3989a4d71cf0cce9799ffb19d806f0a19 100644 (file)
@@ -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