[postgis-users] Points from Polygon
Mike Toews
mwtoews at sfu.ca
Sat Jun 27 18:23:24 PDT 2009
tommy408 wrote:
> How can I extract points from all the vertex of a polygon?
>
> I see there are ST_NPoints and ST_PointN for linestring. But nothing for
> polygons. Maybe convert polygon to linestring then linestring to points?
>
I had the same requirement a few weeks ago, and it turns out there is
not built-in function (yet), so you need to write your own function.
Here is what I came up with. It returns a geometry_dump data type, which
has members 'part' and 'geom'. It is similar to ST_Dump(), but returns
points. I have Postgres 8.3, which means that I need to wrap one
set-returning function in another so I can use the function on the
left-side of the FROM in an SQL statement. (This is a non-issue with
8.4). It works with POLYGON and MULTIPOLYGON geometry types. Also, my
solution only returns points for boundary polygons (not inner
rings/islands, etc.):
CREATE OR REPLACE FUNCTION st_dumppoints_plpgsql(geometry)
RETURNS SETOF geometry_dump AS
$BODY$DECLARE
m integer;
g geometry;
n integer;
p geometry_dump%ROWTYPE;
BEGIN
IF GeometryType($1) LIKE 'MULTI%' THEN
FOR m IN SELECT generate_series(1, ST_NumGeometries($1)) LOOP
p.path[1] := m; -- use to store Multipolygon number
g := ST_Boundary(ST_GeometryN($1, m));
FOR n IN SELECT generate_series(1, ST_NumPoints(g) - 1) LOOP
p.path[2] := n; -- use to store Point number
p.geom := ST_PointN(g, n);
RETURN NEXT p;
END LOOP;
END LOOP;
ELSE -- It is not a MULTI- geometry
g := ST_Boundary($1);
FOR n IN SELECT generate_series(1, ST_NumPoints(g) - 1) LOOP
p.path[1] := n; -- use to store Point number
p.geom := ST_PointN(g, n);
RETURN NEXT p;
END LOOP;
END IF;
RETURN;
END;$BODY$
LANGUAGE 'plpgsql' IMMUTABLE STRICT
COST 100
ROWS 1000;
CREATE OR REPLACE FUNCTION st_dumppoints(geometry)
RETURNS SETOF geometry_dump AS
'SELECT * FROM ST_DumpPoints_plpgsql($1);'
LANGUAGE 'sql' IMMUTABLE STRICT
COST 100
ROWS 1000;
--Mike
More information about the postgis-users
mailing list