From: Sandro Santilli Date: Wed, 25 Apr 2012 19:41:33 +0000 (+0000) Subject: Fix toTopoGeom handling of duplicated primitives (#1790) X-Git-Tag: 2.0.1~108 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b742fe8cfa0b2d8668c1518c6d33658e0f0ca756;p=postgis Fix toTopoGeom handling of duplicated primitives (#1790) git-svn-id: http://svn.osgeo.org/postgis/trunk@9675 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index ecd013c97..4b27a5fd6 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,7 @@ PostGIS 2.0.1 - #1763, topology.toTopoGeom use with custom search_path. - #1755, ST_GeographyFromText support for higher dimensions. - #1782, fix spatial reference string handling in raster. + - #1790, fix toTopoGeom handling of duplicated primitives. * Enhancements * diff --git a/topology/sql/topogeometry/totopogeom.sql.in.c b/topology/sql/topogeometry/totopogeom.sql.in.c index 86d2e2307..40efd8da1 100644 --- a/topology/sql/topogeometry/totopogeom.sql.in.c +++ b/topology/sql/topogeometry/totopogeom.sql.in.c @@ -114,44 +114,34 @@ BEGIN 'Unexpected feature dimension %', ST_Dimension(ageom); END IF; - -- Now that we have a topogeometry, we loop over components + -- Now that we have a topogeometry, we loop over distinct 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, topology.topogeo_addPoint(' - || quote_literal(atopology) || ', ' - || quote_literal(rec.geom::text) || '::geometry, ' || tolerance - || ');'; - --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, topology.topogeo_addLineString(' - || quote_literal(atopology) || ', ' - || quote_literal(rec.geom::text) || '::geometry, ' || tolerance - || ');'; - --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, topology.topogeo_addPolygon(' - || quote_literal(atopology) || ', ' - || quote_literal(rec.geom::text) || '::geometry, ' || tolerance - || ');'; - --RAISE DEBUG '%', sql; - EXECUTE sql; - ELSE - RAISE EXCEPTION 'Unexpected dimension % for component %', ST_Dimension(rec.geom), ST_AsText(rec.geom); - END IF; - + FOR rec IN SELECT DISTINCT id(tg), alayer as lyr, + CASE WHEN ST_Dimension(geom) = 0 THEN 1 + WHEN ST_Dimension(geom) = 1 THEN 2 + WHEN ST_Dimension(geom) = 2 THEN 3 + END as type, + CASE WHEN ST_Dimension(geom) = 0 THEN + topology.topogeo_addPoint(atopology, geom, tolerance) + WHEN ST_Dimension(geom) = 1 THEN + topology.topogeo_addLineString(atopology, geom, tolerance) + WHEN ST_Dimension(geom) = 2 THEN + topology.topogeo_addPolygon(atopology, geom, tolerance) + END as primitive + FROM (SELECT (ST_Dump(ageom)).geom) as f + WHERE NOT ST_IsEmpty(geom) + LOOP + -- TODO: consider use a single INSERT statement for the whole thing + sql := 'INSERT INTO ' || quote_ident(atopology) + || '.relation(topogeo_id, layer_id, element_type, element_id) VALUES (' + || rec.id || ',' || rec.lyr || ',' || rec.type + || ',' || rec.primitive || ')'; +#ifdef POSTGIS_TOPOLOGY_DEBUG + RAISE DEBUG '%', sql; +#endif + EXECUTE sql; END LOOP; RETURN tg; diff --git a/topology/test/regress/totopogeom.sql b/topology/test/regress/totopogeom.sql index d6d5b06bf..e2ee7561d 100644 --- a/topology/test/regress/totopogeom.sql +++ b/topology/test/regress/totopogeom.sql @@ -137,6 +137,33 @@ tg as ( select topology.totopogeom(g, 'tt', 1) as g from inp ) select 'custom_search_path', ST_HausdorffDistance(inp.g, tg.g::geometry) FROM inp, tg; reset search_path; +-- http://trac.osgeo.org/postgis/ticket/1790 +UPDATE topology.topology SET precision=0 WHERE name = 'tt'; +with inp as ( select +'GEOMETRYCOLLECTION( + POINT(200 200), + POINT(200 200) +)' + ::geometry as g), +tg as ( select totopogeom(g, 'tt', 5) as g from inp ) +select '#1790.1', ST_HausdorffDistance(inp.g, tg.g::geometry), ST_HausdorffDistance(tg.g::geometry, inp.g) FROM inp, tg; +with inp as ( select +'GEOMETRYCOLLECTION( + LINESTRING(300 300, 310 300), + LINESTRING(300 300, 310 300) +)' + ::geometry as g), +tg as ( select totopogeom(g, 'tt', 5) as g from inp ) +select '#1790.2', ST_HausdorffDistance(inp.g, tg.g::geometry), ST_HausdorffDistance(tg.g::geometry, inp.g) FROM inp, tg; +with inp as ( select +'GEOMETRYCOLLECTION( + POLYGON((400 400, 450 450, 500 400, 400 400)), + POLYGON((400 400, 450 450, 500 400, 400 400)) +)' + ::geometry as g), +tg as ( select totopogeom(g, 'tt', 5) as g from inp ) +select '#1790.3', ST_HausdorffDistance(inp.g, tg.g::geometry), ST_HausdorffDistance(tg.g::geometry, inp.g) FROM inp, tg; + DROP TABLE tt.f_coll; DROP TABLE tt.f_areal; diff --git a/topology/test/regress/totopogeom_expected b/topology/test/regress/totopogeom_expected index 92f08434d..c04be1421 100644 --- a/topology/test/regress/totopogeom_expected +++ b/topology/test/regress/totopogeom_expected @@ -33,4 +33,7 @@ tolerance_1|0.5 tolerance_topo_1|0.5 tolerance_0|0 custom_search_path|0 +#1790.1|0|0 +#1790.2|0|0 +#1790.3|0|0 Topology 'tt' dropped