[postgis-tickets] [SCM] PostGIS branch main updated. 3.1.0rc1-278-g68b17cd

git at osgeo.org git at osgeo.org
Wed Jul 7 02:05:44 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, main has been updated
       via  68b17cd25273008060ecba05bc210eec0e6deb19 (commit)
       via  0bfe9da85da27efd3b61e567ba7817f0e50da4b4 (commit)
      from  098c52a9c998b8d0b520c5b934f0389ea2acad6b (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 68b17cd25273008060ecba05bc210eec0e6deb19
Author: Sandro Santilli <strk at kbt.io>
Date:   Tue Jul 6 23:48:49 2021 +0200

    Add edge linking validation to ValidateTopology
    
    Closes #3042
    Includes regression tests

diff --git a/topology/sql/manage/ValidateTopology.sql.in b/topology/sql/manage/ValidateTopology.sql.in
index bc45e6b..43ca7e3 100644
--- a/topology/sql/manage/ValidateTopology.sql.in
+++ b/topology/sql/manage/ValidateTopology.sql.in
@@ -23,6 +23,45 @@ CREATE TYPE topology.ValidateTopology_ReturnType AS (
   id2 integer
 );
 
+CREATE OR REPLACE FUNCTION topology._CheckEdgeLinking(curedge ANYELEMENT, prevedge ANYELEMENT)
+RETURNS topology.ValidateTopology_ReturnType
+AS
+$BODY$
+DECLARE
+  retrec topology.ValidateTopology_ReturnType;
+BEGIN
+  IF prevedge.edge_id > 0
+  THEN -- previous was outgoing, this one should be next-right
+    IF prevedge.next_right_edge != curedge.edge_id THEN
+      RAISE DEBUG 'Edge % should be next-right of edge %, is % instead',
+        curedge.edge_id,
+        abs(prevedge.edge_id),
+        prevedge.next_right_edge
+      ;
+      retrec.error = 'invalid next_right_edge';
+      retrec.id1 = abs(prevedge.edge_id);
+      retrec.id2 = curedge.edge_id; -- we put the expected one here, for convenience
+      RETURN retrec;
+    END IF;
+  ELSE -- previous was incoming, this one should be next-left
+    IF prevedge.next_left_edge != curedge.edge_id THEN
+      RAISE DEBUG 'Edge % should be next-left of edge %, is % instead',
+        curedge.edge_id,
+        abs(prevedge.edge_id),
+        prevedge.next_left_edge
+      ;
+      retrec.error = 'invalid next_left_edge';
+      retrec.id1 = abs(prevedge.edge_id);
+      retrec.id2 = curedge.edge_id; -- we put the expected one here, for convenience
+      RETURN retrec;
+    END IF;
+  END IF;
+
+  RETURN retrec;
+END;
+$BODY$
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;
+
 --{
 --  ValidateTopology(toponame, [bbox])
 --
@@ -44,6 +83,9 @@ DECLARE
   invalid_edges integer[];
   invalid_faces integer[];
   search_path_backup text;
+  last_node_id int;
+  last_node_first_edge RECORD;
+  last_node_prev_edge RECORD;
 BEGIN
 
   IF NOT EXISTS (
@@ -318,6 +360,103 @@ BEGIN
     RETURN NEXT retrec;
   END LOOP; --}
 
+  RAISE DEBUG 'Checking edge linking';
+  -- NOTE: this check relies on correct start_node and end_node
+  --       for edges, if those are not correct the results
+  --       of this check do not make much sense.
+  FOR rec IN
+      WITH
+      nodes AS (
+        SELECT node_id
+        FROM node
+        WHERE containing_face IS NULL
+        AND (
+          bbox IS NULL
+          OR geom && bbox
+        )
+      ),
+      incident_edges AS (
+        SELECT
+          n.node_id,
+          e.edge_id,
+          e.start_node,
+          e.end_node,
+          e.next_left_edge,
+          e.next_right_edge,
+          ST_RemoveRepeatedPoints(e.geom) as edge_geom
+        FROM edge_data e, nodes n
+        WHERE e.start_node = n.node_id
+        or e.end_node = n.node_id
+      ),
+      edge_star AS (
+        SELECT
+          node_id,
+          edge_id,
+          next_left_edge,
+          next_right_edge,
+          ST_Azimuth(ST_StartPoint(edge_geom), ST_PointN(edge_geom, 2)) as az
+        FROM incident_edges
+        WHERE start_node = node_id
+          UNION ALL
+        SELECT
+          node_id,
+          -edge_id,
+          next_left_edge,
+          next_right_edge,
+          ST_Azimuth(ST_EndPoint(edge_geom), ST_PointN(edge_geom, ST_NumPoints(edge_geom)-1))
+        FROM incident_edges
+        WHERE end_node = node_id
+      ),
+      sequenced_edge_star AS (
+        SELECT
+          row_number() over (partition by node_id order by az, edge_id) seq,
+          *
+        FROM edge_star
+      )
+      SELECT * FROM sequenced_edge_star
+      ORDER BY node_id, seq
+  LOOP --{
+    IF last_node_id IS NULL OR last_node_id != rec.node_id
+    THEN --{
+      IF last_node_id IS NOT NULL
+      THEN
+        -- Check that last edge (CW from prev one) is correctly linked
+        retrec := topology._CheckEdgeLinking(last_node_first_edge, last_node_prev_edge);
+        IF retrec IS NOT NULL
+        THEN
+          RETURN NEXT retrec;
+        END IF;
+        --RAISE DEBUG 'Finished analisys of edge star around node %', last_node_id;
+      END IF;
+      --RAISE DEBUG 'Analyzing edge star around node %', rec.node_id;
+      last_node_id = rec.node_id;
+      last_node_first_edge = rec;
+    ELSE --{
+      -- Check that this edge (CW from last one) is correctly linked
+      retrec := topology._CheckEdgeLinking(rec, last_node_prev_edge);
+      IF retrec IS NOT NULL
+      THEN
+        RETURN NEXT retrec;
+      END IF;
+    END IF; --}
+    last_node_prev_edge = rec;
+  END LOOP; --}
+  IF last_node_id IS NOT NULL THEN
+    --RAISE DEBUG 'Out of loop: last_node_id: %', last_node_id;
+    --RAISE DEBUG 'Out of loop: last_node_first_edge edge_id:% next_left_edge:%', last_node_first_edge.edge_id, last_node_first_edge.next_left_edge;
+    --RAISE DEBUG 'Out of loop: last_node_prev_edge edge_id:% next_left_edge:%', last_node_prev_edge.edge_id, last_node_prev_edge.next_left_edge;
+    --RAISE DEBUG 'Out of loop: last_node_first_edge: %', last_node_first_edge;
+    -- Check that last edge (CW from prev one) is correctly linked
+    retrec := topology._CheckEdgeLinking(last_node_first_edge, last_node_prev_edge);
+    IF retrec IS NOT NULL
+    THEN
+      RETURN NEXT retrec;
+    END IF;
+    --RAISE DEBUG 'Finished analisys of edge star around node % (out of loop)', last_node_id;
+  END IF;
+
+
+
   -- Now create a temporary table to construct all face geometries
   -- for checking their consistency
 
diff --git a/topology/test/regress/legacy_invalid.sql b/topology/test/regress/legacy_invalid.sql
index 4913451..7f4a972 100644
--- a/topology/test/regress/legacy_invalid.sql
+++ b/topology/test/regress/legacy_invalid.sql
@@ -4,8 +4,9 @@ set client_min_messages to WARNING;
 
 -- Validate full topology, store invalidities in a table
 CREATE TABLE invalid_topology.invalidities AS
-SELECT * from topology.validatetopology('invalid_topology');
-SELECT * FROM invalid_topology.invalidities;
+SELECT * FROM topology.validatetopology('invalid_topology');
+SELECT * FROM invalid_topology.invalidities
+ORDER BY 1,2,3;
 
 -- Test bbox-limited checking
 -- See https://trac.osgeo.org/postgis/ticket/4936
@@ -54,7 +55,7 @@ FROM invalid_topology.missing_invalidities ;
 
 SELECT '#4936', 'missing', *
 FROM invalid_topology.missing_invalidities
-ORDER BY error ASC;
+ORDER BY 1, 2, 3 ASC;
 
 -- clean up
 SELECT topology.DropTopology('invalid_topology');
diff --git a/topology/test/regress/legacy_invalid_expected b/topology/test/regress/legacy_invalid_expected
index 1cb4222..c1e3b5c 100644
--- a/topology/test/regress/legacy_invalid_expected
+++ b/topology/test/regress/legacy_invalid_expected
@@ -1,9 +1,5 @@
 t
 coincident nodes|1|23
-edge crosses node|1|23
-edge crosses node|27|14
-edge not simple|28|
-invalid edge|33|
 edge crosses edge|2|28
 edge crosses edge|2|29
 edge crosses edge|2|32
@@ -12,18 +8,36 @@ edge crosses edge|10|27
 edge crosses edge|19|27
 edge crosses edge|20|27
 edge crosses edge|30|32
-edge start node geometry mis-match|30|4
+edge crosses node|1|23
+edge crosses node|27|14
 edge end node geometry mis-match|30|3
-face without edges|10|
-face within face|2|11
-face overlaps face|2|12
-face has wrong mbr|3|
-face has wrong mbr|6|
-face has no rings|10|
-not-isolated node has not-null containing_face|4|
 edge not covered by both its side faces|27|
 edge not covered by both its side faces|28|
 edge not covered by both its side faces|30|
+edge not simple|28|
+edge start node geometry mis-match|30|4
+face has no rings|10|
+face has wrong mbr|3|
+face has wrong mbr|6|
+face overlaps face|2|12
+face within face|2|11
+face without edges|10|
+invalid edge|33|
+invalid next_left_edge|2|3
+invalid next_left_edge|3|-29
+invalid next_left_edge|6|29
+invalid next_left_edge|18|-27
+invalid next_left_edge|27|10
+invalid next_left_edge|29|-33
+invalid next_left_edge|30|-3
+invalid next_left_edge|31|-28
+invalid next_left_edge|33|33
+invalid next_right_edge|9|27
+invalid next_right_edge|27|-22
+invalid next_right_edge|28|-30
+invalid next_right_edge|29|7
+invalid next_right_edge|33|31
+not-isolated node has not-null containing_face|4|
 #4936|missing_count|4
 #4936|missing|face has no rings|10|
 #4936|missing|face overlaps face|2|12
diff --git a/topology/test/regress/validatetopology.sql b/topology/test/regress/validatetopology.sql
index e869a1f..33a8b27 100644
--- a/topology/test/regress/validatetopology.sql
+++ b/topology/test/regress/validatetopology.sql
@@ -72,12 +72,6 @@ SELECT null from ( select TopoGeo_addLineString('t',
 ) al;
 SELECT '#4830.0', (ValidateTopology('t')).* UNION
 SELECT '#4830.0', '---', null, null ORDER BY 1,2,3,4;
--- 0. Set edge 1 self-linking to avoid "face with no rings"
---    invalidity.
-UPDATE t.edge_data SET
-  next_left_edge = 1,
-  next_right_edge = -1
-  WHERE edge_id = 1;
 -- 1. Set wrong left_face for dangling inside edges
 BEGIN;
 UPDATE t.edge_data SET left_face = 2
@@ -123,3 +117,24 @@ SELECT '#4830.5', (ValidateTopology('t')).* UNION
 SELECT '#4830.5', '---', null, null ORDER BY 1,2,3,4;
 ROLLBACK;
 SELECT null from ( select topology.DropTopology('t') ) as dt;
+
+-- Test correctness of edge linking
+-- See https://trac.osgeo.org/postgis/ticket/3042
+\i ../load_topology.sql
+--set client_min_messages to NOTICE;
+SELECT '#3042.0', * FROM ValidateTopology('city_data');
+BEGIN;
+-- Break edge linking for all edges around node 14
+UPDATE city_data.edge_data SET next_left_edge = -next_left_edge where edge_id in (9,10,20);
+UPDATE city_data.edge_data SET next_right_edge = -next_right_edge where edge_id = 19;
+-- Break edge linking of dangling edges, including one around last node (3)
+UPDATE city_data.edge_data
+SET
+  next_left_edge = -next_left_edge,
+  next_right_edge = -next_right_edge
+where edge_id in (3,25);
+set client_min_messages to WARNING;
+SELECT '#3042.1', * FROM ValidateTopology('city_data');
+ROLLBACK;
+SELECT NULL FROM topology.DropTopology('city_data');
+
diff --git a/topology/test/regress/validatetopology_expected b/topology/test/regress/validatetopology_expected
index c5254ab..b164c91 100644
--- a/topology/test/regress/validatetopology_expected
+++ b/topology/test/regress/validatetopology_expected
@@ -22,3 +22,11 @@
 #4830.4|edge not covered by both its side faces|8|
 #4830.5|---||
 #4830.5|edge covered by some face has universal face on both sides|9|
+#3042.1|invalid next_right_edge|3|2
+#3042.1|invalid next_left_edge|3|-3
+#3042.1|invalid next_right_edge|19|-10
+#3042.1|invalid next_left_edge|10|-20
+#3042.1|invalid next_left_edge|20|-9
+#3042.1|invalid next_left_edge|9|19
+#3042.1|invalid next_right_edge|25|25
+#3042.1|invalid next_left_edge|25|-25

commit 0bfe9da85da27efd3b61e567ba7817f0e50da4b4
Author: Sandro Santilli <strk at kbt.io>
Date:   Wed Jul 7 01:04:33 2021 +0200

    Fix reference to ticket about face coverage check
    
    NOTE: this is currently the slowest test in ValidateTopology

diff --git a/topology/sql/manage/ValidateTopology.sql.in b/topology/sql/manage/ValidateTopology.sql.in
index 5bc19cb..bc45e6b 100644
--- a/topology/sql/manage/ValidateTopology.sql.in
+++ b/topology/sql/manage/ValidateTopology.sql.in
@@ -460,7 +460,7 @@ BEGIN
     RETURN NEXT retrec;
   END LOOP; --}
 
-  -- Check edges are covered by their left-right faces (#4831)
+  -- Check edges are covered by their left-right faces (#4830)
   RAISE DEBUG 'Checking for edges coverage';
   FOR rec IN
     WITH edge_coverage AS (

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

Summary of changes:
 topology/sql/manage/ValidateTopology.sql.in     | 141 +++++++++++++++++++++++-
 topology/test/regress/legacy_invalid.sql        |   7 +-
 topology/test/regress/legacy_invalid_expected   |  38 +++++--
 topology/test/regress/validatetopology.sql      |  27 ++++-
 topology/test/regress/validatetopology_expected |   8 ++
 5 files changed, 199 insertions(+), 22 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list