[SCM] PostGIS branch master updated. 3.6.0rc2-461-ge21fe0083

git at osgeo.org git at osgeo.org
Wed Apr 15 08:50:38 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  e21fe0083bd1fdd7477e60162b793870f8b536fc (commit)
       via  83ba9c60da7d47e936848eb2a764b23e53c37598 (commit)
       via  5e3b36d6ab3cd2c1c1191ac95257332fef0e9e1b (commit)
      from  8b5d974cb7f4376c5ebc9936b5ba93aaf826452c (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 e21fe0083bd1fdd7477e60162b793870f8b536fc
Author: Sandro Santilli <strk at kbt.io>
Date:   Wed Apr 15 17:42:00 2026 +0200

    Revert "Skip dangling parts of ring when computing orientation"
    
    This reverts commit 43af076ad4cf42a4fb1c12cb497425b958246c6f.
    
    The implementation fails for CCW rings with holes touching the ring

diff --git a/topology/sql/manage/ValidateTopology.sql.in b/topology/sql/manage/ValidateTopology.sql.in
index 9bedb0654..4dff69603 100644
--- a/topology/sql/manage/ValidateTopology.sql.in
+++ b/topology/sql/manage/ValidateTopology.sql.in
@@ -468,8 +468,7 @@ BEGIN
       SELECT
         r.ring_id,
         e.seq,
-        e.edge signed_edge_id,
-        count(e.edge) over (PARTITION BY ring_id, abs(e.edge)) > 1 as dangling
+        e.edge signed_edge_id
       FROM all_rings r
       LEFT JOIN LATERAL unnest(r.edges) WITH ORDINALITY AS e(edge, seq)
       ON TRUE
@@ -483,16 +482,9 @@ BEGIN
           ELSE
             ST_Reverse(e.geom)
           END
+           -- TODO: how to make sure rows are ordered ?
           ORDER BY seq
         ) geom,
-        ST_LineMerge( ST_Collect(
-          CASE WHEN signed_edge_id > 0 THEN
-            e.geom
-          ELSE
-            ST_Reverse(e.geom)
-          END
-        ) FILTER ( WHERE NOT r.dangling ) )
-        non_dangling_edges_merge,
         array_agg(
           DISTINCT
           CASE WHEN signed_edge_id > 0 THEN
@@ -509,7 +501,7 @@ BEGIN
       WHERE e.edge_id = abs(r.signed_edge_id)
       GROUP BY ring_id
     ) --}{
-    SELECT ring_id, geom as ring_geom, non_dangling_edges_merge, side_faces, distinct_edges, num_edges
+    SELECT ring_id, geom as ring_geom, side_faces, distinct_edges, num_edges
     FROM all_rings_with_ring_geom
   LOOP --}{
 
@@ -556,28 +548,10 @@ BEGIN
     IF ST_NPoints(rec.ring_geom) > 3 AND
        rec.num_edges != rec.distinct_edges * 2
     THEN
-      -- TODO: directly build candidate shell polygon from non-dangling portions ?
       ring_poly := ST_MakePolygon(rec.ring_geom);
-      /*
-        1. Make polygon from non-dangling edge merge
-        2. Pick the one with largest area
-        3. Check if CCW
-      */
-      WITH irings AS (
-        SELECT ST_MakePolygon(geom) geom
-        FROM ST_Dump(rec.non_dangling_edges_merge)
-        -- TODO: report non-closed rings from non-dangling edges as another invalidity
-        WHERE ST_StartPoint(geom) = ST_EndPoint(geom)
-      ),
-      largest_iring AS (
-        SELECT geom FROM irings
-        ORDER BY ST_Area(geom) DESC LIMIT 1
-      )
-      SELECT ST_IsPolygonCCW(geom) FROM largest_iring
-      INTO is_shell;
-#if POSTGIS_TOPOLOGY_DEBUG > 1
-      RAISE NOTICE 'Ring % is CCW ? %', rec.ring_id, is_shell;
-#endif
+      IF ST_IsPolygonCCW(ring_poly) THEN
+        is_shell := true;
+      END IF;
     END IF;
 
 #ifdef POSTGIS_TOPOLOGY_DEBUG

commit 83ba9c60da7d47e936848eb2a764b23e53c37598
Author: Sandro Santilli <strk at kbt.io>
Date:   Wed Apr 15 17:39:49 2026 +0200

    Revert CCW computation changes in liblwgeom-topo
    
    The implementation fails for CCW rings with holes touching the ring
    
    This reverts 00440ad2900ced28817d18e4908a13bff455588a
    but keeps the changes that might make it easier to
    improve orientation later.

diff --git a/liblwgeom/topo/lwgeom_topo.c b/liblwgeom/topo/lwgeom_topo.c
index 0faec58e5..4abef795c 100644
--- a/liblwgeom/topo/lwgeom_topo.c
+++ b/liblwgeom/topo/lwgeom_topo.c
@@ -1887,15 +1887,12 @@ static LWPOLY *
 _lwt_MakeRingShell(LWT_TOPOLOGY *topo, LWT_ELEMID *signed_edge_ids, uint64_t num_signed_edge_ids, int *isccw, GBOX *ringbox)
 {
   LWT_ELEMID *edge_ids;
-  LWT_ELEMID *dangling_edge_ids;
-  uint64_t numedges, num_dangling, j, i;
+  uint64_t numedges, j, i;
   LWT_ISO_EDGE *ring_edges;
 
   /* Construct a polygon using edges of the ring */
   numedges = 0;
-  num_dangling = 0;
   edge_ids = lwalloc(sizeof(LWT_ELEMID)*num_signed_edge_ids);
-  dangling_edge_ids = lwalloc(sizeof(LWT_ELEMID)*num_signed_edge_ids);
   for (i=0; i<num_signed_edge_ids; ++i) {
     LWT_ELEMID absid = llabs(signed_edge_ids[i]);
     int found = 0;
@@ -1903,7 +1900,6 @@ _lwt_MakeRingShell(LWT_TOPOLOGY *topo, LWT_ELEMID *signed_edge_ids, uint64_t num
     for (j=0; j<numedges; ++j) {
       if ( edge_ids[j] == absid ) {
         found = 1;
-        dangling_edge_ids[num_dangling++] = absid;
         break;
       }
     }
@@ -1917,13 +1913,11 @@ _lwt_MakeRingShell(LWT_TOPOLOGY *topo, LWT_ELEMID *signed_edge_ids, uint64_t num
   lwfree( edge_ids );
   if (i == UINT64_MAX)
   {
-    lwfree( dangling_edge_ids );
     PGTOPO_BE_ERROR();
     return NULL;
   }
   else if ( i != numedges )
   {
-    lwfree( dangling_edge_ids );
     lwfree( signed_edge_ids );
     _lwt_release_edges(ring_edges, i);
     lwerror("Unexpected error: %" LWTFMT_ELEMID
@@ -1939,7 +1933,6 @@ _lwt_MakeRingShell(LWT_TOPOLOGY *topo, LWT_ELEMID *signed_edge_ids, uint64_t num
       GBOX edgebox;
       if ( LW_SUCCESS != ptarray_calculate_gbox_cartesian(ring_edges[i].geom->points, &edgebox) )
       {
-        lwfree( dangling_edge_ids );
         lwerror("Could not calculate bounding box of edge %" LWTFMT_ELEMID, ring_edges[i].edge_id);
         return NULL;
       }
@@ -1951,7 +1944,6 @@ _lwt_MakeRingShell(LWT_TOPOLOGY *topo, LWT_ELEMID *signed_edge_ids, uint64_t num
   /* Should now build a polygon with those edges, in the order
    * given by GetRingEdges.
    */
-  LWCOLLECTION *non_dangling_collection = NULL;
   POINTARRAY *full_ring_pa = NULL;
   for ( i=0; i<num_signed_edge_ids; ++i )
   {
@@ -1970,7 +1962,6 @@ _lwt_MakeRingShell(LWT_TOPOLOGY *topo, LWT_ELEMID *signed_edge_ids, uint64_t num
     }
     if ( edge == NULL )
     {
-      lwfree( dangling_edge_ids );
       _lwt_release_edges(ring_edges, numedges);
       lwerror("missing edge that was found in ring edges loop");
       return NULL;
@@ -1996,42 +1987,7 @@ _lwt_MakeRingShell(LWT_TOPOLOGY *topo, LWT_ELEMID *signed_edge_ids, uint64_t num
         ptarray_append_ptarray(full_ring_pa, edge->geom->points, 0);
       }
     }
-
-    int found = 0;
-    for ( j=0; j<num_dangling; ++j )
-    {
-      if ( dangling_edge_ids[j] == edge->edge_id )
-      {
-        found = 1;
-        break;
-      }
-    }
-    if ( found )
-    {
-      LWDEBUGF(2, "Edge %" LWTFMT_ELEMID " is dangling (index %" PRIu64 ")", edge->edge_id, j);
-      continue;
-    }
-
-    if ( non_dangling_collection == NULL )
-    {
-      non_dangling_collection = lwcollection_construct_empty(
-          COLLECTIONTYPE,
-          topo->srid,
-          topo->hasZ,
-          0
-      );
-    }
-    POINTARRAY *pa_toadd = ptarray_clone_deep(edge->geom->points);
-    if ( eid < 0 )
-    {
-      ptarray_reverse_in_place(pa_toadd);
-    }
-    lwcollection_add_lwgeom(
-        non_dangling_collection,
-        lwline_as_lwgeom(lwline_construct(topo->srid, NULL, pa_toadd))
-    );
   }
-  lwfree( dangling_edge_ids );
   _lwt_release_edges(ring_edges, numedges);
 
   if ( ! ptarray_is_closed_2d(full_ring_pa) )
@@ -2041,58 +1997,6 @@ _lwt_MakeRingShell(LWT_TOPOLOGY *topo, LWT_ELEMID *signed_edge_ids, uint64_t num
     return NULL;
   }
 
-  if ( non_dangling_collection == NULL ) /* all edges are dangling ! */
-  {
-    lwnotice("All edges in ring are dangling, will not report as ccw");
-    *isccw = 0;
-  }
-
-  LWGEOM *merged = lwgeom_linemerge(lwcollection_as_lwgeom(non_dangling_collection));
-  lwcollection_free(non_dangling_collection);
-
-  LWDEBUGG(2, merged, "Linemerged non-dangling edges");
-
-  switch (merged->type)
-  {
-    case LINETYPE:
-    {
-			LWLINE *line = (LWLINE *)(merged);
-      POINTARRAY *pa = line->points;
-      *isccw = ptarray_isccw(pa);
-      break;
-    }
-    case MULTILINETYPE:
-    {
-      double maxarea = 0;
-			LWMLINE *mline = (LWMLINE *)(merged);
-      /* find the one with the largest area */
-      for ( i=0; i<mline->ngeoms; ++i )
-      {
-        const LWLINE *l = mline->geoms[i];
-        const POINTARRAY *pa = l->points;
-        double sarea;
-
-        /* skip non-closed rings */
-        //if ( ! ptarray_is_closed_2d(pa) ) continue;
-
-        sarea = ptarray_signed_area(pa);
-        LWDEBUGF(3, "Signed area of ring %" PRIu64 ": %g", i, sarea);
-        if ( fabs(sarea) > fabs(maxarea) ) {
-          maxarea = sarea;
-        }
-      }
-      LWDEBUGF(2, "Maxarea: %g", maxarea);
-      *isccw = maxarea < 0 ? 1 : 0;
-      break;
-    }
-    default:
-    {
-      lwerror("%s: Unexpected geometry type from lwgeom_linemerge: %s", __func__, lwtype_name(merged->type));
-      return NULL;
-    }
-  }
-
-
   POINTARRAY **points = lwalloc(sizeof(POINTARRAY*));
   points[0] = full_ring_pa;
 
@@ -2100,12 +2004,10 @@ _lwt_MakeRingShell(LWT_TOPOLOGY *topo, LWT_ELEMID *signed_edge_ids, uint64_t num
    *       which would make it topologically invalid
    */
   LWPOLY* shell = lwpoly_construct(0, 0, 1, points);
-#if POSTGIS_DEBUG_LEVEL > 0
-  if ( ptarray_isccw(shell->rings[0]) != *isccw )
-  {
-    LWDEBUGF(1, "CCW disagreement on signed edge id %" LWTFMT_ELEMID, signed_edge_ids[0]);
-  }
-#endif
+
+  /* TODO: skip if all edges were dangling ? */
+  *isccw = ptarray_isccw(shell->rings[0]);
+
   return shell;
 }
 

commit 5e3b36d6ab3cd2c1c1191ac95257332fef0e9e1b
Author: Sandro Santilli <strk at kbt.io>
Date:   Wed Apr 15 17:43:42 2026 +0200

    Back to long-double
    
    This reverts commit cfb81e6a5bf761b6603a6425e689d82d5f3b046c.

diff --git a/liblwgeom/ptarray.c b/liblwgeom/ptarray.c
index 5c6796e75..65b72290b 100644
--- a/liblwgeom/ptarray.c
+++ b/liblwgeom/ptarray.c
@@ -1083,7 +1083,7 @@ ptarray_signed_area(const POINTARRAY *pa)
 	const POINT2D *P1;
 	const POINT2D *P2;
 	const POINT2D *P3;
-	double sum = 0.0;
+	long double sum = 0.0;
 	double x0, x, y1, y2;
 	uint32_t i;
 

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

Summary of changes:
 liblwgeom/ptarray.c                         |   2 +-
 liblwgeom/topo/lwgeom_topo.c                | 108 ++--------------------------
 topology/sql/manage/ValidateTopology.sql.in |  38 ++--------
 3 files changed, 12 insertions(+), 136 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list