Opened 2 years ago
Closed 17 months ago
#5293 closed defect (worksforme)
toTopoGeom: corrupted topology: face xxx could not be constructed only from edges knowing about it (like edge yyy).
Reported by: | strk | Owned by: | strk |
---|---|---|---|
Priority: | medium | Milestone: | PostGIS 3.4.0 |
Component: | topology | Version: | master |
Keywords: | Cc: |
Description
Single-process incremental population of a topology resulted in receiving corrupted-topology messages:
toto=# update uso_suolo set tgeom = totopogeom(cgeom, 'topo_uso_suolo', 1, 1e-3) where id < 1000; UPDATE 999 Time: 2787.209 ms (00:02.787) toto=# update uso_suolo set tgeom = totopogeom(cgeom, 'topo_uso_suolo', 1, 1e-3) where id between 1001 and 3000; UPDATE 2000 Time: 6922.480 ms (00:06.922) toto=# update uso_suolo set tgeom = totopogeom(cgeom, 'topo_uso_suolo', 1, 1e-3) where id between 3001 and 5000; UPDATE 2000 Time: 26212.861 ms (00:26.213) toto=# update uso_suolo set tgeom = totopogeom(cgeom, 'topo_uso_suolo', 1, 1e-3) where id between 5001 and 6000; UPDATE 1000 Time: 3472.713 ms (00:03.473) toto=# update uso_suolo set tgeom = totopogeom(cgeom, 'topo_uso_suolo', 1, 1e-3) where id between 6001 and 10000; UPDATE 4000 Time: 68680.044 ms (01:08.680) toto=# update uso_suolo set tgeom = totopogeom(cgeom, 'topo_uso_suolo', 1, 1e-3) where id between 10001 and 15000; UPDATE 5000 Time: 160572.868 ms (02:40.573) toto=# update uso_suolo set tgeom = totopogeom(cgeom, 'topo_uso_suolo', 1, 1e-3) where id between 15001 and 20000; NOTICE: Corrupted topology: face 6269 could not be constructed only from edges knowing about it (like edge 43264). NOTICE: Corrupted topology: face 4989 could not be constructed only from edges knowing about it (like edge 43601). NOTICE: Corrupted topology: face 14444 could not be constructed only from edges knowing about it (like edge 43499). NOTICE: Corrupted topology: face 4989 could not be constructed only from edges knowing about it (like edge 43601). UPDATE 642 Time: 18218.007 ms (00:18.218)
It looks like topology was corrupted in one of the first steps. I'm opening the ticket without much detail to not forget about it. The plan is to add more detail later, when found.
PostGIS full version is:
POSTGIS="3.4.0dev 3.3.0rc2-330-gb4e198bf3" [EXTENSION] PGSQL="130" GEOS="3.11.0dev-CAPI-1.16.0" PROJ="8.2.1" LIBXML="2.9.13" LIBJSON="0.15" LIBPROTOBUF="1.3.3" WAGYU="0.5.0 (Internal)" TOPOLOGY
The topology is in meters so we're talking about a "snap tolerance" of 1mm.
Attachments (5)
Change History (20)
comment:1 by , 2 years ago
comment:2 by , 2 years ago
comment:3 by , 21 months ago
I could reproduce and found corruption already between 6001 and 10000:
=# update uso_suolo set tgeom = totopogeom(cgeom, 'topo_uso_suolo', 1, 1e-3) where id between 6001 and 10000; NOTICE: Corrupted topology: face 7486 could not be constructed only from edges knowing about it (like edge 21197). UPDATE 4000 =# select * from validatetopology('topo_uso_suolo'); NOTICE: Checking for coincident nodes NOTICE: Checking for edges crossing nodes NOTICE: Checking for invalid or not-simple edges NOTICE: Checking for crossing edges NOTICE: Checking for edges start_node mismatch NOTICE: Checking for edges end_node mismatch NOTICE: Checking for faces without edges NOTICE: Checking edge linking NOTICE: Building edge rings NOTICE: Found 14290 rings, 10818 valid shells, 3471 valid holes error | id1 | id2 -----------------------------+--------+----- mixed face labeling in ring | -21197 | (1 row)
I'm not sure if it's good for the Corrupted topology
message to be just a NOTICE rather than an Exception, at that point ...
comment:4 by , 21 months ago
Confirmed the same problem here I think https://gitlab.com/nibioopensource/resolve-overlap-and-gap/-/issues/16#note_1262985363 .
comment:5 by , 21 months ago
Here is test creating topology error with one tread and 7 input polygon https://gitlab.com/nibioopensource/resolve-overlap-and-gap/-/jobs/3736311302
The error we get is this
And the issue is here https://gitlab.com/nibioopensource/resolve-overlap-and-gap/-/issues/46
If i run the same test on db01tempdata.nibio.no postgres@rmp_build_tiltak_layers=#
POSTGIS="3.4.0dev 3.3.0rc2-573-g9db2a5fb0" [EXTENSION] PGSQL="120" GEOS="3.9.1-CAPI-1.14.2" SFCGAL="1.3.7" PROJ="7.2.1" LIBXML="2.9.10" LIBJSON="0.13.1" LIBPROTOBUF="1.3.3" WAGYU="0.5.0 (Internal)" TOPOLOGY
I get this errors
validation postgis_ticket_5293_1 | invalid next_right_edge | 128 | -127 validation postgis_ticket_5293_1 | invalid next_left_edge | 127 | 131
comment:6 by , 21 months ago
I am testing on
POSTGIS="3.2.3 2f97b6c" [EXTENSION] PGSQL="140" GEOS="3.11.0-CAPI-1.17.0" PROJ="9.0.1" LIBXML="2.9.14" LIBJSON="0.16" LIBPROTOBUF="1.4.1" WAGYU="0.5.0 (Internal)" TOPOLOGY
This are also the same error messages related to this error https://gitlab.com/nibioopensource/resolve-overlap-and-gap/-/issues/46
When I run the command below with test.sql a couple of times this, I see the log below.
rm /tmp/error.out; psql nibio_reg -f /tmp/test.sql 2>/tmp/error.out; cat /tmp/error.out
I find this in error.out file.
Larss-MacBook-Pro:resolve-overlap-and-gap lop$ cat /tmp/error.out psql:/tmp/test.sql:1: NOTICE: 00000: Dropping all layers from topology 'postgis_ticket_5293_topo' (3) LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:1: NOTICE: 00000: drop cascades to 6 other objects DETAIL: drop cascades to table postgis_ticket_5293_topo.face drop cascades to table postgis_ticket_5293_topo.node drop cascades to table postgis_ticket_5293_topo.edge_data drop cascades to view postgis_ticket_5293_topo.edge drop cascades to sequence postgis_ticket_5293_topo.layer_id_seq drop cascades to table postgis_ticket_5293_topo.relation LOCATION: reportDependentObjects, dependency.c:1216 psql:/tmp/test.sql:74: ERROR: XX000: Corrupted topology: adjacent edges -64 and -64 bind different face (45 and 0) LOCATION: pg_error, lwgeom_pg.c:342 psql:/tmp/test.sql:79: ERROR: XX000: Corrupted topology: adjacent edges -64 and -64 bind different face (45 and 0) LOCATION: pg_error, lwgeom_pg.c:342 psql:/tmp/test.sql:111: NOTICE: 00000: Checking for coincident nodes LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checking for edges crossing nodes LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checking for invalid or not-simple edges LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checking for crossing edges LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checking for edges start_node mismatch LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checking for edges end_node mismatch LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checking for faces without edges LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checking edge linking LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Building edge rings LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Found 95 rings, 63 valid shells, 32 valid holes LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Constructing geometry of all faces LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checking faces LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checked 63 faces LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checking for holes coverage LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Finished checking for coverage of 32 holes LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:111: NOTICE: 00000: Checking for node containing_face correctness LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:112: ERROR: XX000: Corrupted topology: adjacent edges -64 and -64 bind different face (45 and 52) LOCATION: pg_error, lwgeom_pg.c:342 psql:/tmp/test.sql:113: NOTICE: 00000: Checking for coincident nodes LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checking for edges crossing nodes LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checking for invalid or not-simple edges LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checking for crossing edges LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checking for edges start_node mismatch LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checking for edges end_node mismatch LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checking for faces without edges LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checking edge linking LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Building edge rings LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Found 95 rings, 63 valid shells, 32 valid holes LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Constructing geometry of all faces LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checking faces LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checked 63 faces LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checking for holes coverage LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Finished checking for coverage of 32 holes LOCATION: exec_stmt_raise, pl_exec.c:3873 psql:/tmp/test.sql:113: NOTICE: 00000: Checking for node containing_face correctness LOCATION: exec_stmt_raise, pl_exec.c:3873
comment:7 by , 17 months ago
I've just tested the test you attached (thanks!) and it gives me a slightly different (and funny) error:
ERROR: Corrupted topology: adjacent edges 65 and 65 bind different face (52 and 45)
In any case it's capable of reproducing the problem so great work there!
by , 17 months ago
Attachment: | postgis_ticket_5293_topo.pgdump added |
---|
by , 17 months ago
Attachment: | tinyFaces.png added |
---|
by , 17 months ago
Attachment: | nearlyCoincidentEdges.png added |
---|
comment:8 by , 17 months ago
I've split your script in a "prepare" and a "test" phase, whereas the "prepare" creates the topology up to the point in which you test it for validity and it passes it, and the "test" attempts to add the last line, failing with the message above and rolls it back.
In this was I was able to further reduce the dataset and I've attached a smaller topology dump file ( to be used with pgtopo_import ) to create the starting condition. https://trac.osgeo.org/postgis/attachment/ticket/5293/postgis_ticket_5293_topo.pgdump
Next I'm looking at the found-to-be-valid topology via QGIS and immediately realizing there are a lot of nearly cohincident edges, so close each other that QGIS itself is unable to show the gap. The Topology Viewer is capable of showing us the faces though, via the "face seed" layer, which I'm showing here:
The edges referred to by my error message are showed here, with all the limits QGIS imposes (is unable to show the node, and to show the labels):
Faces 52 and 45 are the "external" faces (not the tiny faces in between those two edges).
I guess when the incoming line is noded with the existing lines those almost coincident edges are going to confuse the algorithms computing sides and order of edges around a node.
The good thing is that on my system there's no corruption because the attempt to insert the last line fails instead. My system's versions:
POSTGIS="3.4.0dev 3.3.0rc2-902-g9ea7418ef" [EXTENSION] PGSQL="130" GEOS="3.12.0dev-CAPI-1.18.0" PROJ="9.1.1" LIBXML="2.9.13" LIBJSON="0.15" LIBPROTOBUF="1.3.3" WAGYU="0.5.0 (Internal)" TOPOLOGY
comment:9 by , 17 months ago
For the record: in the situation described above, removing one of the two edges contending that node allowed to succeed in inserting the incoming line:
select topology.ST_RemEdgeModFace('postgis_ticket_5293_topo', 65);
I should note that after adding the incoming line we're still left with many tiny tiny faces:
=# select face_id, st_area(topology.st_getfacegeometry('postgis_ticket_5293_topo', face_id)) from postgis_ticket_5293_topo.face where face_id > 0; face_id | st_area ---------+------------------------ 35 | 3.225338615683592e-15 36 | 3.0876028734852634e-16 37 | 1.325799232980171e-14 38 | 1.692312908156489e-14 39 | 1.2586570072969456e-16 40 | 5.816003342750131e-15 41 | 9.482633197950748e-16 42 | 5.071487202375476e-15 43 | 1.9242697442172733e-15 44 | 2.7261901069676923e-15 46 | 2.687186386597784e-15 47 | 1.2678269542001519e-14 48 | 4.2527341168471194e-16 45 | 1.4590039951102688e-06 (14 rows)
I'm guessing only face 45 is a face really needed, given it's size.
comment:10 by , 17 months ago
The smallest input still able to trigger the error after loading the topology from my dump is just two vertices, so a corrupt.sql script could contain just this code:
BEGIN; -- so it can be reproducible SELECT topology.TopoGeo_addLinestring( 'postgis_ticket_5293_topo', 'SRID=4258;LINESTRING(5.803646305 59.263416658000004, 5.803874188 59.263357466500004)', 0 ); ROLLBACK;
by , 17 months ago
Attachment: | incomingLine.png added |
---|
comment:11 by , 17 months ago
This is a picture of the small incoming line found, with evidence of the first point of it added to the topology.
The problem is with adding that single point, and specifically with the code trying to figure out in which face that point would fall, and doing so by attempting to compute angles. The test thus reduces to this:
BEGIN; -- so it can be reproducible SELECT topology.TopoGeo_addPoint( 'postgis_ticket_5293_topo', 'SRID=4258;POINT(5.803646305 59.263416658000004)', 0 ); ROLLBACK;
The problem seems to be with ordering the nearly cohincident edges (64 and 65) around their node to find where the newly added node lays.
From the logs I discover the problem being in the code computing the endpoint, bogusly considering the last two points of edge 64 being the same, due to use of p2d_same function using FP_EQUALS instead of strict equality.
comment:12 by , 17 months ago
This pull request fixes the problem with the small test: https://git.osgeo.org/gitea/postgis/postgis/pulls/124
I've yet to test this with the original submission
comment:13 by , 17 months ago
I now believe the original submission in this bug is different, in that it was about a corrupted topology resulting from loading data from a single thread. The problem reported by Lars in comment:6 and then simplified by me is instead about the inability to populate a topology due to an exception with a message reporting a topology corruption that doesn't really exist. I've created ticket #5394 to track that case, so we can keep this for the original submission.
comment:14 by , 17 months ago
I could not reproduce the problem in the original submission, so closing as non actable.
comment:15 by , 17 months ago
Resolution: | → worksforme |
---|---|
Status: | new → closed |
Interesting fact: removing the edges reported as being the start of a ring with mixed-face labeling using the qgis-topo-edit plugin fixed the invalidity.
ValidateTopology output before fixing things:
With QGIS I've selected the 3 edges reported in column
id1
and hit the 'delete edges' icon. The operation successfully removed all 3 edges (no complains about them being needed for any TopoGeometry) and at the end of that operation ValidateTopology runs clean: