I have a 3D MultiLineString (roughly ~2'400 segments) in PostGIS forming kind of a V-shape (blue line on the image bellow) which I need to close (e.g. with the desired green closing straight line) in order to form a Polygon:
I found ST_MakePolygon which looked promising, but it raises an error:
ERROR: Shell is not a line
SQL state: XX000
This is certainly because the line is actually of type ST_MultiLineString.
So I tried to figure out a way to convert this to a true LineString but the usage of ST_LineMerge doesn't seem to have any effect on the resulting geometry type:
SELECT ST_GeometryType(ST_LineMerge(geom)) AS geomtype;
geomtype
ST_MultiLineString
(1 row)
Any ideas on how to succeed ?
The line should be connected, but based on these observations, it's apparently not.
The differences (i.e. gaps?), if existing, should be due to numerical approximations.
The original geometry is valid (ST_IsValid returns true).
EDIT:
I confirm the gaps (in the blue multilinestring) due to computational issues, e.g. with these two lines which should be connected with their first respective points:
MULTILINESTRING Z (( 2702603.3370974000 1253383.3314513000 607.1897036409243, <POINT_B> ))
MULTILINESTRING Z (( 2702603.3370974010 1253383.3314512996 607.1897036407847, <POINT_D> ))
Those are two original parts which are aggregated to actually compose the blue multilinestring.
Note: I appended trailing zeroes in coordinates to keep numbers vertically aligned for a better visual perception but they were not present in the query results.
EDIT 2:
ST_MakePolygon() doesn't seem to work on a mathematically perfectly connected multilinestring, but it actually throws another error:
SELECT
ST_MakePolygon(
ST_LineMerge(
ST_GeomFromText(
'MULTILINESTRING(
(2702703.3370974000 1253383.3314513000 607.1897036409243,
2702779.0888727466 1253368.1777454934 596.9877159267046),
(2702703.3370974000 1253383.3314513000 607.1897036409243,
2702638.0847548526 1253396.2982941763 613.5631635554059),
(2702638.0847548526 1253396.2982941763 613.5631635554059,
2702678.5554887933 1253321.3220054788 609.5533124641558),
(2702678.5554887933 1253321.3220054788 609.5533124641558,
2702682.5996487933 1253250.0846754788 601.2201976641112)
)',
2056
)
)
)
This raises:
ERROR: lwpoly_from_lwlines: shell must be closed
SQL state: XX000
And the ST_ConcaveHull(), as suggested by @hbg in the comment below, is not working either:
SELECT
ST_ConcaveHull(
ST_LineMerge(
ST_GeomFromText(
'MULTILINESTRING(
(2702703.3370974000 1253383.3314513000 607.1897036409243,
2702779.0888727466 1253368.1777454934 596.9877159267046),
(2702703.3370974000 1253383.3314513000 607.1897036409243,
2702638.0847548526 1253396.2982941763 613.5631635554059),
(2702638.0847548526 1253396.2982941763 613.5631635554059,
2702678.5554887933 1253321.3220054788 609.5533124641558),
(2702678.5554887933 1253321.3220054788 609.5533124641558,
2702682.5996487933 1253250.0846754788 601.2201976641112)
)',
2056
)
)
,0.1
)
which raises:
ERROR: Cannot ST_Collect geometries with differing dimensionality.
CONTEXT: PL/pgSQL function _st_concavehull(geometry) line 67 at assignment
PL/pgSQL function st_concavehull(geometry,double precision,boolean) line 152 at assignment
PL/pgSQL assignment "var_tempgeom := public.ST_Buffer(public.ST_ConcaveHull(var_geoms[1],least(param_pctconvex + param_pctconvex/var_div),true),var_buf, 'quad_segs=2')"
PL/pgSQL function st_concavehull(geometry,double precision,boolean) line 114 at assignment
PL/pgSQL assignment "var_tempgeom := public.ST_Buffer(public.ST_ConcaveHull(var_geoms[1],least(param_pctconvex + param_pctconvex/var_div),true),var_buf, 'quad_segs=2')"
PL/pgSQL function st_concavehull(geometry,double precision,boolean) line 114 at assignment
PL/pgSQL assignment "var_tempgeom := public.ST_Buffer(public.ST_ConcaveHull(var_geoms[1],least(param_pctconvex + param_pctconvex/var_div),true),var_buf, 'quad_segs=2')"
...the two previous lines being repeated multiple times.
PL/pgSQL function st_concavehull(geometry,double precision,boolean) line 114 at assignment
SQL state: XX000
Notice: the same errors on the two last examples also occur with PG 14 + PostGIS 3.3.0 (docker image: postgis/postgis:14-3.3.0rc2-alpine based on GEOS="3.10.2-CAPI-1.16.0")
PostGIS 3.3.1 with the very latest PG 15 (beta4) is still based on GEOS 3.10.2:
POSTGIS="3.3.1 0" [EXTENSION] PGSQL="150" GEOS="3.10.2-CAPI-1.16.0".
Version info:
PostgreSQL 14.0 (Debian 14.0-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
POSTGIS="3.1.4 ded6c34" [EXTENSION] PGSQL="140" GEOS="3.9.0-CAPI-1.16.2" SFCGAL="1.3.8" PROJ="7.2.1" LIBXML="2.9.10" LIBJSON="0.15" LIBPROTOBUF="1.3.3" WAGYU="0.5.0 (Internal)" TOPOLOGY



ST_LineMergeaccepted adistanceToleranceparameter so it could snap close endpoints together. – dr_jts Sep 09 '22 at 19:36ST_ConcaveHullhas been improved in PostGIS 3.3/GEOS 3.11, so you could try that. While it may seem odd, theoretically it could provide a polygon that respects the input line if the tolerance value is small. – dr_jts Sep 10 '22 at 18:08ST_SnapToGridto remove the excess precision causing the discrepancy between endpoints. – dr_jts Sep 10 '22 at 18:10ST_ConcaveHull()trick and its results. @dr_jts I also tried PostGIS 3.3.0 but the errors persist. See last update in main post. – swiss_knight Sep 10 '22 at 18:28ST_MakePolygondoes require rings to be closed (have duplicate start and end points. – dr_jts Sep 10 '22 at 19:04