]> granicus.if.org Git - postgis/commitdiff
Complete implementation and regress test for toTopoGeom (#1017)
authorSandro Santilli <strk@keybit.net>
Wed, 4 Jan 2012 18:33:06 +0000 (18:33 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 4 Jan 2012 18:33:06 +0000 (18:33 +0000)
You can start playing with this. Lacks documentation.
Expect troubles. Feel free to report them.

git-svn-id: http://svn.osgeo.org/postgis/trunk@8671 b70326c6-7e19-0410-871a-916f4a2858ee

topology/sql/topogeometry/totopogeom.sql
topology/test/regress/totopogeom.sql
topology/test/regress/totopogeom_expected

index d9ce690fc1c68288bc8a2ccf0799f4230de2db10..c9f9e95e66506e54d4bf98c547af61ba75b760f1 100644 (file)
@@ -23,6 +23,11 @@ $$
 DECLARE
   layer_info RECORD;
   topology_info RECORD;
+  rec RECORD;
+  tg topology.TopoGeometry;
+  elems topology.TopoElementArray = '{{0,0}}';
+  sql TEXT;
+  typ TEXT;
 BEGIN
 
   -- Get topology information
@@ -63,48 +68,91 @@ BEGIN
 
 
   -- 
-  -- Check type compatibility 
+  -- Check type compatibility and create empty TopoGeometry
   -- 1:puntal, 2:lineal, 3:areal, 4:collection
   --
-  IF geometrytype(ageom) = 'GEOMETRYCOLLECTION' THEN
+  typ = geometrytype(ageom);
+  IF typ = 'GEOMETRYCOLLECTION' THEN
     --  A collection can only go collection layer
     IF layer_info.feature_type != 4 THEN
       RAISE EXCEPTION
         'Layer "%" of topology "%" is %, cannot hold a collection feature.',
         layer_info.layer_id, topology_info.name, layer_info.typename;
     END IF;
-  ELSIF ST_Dimension(ageom) = 0 THEN -- puntal
+    tg := topology.CreateTopoGeom(atopology, 4, alayer);
+  ELSIF typ = 'POINT' OR typ = 'MULTIPOINT' THEN -- puntal
     --  A point can go in puntal or collection layer
     IF layer_info.feature_type != 4 and layer_info.feature_type != 1 THEN
       RAISE EXCEPTION
         'Layer "%" of topology "%" is %, cannot hold a puntal feature.',
         layer_info.layer_id, topology_info.name, layer_info.typename;
     END IF;
-  ELSIF ST_Dimension(ageom) = 1 THEN -- lineal
+    tg := topology.CreateTopoGeom(atopology, 1, alayer);
+  ELSIF typ = 'LINESTRING' or typ = 'MULTILINESTRING' THEN -- lineal
     --  A line can go in lineal or collection layer
     IF layer_info.feature_type != 4 and layer_info.feature_type != 2 THEN
       RAISE EXCEPTION
         'Layer "%" of topology "%" is %, cannot hold a lineal feature.',
         layer_info.layer_id, topology_info.name, layer_info.typename;
     END IF;
-  ELSIF ST_Dimension(ageom) = 2 THEN -- areal
+    tg := topology.CreateTopoGeom(atopology, 2, alayer);
+  ELSIF typ = 'POLYGON' OR typ = 'MULTIPOLYGON' THEN -- areal
     --  An area can go in areal or collection layer
     IF layer_info.feature_type != 4 and layer_info.feature_type != 3 THEN
       RAISE EXCEPTION
         'Layer "%" of topology "%" is %, cannot hold an areal feature.',
         layer_info.layer_id, topology_info.name, layer_info.typename;
     END IF;
+    tg := topology.CreateTopoGeom(atopology, 3, alayer);
   ELSE
       -- Should never happen
       RAISE EXCEPTION
         'Unexpected feature dimension %', ST_Dimension(ageom);
   END IF;
 
-  -- TODO: handle empty
+  -- Now that we have a topogeometry, we loop over components 
+  -- and add them to the definition of it. We add them as soon
+  -- as possible so that each element can further edit the
+  -- definition by splitting
+  FOR rec IN SELECT (ST_Dump(ageom)).geom LOOP
+    IF ST_IsEmpty(rec.geom) THEN
+      RAISE DEBUG 'Skipped empty component';
+    ELSIF ST_Dimension(rec.geom) = 0 THEN
+      sql := 'INSERT INTO ' || quote_ident(atopology)
+        || '.relation(topogeo_id, layer_id, element_type, element_id) SELECT '
+        || id(tg) || ', ' || alayer || ', 1, topogeo_addPoint('
+        || quote_literal(atopology) || ', '
+        || quote_literal(rec.geom::text) || '::geometry, ' || atolerance
+        || ');';
+      RAISE DEBUG '%', sql;
+      EXECUTE sql;
+    ELSIF ST_Dimension(rec.geom) = 1 THEN
+      sql := 'INSERT INTO ' || quote_ident(atopology)
+        || '.relation(topogeo_id, layer_id, element_type, element_id) SELECT '
+        || id(tg) || ', ' || alayer || ', 2, topogeo_addLineString('
+        || quote_literal(atopology) || ', '
+        || quote_literal(rec.geom::text) || '::geometry, ' || atolerance
+        || ');';
+      RAISE DEBUG '%', sql;
+      EXECUTE sql;
+    ELSIF ST_Dimension(rec.geom) = 2 THEN
+      sql := 'INSERT INTO ' || quote_ident(atopology)
+        || '.relation(topogeo_id, layer_id, element_type, element_id) SELECT '
+        || id(tg) || ', ' || alayer || ', 3, topogeo_addPolygon('
+        || quote_literal(atopology) || ', '
+        || quote_literal(rec.geom::text) || '::geometry, ' || atolerance
+        || ');';
+      RAISE DEBUG '%', sql;
+      EXECUTE sql;
+    ELSE
+      RAISE EXCEPTION 'Unexpected dimension % for component %', ST_Dimension(rec.geom), ST_AsText(rec.geom);
+    END IF;
+
+  END LOOP;
 
-  RAISE EXCEPTION 'toTopoGeometry not implemented yet';
+  RETURN tg;
 
 END
 $$
-LANGUAGE 'plpgsql' STABLE STRICT;
+LANGUAGE 'plpgsql' VOLATILE STRICT;
 -- }
index d011b308e586f111d0df5aa9f23cfb42d5fe7c42..4f5fe68dd258874a64a21f80b6c9e49d71e28f74 100644 (file)
@@ -41,7 +41,59 @@ select totopogeom('MULTIPOINT(0 0, 10 10)'::geometry, 'tt', 4); -- invalid (area
 select totopogeom('POLYGON((0 0, 10 10, 10 0, 0 0))'::geometry, 'tt', 1); -- invalid (puntal) layer
 select totopogeom('POLYGON((0 0, 10 10, 10 0, 0 0))'::geometry, 'tt', 3); -- invalid (lineal) layer
 
+-- Convert a point
+with inp as ( select 'POINT(0 0)' ::geometry as g)
+select St_AsText(g), ST_Equals(totopogeom(g, 'tt', 1)::geometry, g) from inp;
 
+-- Convert a line
+with inp as ( select 'LINESTRING(0 10, 10 10)' ::geometry as g)
+select St_AsText(g), ST_Equals(totopogeom(g, 'tt', 3)::geometry, g) from inp;
+
+-- Convert a polygon
+with inp as ( select
+'POLYGON((0 20, 10 20, 5 30, 0 20),(2 22, 8 22, 5 28, 2 22))'
+ ::geometry as g)
+select St_AsText(g), ST_Equals(totopogeom(g, 'tt', 4)::geometry, g) from inp;
+
+-- Convert a multipoint
+with inp as ( select 'MULTIPOINT((0 -10),(5 -10))' ::geometry as g)
+select St_AsText(g), ST_Equals(totopogeom(g, 'tt', 1)::geometry, g) from inp;
+
+-- Convert a multiline
+with inp as ( select 'MULTILINESTRING((-1 10, -10 10),(-10 8, -2 9))' ::geometry as g)
+select St_AsText(g), ST_Equals(totopogeom(g, 'tt', 3)::geometry, g) from inp;
+
+-- Convert a multipolygon
+with inp as ( select
+'MULTIPOLYGON(((100 20, 110 20, 105 30, 100 20),(102 22, 108 22, 105 28, 102 22)),((80 20, 90 20, 90 60, 80 20)))'
+ ::geometry as g)
+select St_AsText(g), ST_Equals(totopogeom(g, 'tt', 4)::geometry, g) from inp;
+
+-- Convert a collection
+with
+inp as ( select
+'GEOMETRYCOLLECTION(
+ POINT(-100 -100),
+ LINESTRING(-100 -90,-90 -90),
+ POLYGON((-100 -80,-90 -80,-95 -70,-100 -80),(-98 -78,-92 -78,-95 -72,-98 -78)),
+ MULTIPOINT(-100 -110,-95 -110),
+ LINESTRING EMPTY,
+ MULTILINESTRING((-101 -90,-110 -90),(-110 -92,-102 -91)),
+ MULTIPOLYGON(((0 -80,10 -80,5 -70,0 -80),(2 -78,8 -78,5 -72,2 -78)),((-20 -80,-10 -80,-10 -40,-20 -80)))
+)'
+ ::geometry as g),
+tg as ( select totopogeom(g, 'tt', 5) as g from inp )
+select St_AsText(inp.g), st_astext(tg.g::geometry) from inp, tg;
+
+
+-- Convert some empties
+SELECT ST_AsText(toTopoGeom('POINT EMPTY', 'tt', 1)::geometry);
+SELECT ST_AsText(toTopoGeom('MULTIPOINT EMPTY', 'tt', 1)::geometry);
+SELECT ST_AsText(toTopoGeom('LINESTRING EMPTY', 'tt', 3)::geometry);
+SELECT ST_AsText(toTopoGeom('MULTILINESTRING EMPTY', 'tt', 3)::geometry);
+SELECT ST_AsText(toTopoGeom('POLYGON EMPTY', 'tt', 4)::geometry);
+SELECT ST_AsText(toTopoGeom('MULTIPOLYGON EMPTY', 'tt', 4)::geometry);
+SELECT ST_AsText(toTopoGeom('GEOMETRYCOLLECTION EMPTY', 'tt', 5)::geometry);
 
 DROP TABLE tt.f_coll;
 DROP TABLE tt.f_areal;
index 8fbcabf77eab1761725a370e3324f4abb629d8f2..ce5d19a9da83b4cc701ba151b6c819da026d566c 100644 (file)
@@ -15,4 +15,18 @@ ERROR:  Layer "3" of topology "tt" is lineal, cannot hold a puntal feature.
 ERROR:  Layer "4" of topology "tt" is areal, cannot hold a puntal feature.
 ERROR:  Layer "1" of topology "tt" is puntal, cannot hold an areal feature.
 ERROR:  Layer "3" of topology "tt" is lineal, cannot hold an areal feature.
+POINT(0 0)|t
+LINESTRING(0 10,10 10)|t
+POLYGON((0 20,10 20,5 30,0 20),(2 22,8 22,5 28,2 22))|t
+MULTIPOINT(0 -10,5 -10)|t
+MULTILINESTRING((-1 10,-10 10),(-10 8,-2 9))|t
+MULTIPOLYGON(((100 20,110 20,105 30,100 20),(102 22,108 22,105 28,102 22)),((80 20,90 20,90 60,80 20)))|t
+GEOMETRYCOLLECTION(POINT(-100 -100),LINESTRING(-100 -90,-90 -90),POLYGON((-100 -80,-90 -80,-95 -70,-100 -80),(-98 -78,-92 -78,-95 -72,-98 -78)),MULTIPOINT(-100 -110,-95 -110),LINESTRING EMPTY,MULTILINESTRING((-101 -90,-110 -90),(-110 -92,-102 -91)),MULTIPOLYGON(((0 -80,10 -80,5 -70,0 -80),(2 -78,8 -78,5 -72,2 -78)),((-20 -80,-10 -80,-10 -40,-20 -80))))|GEOMETRYCOLLECTION(MULTIPOLYGON(((-100 -80,-95 -70,-90 -80,-100 -80),(-98 -78,-92 -78,-95 -72,-98 -78)),((0 -80,5 -70,10 -80,0 -80),(2 -78,8 -78,5 -72,2 -78)),((-20 -80,-10 -40,-10 -80,-20 -80))),MULTILINESTRING((-110 -92,-102 -91),(-101 -90,-110 -90),(-100 -90,-90 -90)),MULTIPOINT(-100 -110,-100 -100,-95 -110))
+POINT EMPTY
+POINT EMPTY
+LINESTRING EMPTY
+LINESTRING EMPTY
+POLYGON EMPTY
+POLYGON EMPTY
+GEOMETRYCOLLECTION EMPTY
 Topology 'tt' dropped