ST_MakePolygon
Name
ST_MakePolygon — Creates a Polygon from a shell and optional list of holes.
Synopsis
geometry
ST_MakePolygon
(
geometry
linestring
)
;
geometry
ST_MakePolygon
(
geometry
outerlinestring
, geometry[]
interiorlinestrings
)
;
Description
Creates a Polygon formed by the given shell and optional array of holes. Input geometries must be closed LineStrings (rings).
Variant 1: Accepts one shell LineString.
Variant 2: Accepts a shell LineString and an array of inner (hole) LineStrings. A geometry array can be constructed using the PostgreSQL array_agg(), ARRAY[] or ARRAY() constructs.
This function does not accept MultiLineStrings. Use ST_LineMerge to generate a LineString, or ST_Dump to extract LineStrings. |
This function supports 3d and will not drop the z-index.
Examples: Single input variant
Create a Polygon from a 2D LineString.
SELECT ST_MakePolygon( ST_GeomFromText('LINESTRING(75 29,77 29,77 29, 75 29)'));
Create a Polygon from an open LineString, using ST_StartPoint and ST_AddPoint to close it.
SELECT ST_MakePolygon( ST_AddPoint(foo.open_line, ST_StartPoint(foo.open_line)) ) FROM ( SELECT ST_GeomFromText('LINESTRING(75 29,77 29,77 29, 75 29)') As open_line) As foo;
Create a Polygon from a 3D LineString
SELECT ST_AsEWKT( ST_MakePolygon( 'LINESTRING(75.15 29.53 1,77 29 1,77.6 29.5 1, 75.15 29.53 1)')); st_asewkt ----------- POLYGON((75.15 29.53 1,77 29 1,77.6 29.5 1,75.15 29.53 1))
Create a Polygon from a LineString with measures
SELECT ST_AsEWKT( ST_MakePolygon( 'LINESTRINGM(75.15 29.53 1,77 29 1,77.6 29.5 2, 75.15 29.53 2)' )); st_asewkt ---------- POLYGONM((75.15 29.53 1,77 29 1,77.6 29.5 2,75.15 29.53 2))
Examples: Outer shell with inner holes variant
Create a donut Polygon with an extra hole
SELECT ST_MakePolygon( ST_ExteriorRing( ST_Buffer(ring.line,10)), ARRAY[ ST_Translate(ring.line, 1, 1), ST_ExteriorRing(ST_Buffer(ST_Point(20,20),1)) ] ) FROM (SELECT ST_ExteriorRing( ST_Buffer(ST_Point(10,10),10,10)) AS line ) AS ring;
Create a set of province boundaries with holes
representing lakes. The input is a table of
province Polygons/MultiPolygons and a table of water linestrings.
Lines forming lakes are determined by using
ST_IsClosed
.
The province linework is extracted by using
ST_Boundary
.
As required by
ST_MakePolygon
,
the boundary is forced to be a single LineString by using
ST_LineMerge
.
(However, note that if a province has more than one region or has islands
this will produce an invalid polygon.)
Using a LEFT JOIN ensures all provinces are included even if they have no lakes.
The CASE construct is used because passing a null array into ST_MakePolygon results in a NULL return value. |
SELECT p.gid, p.province_name, CASE WHEN array_agg(w.geom) IS NULL THEN p.geom ELSE ST_MakePolygon( ST_LineMerge(ST_Boundary(p.geom)), array_agg(w.geom)) END FROM provinces p LEFT JOIN waterlines w ON (ST_Within(w.geom, p.geom) AND ST_IsClosed(w.geom)) GROUP BY p.gid, p.province_name, p.geom;
Another technique is to utilize a correlated subquery and the ARRAY() constructor that converts a row set to an array.
SELECT p.gid, p.province_name, CASE WHEN EXISTS( SELECT w.geom FROM waterlines w WHERE ST_Within(w.geom, p.geom) AND ST_IsClosed(w.geom)) THEN ST_MakePolygon( ST_LineMerge(ST_Boundary(p.geom)), ARRAY( SELECT w.geom FROM waterlines w WHERE ST_Within(w.geom, p.geom) AND ST_IsClosed(w.geom))) ELSE p.geom END AS geom FROM provinces p;