Opened 3 years ago

Closed 3 years ago

#4943 closed defect (fixed)

st_equals fails on invalid geometry with GEOS error

Reported by: mschott Owned by: pramsey
Priority: medium Milestone: PostGIS 3.1.3
Component: postgis Version: 3.1.x
Keywords: st_equals, GEOS, invalid Cc:

Description

To my understanding the documentation of st_equals implies that it can handle (any) invalid geometry:

This function will return false if either geometry is invalid except in the case where they are binary equal.

It does well for some invalidities but yet it seems there are some invalidities it cannot handle (ERROR: GEOSEquals: TopologyException: side location conflict at):

(Please excuse the complex geometries, that is what I have at hand.)

WITH geoms AS (
    SELECT
        st_geomfromtext('MULTIPOLYGON(((14.711908999999999 46.175287799999985,14.7119403 46.17528399999999,14.712043699999999 46.17527129999999,14.712023999999998 46.17515749999998,14.711904699999998 46.1748776,14.711897200000001 46.17485999999999,14.7119029 46.174857499999995,14.711919700000001 46.1748503,14.711959199999997 46.174827,14.7120661 46.174817499999996,14.7120608 46.174768599999986,14.7122971 46.174734,14.712238999999999 46.174561999999995,14.712192000000002 46.17439979999999,14.7121222 46.1741564,14.712056299999997 46.174006000000006,14.7120263 46.17394689999999,14.7120451 46.1739321,14.712129399999998 46.173891399999995,14.7122754 46.17383729999999,14.712357299999999 46.173807599999996,14.7123322 46.173750899999995,14.712368999999999 46.1737399,14.7123427 46.17366809999999,14.7121531 46.17327459999999,14.712130499999999 46.17324029999999,14.7120963 46.17324879999999,14.7119517 46.17325830000001,14.711925999999998 46.173229500000005,14.7120755 46.173199499999996,14.712074200000002 46.1730594,14.712032899999999 46.1730325,14.712009499999999 46.172948899999994,14.7119561 46.172940999999994,14.7118971 46.1728275,14.7117781 46.1728756,14.711801000000001 46.17292769999999,14.7117356 46.172946299999985,14.711682000000001 46.1729615,14.711538399999998 46.1727602,14.7115076 46.17272059999999,14.711494799999997 46.17270499999999,14.7114768 46.17268289999999,14.711366600000002 46.1725103,14.711145799999999 46.17216689999999,14.711139699999999 46.17212899999999,14.7111287 46.17207719999999,14.711133 46.17205119999999,14.7112039 46.17201279999999,14.7113616 46.1719598,14.7113496 46.17185769999999,14.7113159 46.171853699999986,14.711257 46.1718184,14.711195499999999 46.171753800000005,14.711153800000002 46.17168949999999,14.711139600000001 46.1716931,14.7109884 46.171721600000005,14.710844199999997 46.1717354,14.710749999999999 46.1717489,14.7108627 46.17196779999999,14.710812299999999 46.171982400000005,14.710813799999999 46.17199859999999,14.7108034 46.172016499999984,14.710631500000002 46.1720903,14.710596400000002 46.1720921,14.7105497 46.17212920000001,14.710518599999997 46.1721529,14.710184799999999 46.1722633,14.7100399 46.1723096,14.709667300000001 46.172414499999995,14.7092561 46.172506799999994,14.7089821 46.17255459999999,14.708867 46.17257,14.7088886 46.1726602,14.7089738 46.172674799999996,14.709225799999999 46.17269699999999,14.7093456 46.1727044,14.709396000000002 46.172713599999994,14.709478399999998 46.1727371,14.709643499999997 46.17275359999999,14.7098084 46.1727917,14.709956900000002 46.172876499999994,14.7100807 46.172921599999995,14.710359200000001 46.173070899999985,14.710397599999999 46.17311939999999,14.710477099999999 46.17321639999999,14.710693099999997 46.17335499999999,14.7108192 46.17342699999998,14.710888599999997 46.1734621,14.7109351 46.1734667,14.711037699999999 46.17343909999999,14.711065699999999 46.173454799999995,14.710973599999999 46.1734991,14.710882400000001 46.1735696,14.710893599999999 46.173603,14.7109552 46.17364339999999,14.711024300000002 46.173689200000005,14.711145599999998 46.17376949999999,14.711179399999997 46.173854000000006,14.7112159 46.17405539999999,14.7112336 46.17416419999999,14.711363899999998 46.174357099999995,14.7113994 46.174346999999976,14.7114614 46.17431789999999,14.7115851 46.174326,14.711647099999997 46.174296799999986,14.711803199999999 46.1745492,14.711628699999999 46.17458909999999,14.711710699999998 46.17476070000001,14.711728899999999 46.1747593,14.7118483 46.175072799999995,14.711825999999999 46.17514149999999,14.711859599999999 46.1752496,14.7119036 46.17524869999999,14.711908999999999 46.175287799999985),(14.711754799999998 46.17316590000001,14.7118191 46.17324839999999,14.711830099999998 46.17329750000001,14.7117808 46.1733315,14.711769900000002 46.173338500000014,14.711719999999998 46.17337089999999,14.7115953 46.173447299999985,14.7115415 46.1734717,14.711524599999999 46.173471699999986,14.711439299999997 46.17342929999999,14.7113556 46.17338719999999,14.7112634 46.173338199999996,14.711184900000001 46.17326829999999,14.711171499999999 46.17323090000001,14.711110399999999 46.173115900000006,14.7110679 46.1730466,14.711295999999999 46.1729729,14.711145299999998 46.17276739999999,14.7114072 46.1726841,14.711466 46.172779699999985,14.711578799999998 46.172939699999986,14.711754799999998 46.17316590000001)))') AS a,
        st_geomfromtext('MULTIPOLYGON(((14.711909 46.1752878,14.7119403 46.175284,14.7120437 46.1752713,14.712024 46.1751575,14.7119047 46.1748776,14.7118972 46.17486,14.7119029 46.1748575,14.7119197 46.1748503,14.7119592 46.174827,14.7120661 46.1748175,14.7120608 46.1747686,14.7122971 46.174734,14.712239 46.174562,14.712192 46.1743998,14.7121222 46.1741564,14.7120563 46.174006,14.7120263 46.1739469,14.7120451 46.1739321,14.7121294 46.1738914,14.7122754 46.1738373,14.7123573 46.1738076,14.7123322 46.1737509,14.712369 46.1737399,14.7123427 46.1736681,14.7121531 46.1732746,14.7121305 46.1732403,14.7120963 46.1732488,14.7119517 46.1732583,14.711926 46.1732295,14.7120755 46.1731995,14.7120742 46.1730594,14.7120329 46.1730325,14.7120095 46.1729489,14.7119561 46.172941,14.7118971 46.1728275,14.7117781 46.1728756,14.711801 46.1729277,14.7117356 46.1729463,14.711682 46.1729615,14.7115384 46.1727602,14.7115076 46.1727206,14.7114948 46.172705,14.7114768 46.1726829,14.7113666 46.1725103,14.7111458 46.1721669,14.7111397 46.172129,14.7111287 46.1720772,14.711133 46.1720512,14.7112039 46.1720128,14.7113616 46.1719598,14.7113496 46.1718577,14.7113159 46.1718537,14.711257 46.1718184,14.7111955 46.1717538,14.7111538 46.1716895,14.7111396 46.1716931,14.7109884 46.1717216,14.7108442 46.1717354,14.71075 46.1717489,14.7108627 46.1719678,14.7108123 46.1719824,14.7108138 46.1719986,14.7108034 46.1720165,14.7106315 46.1720903,14.7105964 46.1720921,14.7105497 46.1721292,14.7105186 46.1721529,14.7101848 46.1722633,14.7100399 46.1723096,14.7096673 46.1724145,14.7092561 46.1725068,14.7089821 46.1725546,14.708867 46.17257,14.7088886 46.1726602,14.7089738 46.1726748,14.7092258 46.172697,14.7093456 46.1727044,14.709396 46.1727136,14.7094784 46.1727371,14.7096435 46.1727536,14.7098084 46.1727917,14.7099569 46.1728765,14.7100807 46.1729216,14.7103592 46.1730709,14.7103976 46.1731194,14.7104771 46.1732164,14.7106931 46.173355,14.7108192 46.173427,14.7108886 46.1734621,14.7109351 46.1734667,14.7110377 46.1734391,14.7110657 46.1734548,14.7109736 46.1734991,14.7108824 46.1735696,14.7108936 46.173603,14.7109552 46.1736434,14.7110243 46.1736892,14.7111456 46.1737695,14.7111794 46.173854,14.7112159 46.1740554,14.7112336 46.1741642,14.7113639 46.1743571,14.7113994 46.174347,14.7114614 46.1743179,14.7115851 46.174326,14.7116471 46.1742968,14.7118032 46.1745492,14.7116287 46.1745891,14.7117107 46.1747607,14.7117289 46.1747593,14.7118483 46.1750728,14.711826 46.1751415,14.7118596 46.1752496,14.7119036 46.1752487,14.711909 46.1752878),(14.7117808 46.1733315,14.7118301 46.1732975,14.7118191 46.1732484,14.7117548 46.1731659,14.7117684 46.1733204,14.7117699 46.1733385,14.7117808 46.1733315),(14.711296 46.1729729,14.7110679 46.1730466,14.7111104 46.1731159,14.7111715 46.1732309,14.7111849 46.1732683,14.7112634 46.1733382,14.7113556 46.1733872,14.7114393 46.1734293,14.7115246 46.1734717,14.7115415 46.1734717,14.7115953 46.1734473,14.71172 46.1733709,14.7117699 46.1733385,14.7117684 46.1733204,14.7117548 46.1731659,14.7115788 46.1729397,14.711466 46.1727797,14.7114072 46.1726841,14.7111453 46.1727674,14.711296 46.1729729)))') AS b
)
SELECT
    st_isvalid(a),
    st_isvalid(b),
    st_isvalid(st_snaptogrid(a,0.0000001)),
    st_isvalid(st_snaptogrid(b,0.0000001)),
    st_equals(a,b)
    --,st_equals(st_snaptogrid(a,0.0000001),st_snaptogrid(b,0.0000001)) --this line will fail with ERROR: GEOSEquals: TopologyException: side location conflict at 14.7117548 46.173165900000001
FROM
    geoms; 

Side note: The st_snaptogrid is necessary for me as some geometries that are in fact equal are perceived as not equal due to rounding errors.

Change History (5)

comment:1 by mschott, 3 years ago

Sorry missed the version info:

PostgreSQL 13.3 on x86_64-pc-linux-musl, compiled by gcc (Alpine 10.3.1_git20210424) 10.3.1 20210424, 64-bit

POSTGIS="3.1.2 0" [EXTENSION] PGSQL="130" GEOS="3.9.1-CAPI-1.14.2" PROJ="7.2.1" GDAL="GDAL 3.2.2, released 2021/03/05" LIBXML="2.9.12" LIBJSON="0.15" LIBPROTOBUF="1.3.3" WAGYU="0.5.0 (Internal)" (core procs from "3.1.1 aaf4c79" need upgrade) RASTER (raster procs from "3.1.1 aaf4c79" need upgrade)

comment:2 by mdavis, 3 years ago

Yes, the doc appears to be aspirational rather than accurate. It would be nice if ST_Equals did not error out on invalid geometry. That will require a fix in GEOS.

In this case one geometry is valid, and one is invalid, so clearly they are not equal. You could test for this condition before running ST_Equals.

Another alternative is to run ST_Normalize on each snapped input, and then use ST_OrderingEquals.

comment:3 by mdavis, 3 years ago

Equality checking is surprisingly complex. ST_Equals is actually testing topological equality rather than pointwise equality. One effect of this is that it treats vertices which lie exactly on lines as equal (this case is rare in practice).

In the near future we hope to provide a new implementation for the spatial predicates which will not be so sensitive to invalidity. And hopefully it will provide a tolerance value as well, which will avoid the need for using ST_SnapToGrid.

comment:4 by mschott, 3 years ago

thank you for your great comments.

comment:5 by Paul Ramsey <pramsey@…>, 3 years ago

Resolution: fixed
Status: newclosed

In 6230cdfe/git:

Remove spurious promise that invalid inputs will result in FALSE equality return. Closes #4943

Note: See TracTickets for help on using tickets.