On 07/31/09 20:20, Kevin Neufeld wrote: > Unfortunately, I think your solution is overly simplistic.
Of course, it is a little function dedicated to a specific use case for my program. > I think the > community is after something that mimics the ST_Dump and ST_DumpRings > functionality. I agree. > ie. > SELECT (ST_Dump('MULTILINESTRING((0 0, 1 1),(2 2, 3 3))'::geometry)).*; > path | geom > ------+------------------------------------------------------------------------------------ > > {1} | > 01020000000200000000000000000000000000000000000000000000000000F03F000000000000F03F > > {2} | > 0102000000020000000000000000000040000000000000004000000000000008400000000000000840 > > (2 rows) > > In order to extract all the points from every geometry in a table we > would need to be able to have this example query work that also returns > a SETOF geometry_dump: > > SELECT (ST_DumpPoints(the_geom)).* > FROM my_spatial_table; > > The path portion of the geometry_dump datatype is important because > users know the index of POINT in the geometry. It'll be possible then, > for example, to extract all but the endpoints. Additionally, users > could group the points back together to rebuild the original geometry > from whence they came. > > Also, your function would need to be a lot more robust (ie. ideally, > able to accept all geometry types, POINT, LINESTRING, MULTIPOLYGON, > GEOMETRYCOLLECTION, etc). > > I agree, the st_dump code does indeed look a little overwhelming. I > don't think we're tied to having the function written in C (there are > many plpgsql functions in PostGIS). The only problem with plpgsql functions is that in versions prior to PostgreSQL 8.4 you cannot mimic the 'RETURN SETOF' of the C. [1] This can be solved by adding a sql function wrapper though. [1] http://www.depesz.com/index.php/2008/11/03/waiting-for-84-pl-srf-functions-in-selects/ > If you think you can come up with > something that meets the desired specifications, please, by all means, > feel free to propose something to the postgis-devel list. We'd love the > help! Here is a first draft (code is attached). The function handles any kind of geometries and path. - POINT > # SELECT path,astext(geom) FROM (SELECT (my_ST_DumpPoints('POINT(0 0)')).*) > AS foo; > path | astext > ------+------------ > {1} | POINT(0 0) - MULTIPOINT > # SELECT path,astext(geom) FROM (SELECT (my_ST_DumpPoints('MULTIPOINT((0 0), > (1 1), (2 2))')).*) AS foo; > path | astext > -------+------------ > {1,1} | POINT(0 0) > {2,1} | POINT(1 1) > {3,1} | POINT(2 2) - LINESTRING > # SELECT path,astext(geom) FROM (SELECT (my_ST_DumpPoints('LINESTRING(0 3, 1 > 4, 1 5)')).*) AS foo; > path | astext > ------+------------ > {1} | POINT(0 3) > {2} | POINT(1 4) > {3} | POINT(1 5) - CIRCULARSTRING > # SELECT path,astext(geom) FROM (SELECT (my_ST_DumpPoints('CIRCULARSTRING(0 > 3, 1 4, 1 5)')).*) AS foo; > path | astext > ------+------------ > {1} | POINT(0 3) > {2} | POINT(1 4) > {3} | POINT(1 5) - MULTILINESTRING > # SELECT path,astext(geom) FROM (SELECT (my_ST_DumpPoints('MULTILINESTRING((0 > 3, 1 4, 1 5),(10 10, 15 10, 42 42))')).*) AS foo; > path | astext > -------+-------------- > {1,1} | POINT(0 3) > {1,2} | POINT(1 4) > {1,3} | POINT(1 5) > {2,1} | POINT(10 10) > {2,2} | POINT(15 10) > {2,3} | POINT(42 42) - POLYGON > # SELECT path,astext(geom) FROM (SELECT (my_ST_DumpPoints('POLYGON((0 0, 50 > 50, 42 42, 0 0))')).*) AS foo; > path | astext > ------+-------------- > {1} | POINT(0 0) > {2} | POINT(50 50) > {3} | POINT(42 42) > {4} | POINT(0 0) - MULTIPOLYGON > # SELECT path,astext(geom) FROM (SELECT (my_ST_DumpPoints('MULTIPOLYGON(((0 > 0, 1 1, 2 2, 0 0)), ((50 50, 40 40, 30 30, 50 50)))')).*) AS foo; > path | astext > -------+-------------- > {1,1} | POINT(0 0) > {1,2} | POINT(1 1) > {1,3} | POINT(2 2) > {1,4} | POINT(0 0) > {2,1} | POINT(50 50) > {2,2} | POINT(40 40) > {2,3} | POINT(30 30) > {2,4} | POINT(50 50) - GEOMETRYCOLLECTION > # SELECT path,astext(geom) FROM (SELECT > (my_ST_DumpPoints('GEOMETRYCOLLECTION(POINT(0 0), POLYGON((10 10, 20 10, 20 > 20, 10 10)))')).*) AS foo; > path | astext > -------+-------------- > {1,1} | POINT(0 0) > {2,1} | POINT(10 10) > {2,2} | POINT(20 10) > {2,3} | POINT(20 20) > {2,4} | POINT(10 10) -- yabo
CREATE FUNCTION _my_ST_DumpPoints(the_geom geometry, cur_path integer[]) RETURNS SETOF geometry_dump AS $$ DECLARE tmp geometry_dump; nb_points integer; nb_geom integer; BEGIN -- Special case (POLYGON) : return the points of the exterior ring of a polygon IF (ST_GeometryType(the_geom) = 'ST_Polygon') THEN -- Support PostgreSQL < 8.4 FOR tmp IN SELECT * FROM _my_ST_DumpPoints(ST_ExteriorRing(the_geom), cur_path) LOOP RETURN NEXT tmp; END LOOP; -- PostgreSQL 8.4 required -- RETURN QUERY (SELECT * FROM _my_ST_DumpPoints(ST_ExteriorRing(the_geom), NULL)); RETURN; END IF; -- Special case (MULTI* OR GEOMETRYCOLLECTION) : iterate and return the DumpPoints of the geometries SELECT ST_NumGeometries(the_geom) INTO nb_geom; IF (nb_geom IS NOT NULL) THEN FOR i IN 1..nb_geom LOOP -- Support PostgreSQL < 8.4 FOR tmp IN SELECT * FROM _my_ST_DumpPoints(ST_GeometryN(the_geom, i), cur_path || ARRAY[i]) LOOP RETURN NEXT tmp; END LOOP; -- PostgreSQL 8.4 required -- RETURN QUERY (SELECT * FROM _my_ST_DumpPoints(ST_GeometryN(the_geom, i), cur_path || ARRAY(i))); END LOOP; RETURN; END IF; -- Special case (POINT) : return the point IF (ST_GeometryType(the_geom) = 'ST_Point') THEN tmp.path = cur_path || ARRAY[1]; tmp.geom = the_geom; RETURN NEXT tmp; RETURN; END IF; -- Use ST_NumPoints rather than ST_NPoints to have a NULL value if the_geom isn't -- a LINESTRING or CIRCULARSTRING. SELECT ST_NumPoints(the_geom) INTO nb_points; -- This should never happen IF (nb_points IS NULL) THEN RAISE EXCEPTION 'Unexpected error while dumping geometry %', ST_AsText(the_geom); END IF; FOR i IN 1..nb_points LOOP tmp.path = cur_path || i; tmp.geom := ST_PointN(the_geom, i); RETURN NEXT tmp; END LOOP; END $$ LANGUAGE plpgsql; CREATE FUNCTION my_ST_DumpPoints(geometry) RETURNS SETOF geometry_dump AS $$ SELECT * FROM _my_ST_DumpPoints($1, NULL); $$ LANGUAGE SQL;
_______________________________________________ postgis-users mailing list postgis-users@postgis.refractions.net http://postgis.refractions.net/mailman/listinfo/postgis-users