]> granicus.if.org Git - postgis/commitdiff
Don't let ST_RemEdge* destroy TopoGeometry objects (#1766)
authorSandro Santilli <strk@keybit.net>
Wed, 11 Apr 2012 19:17:49 +0000 (19:17 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 11 Apr 2012 19:17:49 +0000 (19:17 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@9627 b70326c6-7e19-0410-871a-916f4a2858ee

topology/sql/sqlmm.sql.in.c
topology/test/regress/st_remedgemodface.sql
topology/test/regress/st_remedgemodface_expected
topology/test/regress/st_remedgenewface.sql
topology/test/regress/st_remedgenewface_expected

index 8ac9f8064437c66262a46ee145a4d2dadbcdcd4e..a6b6a1d8e42b5cc7cbc5ae3b46b812e965fe2dff 100644 (file)
@@ -860,35 +860,38 @@ BEGIN
     -- joined faces. In such case there would be no way to adapt
     -- the definition in case of healing, so we'd have to bail out
     --
-    -- We do this only when no universal face is involved
-    -- (no surface can be defined by universal face)
+    -- TODO: use an internal function and share with ST_RemEdgeNewFace
+    --
     -- 
-    IF e1rec.left_face != 0 AND e1rec.right_face != 0
-    THEN -- {
-      fidary = ARRAY[e1rec.left_face, e1rec.right_face];
-      sql := 'SELECT t.* from ('
-        || 'SELECT r.topogeo_id, r.layer_id'
-        || ', l.schema_name, l.table_name, l.feature_column'
-        || ', array_agg(r.element_id) as elems '
-        || 'FROM topology.layer l INNER JOIN '
-        || quote_ident(toponame)
-        || '.relation r ON (l.layer_id = r.layer_id) '
-        || 'WHERE l.level = 0 AND l.feature_type = 3 '
-        || ' AND l.topology_id = ' || topoid
-        || ' AND r.element_id IN (' || e1rec.left_face || ',' || e1rec.right_face || ') '
-        || 'group by r.topogeo_id, r.layer_id, l.schema_name, l.table_name, '
-        || ' l.feature_column ) t WHERE NOT t.elems @> '
-        || quote_literal(fidary);
+    fidary = ARRAY[e1rec.left_face, e1rec.right_face];
+    sql := 'SELECT t.* from ('
+      || 'SELECT r.topogeo_id, r.layer_id'
+      || ', l.schema_name, l.table_name, l.feature_column'
+      || ', array_agg(r.element_id) as elems '
+      || 'FROM topology.layer l INNER JOIN '
+      || quote_ident(toponame)
+      || '.relation r ON (l.layer_id = r.layer_id) '
+      || 'WHERE l.level = 0 AND l.feature_type = 3 '
+      || ' AND l.topology_id = ' || topoid
+      || ' AND r.element_id = ANY (' || quote_literal(fidary)
+      || ') group by r.topogeo_id, r.layer_id, l.schema_name, l.table_name, '
+      || ' l.feature_column ) t';
+
+    -- No surface can be defined by universal face 
+    IF e1rec.left_face != 0 AND e1rec.right_face != 0 THEN -- {
+      sql := sql || ' WHERE NOT t.elems @> ' || quote_literal(fidary);
+    END IF; -- }
+
 #ifdef POSTGIS_TOPOLOGY_DEBUG
-      RAISE DEBUG 'SQL: %', sql;
+    RAISE DEBUG 'SQL: %', sql;
 #endif
-      FOR rec IN EXECUTE sql LOOP
-        RAISE EXCEPTION 'TopoGeom % in layer % (%.%.%) cannot be represented healing faces % and %',
-              rec.topogeo_id, rec.layer_id,
-              rec.schema_name, rec.table_name, rec.feature_column,
-              e1rec.right_face, e1rec.left_face;
-      END LOOP;
-    END IF; -- }
+
+    FOR rec IN EXECUTE sql LOOP
+      RAISE EXCEPTION 'TopoGeom % in layer % (%.%.%) cannot be represented healing faces % and %',
+            rec.topogeo_id, rec.layer_id,
+            rec.schema_name, rec.table_name, rec.feature_column,
+            e1rec.right_face, e1rec.left_face;
+    END LOOP;
 
     IF e1rec.left_face = 0 OR e1rec.right_face = 0 THEN -- {
 
@@ -1228,35 +1231,37 @@ BEGIN
     -- joined faces. In such case there would be no way to adapt
     -- the definition in case of healing, so we'd have to bail out
     --
-    -- We do this only when no universal face is involved
-    -- (no surface can be defined by universal face)
-    -- 
-    IF e1rec.left_face != 0 AND e1rec.right_face != 0
-    THEN -- {
-      fidary = ARRAY[e1rec.left_face, e1rec.right_face];
-      sql := 'SELECT t.* from ('
-        || 'SELECT r.topogeo_id, r.layer_id'
-        || ', l.schema_name, l.table_name, l.feature_column'
-        || ', array_agg(r.element_id) as elems '
-        || 'FROM topology.layer l INNER JOIN '
-        || quote_ident(toponame)
-        || '.relation r ON (l.layer_id = r.layer_id) '
-        || 'WHERE l.level = 0 AND l.feature_type = 3 '
-        || ' AND l.topology_id = ' || topoid
-        || ' AND r.element_id IN (' || e1rec.left_face || ',' || e1rec.right_face || ') '
-        || 'group by r.topogeo_id, r.layer_id, l.schema_name, l.table_name, '
-        || ' l.feature_column ) t WHERE NOT t.elems @> '
-        || quote_literal(fidary);
+    -- TODO: use an internal function and share with ST_RemEdgeNewFace
+    --
+    fidary = ARRAY[e1rec.left_face, e1rec.right_face];
+    sql := 'SELECT t.* from ('
+      || 'SELECT r.topogeo_id, r.layer_id'
+      || ', l.schema_name, l.table_name, l.feature_column'
+      || ', array_agg(r.element_id) as elems '
+      || 'FROM topology.layer l INNER JOIN '
+      || quote_ident(toponame)
+      || '.relation r ON (l.layer_id = r.layer_id) '
+      || 'WHERE l.level = 0 AND l.feature_type = 3 '
+      || ' AND l.topology_id = ' || topoid
+      || ' AND r.element_id = ANY (' || quote_literal(fidary) 
+      || ') group by r.topogeo_id, r.layer_id, l.schema_name, l.table_name, '
+      || ' l.feature_column ) t';
+
+    -- No surface can be defined by universal face 
+    IF NOT 0 = ANY ( fidary ) THEN -- {
+      sql := sql || ' WHERE NOT t.elems @> ' || quote_literal(fidary);
+    END IF; -- }
+
 #ifdef POSTGIS_TOPOLOGY_DEBUG
-      RAISE DEBUG 'SQL: %', sql;
+    RAISE DEBUG 'SQL: %', sql;
 #endif
-      FOR rec IN EXECUTE sql LOOP
-        RAISE EXCEPTION 'TopoGeom % in layer % (%.%.%) cannot be represented healing faces % and %',
-              rec.topogeo_id, rec.layer_id,
-              rec.schema_name, rec.table_name, rec.feature_column,
-              e1rec.right_face, e1rec.left_face;
-      END LOOP;
-    END IF; -- }
+
+    FOR rec IN EXECUTE sql LOOP
+      RAISE EXCEPTION 'TopoGeom % in layer % (%.%.%) cannot be represented healing faces % and %',
+            rec.topogeo_id, rec.layer_id,
+            rec.schema_name, rec.table_name, rec.feature_column,
+            e1rec.right_face, e1rec.left_face;
+    END LOOP;
 
     IF e1rec.left_face = 0 OR e1rec.right_face = 0 THEN -- {
 
index f7517289becb689efbf7cfbd488463edca81781d..d5e9a646cb287105018a21fbe1b2bc5e7000ee07 100644 (file)
@@ -390,6 +390,12 @@ SELECT '*RM(17)', topology.ST_RemEdgeModFace('city_data', 17);
 SELECT 'RM(11)', 'relations_before:', count(*) FROM city_data.relation;
 SELECT 'RM(11)', topology.ST_RemEdgeModFace('city_data', 11);
 SELECT 'RM(11)', 'relations_after:', count(*) FROM city_data.relation;
+
+-- Land parcel P3 is now defined by face 8, so we can't drop
+-- any edge which would destroy that face.
+SELECT '*RM(8)', topology.ST_RemEdgeModFace('city_data', 8); -- face_right=8
+SELECT '*RM(15)', topology.ST_RemEdgeModFace('city_data', 15); -- face_left=8
+
 -- Check that no land_parcel objects had topology changed
 SELECT 'RM(11)', feature_name, 
  ST_Equals( ST_Multi(feature::geometry), ST_Multi(the_geom) ) as unchanged
index 8613e7f68fbc441815612117dde9b96e1a4ff3c4..410a10f4566c5bf0ca7842cec49fd2a12bc4bc06 100644 (file)
@@ -203,6 +203,8 @@ ERROR:  TopoGeom 2 in layer 1 (features.land_parcels.feature) cannot be represen
 RM(11)|relations_before:|18
 RM(11)|8
 RM(11)|relations_after:|17
+ERROR:  TopoGeom 3 in layer 1 (features.land_parcels.feature) cannot be represented healing faces 8 and 0
+ERROR:  TopoGeom 3 in layer 1 (features.land_parcels.feature) cannot be represented healing faces 0 and 8
 RM(11)|P1|t
 RM(11)|P2|t
 RM(11)|P3|t
index ea44c3cf9830ba83c50143436cf23d5967bcf087..10e8ca044ee608af65c6fc32f9769dd356e84ce5 100644 (file)
@@ -390,6 +390,12 @@ SELECT '*RN(17)', topology.ST_RemEdgeNewFace('city_data', 17);
 SELECT 'RN(11)', 'relations_before:', count(*) FROM city_data.relation;
 SELECT 'RN(11)', topology.ST_RemEdgeNewFace('city_data', 11);
 SELECT 'RN(11)', 'relations_after:', count(*) FROM city_data.relation;
+
+-- Land parcel P3 is now defined by face 10, so we can't drop
+-- any edge which would destroy that face.
+SELECT '*RM(8)', topology.ST_RemEdgeModFace('city_data', 8); -- face_right=10
+SELECT '*RM(15)', topology.ST_RemEdgeModFace('city_data', 15); -- face_left=10
+
 -- Check that no land_parcel objects had topology changed
 SELECT 'RN(11)', feature_name, 
  ST_Equals( ST_Multi(feature::geometry), ST_Multi(the_geom) ) as unchanged
index ded283d1a3f5812ffc742ecbabc32d2c422496c4..61d88d5040b5c3ae19ade20ab1478180cfc1937b 100644 (file)
@@ -233,6 +233,8 @@ ERROR:  TopoGeom 2 in layer 1 (features.land_parcels.feature) cannot be represen
 RN(11)|relations_before:|18
 RN(11)|10
 RN(11)|relations_after:|17
+ERROR:  TopoGeom 3 in layer 1 (features.land_parcels.feature) cannot be represented healing faces 10 and 0
+ERROR:  TopoGeom 3 in layer 1 (features.land_parcels.feature) cannot be represented healing faces 0 and 10
 RN(11)|P1|t
 RN(11)|P2|t
 RN(11)|P3|t