Opened 5 days ago

Last modified 4 days ago

#5859 new defect

Postgis Topology err Programmatic error ? Geometry of face 1098 is empty!

Reported by: Lars Aksel Opsahl Owned by: strk
Priority: medium Milestone: PostGIS 3.6.0
Component: topology Version: master
Keywords: robustness Cc: Lars Aksel Opsahl

Description

Run the file ar50_test_03_topo_1449_test.sql.gz

The topology is valid add this line

SELECT ARRAY(SELECT abs(topogeo_addlinestring) FROM topology.TopoGeo_addLinestring('ar50_test_03_topo_1449','0102000020A210000005000000DCFB152B90082740A1CB42146B814D40AC9DD8F2A6082740D604853B6B814D405E6CD922A8082740AE95904B68814D40CAB06C5B91082740795C4E2468814D40DCFB152B90082740A1CB42146B814D40',    0) )  ;

and we see this in the log

DEBUG:  00000: rehashing catalog cache id 44 for pg_proc; 33 lists, 16 buckets
LINE 1: ...lumn_default, POSITION('(' IN column_default)+2, (POSITION('...
                                                             ^
QUERY:  SELECT nextval(SUBSTRING(column_default, POSITION('(' IN column_default)+2, (POSITION(':' IN column_default)-POSITION('(' IN column_default)-3))) FROM information_schema.columns WHERE table_schema = 'ar50_test_03_topo_1449' AND table_name='edge_data' AND column_name = 'edge_id' 

LOCATION:  RehashCatCacheLists, catcache.c:926
DEBUG:  00000: rehashing catalog cache id 7 for pg_attribute; 257 tups, 128 buckets
LOCATION:  RehashCatCache, catcache.c:888
DEBUG:  00000: rehashing catalog cache id 36 for pg_namespace; 33 tups, 16 buckets
LOCATION:  RehashCatCache, catcache.c:888
NOTICE:  00000: Corrupted topology: face 1098 could not be constructed only from edges knowing about it (like edge 2978).
LOCATION:  pg_notice, lwgeom_pg.c:389
ERROR:  XX000: Programmatic error ? Geometry of face 1098 is empty!
LOCATION:  pg_error, lwgeom_pg.c:363

This is tested on

POSTGIS="3.6.0dev 3.5.0-191-g09b3419dc" [EXTENSION] PGSQL="160" GEOS="3.13.0-CAPI-1.19.0" PROJ="9.5.1 NETWORK_ENABLED=OFF URL_ENDPOINT=https://cdn.proj.org USER_WRITABLE_DIRECTORY=/Users/lop/Library/Application Support/proj DATABASE_PATH=/opt/homebrew/Cellar/proj/9.5.1/share/proj/proj.db" (compiled against PROJ 9.5.1) LIBXML="2.13.0" LIBJSON="0.18" TOPOLOGY

Change History (12)

by Lars Aksel Opsahl, 5 days ago

testfile

comment:1 by strk, 5 days ago

Does ValidateTopology not report an error ? I'll try myself but I'd expect an "empty face" to be reported as a topology invalidity, or that'd be the first bug (not reporting it)

comment:2 by strk, 5 days ago

Ok I can reproduce with:

NOTICE: Corrupted topology: face 1098 could not be constructed only from edges knowing about it (like edge 2978). ERROR: Programmatic error ? Geometry of face 1098 is empty!

A NOTICE message indeed reports an invalid topology:

NOTICE: Corrupted topology: face 1098 could not be constructed only from edges knowing about it (like edge 2978). ERROR: Programmatic error ? Geometry of face 1098 is empty!

So we probably have a bug in ValidateTopology which indeed does not report any error about having an empty face.

comment:3 by strk, 5 days ago

Another interesting observation is that face 1098 is NOT empty before the exception-throwing attempt at adding a line:

# select ST_Area(ST_GetFaceGeometry('ar50_test_03_topo_1449', 1098));
        st_area         
------------------------
 1.5621632099928084e-08
(1 row)

So it might become empty during the introduction of the new line. Digging further…

by strk, 4 days ago

Attachment: t5859.sql added

simplified testcase

by strk, 4 days ago

Attachment: case.png added

comment:4 by strk, 4 days ago

I've attached a simplified testcase with just 2 edges. The problem seems to be that these 2 edges have an almost coincident segment in common, as shown by this figure:

comment:5 by strk, 4 days ago

I guess edge 2 entered the topology AFTER edge 1 and thus missed to have edge 1 (pre-existing) SNAP to the very-close vertex of edge 2. This is the mother of all robustness bugs in PostGIS Topology. The experimental code handling edge merges now exists in the codebase but it is still only ever used when adding new NODES so this case doesn't trigger that code because no new node is considered to be needed by the preparation step.

Maybe by using fixed-precision GEOS (available since GEOS-3.9) we'd get more nodes, this could be the road ahead…

comment:6 by Lars Aksel Opsahl, 4 days ago

I am running a test now with tolerance 1e-07 to see what happens.

comment:7 by strk, 4 days ago

Keywords: robustness added

comment:8 by strk, 4 days ago

The problem is that no matter tolerance you would still NOT snap an incoming vertex to a pre-existing segment. At the moment we always ever snap incoming SEGMENTS to pre-existing VERTEXES. Except when a new intersection point is detected (as it is likely the case with #5862)

comment:9 by Lars Aksel Opsahl, 4 days ago

Running with a tolerance off 1e-07 and do simplify input by find missing edge parts when topo error on second gives us a much better result as it seems. Number of topo errors are reduced from around 600 to less than 200.

Related to gaps (missing areas) it's much better also. We had around 60 areas that got lost, we are now down to one single polygon and that polygon is also a problem with zero tolerance. We may now have result that we actually can use.

I will try create test case for that missing area later, but I have to work with other stuff now for days.

Note: See TracTickets for help on using tickets.