From 011b81a85ddc3c44612444b1c02e2d5cff5905db Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Wed, 24 Feb 2016 17:25:11 +0000 Subject: [PATCH] Check for side-location conflicts when adding a new edge It is possible to trigger such failure adding an edge to a corrupted topology. Test added. See #3464 git-svn-id: http://svn.osgeo.org/postgis/trunk@14690 b70326c6-7e19-0410-871a-916f4a2858ee --- liblwgeom/lwgeom_topo.c | 18 +++++++++++++ topology/test/regress/st_addedgemodface.sql | 25 +++++++++++++++++++ .../test/regress/st_addedgemodface_expected | 2 ++ 3 files changed, 45 insertions(+) diff --git a/liblwgeom/lwgeom_topo.c b/liblwgeom/lwgeom_topo.c index d2741c36f..f525f3b5a 100644 --- a/liblwgeom/lwgeom_topo.c +++ b/liblwgeom/lwgeom_topo.c @@ -2561,9 +2561,27 @@ _lwt_AddEdge( LWT_TOPOLOGY* topo, newedge.edge_id, newedge.next_left, prev_right); if ( newedge.face_right == -1 ) { newedge.face_right = span.ccwFace; + } else if ( newedge.face_right != epan.ccwFace ) { + /* side-location conflict */ + lwerror("Side-location conflict: " + "new edge starts in face" + " %" PRId64 " and ends in face" + " %" PRId64, + newedge.face_right, epan.ccwFace + ); + return -1; } if ( newedge.face_left == -1 ) { newedge.face_left = span.cwFace; + } else if ( newedge.face_left != epan.cwFace ) { + /* side-location conflict */ + lwerror("Side-location conflict: " + "new edge starts in face" + " %" PRId64 " and ends in face" + " %" PRId64, + newedge.face_left, epan.cwFace + ); + return -1; } } else { epan.was_isolated = 1; diff --git a/topology/test/regress/st_addedgemodface.sql b/topology/test/regress/st_addedgemodface.sql index 31caa4481..f6b066853 100644 --- a/topology/test/regress/st_addedgemodface.sql +++ b/topology/test/regress/st_addedgemodface.sql @@ -476,6 +476,31 @@ SELECT 'T29', 'E'||edge_id, next_left_edge, next_right_edge, ( SELECT edge_id FROM newedge WHERE id = 29 ) ) ORDER BY edge_id; +-- +-- Attempt to add an edge to a topology with conflicting +-- side-locations (face left/right information) +-- +-- See https://trac.osgeo.org/postgis/ticket/3464 + +--BEGIN; prot +-- Break face info for edge 6 +UPDATE city_data.edge_data SET left_face = left_face + 1 + WHERE edge_id = 6; +-- First attempt to add edge, expect to find corrupted topology +SELECT '#3464.1', topology.ST_AddEdgeModFace('city_data', 16, 19, + 'LINESTRING(9 22,28 25,47 22)'); +-- Break face info for edges 21 +UPDATE city_data.edge_data SET left_face = left_face + 1 + WHERE edge_id = 21; +-- Second attempt to add an edge splitting the now-conflicting face +SELECT '#3464.2', topology.ST_AddEdgeModFace('city_data', 16, 19, + 'LINESTRING(9 22,28 25,47 22)'); +-- Restore face info for edge 6 and 21 +UPDATE city_data.edge_data SET left_face = left_face - 1 + WHERE edge_id in ( 6, 21 ); + +--BEGIN; prot; + --------------------------------------------------------------------- -- Check new relations and faces status --------------------------------------------------------------------- diff --git a/topology/test/regress/st_addedgemodface_expected b/topology/test/regress/st_addedgemodface_expected index 31b944c13..cb03d4224 100644 --- a/topology/test/regress/st_addedgemodface_expected +++ b/topology/test/regress/st_addedgemodface_expected @@ -167,6 +167,8 @@ T29|E21|6|34|0|35 T29|E33|-55|-6|17|3 T29|E34|55|9|35|16 T29|E55|-21|19|35|17 +ERROR: Corrupted topology: adjacent edges 6 and -21 bind different face (1 and 0) +ERROR: Side-location conflict: new edge starts in face 1 and ends in face 0 F17|{3:17,3:35} F3,F4|{3:3,3:4,3:10,3:16,3:17,3:35} F5,N4|{1:4,3:5,3:11} -- 2.40.0