[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0rc1-156-g3c622d0

git at osgeo.org git at osgeo.org
Mon Apr 26 02:32:43 PDT 2021


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  3c622d02437567d718b56bf336fdbe77b2e8ec0b (commit)
       via  fb9fa7e9ddb3eb59c7dec63a44a040b4c0e88332 (commit)
       via  fea3aac3989348b85c20a7e59f4d90bd83198035 (commit)
      from  05eaa361c5a7745d335166bd8e8d708b22103170 (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 3c622d02437567d718b56bf336fdbe77b2e8ec0b
Author: Sandro Santilli <strk at kbt.io>
Date:   Mon Apr 26 11:30:34 2021 +0200

    Add NEWS item

diff --git a/NEWS b/NEWS
index bfc48bc..89ff3c8 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,8 @@ PostGIS 3.2.0
   - #4870, Allow open options to be passed to GDAL drivers (Paul Ramsey)
   - ST_Value() accepts resample parameter to add bilinear option (Paul Ramsey)
   - #3778, #4401, ST_Boundary now works for TIN and does not linearize curves (Aliaksandr Kalenik)
+  - #4881, #4884, Store sign of edge_id for lineal TopoGeometry in relation table
+           to retain direction (Sandro Santilli)
 
  * New features*
   - #4841, FindTopology to quickly get a topology record (Sandro Santilli)
@@ -20,7 +22,7 @@ PostGIS 3.2.0
     using one of a number of algorithms (inverse weighted distance, average, etc)
     using algorithms from GDAL
     (Paul Ramsey)
-  - ST_Contour() generates contour lines from raster values 
+  - ST_Contour() generates contour lines from raster values
     using algorithms from GDAL (Paul Ramsey)
   - ST_SetZ()/ST_SetM() fills in z/m coordinates of a geometry using data read
     from a raster (Paul Ramsey)

commit fb9fa7e9ddb3eb59c7dec63a44a040b4c0e88332
Author: Sandro Santilli <strk at kbt.io>
Date:   Mon Apr 26 10:44:06 2021 +0200

    Have TopoGeo_addLinestring return signed edge ids for lineals
    
    Closes #4884 in main branch (3.2.0dev)
    
    Update expected results accordingly
    Add specific tests for totopogeom.

diff --git a/liblwgeom/lwgeom_topo.c b/liblwgeom/lwgeom_topo.c
index 2c7d3fd..e48bdd4 100644
--- a/liblwgeom/lwgeom_topo.c
+++ b/liblwgeom/lwgeom_topo.c
@@ -5253,9 +5253,13 @@ lwt_AddPoint(LWT_TOPOLOGY* topo, LWPOINT* point, double tol)
 
 /* Return identifier of an equal edge, 0 if none or -1 on error
  * (and lwerror gets called on error)
+ *
+ * If an equal edge is found, specify, in "forward" variable whether
+ * the edge is also equal direction-wise
+ *
  */
 static LWT_ELEMID
-_lwt_GetEqualEdge( LWT_TOPOLOGY *topo, LWLINE *edge )
+_lwt_GetEqualEdge( LWT_TOPOLOGY *topo, LWLINE *edge, int *forward )
 {
   LWT_ELEMID id;
   LWT_ISO_EDGE *edges;
@@ -5307,6 +5311,40 @@ _lwt_GetEqualEdge( LWT_TOPOLOGY *topo, LWLINE *edge )
       if ( equals )
       {
         id = e->edge_id;
+        /* Check if direction also matches */
+        if ( forward )
+        {
+          /* If input line is closed, we use winding order */
+          if ( lwline_is_closed(edge) )
+          {
+            if ( ptarray_isccw(edge->points) == ptarray_isccw(e->geom->points) )
+            {
+              *forward = 1;
+            }
+            else
+            {
+              *forward = 0;
+            }
+          }
+          else
+          {
+            /* Input line is not closed, checking fist point is enough */
+            if (
+              memcmp(
+                  getPoint_internal(edge->points, 0),
+                  getPoint_internal(e->geom->points, 0),
+                  sizeof(POINT2D)
+              ) == 0
+            )
+            {
+              *forward = 1;
+            }
+            else
+            {
+              *forward = 0;
+            }
+          }
+        }
         GEOSGeom_destroy(edgeg);
         _lwt_release_edges(edges, num);
         return id;
@@ -5327,10 +5365,16 @@ _lwt_GetEqualEdge( LWT_TOPOLOGY *topo, LWLINE *edge )
  *        if the newly added edge would split a face and if so
  *        would create new faces accordingly. Otherwise it will
  *        set left_face and right_face to null (-1)
+ *
+ * @param forward output parameter, will be populated if
+ *        a pre-existing edge was found in the topology,
+ *        in which case a value of 1 means the incoming
+ *        line will have the same direction of the edge,
+ *        and 0 that the incomine line has opposite direction
  */
 static LWT_ELEMID
 _lwt_AddLineEdge( LWT_TOPOLOGY* topo, LWLINE* edge, double tol,
-                  int handleFaceSplit )
+                  int handleFaceSplit, int *forward )
 {
   LWCOLLECTION *col;
   LWPOINT *start_point, *end_point;
@@ -5456,7 +5500,7 @@ _lwt_AddLineEdge( LWT_TOPOLOGY* topo, LWLINE* edge, double tol,
   }
 
   /* check if the so-snapped edge _now_ exists */
-  id = _lwt_GetEqualEdge ( topo, edge );
+  id = _lwt_GetEqualEdge ( topo, edge, forward );
   LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
   if ( id == -1 )
   {
@@ -5490,7 +5534,7 @@ _lwt_AddLineEdge( LWT_TOPOLOGY* topo, LWLINE* edge, double tol,
     }
 
     /* check if the so-decimated edge _now_ exists */
-    id = _lwt_GetEqualEdge ( topo, edge );
+    id = _lwt_GetEqualEdge ( topo, edge, forward );
     LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
     if ( id == -1 )
     {
@@ -5515,6 +5559,7 @@ _lwt_AddLineEdge( LWT_TOPOLOGY* topo, LWLINE* edge, double tol,
   }
   lwgeom_free(tmp); /* possibly takes "edge" down with it */
 
+  *forward = 1;
   return id;
 }
 
@@ -5557,6 +5602,7 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
   uint64_t num, numedges = 0, numnodes = 0;
   uint64_t i;
   GBOX qbox;
+  int forward;
 
   *nedges = -1; /* error condition, by default */
 
@@ -5842,7 +5888,7 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
     }
 #endif
 
-    id = _lwt_AddLineEdge( topo, lwgeom_as_lwline(g), tol, handleFaceSplit );
+    id = _lwt_AddLineEdge( topo, lwgeom_as_lwline(g), tol, handleFaceSplit, &forward );
     LWDEBUGF(1, "_lwt_AddLineEdge returned %" LWTFMT_ELEMID, id);
     if ( id < 0 )
     {
@@ -5856,9 +5902,9 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
       continue;
     }
 
-    LWDEBUGF(1, "Component %d of split line is edge %" LWTFMT_ELEMID,
-                  i, id);
-    ids[num++] = id; /* TODO: skip duplicates */
+    LWDEBUGF(1, "Component %d of split line is %s edge %" LWTFMT_ELEMID,
+                  i, forward ? "forward" : "backward", id);
+    ids[num++] = forward ? id : -id; /* TODO: skip duplicates */
   }
 
   LWDEBUGG(1, noded, "Noded before free");
diff --git a/topology/test/regress/topogeo_addlinestring_expected b/topology/test/regress/topogeo_addlinestring_expected
index d786940..9c09021 100644
--- a/topology/test/regress/topogeo_addlinestring_expected
+++ b/topology/test/regress/topogeo_addlinestring_expected
@@ -71,7 +71,7 @@ crossover|E|LINESTRING(9 20,16.2 14)
 crossover|E|LINESTRING(9 14,9 18)
 crossover|E|LINESTRING(9 18,9 20)
 crossover_again|4
-contains|25
+contains|-25
 contains|46
 contains|47
 contains|N||POINT(7 36)
@@ -139,7 +139,7 @@ iso_ex_2segs|28
 #1650.2|N||POINT(0 0)
 #1650.2|N||POINT(0 1)
 #1650.2|E|LINESTRING(0 0,0 1)
-#1650.3|65
+#1650.3|-65
 #1650.3|66
 #1650.3|N||POINT(10 0)
 #1650.3|E|LINESTRING(0 0,10 0)
diff --git a/topology/test/regress/totopogeom.sql b/topology/test/regress/totopogeom.sql
index 91bb7cf..f72d58d 100644
--- a/topology/test/regress/totopogeom.sql
+++ b/topology/test/regress/totopogeom.sql
@@ -221,6 +221,25 @@ SELECT '#3359.area.1', ST_Area(toTopoGeom('POLYGON ((0 0,1 0,1 1,0 1,0 0))'
 SELECT '#3359.area.2', ST_Area(toTopoGeom('POLYGON ((0 0,1 0,1 2,0 2,0 0))'
 ::geometry, 'tt', 4));
 
+--------------------------------------------------------
+-- http://trac.osgeo.org/postgis/ticket/4884
+--------------------------------------------------------
+TRUNCATE tt.relation CASCADE;
+TRUNCATE tt.edge_data CASCADE;
+TRUNCATE tt.node CASCADE;
+DELETE FROM tt.face WHERE face_id > 0;
+SELECT '#4884.setval',
+       setval('tt.edge_data_edge_id_seq', 1, false),
+       -- face_id is intentionally set to 2
+       setval('tt.face_face_id_seq', 2, false),
+       setval('tt.node_node_id_seq', 1, false);
+SELECT '#4884.l2r', ST_AsText(toTopoGeom('LINESTRING (0 0,1 0)' ::geometry, 'tt', 3));
+SELECT '#4884.r2l', ST_AsText(toTopoGeom('LINESTRING (1 0,0 0)' ::geometry, 'tt', 3));
+
+--------------------------------------------------------
+-- Cleanups
+--------------------------------------------------------
+
 DROP TABLE tt.f_coll;
 DROP TABLE tt.f_areal;
 DROP TABLE tt.f_lineal;
diff --git a/topology/test/regress/totopogeom_expected b/topology/test/regress/totopogeom_expected
index bda0c3a..6ba1e0a 100644
--- a/topology/test/regress/totopogeom_expected
+++ b/topology/test/regress/totopogeom_expected
@@ -49,4 +49,7 @@ tgup1.3|5|200|4
 #3359.line.2|2
 #3359.area.1|1
 #3359.area.2|2
+#4884.setval|1|2|1
+#4884.l2r|MULTILINESTRING((0 0,1 0))
+#4884.r2l|MULTILINESTRING((1 0,0 0))
 Topology 'tt' dropped

commit fea3aac3989348b85c20a7e59f4d90bd83198035
Author: Sandro Santilli <strk at kbt.io>
Date:   Fri Mar 12 09:20:11 2021 +0100

    Rewrite TopoGeometry::geometry cast for lineals to retain direction
    
    Includes test
    
    Closes #4881 in main branch (3.2.0dev)

diff --git a/topology/test/regress/geometry_cast.sql b/topology/test/regress/geometry_cast.sql
index 5e65870..6ec9d07 100644
--- a/topology/test/regress/geometry_cast.sql
+++ b/topology/test/regress/geometry_cast.sql
@@ -4,35 +4,35 @@ set client_min_messages to WARNING;
 select NULL FROM createtopology('tt', 4326);
 
 -- layer 1 is PUNTUAL
-CREATE TABLE tt.f_point(id serial);
+CREATE TABLE tt.f_point(lbl text primary key);
 SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_point', 'g', 'POINT');
 
 -- layer 2 is LINEAL
-CREATE TABLE tt.f_line(id serial);
+CREATE TABLE tt.f_line(lbl text primary key );
 SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_line', 'g', 'LINE');
 
 -- layer 3 is AREAL
-CREATE TABLE tt.f_area(id serial);
+CREATE TABLE tt.f_area(lbl text primary key);
 SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_area', 'g', 'POLYGON');
 
 -- layer 4 is MIXED
-CREATE TABLE tt.f_coll(id serial);
+CREATE TABLE tt.f_coll(lbl text primary key);
 SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_coll', 'g', 'COLLECTION');
 
 -- layer 5 is HIERARCHICAL PUNTUAL
-CREATE TABLE tt.f_hier_point(id serial);
+CREATE TABLE tt.f_hier_point(lbl text primary key);
 SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_hier_point', 'g', 'POINT', 1);
 
 -- layer 6 is HIERARCHICAL LINEAL
-CREATE TABLE tt.f_hier_line(id serial);
+CREATE TABLE tt.f_hier_line(lbl text primary key);
 SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_hier_line', 'g', 'LINE', 2);
 
 -- layer 7 is HIERARCHICAL AREAL
-CREATE TABLE tt.f_hier_area(id serial);
+CREATE TABLE tt.f_hier_area(lbl text primary key);
 SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_hier_area', 'g', 'POLYGON', 3);
 
 -- layer 8 is HIERARCHICAL MIXED
-CREATE TABLE tt.f_hier_coll(id serial);
+CREATE TABLE tt.f_hier_coll(lbl text primary key);
 SELECT NULL FROM AddTopoGeometryColumn('tt', 'tt', 'f_hier_coll', 'g', 'COLLECTION', 4);
 
 
@@ -47,5 +47,80 @@ SELECT 'empty', 'hier', 'lineal', ST_AsEWKT(CreateTopoGeom('tt', 2, 6)::geometry
 SELECT 'empty', 'hier', 'areal', ST_AsEWKT(CreateTopoGeom('tt', 3, 7)::geometry);
 SELECT 'empty', 'hier', 'mixed', ST_AsEWKT(CreateTopoGeom('tt', 4, 8)::geometry);
 
+-- Cast directed lineal
+-- See https://trac.osgeo.org/postgis/ticket/4881
+
+-- Insert 3 horizontal edge going in mixed directions
+-- Odd ids: left-to-right
+-- Even ids: right-to-left
+INSERT INTO tt.node(node_id, containing_face, geom) VALUES
+( 1, NULL, 'SRID=4326;POINT(1 0)' ),
+( 2, NULL, 'SRID=4326;POINT(2 0)' ),
+( 3, NULL, 'SRID=4326;POINT(3 0)' ),
+( 4, NULL, 'SRID=4326;POINT(4 0)' )
+;
+SELECT NULL FROM setval('tt.node_node_id_seq', 3);
+INSERT INTO tt.edge(
+  edge_id, start_node, end_node,
+  next_left_edge, next_right_edge,
+  left_face, right_face,
+  geom
+)
+VALUES (
+  1, 1, 2,
+  -2, 1,
+  0, 0,
+  'SRID=4326;LINESTRING(0 0, 1 0)'
+),(
+  2, 3, 2,
+  -1, 2,
+  0, 0,
+  'SRID=4326;LINESTRING(2 0, 1 0)'
+),(
+  3, 3, 4,
+  -3, 2,
+  0, 0,
+  'SRID=4326;LINESTRING(2 0, 3 0)'
+)
+;
+SELECT NULL FROM setval('tt.edge_data_edge_id_seq', 2);
+
+-- Insert two lines using the horizontal edge
+-- in opposite directions
+INSERT INTO tt.f_line(lbl, g) VALUES (
+  'dir.2r', CreateTopoGeom('tt', 2, 2, '{{1,2},{-2,2},{3,2}}')
+), (
+  'dir.2l', CreateTopoGeom('tt', 2, 2, '{{-1,2},{-3,2},{2,2}}')
+), (
+  'dir.multi.2r', CreateTopoGeom('tt', 2, 2, '{{1,2},{3,2}}')
+), (
+  'dir.multi.2l', CreateTopoGeom('tt', 2, 2, '{{-1,2},{-3,2}}')
+), (
+  'dir.multi.converge', CreateTopoGeom('tt', 2, 2, '{{1,2},{-3,2}}')
+), (
+  'dir.multi.diverge', CreateTopoGeom('tt', 2, 2, '{{-1,2},{3,2}}')
+);
+
+-- Check out lines are rendered with direction
+-- based on their signed element_id
+SELECT
+  '#4881',
+  'E',
+  e.edge_id,
+  ST_AsText(e.geom)
+FROM tt.edge e
+ORDER BY e.edge_id;
+
+SELECT
+  '#4881',
+  l.lbl,
+  ST_AsEWKT(ST_CollectionHomogenize(l.g::geometry)),
+  array_agg(r.element_id ORDER BY abs(r.element_id))
+FROM tt.f_line l, tt.relation r
+WHERE lbl like 'dir.%'
+AND r.topogeo_id = id(l.g)
+GROUP BY 1,2,3
+ORDER BY lbl;
+
 -- Cleanup
 SELECT NULL FROM DropTopology('tt');
diff --git a/topology/test/regress/geometry_cast_expected b/topology/test/regress/geometry_cast_expected
index b692443..4ef94e4 100644
--- a/topology/test/regress/geometry_cast_expected
+++ b/topology/test/regress/geometry_cast_expected
@@ -6,3 +6,12 @@ empty|hier|puntal|SRID=4326;MULTIPOINT EMPTY
 empty|hier|lineal|SRID=4326;MULTILINESTRING EMPTY
 empty|hier|areal|SRID=4326;MULTIPOLYGON EMPTY
 empty|hier|mixed|SRID=4326;GEOMETRYCOLLECTION EMPTY
+#4881|E|1|LINESTRING(0 0,1 0)
+#4881|E|2|LINESTRING(2 0,1 0)
+#4881|E|3|LINESTRING(2 0,3 0)
+#4881|dir.2l|SRID=4326;LINESTRING(3 0,2 0,1 0,0 0)|{-1,2,-3}
+#4881|dir.2r|SRID=4326;LINESTRING(0 0,1 0,2 0,3 0)|{1,-2,3}
+#4881|dir.multi.2l|SRID=4326;MULTILINESTRING((1 0,0 0),(3 0,2 0))|{-1,-3}
+#4881|dir.multi.2r|SRID=4326;MULTILINESTRING((0 0,1 0),(2 0,3 0))|{1,3}
+#4881|dir.multi.converge|SRID=4326;MULTILINESTRING((0 0,1 0),(3 0,2 0))|{1,-3}
+#4881|dir.multi.diverge|SRID=4326;MULTILINESTRING((1 0,0 0),(2 0,3 0))|{-1,3}
diff --git a/topology/topology.sql.in b/topology/topology.sql.in
index aa3383f..4f01bc0 100644
--- a/topology/topology.sql.in
+++ b/topology/topology.sql.in
@@ -1343,15 +1343,30 @@ AND element_type = 3
 
   ELSIF topogeom.type = 2 THEN -- [multi]line -- }{
 
-    sql :=
-      'SELECT st_multi(ST_LineMerge(ST_Collect(e.geom))) as g FROM '
-      || quote_ident(toponame) || '.edge e, '
-      || quote_ident(toponame) || '.relation r '
-         ' WHERE r.topogeo_id = ' || topogeom.id
-      || ' AND r.layer_id = ' || topogeom.layer_id
-      || ' AND r.element_type = 2 '
-         ' AND abs(r.element_id) = e.edge_id';
-    EXECUTE sql INTO geom;
+    sql := format(
+      $$
+SELECT
+  st_multi(
+    ST_LineMerge(
+      ST_Collect(
+        CASE
+          WHEN r.element_id > 0 THEN
+            e.geom
+          ELSE
+            ST_Reverse(e.geom)
+        END
+      )
+    )
+  ) as g
+FROM %1$I.edge e, %1$I.relation r
+WHERE r.topogeo_id = id($1)
+AND r.layer_id = layer_id($1)
+AND r.element_type = 2
+AND abs(r.element_id) = e.edge_id
+      $$,
+      toponame
+    );
+    EXECUTE sql USING topogeom INTO geom;
 
   ELSIF topogeom.type = 1 THEN -- [multi]point -- }{
 

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

Summary of changes:
 NEWS                                               |  4 +-
 liblwgeom/lwgeom_topo.c                            | 62 +++++++++++++--
 topology/test/regress/geometry_cast.sql            | 91 ++++++++++++++++++++--
 topology/test/regress/geometry_cast_expected       |  9 +++
 .../test/regress/topogeo_addlinestring_expected    |  4 +-
 topology/test/regress/totopogeom.sql               | 19 +++++
 topology/test/regress/totopogeom_expected          |  3 +
 topology/topology.sql.in                           | 33 +++++---
 8 files changed, 197 insertions(+), 28 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list