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
--
- -- 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;
-- }
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;
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