[SCM] PostGIS branch master updated. 3.7.0alpha1-86-g63345d444
git at osgeo.org
git at osgeo.org
Thu Jul 9 03:46:13 PDT 2026
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".
The branch, master has been updated
via 63345d444bdb865524444eb0f4a4189a0890cf0a (commit)
via 09f9558ae04577e6277b3c1c30cbb8921ea58a71 (commit)
via 9c931e6fcdcf78a5d605a0d445b4a51564f78ff5 (commit)
via ca3323d8c748dd806bab188028bb61c5f67b39af (commit)
from ec3216f2897fa8dccf7db5750e38653f9b012261 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 63345d444bdb865524444eb0f4a4189a0890cf0a
Merge: ec3216f28 09f9558ae
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Thu Jul 9 14:11:48 2026 +0400
Merge pull request #1160 from Komzpa/codex/ci-wrapx-collection-output
Stabilize GEOS main linework handling
commit 09f9558ae04577e6277b3c1c30cbb8921ea58a71
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Thu Jul 9 11:33:15 2026 +0400
Keep manual examples stable across GEOS linework merging
Use disjoint lines in the ST_Union array example and avoid a vertex
inside a straight shared stretch in the ST_SharedPaths examples, so
the documented outputs are identical across GEOS versions. Document
that ST_SharedPaths segmentation may vary with the GEOS version.
diff --git a/doc/reference_overlay.xml b/doc/reference_overlay.xml
index 64a20bbf2..8e96c75bf 100644
--- a/doc/reference_overlay.xml
+++ b/doc/reference_overlay.xml
@@ -1056,9 +1056,9 @@ FROM (
<para>This example unions an array of linestrings.</para>
<programlisting>SELECT ST_AsText(ST_Union(ARRAY[
ST_GeomFromText('LINESTRING(1 2, 3 4)'),
- ST_GeomFromText('LINESTRING(3 4, 4 5)')
+ ST_GeomFromText('LINESTRING(4 5, 5 6)')
])) As wktunion;</programlisting>
-<screen>MULTILINESTRING((1 2,3 4),(3 4,4 5))</screen>
+<screen>MULTILINESTRING((1 2,3 4),(4 5,5 6))</screen>
</refsection>
<refsection>
<title>See Also</title>
diff --git a/doc/reference_processing.xml b/doc/reference_processing.xml
index 72e46b615..ffa35213f 100644
--- a/doc/reference_processing.xml
+++ b/doc/reference_processing.xml
@@ -2596,6 +2596,8 @@ FROM (SELECT ST_Polygonize(geom_4269) AS polycoll
</refsection>
<refsection>
<title>Examples: Finding shared paths</title>
+ <para>Adjacent shared path segments may be returned as separate or merged LineStrings
+ depending on the GEOS version.</para>
<informaltable>
<tgroup cols="1">
<tbody>
@@ -2622,11 +2624,11 @@ FROM (SELECT ST_Polygonize(geom_4269) AS polycoll
<programlisting>
SELECT ST_AsText(ST_SharedPaths(ST_GeomFromText('MULTILINESTRING((26 125,26 200,126 200,126 125,26 125),
(51 150,101 150,76 175,51 150))'),
- ST_GeomFromText('LINESTRING(151 100,126 156.25,126 125,90 161, 76 175)')
+ ST_GeomFromText('LINESTRING(151 100,126 156.25,126 125,101 150, 76 175)')
)
)</programlisting>
<screen>GEOMETRYCOLLECTION(MULTILINESTRING((126 156.25,126 125),
- (101 150,90 161),(90 161,76 175)),MULTILINESTRING EMPTY)</screen>
+ (101 150,76 175)),MULTILINESTRING EMPTY)</screen>
</para>
</entry>
</row>
@@ -2636,13 +2638,13 @@ FROM (SELECT ST_Polygonize(geom_4269) AS polycoll
<lineannotation>
same example but linestring orientation flipped
</lineannotation>
-SELECT ST_AsText(ST_SharedPaths(ST_GeomFromText('LINESTRING(76 175,90 161,126 125,126 156.25,151 100)'),
+SELECT ST_AsText(ST_SharedPaths(ST_GeomFromText('LINESTRING(76 175,101 150,126 125,126 156.25,151 100)'),
ST_GeomFromText('MULTILINESTRING((26 125,26 200,126 200,126 125,26 125),
(51 150,101 150,76 175,51 150))')
)
)</programlisting>
<screen>GEOMETRYCOLLECTION(MULTILINESTRING EMPTY,
-MULTILINESTRING((76 175,90 161),(90 161,101 150),(126 125,126 156.25)))</screen>
+MULTILINESTRING((76 175,101 150),(126 125,126 156.25)))</screen>
</para>
</entry>
</row>
commit 9c931e6fcdcf78a5d605a0d445b4a51564f78ff5
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Thu Jul 9 11:33:15 2026 +0400
Fix GEOS version parser in wrapx regression
A stray ']' made the regexp never match, so the GEOS >= 3.15
expected outputs were never selected.
diff --git a/regress/core/wrapx.sql b/regress/core/wrapx.sql
index 321958d52..b35504961 100644
--- a/regress/core/wrapx.sql
+++ b/regress/core/wrapx.sql
@@ -15,7 +15,7 @@ $$ LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION geos_version()
RETURNS integer AS $$
SELECT (matches[1]::integer * 100) + matches[2]::integer
- FROM regexp_match(postgis_geos_version(), E'^([0-9]+)]\\.([0-9]+)') AS matches;
+ FROM regexp_match(postgis_geos_version(), E'^([0-9]+)\\.([0-9]+)') AS matches;
$$ LANGUAGE 'sql' IMMUTABLE;
commit ca3323d8c748dd806bab188028bb61c5f67b39af
Author: Darafei Praliaskouski <me at komzpa.net>
Date: Thu Jul 9 11:33:15 2026 +0400
Preserve topology overlay junctions under GEOS >= 3.15 line merging
GEOS >= 3.15 returns overlay output line-merged, hiding the junctions
between the shared and non-shared linework of a new line inside line
interiors. Collect the crossing points and the mod-2 boundary of the
shared linework from the intersection, and re-split the noded line at
them: a no-op with older GEOS, which keeps them as component
boundaries.
Assert edge count instead of edge ids in the snap regression: the
final topology is identical but edge id assignment depends on GEOS
overlay output ordering.
References https://github.com/postgis/postgis/pull/1160
diff --git a/NEWS b/NEWS
index 4fa4d414c..d101510e3 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ To take advantage of all postgis_sfcgal extension features SFCGAL 2.3+ is needed
* Bug Fixes *
+ - GH-1160, [topology] Preserve overlay intersection boundaries when
+ noding lines with GEOS main (Darafei Praliaskouski)
- #6093, Fix SQL generation on ppc64el when NURBS comments are
preprocessed with AltiVec vector macros (Darafei Praliaskouski)
- #6094, [upgrade] Avoid legacy string literal warnings in downgrade checks
diff --git a/liblwgeom/topo/lwgeom_topo.c b/liblwgeom/topo/lwgeom_topo.c
index b119d5dae..a8d00c108 100644
--- a/liblwgeom/topo/lwgeom_topo.c
+++ b/liblwgeom/topo/lwgeom_topo.c
@@ -7379,6 +7379,57 @@ _lwt_split_by_nodes(const LWGEOM *g, const LWGEOM *nodes)
return bg;
}
+/*
+ * Compute the junction points between the overlay intersection linework
+ * (shared paths and crossings between the noded line and nearby edges)
+ * and the rest of the noded line: the 0-dimensional intersection
+ * components plus the mod-2 boundary of the 1-dimensional ones.
+ *
+ * These junctions must become topology nodes. GEOS >= 3.15 returns
+ * overlay output line-merged, which would otherwise hide them inside
+ * line interiors. Older GEOS keeps them as boundaries of the overlay
+ * output components, making a split at them a no-op.
+ *
+ * Returns a MULTIPOINT.
+ */
+static LWGEOM *
+_lwt_overlay_split_points(const LWGEOM *xset)
+{
+ LWGEOM *multi = lwgeom_as_multi(xset);
+ LWCOLLECTION *xcol = lwgeom_as_lwcollection(multi);
+ LWCOLLECTION *epoints = lwcollection_extract(xcol, POINTTYPE);
+ LWCOLLECTION *points = lwcollection_construct_empty(MULTIPOINTTYPE, xset->srid,
+ FLAGS_GET_Z(xset->flags), FLAGS_GET_M(xset->flags));
+ LWCOLLECTION *lines = lwcollection_extract(xcol, LINETYPE);
+ LWGEOM *bnd = lwgeom_boundary(lwcollection_as_lwgeom(lines));
+ uint32_t i;
+
+ for (i = 0; i < epoints->ngeoms; i++)
+ lwcollection_add_lwgeom(points, lwgeom_clone_deep(epoints->geoms[i]));
+
+ if (bnd)
+ {
+ LWCOLLECTION *bcol = lwgeom_as_lwcollection(bnd);
+ if (bcol)
+ {
+ for (i = 0; i < bcol->ngeoms; i++)
+ lwcollection_add_lwgeom(points, lwgeom_clone_deep(bcol->geoms[i]));
+ }
+ else if (!lwgeom_is_empty(bnd))
+ {
+ lwcollection_add_lwgeom(points, lwgeom_clone_deep(bnd));
+ }
+ lwgeom_free(bnd);
+ }
+
+ lwcollection_release(epoints);
+ lwcollection_release(lines);
+ lwgeom_release(multi);
+
+ points->srid = xset->srid;
+ return lwcollection_as_lwgeom(points);
+}
+
static LWT_ELEMID*
_lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
int handleFaceSplit, int maxNewEdges)
@@ -7386,7 +7437,7 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
LWGEOM *geomsbuf[1];
LWGEOM **geoms;
uint32_t ngeoms;
- LWGEOM *noded, *tmp;
+ LWGEOM *noded, *tmp, *xsplit = NULL;
LWCOLLECTION *col;
LWT_ELEMID *ids;
LWT_ISO_EDGE *edges;
@@ -7601,6 +7652,9 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
xset = lwgeom_intersection(noded, iedges);
LWDEBUGG(1, xset, "Intersected");
lwgeom_free(noded);
+ /* Collect the junctions between shared and non-shared linework
+ * before line merging can hide them (see step 2.5) */
+ xsplit = _lwt_overlay_split_points(xset);
/* We linemerge here because INTERSECTION, as of GEOS 3.8,
* will result in shared segments being output as multiple
@@ -7691,6 +7745,25 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
lwcollection_release(col);
}
+ /* 2.5. Split by overlay junctions
+ *
+ * GEOS >= 3.15 returns line-merged overlay output, hiding the
+ * junctions between shared and non-shared linework inside line
+ * interiors. Splitting restores them; older GEOS keeps them as
+ * component boundaries and the split is a no-op.
+ */
+ if ( xsplit )
+ {
+ if ( !lwgeom_is_empty(xsplit) )
+ {
+ tmp = _lwt_split_by_nodes(noded, xsplit);
+ lwgeom_free(noded);
+ noded = tmp;
+ LWDEBUGG(1, noded, "Overlay-junction-split");
+ }
+ lwgeom_free(xsplit);
+ }
+
LWDEBUG(1, "Freeing up nearby elements");
diff --git a/topology/test/regress/topogeo_addlinestring.sql b/topology/test/regress/topogeo_addlinestring.sql
index 5946ceec0..1f67b7198 100644
--- a/topology/test/regress/topogeo_addlinestring.sql
+++ b/topology/test/regress/topogeo_addlinestring.sql
@@ -99,9 +99,9 @@ SELECT 'cross', TopoGeo_addLineString('city_data', 'SRID=4326;LINESTRING(49 18,
SELECT check_changes('cross');
-- Snapping (and splitting a face)
-SELECT 'snap', TopoGeo_addLineString('city_data', 'SRID=4326;LINESTRING(18 22.2, 22.5 22.2, 21.2 20.5)', 1) ORDER BY 2;
+SELECT 'snap', COUNT(*) FROM TopoGeo_addLineString('city_data', 'SRID=4326;LINESTRING(18 22.2, 22.5 22.2, 21.2 20.5)', 1);
SELECT check_changes('snap');
-SELECT 'snap_again', TopoGeo_addLineString('city_data', 'SRID=4326;LINESTRING(18 22.2, 22.5 22.2, 21.2 20.5)', 1) ORDER BY 2;
+SELECT 'snap_again', COUNT(*) FROM TopoGeo_addLineString('city_data', 'SRID=4326;LINESTRING(18 22.2, 22.5 22.2, 21.2 20.5)', 1);
SELECT check_changes('snap_again');
-- A mix of crossing and overlapping, splitting another face
diff --git a/topology/test/regress/topogeo_addlinestring_expected b/topology/test/regress/topogeo_addlinestring_expected
index 5035a8654..957ed5f3c 100644
--- a/topology/test/regress/topogeo_addlinestring_expected
+++ b/topology/test/regress/topogeo_addlinestring_expected
@@ -38,9 +38,7 @@ cross|E|LINESTRING(47 14,47 17.6)
cross|E|LINESTRING(47 17.6,47 22)
cross|E|LINESTRING(47 17.6,44 17)
cross|E|LINESTRING(49 18,47 17.6)
-snap|7
-snap|36
-snap|38
+snap|3
snap|N||POINT(21.2 20.5)
snap|N||POINT(22.35 22)
snap|N||POINT(18 22.2)
@@ -48,9 +46,7 @@ snap|E|LINESTRING(22.35 22,35 22)
snap|E|LINESTRING(22.35 22,21.2 20.5)
snap|E|LINESTRING(21 22,22.35 22)
snap|E|LINESTRING(18 22.2,21 22)
-snap_again|7
-snap_again|36
-snap_again|38
+snap_again|3
crossover|4
crossover|N||POINT(21 10)
crossover|N||POINT(16.2 14)
-----------------------------------------------------------------------
Summary of changes:
NEWS | 2 +
doc/reference_overlay.xml | 4 +-
doc/reference_processing.xml | 10 +--
liblwgeom/topo/lwgeom_topo.c | 75 +++++++++++++++++++++-
regress/core/wrapx.sql | 2 +-
topology/test/regress/topogeo_addlinestring.sql | 4 +-
.../test/regress/topogeo_addlinestring_expected | 8 +--
7 files changed, 89 insertions(+), 16 deletions(-)
hooks/post-receive
--
PostGIS
More information about the postgis-tickets
mailing list