peterstace / simplefeatures

Simple Features is a pure Go Implementation of the OpenGIS Simple Feature Access Specification
MIT License
129 stars 19 forks source link

Investigate possible bug in validation algorithm #275

Closed peterstace closed 3 years ago

peterstace commented 3 years ago

GEOS has emitted the attached WKBs, and simplefeatures as reporting them as invalid. There are two possibilities:

The task here is to investigate to see which of the two cases we are looking at. possible_validation_bug.txt

peterstace commented 3 years ago

The first multipolygon in the attached file contains 6 child polygons. The 4th child polygon's exterior ring is not simple, which violates the validation rules for polygons. In particular, the offending control points in the exterior ring are:

Index  Point
297    {151.1567491196036 -33.578014746144}
298    {151.15686002573   -33.57427243628813}
299    {151.15686002573   -33.57427243628814}
300    {151.15686002573   -33.57427243628813}
301    {151.1568730920001 -33.57428004599996}
302    {151.1569620060001 -33.57433404699998}

The 298th and 300th control point are identical, so this ring doubles back on itself (thus making it non-simple and thus the Polgyon invalid).

This confirms that GEOS has emitted an invalid geometry it this case, and simplefeatures' MultiPolygon validation algorithm is correctly identifying it as such.

This agrees with what PostGIS is saying as well:

SELECT ST_IsValid('01060000000600000... omitted for brevity ...417eb119bc40c0'::geometry);

NOTICE:  Self-intersection at or near point 151.15686002573 -33.57427243628814
 st_isvalid
------------
 f
(1 row)

Interestingly the 299th control point is only a single ULP away from the 298th and 300th control point, so we're dealing with a very marginal case here (so it's understandable that GEOS doesn't get this 100% correct).


What I'm thinking right now is that we probably have to just deal with GEOS sometimes giving invalid geometries. There are a few possible ways to work around this:

I'm thinking that option 2 is probably the best.

peterstace commented 3 years ago

Something that I haven't considered yet is that GEOS emitted invalid geometries because the inputs to its operation (intersection in this case) were invalid. If this is the case, it would mean that there is a bug in simplefeatures geometry validation logic (i.e. it didn't detect an invalid geometry as being invalid). I'll take a look into that. EDIT: this turned out not to be the case, see the comment below).

peterstace commented 3 years ago

The input geometries to the GEOS operation seems to be valid. However, they contain control points that are extremely close together.

This is an extract from the input geometry to GEOS around 151.15686002573, -33.57427243628814 (which is where the GEOS result had self-intersection in its outer ring):

        [
          151.1567888500001,
          -33.57423098399994
        ],
        [
          151.15686002573,
          -33.57427243628814
        ],
        [
          151.15686002573,
          -33.57427243628813
        ],
        [
          151.1568730920001,
          -33.57428004599996
        ],

With adjacent control points only a single ULP appart from each other, I'm not surprised at all that GEOS has trouble with these.

peterstace commented 3 years ago

Nothing more to do here, closing.