[SCM] PostGIS branch master updated. 3.5.0-33-gf02b6db36

git at osgeo.org git at osgeo.org
Tue Oct 29 02:34:35 PDT 2024


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  f02b6db36beb5e9e772c211dc08556377cf1a4d0 (commit)
      from  aa67372e126a263aa03ea55535efca4478ee8965 (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 f02b6db36beb5e9e772c211dc08556377cf1a4d0
Author: Sandro Santilli <strk at kbt.io>
Date:   Wed Oct 9 17:48:51 2024 +0200

    Check motion range upon snap/splitting edge to existing node
    
    References #5792 (fixing it)
    References #5786 (not resolving the problem)
    Includes regress test

diff --git a/liblwgeom/topo/lwgeom_topo.c b/liblwgeom/topo/lwgeom_topo.c
index c5accb28c..e79b2a961 100644
--- a/liblwgeom/topo/lwgeom_topo.c
+++ b/liblwgeom/topo/lwgeom_topo.c
@@ -5288,7 +5288,7 @@ _lwt_SnapEdgeToExistingNode(
   for ( n=0; n<2; ++n)
   {
     int forward;
-    /* TODO: directly get full existing edge rather than just id * */
+    /* TODO: directly get full existing edge rather than just id */
     LWT_ELEMID existingEdgeId = _lwt_GetEqualEdge( topo, lwgeom_as_lwline(splitC->geoms[n]), &forward );
     if ( existingEdgeId == -1 )
     {
@@ -5409,8 +5409,74 @@ _lwt_SnapEdgeToExistingNode(
       splitNodeNewEdgeOutgoing = 0;
     }
 
-    /* TODO: check that newSplitEdgeLine part does not crosses any other edge ? */
+    /* TODO: check that newSplitEdgeLine part does not cross any other edge ? */
     /* TODO: check that newSplitEdgeLine retains its position in the edge end star (see ticket #5786) */
+    /* TODO: check that the motion range does not contain any node
+
+    {{
+      // build the motion range shape: splitC->geoms[0] + splitC->geoms[1] - edge->geom
+      POINTARRAY *motionRange = ptarray_clone_deep(lwgeom_as_lwline(splitC->geoms[0])->points);
+      ptarray_append_ptarray(motionRange, lwgeom_as_lwline(splitC->geoms[1])->points, 0);
+      POINTARRAY *reverseNewLine = ptarray_clone_deep(edge->geom->points);
+      ptarray_reverse_in_place(reverseNewLine);
+      ptarray_append_ptarray(motionRange, reverseNewLine, 0);
+      ptarray_free(reverseNewLine);
+
+      // motionBounds takes ownership of motionRange
+      LWLINE *motionBounds = lwline_construct(topo->srid, NULL, motionRange);
+
+      // motionPoly takes ownership of motionBounds
+      LWGEOM *motionPoly = (LWGEOM *)lwpoly_from_lwlines(motionBounds, 0, NULL);
+
+      LWDEBUGG(1, motionPoly, "Motion range");
+
+      // check the Motion range doesn't cover any of
+      // the edges incident to the split node other
+      // than the existing edge
+      GEOSGeometry *motionPolyG = NULL;
+      for ( uint64_t t=0; t<splitNodeEdges->numEdges; t++ )
+      {
+        LWT_ISO_EDGE *e = &(splitNodeEdges->edges[t]);
+        GEOSGeometry *eg;
+        if ( e == existingEdge ) continue;
+        if ( e == edge ) continue;
+        if ( ! motionPolyG ) {
+          motionPolyG = LWGEOM2GEOS( motionPoly, 0 );
+          if ( ! motionPolyG )
+          {
+            lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
+            return -1;
+          }
+        }
+        eg = LWGEOM2GEOS( lwline_as_lwgeom(e->geom), 0 );
+        if ( ! eg )
+        {
+          lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
+          return -1;
+        }
+
+        int covers = GEOSCovers( motionPolyG, eg );
+        // TODO: use preparedCovers ?
+        GEOSGeom_destroy(eg);
+        if (covers == 2)
+        {
+          lwerror("Covers error: %s", lwgeom_geos_errmsg);
+          return -1;
+        }
+        if ( covers )
+        {
+          lwgeom_free(motionPoly);
+          lwerror("snapping edge %" LWTFMT_ELEMID
+            " to new node moves it past edge %" LWTFMT_ELEMID,
+            edge->edge_id, e->edge_id
+          );
+          return -1;
+        }
+      }
+      if ( motionPolyG ) GEOSGeom_destroy(motionPolyG);
+
+      lwgeom_free(motionPoly);
+    }}
 
     LWDEBUGF(1, "Existing edge %"
         LWTFMT_ELEMID " (post-modEdgeSplit) next_right:%"
diff --git a/topology/test/regress/topogeo_addpoint_merge_edges.sql b/topology/test/regress/topogeo_addpoint_merge_edges.sql
index fc0fff28d..1cc0d59bf 100644
--- a/topology/test/regress/topogeo_addpoint_merge_edges.sql
+++ b/topology/test/regress/topogeo_addpoint_merge_edges.sql
@@ -425,4 +425,20 @@ SELECT * FROM runTest('multi-merge-closest-not-containing-projected',
   ], 'POINT(12.472410859513998 70.77020397757477)', 0
 ) WHERE true ;
 
+
+SELECT * FROM runTest('#5792.0',
+  ARRAY[
+    'LINESTRING(11.812075769533624 59.77938755222866,11.811862389533625 59.77938237222866)',
+    'LINESTRING(11.811862389533625 59.77938237222866,11.811969079533624 59.77938496222866,11.812075769533624 59.77938755222866)'
+  ], 'POINT(11.812029186127067 59.7793864213727)', 0
+) WHERE true ;
+
+SELECT * FROM runTest('#5792.1',
+  ARRAY[
+    'LINESTRING(11.812075769533624 59.77938755222866,11.811862389533625 59.77938237222866)',
+    'LINESTRING(11.811862389533625 59.77938237222866,11.811969079533624 59.77938496222866,11.812075769533624 59.77938755222866)',
+    'LINESTRING(11.811862389533625 59.77938237222866,11.811969079533624 59.77938,11.812075769533624 59.77938755222866)'
+  ], 'POINT(11.812029186127067 59.7793864213727)', 0
+) WHERE true ;
+
 DROP FUNCTION runTest(text, geometry[], geometry, float8, bool);
diff --git a/topology/test/regress/topogeo_addpoint_merge_edges_expected b/topology/test/regress/topogeo_addpoint_merge_edges_expected
index 90b2a3d21..994187546 100644
--- a/topology/test/regress/topogeo_addpoint_merge_edges_expected
+++ b/topology/test/regress/topogeo_addpoint_merge_edges_expected
@@ -29,3 +29,5 @@ full-merge-exterior-face|-checking-
 double-merge-forward-backward|-checking-
 multi-merge-forward-backward|-checking-
 multi-merge-closest-not-containing-projected|-checking-
+ERROR:  snapping edge 2 to new node moves it past edge 3
+ERROR:  snapping edge 2 to new node moves it past edge 3

-----------------------------------------------------------------------

Summary of changes:
 liblwgeom/topo/lwgeom_topo.c                       | 70 +++++++++++++++++++++-
 .../test/regress/topogeo_addpoint_merge_edges.sql  | 16 +++++
 .../regress/topogeo_addpoint_merge_edges_expected  |  2 +
 3 files changed, 86 insertions(+), 2 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list