PostGIS
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 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.
|
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;