AS 'MODULE_PATHNAME', 'LWGEOM_dump_rings'
LANGUAGE 'C' IMMUTABLE STRICT;
+-----------------------------------------------------------------------
+-- ST_DumpPoints()
+-----------------------------------------------------------------------
+-- This function mimicks that of ST_Dump for collections, but this function
+-- that returns a path and all the points that make up a particular geometry.
+-- This current implementation in plpgsql does not scale very well at all.
+-- and should be ported to C at some point.
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION ST_DumpPoints(the_geom geometry, cur_path integer[]) RETURNS SETOF geometry_dump AS $$
+DECLARE
+ tmp geometry_dump;
+ tmp2 geometry_dump;
+ nb_points integer;
+ nb_geom integer;
+ i integer;
+ j integer;
+ g geometry;
+
+BEGIN
+
+ RAISE DEBUG '%,%', cur_path, ST_GeometryType(the_geom);
+
+ -- 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
+
+ i = 1;
+ FOR tmp2 IN SELECT (ST_Dump(the_geom)).* LOOP
+
+ FOR tmp IN SELECT * FROM ST_DumpPoints(tmp2.geom, cur_path || tmp2.path) LOOP
+ RETURN NEXT tmp;
+ END LOOP;
+ i = i + 1;
+
+ END LOOP;
+
+ RETURN;
+ END IF;
+
+
+ -- Special case (POLYGON) : return the points of the rings of a polygon
+ IF (ST_GeometryType(the_geom) = 'ST_Polygon') THEN
+
+ FOR tmp IN SELECT * FROM ST_DumpPoints(ST_ExteriorRing(the_geom), cur_path || ARRAY[1]) LOOP
+ RETURN NEXT tmp;
+ END LOOP;
+
+ j := ST_NumInteriorRings(the_geom);
+ FOR i IN 1..j LOOP
+ FOR tmp IN SELECT * FROM ST_DumpPoints(ST_InteriorRingN(the_geom, i), cur_path || ARRAY[i+1]) LOOP
+ RETURN NEXT tmp;
+ END LOOP;
+ 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 || ARRAY[i];
+ tmp.geom := ST_PointN(the_geom, i);
+ RETURN NEXT tmp;
+ END LOOP;
+
+END
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION ST_DumpPoints(geometry) RETURNS SETOF geometry_dump AS $$
+ SELECT * FROM ST_DumpPoints($1, NULL);
+$$ LANGUAGE SQL;
+
+
------------------------------------------------------------------------
--
--- /dev/null
+SELECT path, ST_AsText(geom)
+FROM (
+ SELECT (ST_DumpPoints(g.geom)).*
+ FROM
+ (SELECT
+ 'POINT (0 9)'::geometry AS geom
+ ) AS g
+ ) j;
+
+SELECT path, ST_AsText(geom)
+FROM (
+ SELECT (ST_DumpPoints(g.geom)).*
+ FROM
+ (SELECT
+ 'LINESTRING (
+ 0 0,
+ 0 9,
+ 9 9,
+ 9 0,
+ 0 0
+ )'::geometry AS geom
+ ) AS g
+ ) j;
+
+SELECT path, ST_AsText(geom)
+FROM (
+ SELECT (ST_DumpPoints(g.geom)).*
+ FROM
+ (SELECT
+ 'POLYGON ((
+ 0 0,
+ 0 9,
+ 9 9,
+ 9 0,
+ 0 0
+ ))'::geometry AS geom
+ ) AS g
+ ) j;
+
+
+SELECT path, ST_AsText(geom)
+FROM (
+ SELECT (ST_DumpPoints(g.geom)).*
+ FROM
+ (SELECT
+ 'POLYGON ((
+ 0 0,
+ 0 9,
+ 9 9,
+ 9 0,
+ 0 0
+ ), (
+ 1 1,
+ 1 3,
+ 3 2,
+ 1 1
+ ), (
+ 7 6,
+ 6 8,
+ 8 8,
+ 7 6
+ ))'::geometry AS geom
+ ) AS g
+ ) j;
+
+SELECT path, ST_AsText(geom)
+FROM (
+ SELECT (ST_DumpPoints(g.geom)).*
+ FROM
+ (SELECT
+ 'MULTIPOLYGON (((
+ 0 0,
+ 0 3,
+ 4 3,
+ 4 0,
+ 0 0
+ )), ((
+ 2 4,
+ 1 6,
+ 4 5,
+ 2 4
+ ), (
+ 7 6,
+ 6 8,
+ 8 8,
+ 7 6
+ )))'::geometry AS geom
+ ) AS g
+ ) j;
+
+SELECT path, ST_AsText(geom)
+FROM (
+ SELECT (ST_DumpPoints(g.geom)).*
+ FROM
+ (SELECT
+ 'GEOMETRYCOLLECTION(
+ POINT(99 98),
+ LINESTRING(1 1, 3 3),
+ POLYGON((0 0, 0 1, 1 1, 0 0)),
+ POLYGON((0 0, 0 9, 9 9, 9 0, 0 0), (5 5, 5 6, 6 6, 5 5)),
+ MULTIPOLYGON(((0 0, 0 9, 9 9, 9 0, 0 0), (5 5, 5 6, 6 6, 5 5)))
+ )'::geometry AS geom
+ ) AS g
+ ) j;