diff --git a/internal/cmprefimpl/cmpgeos/checks.go b/internal/cmprefimpl/cmpgeos/checks.go index 3264dec1..000878f2 100644 --- a/internal/cmprefimpl/cmpgeos/checks.go +++ b/internal/cmprefimpl/cmpgeos/checks.go @@ -7,7 +7,6 @@ import ( "fmt" "log" "math" - "math/rand" "strconv" "strings" @@ -658,7 +657,6 @@ func binaryChecks(g1, g2 geom.Geometry, lg *log.Logger) error { {"Intersects", checkIntersects}, {"ExactEquals", checkExactEquals}, {"Distance", checkDistance}, - {"DCELOperations", checkDCELOperations}, } { lg.Printf("checking %s", check.name) if err := check.fn(g1, g2, lg); err != nil { @@ -757,385 +755,3 @@ func checkDistance(g1, g2 geom.Geometry, log *log.Logger) error { } return nil } - -var skipIntersection = map[string]bool{ - "LINESTRING(0 1,0.3333333333 0.6666666667,1 0)": true, - "LINESTRING(1 0,0.5000000000000001 0.5,0 1)": true, - "MULTILINESTRING((0 0,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 2),(0 1,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 0))": true, - "MULTILINESTRING((0 1,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 0))": true, - "MULTILINESTRING((0 1,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 0),(0 0,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 2))": true, - "POLYGON((1 0,0.9807852804032305 -0.19509032201612808,0.923879532511287 -0.3826834323650894,0.8314696123025456 -0.5555702330196017,0.7071067811865481 -0.7071067811865469,0.5555702330196031 -0.8314696123025447,0.38268343236509084 -0.9238795325112863,0.19509032201612964 -0.9807852804032302,0.0000000000000016155445744325867 -1,-0.19509032201612647 -0.9807852804032308,-0.38268343236508784 -0.9238795325112875,-0.5555702330196005 -0.8314696123025463,-0.7071067811865459 -0.7071067811865491,-0.8314696123025438 -0.5555702330196043,-0.9238795325112857 -0.38268343236509234,-0.9807852804032299 -0.19509032201613122,-1 -0.0000000000000032310891488651735,-0.9807852804032311 0.19509032201612486,-0.9238795325112882 0.38268343236508634,-0.8314696123025475 0.555570233019599,-0.7071067811865505 0.7071067811865446,-0.5555702330196058 0.8314696123025428,-0.3826834323650936 0.9238795325112852,-0.19509032201613213 0.9807852804032297,-0.000000000000003736410698672604 1,0.1950903220161248 0.9807852804032311,0.38268343236508673 0.9238795325112881,0.5555702330195996 0.8314696123025469,0.7071067811865455 0.7071067811865496,0.8314696123025438 0.5555702330196044,0.9238795325112859 0.38268343236509206,0.98078528040323 0.19509032201613047,1 0))": true, - "MULTILINESTRING((0 0,2 2.000000000000001),(1 0,-1 2.000000000000001))": true, - "MULTILINESTRING((0 0,0.5 0.5,1 1,2 2.000000000000001),(1 0,0.5 0.5,0 1,-1 2.000000000000001))": true, - "POLYGON((1.5 1,1.353553390593274 0.6464466094067265,1.0000000000000009 0.5,0.646446609406727 0.6464466094067254,0.5 0.9999999999999983,0.6464466094067247 1.3535533905932722,0.9999999999999977 1.5,1.3535533905932717 1.3535533905932757,1.5 1))": true, - "POLYGON((1 0,-0.9 -0.2,-1 -0.0000000000000032310891488651735,-0.9 0.2,1 0))": true, - "LINESTRING(0.5 0,0.5000000000000001 0.5)": true, - "LINESTRING(0.5 1,0.5000000000000001 0.5)": true, - "POLYGON((1 0,0.9807852804032304 -0.19509032201612825,0.9238795325112867 -0.3826834323650898,0.8314696123025452 -0.5555702330196022,0.7071067811865476 -0.7071067811865475,0.5555702330196023 -0.8314696123025452,0.38268343236508984 -0.9238795325112867,0.19509032201612833 -0.9807852804032304,0.00000000000000006123233995736766 -1,-0.1950903220161282 -0.9807852804032304,-0.3826834323650897 -0.9238795325112867,-0.555570233019602 -0.8314696123025455,-0.7071067811865475 -0.7071067811865476,-0.8314696123025453 -0.5555702330196022,-0.9238795325112867 -0.3826834323650899,-0.9807852804032304 -0.1950903220161286,-1 -0.00000000000000012246467991473532,-0.9807852804032304 0.19509032201612836,-0.9238795325112868 0.38268343236508967,-0.8314696123025455 0.555570233019602,-0.7071067811865477 0.7071067811865475,-0.5555702330196022 0.8314696123025452,-0.38268343236509034 0.9238795325112865,-0.19509032201612866 0.9807852804032303,-0.00000000000000018369701987210297 1,0.1950903220161283 0.9807852804032304,0.38268343236509 0.9238795325112866,0.5555702330196018 0.8314696123025455,0.7071067811865474 0.7071067811865477,0.8314696123025452 0.5555702330196022,0.9238795325112865 0.3826834323650904,0.9807852804032303 0.19509032201612872,1 0))": true, - "POLYGON((1.5 1,1.3535533905932737 0.6464466094067263,1 0.5,0.6464466094067263 0.6464466094067263,0.5 0.9999999999999999,0.6464466094067262 1.3535533905932737,0.9999999999999999 1.5,1.3535533905932737 1.353553390593274,1.5 1))": true, - - // Cause simplefeatures DCEL operations to fail with "no rings" error. See - // https://github.com/peterstace/simplefeatures/pull/497 for details. - "POLYGON((-83.58253051 32.73168239,-83.59843118 32.74617142,-83.70048117 32.63984372,-83.58253051 32.73168239))": true, - "POLYGON((-83.70047745 32.63984661,-83.68891846 32.5989632,-83.58253417 32.73167955,-83.70047745 32.63984661))": true, -} - -var skipDifference = map[string]bool{ - "LINESTRING(0 1,0.3333333333 0.6666666667,0.5 0.5,1 0)": true, - "LINESTRING(0 1,0.3333333333 0.6666666667,1 0)": true, - "LINESTRING(1 0,0.5000000000000001 0.5,0 1)": true, - "MULTILINESTRING((0 0,0.5 0.5),(0.5 0.5,1 1),(0 1,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,0.5 0.5),(0.5 0.5,1 0))": true, - "MULTILINESTRING((0 1,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 0))": true, - - "MULTIPOLYGON(((1 0,0 1,0.5 1.5,1 1,1.5 1.5,2 1,1 0)),((1.5 1.5,1 2,0.5 1.5,0.333333333333333 1.66666666666667,0 2,1 3,2 2,1.5 1.5)),((3.5 1.5,4 1,3 0,2 1,2.5 1.5,3 1,3.5 1.5)),((3.5 1.5,3 2,2.5 1.5,2 2,3 3,4 2,3.5 1.5)))": true, - "POLYGON((1 0,-0.9 -0.2,-1 -0.0000000000000032310891488651735,-0.9 0.2,1 0))": true, - "POLYGON((1 0,0.9807852804032305 -0.19509032201612808,0.923879532511287 -0.3826834323650894,0.8314696123025456 -0.5555702330196017,0.7071067811865481 -0.7071067811865469,0.5555702330196031 -0.8314696123025447,0.38268343236509084 -0.9238795325112863,0.19509032201612964 -0.9807852804032302,0.0000000000000016155445744325867 -1,-0.19509032201612647 -0.9807852804032308,-0.38268343236508784 -0.9238795325112875,-0.5555702330196005 -0.8314696123025463,-0.7071067811865459 -0.7071067811865491,-0.8314696123025438 -0.5555702330196043,-0.9238795325112857 -0.38268343236509234,-0.9807852804032299 -0.19509032201613122,-1 -0.0000000000000032310891488651735,-0.9807852804032311 0.19509032201612486,-0.9238795325112882 0.38268343236508634,-0.8314696123025475 0.555570233019599,-0.7071067811865505 0.7071067811865446,-0.5555702330196058 0.8314696123025428,-0.3826834323650936 0.9238795325112852,-0.19509032201613213 0.9807852804032297,-0.000000000000003736410698672604 1,0.1950903220161248 0.9807852804032311,0.38268343236508673 0.9238795325112881,0.5555702330195996 0.8314696123025469,0.7071067811865455 0.7071067811865496,0.8314696123025438 0.5555702330196044,0.9238795325112859 0.38268343236509206,0.98078528040323 0.19509032201613047,1 0))": true, - "MULTILINESTRING((0 0,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 2),(0 1,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 0))": true, - "MULTILINESTRING((0 1,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 0),(0 0,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 2))": true, - "MULTILINESTRING((0 0,2 2.000000000000001),(1 0,-1 2.000000000000001))": true, - "MULTILINESTRING((0 0,0.5 0.5,1 1,2 2.000000000000001),(1 0,0.5 0.5,0 1,-1 2.000000000000001))": true, - "MULTILINESTRING((0 0,0.5 0.5),(0.5 0.5,1 1),(0 1,0.3333333333 0.6666666667,0.5 0.5),(0.5 0.5,1 0))": true, - "LINESTRING(0.5 0,0.5000000000000001 0.5)": true, - "LINESTRING(0.5 1,0.5000000000000001 0.5)": true, - - // The following are not topological differences, but instead bugs in GEOS - // v3.7.1. I believe that it may be fixed in GEOS v3.8.0 but I haven't - // confirmed that. - "POLYGON((0.9 0.1,0.9 1,0.901921471959677 1.019509032201613,0.9076120467488714 1.0382683432365092,0.9168530387697456 1.0555570233019602,0.9292893218813453 1.0707106781186548,0.9444429766980398 1.0831469612302547,0.961731656763491 1.0923879532511287,0.9804909677983872 1.0980785280403231,1 1.1,1.0195090322016127 1.0980785280403231,1.038268343236509 1.0923879532511287,1.0555570233019602 1.0831469612302547,1.0707106781186546 1.0707106781186548,1.0831469612302544 1.0555570233019602,1.0923879532511287 1.0382683432365092,1.0980785280403231 1.019509032201613,1.1 1,1.0717462120245884 0.06467514421272098,0.9353248557872769 -0.07174621202458649,0 -0.1,-0.019509032201612955 -0.09807852804032302,-0.03826834323650912 -0.09238795325112863,-0.055557023301960363 -0.08314696123025443,-0.07071067811865482 -0.07071067811865468,-0.08314696123025457 -0.055557023301960155,-0.0923879532511287 -0.03826834323650893,-0.09807852804032306 -0.01950903220161279,-0.1 0.000000000000000012246467991473533,-0.09807852804032305 0.01950903220161282,-0.0923879532511287 0.03826834323650895,-0.08314696123025456 0.055557023301960176,-0.07071067811865482 0.0707106781186547,-0.05555702330196031 0.08314696123025447,-0.0382683432365091 0.09238795325112864,-0.019509032201612972 0.09807852804032302,0 0.1,0.9 0.1))": true, - "POLYGON((0.9 0.1,0.9 1,0.901921471959677 1.019509032201613,0.9076120467488714 1.0382683432365092,0.9168530387697456 1.0555570233019602,0.9292893218813453 1.0707106781186548,0.9444429766980398 1.0831469612302547,0.961731656763491 1.0923879532511287,0.9804909677983872 1.0980785280403231,1 1.1,1.0195090322016127 1.0980785280403231,1.038268343236509 1.0923879532511287,1.0555570233019602 1.0831469612302547,1.0707106781186546 1.0707106781186548,1.0831469612302544 1.0555570233019602,1.0923879532511287 1.0382683432365092,1.0980785280403231 1.019509032201613,1.1 1,1.1 0,1 -0.1,0 -0.1,-0.019509032201612955 -0.09807852804032302,-0.03826834323650912 -0.09238795325112863,-0.055557023301960363 -0.08314696123025443,-0.07071067811865482 -0.07071067811865468,-0.08314696123025457 -0.055557023301960155,-0.0923879532511287 -0.03826834323650893,-0.09807852804032306 -0.01950903220161279,-0.1 0.000000000000000012246467991473533,-0.09807852804032305 0.01950903220161282,-0.0923879532511287 0.03826834323650895,-0.08314696123025456 0.055557023301960176,-0.07071067811865482 0.0707106781186547,-0.05555702330196031 0.08314696123025447,-0.0382683432365091 0.09238795325112864,-0.019509032201612972 0.09807852804032302,0 0.1,0.9 0.1))": true, - "POLYGON((0.9 0.1,0.9 1,0.901921471959677 1.019509032201613,0.9076120467488714 1.0382683432365092,0.9168530387697456 1.0555570233019602,0.9292893218813453 1.0707106781186548,0.9444429766980398 1.0831469612302547,0.961731656763491 1.0923879532511287,0.9804909677983872 1.0980785280403231,1 1.1,1.0195090322016127 1.0980785280403231,1.038268343236509 1.0923879532511287,1.0555570233019602 1.0831469612302547,1.0707106781186546 1.0707106781186548,1.0831469612302544 1.0555570233019602,1.0923879532511287 1.0382683432365092,1.0980785280403231 1.019509032201613,1.1 1,1.1 0,1.0980785280403231 -0.019509032201612826,1.0923879532511287 -0.03826834323650898,1.0831469612302544 -0.05555702330196022,1.0707106781186548 -0.07071067811865475,1.0555570233019602 -0.08314696123025453,1.038268343236509 -0.09238795325112868,1.019509032201613 -0.09807852804032305,1 -0.1,0 -0.1,-0.019509032201612955 -0.09807852804032302,-0.03826834323650912 -0.09238795325112863,-0.055557023301960363 -0.08314696123025443,-0.07071067811865482 -0.07071067811865468,-0.08314696123025457 -0.055557023301960155,-0.0923879532511287 -0.03826834323650893,-0.09807852804032306 -0.01950903220161279,-0.1 0.000000000000000012246467991473533,-0.09807852804032305 0.01950903220161282,-0.0923879532511287 0.03826834323650895,-0.08314696123025456 0.055557023301960176,-0.07071067811865482 0.0707106781186547,-0.05555702330196031 0.08314696123025447,-0.0382683432365091 0.09238795325112864,-0.019509032201612972 0.09807852804032302,0 0.1,0.9 0.1))": true, - "POLYGON((1 0,0.9807852804032304 -0.19509032201612825,0.9238795325112867 -0.3826834323650898,0.8314696123025452 -0.5555702330196022,0.7071067811865476 -0.7071067811865475,0.5555702330196023 -0.8314696123025452,0.38268343236508984 -0.9238795325112867,0.19509032201612833 -0.9807852804032304,0.00000000000000006123233995736766 -1,-0.1950903220161282 -0.9807852804032304,-0.3826834323650897 -0.9238795325112867,-0.555570233019602 -0.8314696123025455,-0.7071067811865475 -0.7071067811865476,-0.8314696123025453 -0.5555702330196022,-0.9238795325112867 -0.3826834323650899,-0.9807852804032304 -0.1950903220161286,-1 -0.00000000000000012246467991473532,-0.9807852804032304 0.19509032201612836,-0.9238795325112868 0.38268343236508967,-0.8314696123025455 0.555570233019602,-0.7071067811865477 0.7071067811865475,-0.5555702330196022 0.8314696123025452,-0.38268343236509034 0.9238795325112865,-0.19509032201612866 0.9807852804032303,-0.00000000000000018369701987210297 1,0.1950903220161283 0.9807852804032304,0.38268343236509 0.9238795325112866,0.5555702330196018 0.8314696123025455,0.7071067811865474 0.7071067811865477,0.8314696123025452 0.5555702330196022,0.9238795325112865 0.3826834323650904,0.9807852804032303 0.19509032201612872,1 0))": true, - - // Cause simplefeatures DCEL operations to fail with "no rings" error. See - // https://github.com/peterstace/simplefeatures/pull/497 for details. - "POLYGON((-83.58253051 32.73168239,-83.59843118 32.74617142,-83.70048117 32.63984372,-83.58253051 32.73168239))": true, - "POLYGON((-83.70047745 32.63984661,-83.68891846 32.5989632,-83.58253417 32.73167955,-83.70047745 32.63984661))": true, - "POINT(333673.327 6252387.751)": true, - "POINT(456567.479 3973182.99)": true, - "LINESTRING(6080642.11 1886936.97,6092335.13 1905469.04)": true, - "POINT(334368.633648097 6250948.345385009)": true, - "POINT(6080642.11 1886936.97)": true, - - // Causes simplefeatures DCEL operations to fail with "polygon ring not simple" error. - "POLYGON((-1 0,-0.9 0.2,-0.80952380952381 0.19047619047619,0 1,0 0.105263157894737,1 0,-0.9 -0.2,-1 0))": true, - "POLYGON((0 -0.1414213562373095,1.1414213562373097 1,0.9292893218813453 1.0707106781186548,0 -0.1414213562373095))": true, - "POLYGON((0.9292893218813453 1.0707106781186548,1.0707106781186548 0.9292893218813453,0.07071067811865475 -0.07071067811865475,-0.07071067811865475 0.07071067811865475,0.9292893218813453 1.0707106781186548))": true, - "POLYGON((0.9292893218813453 1.0707106781186548,1 1.1414213562373097,1.1414213562373097 1,0.07071067811865475 -0.07071067811865475,0 -0.1414213562373095,-0.1414213562373095 -0.000000000000000013877787807814457,0.9292893218813453 1.0707106781186548))": true, - "POLYGON((0.9292893218813453 1.0707106781186548,1.1414213562373097 1,0.07071067811865475 -0.07071067811865475,0 -0.1414213562373095,0.9292893218813453 1.0707106781186548))": true, -} - -var skipSymDiff = map[string]bool{ - "LINESTRING(0 1,0.3333333333 0.6666666667,0.5 0.5,1 0)": true, - "LINESTRING(0 1,0.3333333333 0.6666666667,1 0)": true, - "LINESTRING(1 0,0.5000000000000001 0.5,0 1)": true, - "MULTILINESTRING((0 0,0.5 0.5),(0.5 0.5,1 1),(0 1,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,0.5 0.5),(0.5 0.5,1 0))": true, - "MULTILINESTRING((0 1,0.3333333333 0.6666666667),(0.3333333333 0.6666666667,1 0))": true, - - // Cause simplefeatures DCEL operations to fail with "no rings" error. See - // https://github.com/peterstace/simplefeatures/pull/497 for details. - "POLYGON((-83.58253051 32.73168239,-83.59843118 32.74617142,-83.70048117 32.63984372,-83.58253051 32.73168239))": true, - "POLYGON((-83.70047745 32.63984661,-83.68891846 32.5989632,-83.58253417 32.73167955,-83.70047745 32.63984661))": true, - "POINT(456567.479 3973182.99)": true, - "POINT(333673.327 6252387.751)": true, - "LINESTRING(6080642.11 1886936.97,6092335.13 1905469.04)": true, - "POINT(334368.633648097 6250948.345385009)": true, - "POINT(6080642.11 1886936.97)": true, - - // Causes simplefeatures "multipolygon has nested child polygons" error. - "POLYGON((1 0,0.9807852804032304 -0.19509032201612825,0.9238795325112867 -0.3826834323650898,0.8314696123025452 -0.5555702330196022,0.7071067811865476 -0.7071067811865475,0.5555702330196023 -0.8314696123025452,0.38268343236508984 -0.9238795325112867,0.19509032201612833 -0.9807852804032304,0.00000000000000006123233995736766 -1,-0.1950903220161282 -0.9807852804032304,-0.3826834323650897 -0.9238795325112867,-0.555570233019602 -0.8314696123025455,-0.7071067811865475 -0.7071067811865476,-0.8314696123025453 -0.5555702330196022,-0.9238795325112867 -0.3826834323650899,-0.9807852804032304 -0.1950903220161286,-1 -0.00000000000000012246467991473532,-0.9807852804032304 0.19509032201612836,-0.9238795325112868 0.38268343236508967,-0.8314696123025455 0.555570233019602,-0.7071067811865477 0.7071067811865475,-0.5555702330196022 0.8314696123025452,-0.38268343236509034 0.9238795325112865,-0.19509032201612866 0.9807852804032303,-0.00000000000000018369701987210297 1,0.1950903220161283 0.9807852804032304,0.38268343236509 0.9238795325112866,0.5555702330196018 0.8314696123025455,0.7071067811865474 0.7071067811865477,0.8314696123025452 0.5555702330196022,0.9238795325112865 0.3826834323650904,0.9807852804032303 0.19509032201612872,1 0))": true, - - // Causes simplefeatures DCEL operations to fail with "polygon ring not simple" error. - "POLYGON((-1 0,-0.9 0.2,-0.80952380952381 0.19047619047619,0 1,0 0.105263157894737,1 0,-0.9 -0.2,-1 0))": true, - "POLYGON((0 -0.1414213562373095,1.1414213562373097 1,0.9292893218813453 1.0707106781186548,0 -0.1414213562373095))": true, - "POLYGON((0.9 0.1,0.9 1,0.901921471959677 1.019509032201613,0.9076120467488714 1.0382683432365092,0.9168530387697456 1.0555570233019602,0.9292893218813453 1.0707106781186548,0.9444429766980398 1.0831469612302547,0.961731656763491 1.0923879532511287,0.9804909677983872 1.0980785280403231,1 1.1,1.0195090322016127 1.0980785280403231,1.038268343236509 1.0923879532511287,1.0555570233019602 1.0831469612302547,1.0707106781186546 1.0707106781186548,1.0831469612302544 1.0555570233019602,1.0923879532511287 1.0382683432365092,1.0980785280403231 1.019509032201613,1.1 1,1.0717462120245884 0.06467514421272098,0.9353248557872769 -0.07174621202458649,0 -0.1,-0.019509032201612955 -0.09807852804032302,-0.03826834323650912 -0.09238795325112863,-0.055557023301960363 -0.08314696123025443,-0.07071067811865482 -0.07071067811865468,-0.08314696123025457 -0.055557023301960155,-0.0923879532511287 -0.03826834323650893,-0.09807852804032306 -0.01950903220161279,-0.1 0.000000000000000012246467991473533,-0.09807852804032305 0.01950903220161282,-0.0923879532511287 0.03826834323650895,-0.08314696123025456 0.055557023301960176,-0.07071067811865482 0.0707106781186547,-0.05555702330196031 0.08314696123025447,-0.0382683432365091 0.09238795325112864,-0.019509032201612972 0.09807852804032302,0 0.1,0.9 0.1))": true, - "POLYGON((0.9 0.1,0.9 1,0.901921471959677 1.019509032201613,0.9076120467488714 1.0382683432365092,0.9168530387697456 1.0555570233019602,0.9292893218813453 1.0707106781186548,0.9444429766980398 1.0831469612302547,0.961731656763491 1.0923879532511287,0.9804909677983872 1.0980785280403231,1 1.1,1.0195090322016127 1.0980785280403231,1.038268343236509 1.0923879532511287,1.0555570233019602 1.0831469612302547,1.0707106781186546 1.0707106781186548,1.0831469612302544 1.0555570233019602,1.0923879532511287 1.0382683432365092,1.0980785280403231 1.019509032201613,1.1 1,1.1 0,1 -0.1,0 -0.1,-0.019509032201612955 -0.09807852804032302,-0.03826834323650912 -0.09238795325112863,-0.055557023301960363 -0.08314696123025443,-0.07071067811865482 -0.07071067811865468,-0.08314696123025457 -0.055557023301960155,-0.0923879532511287 -0.03826834323650893,-0.09807852804032306 -0.01950903220161279,-0.1 0.000000000000000012246467991473533,-0.09807852804032305 0.01950903220161282,-0.0923879532511287 0.03826834323650895,-0.08314696123025456 0.055557023301960176,-0.07071067811865482 0.0707106781186547,-0.05555702330196031 0.08314696123025447,-0.0382683432365091 0.09238795325112864,-0.019509032201612972 0.09807852804032302,0 0.1,0.9 0.1))": true, - "POLYGON((0.9292893218813453 1.0707106781186548,1.0707106781186548 0.9292893218813453,0.07071067811865475 -0.07071067811865475,-0.07071067811865475 0.07071067811865475,0.9292893218813453 1.0707106781186548))": true, - "POLYGON((0.9292893218813453 1.0707106781186548,0.9444429766980399 1.0831469612302547,0.9617316567634911 1.0923879532511287,0.9804909677983873 1.0980785280403231,1 1.1,1.019509032201613 1.0980785280403231,1.038268343236509 1.0923879532511287,1.0555570233019602 1.0831469612302544,1.0707106781186548 1.0707106781186548,1.0831469612302544 1.0555570233019602,1.0923879532511287 1.038268343236509,1.0980785280403231 1.019509032201613,1.1 1,1.0980785280403231 0.9804909677983873,1.0923879532511287 0.9617316567634911,1.0831469612302547 0.9444429766980399,1.0707106781186548 0.9292893218813453,0.07071067811865475 -0.07071067811865475,0.05555702330196012 -0.0831469612302546,0.03826834323650888 -0.09238795325112872,0.019509032201612746 -0.09807852804032308,-0.00000000000000006049014748177263 -0.1,-0.019509032201612864 -0.09807852804032305,-0.03826834323650899 -0.09238795325112868,-0.0555570233019602 -0.08314696123025456,-0.07071067811865475 -0.07071067811865477,-0.08314696123025449 -0.05555702330196029,-0.09238795325112865 -0.03826834323650903,-0.09807852804032302 -0.019509032201612948,-0.1 -0.00000000000000010106430996148606,-0.09807852804032308 0.019509032201612663,-0.09238795325112874 0.038268343236508844,-0.08314696123025465 0.055557023301960044,-0.07071067811865475 0.07071067811865475,0.9292893218813453 1.0707106781186548))": true, - "POLYGON((-83.5825305152402 32.7316823944815,-83.58376293006216 32.73315376178507,-83.58504085655653 32.734597137036324,-83.58636334101533 32.73601156235818,-83.58772946946186 32.73739605462324,-83.58913829287843 32.738749652823024,-83.59058883640313 32.740071417020225,-83.59208009385833 32.74136043125909,-83.59361103333862 32.74261579844315,-83.59518059080796 32.743836647669376,-83.59678768034422 32.745022130852156,-83.59843118482598 32.746171426099316,-83.60010996734121 32.74728373328835,-83.60182286094272 32.74835828151699,-83.60356867749573 32.74939432363171,-83.6053462070958 32.75039113983657,-83.60715421364506 32.75134803897381,-83.60899144521312 32.75226435508957,-83.61085662379259 32.75313945319649,-83.61274845635847 32.75397272333648,-83.61466562799973 32.7547635884388,-83.61660680960262 32.75551149954699,-83.61857065109865 32.756215934654755,-83.62055578961366 32.75687640673859,-83.62256084632457 32.75749245578336,-83.62458442890414 32.75806365483586,-83.62662513245226 32.75858960587211,-83.62868153809899 32.759069943900975,-83.63075221766115 32.759504334926895,-83.6328357331767 32.759892478947584,-83.6349306369047 32.76023410294001,-83.63703547248946 32.76052897293848,-83.63914877915153 32.76077688192745,-83.64126908772954 32.760977657903275,-83.64339492533685 32.76113116287015,-83.64552481489585 32.76123728881648,-83.64765727560365 32.761295961756694,-83.64979082712301 32.761307141684846,-83.65192398562425 32.76127082060284,-83.65405527030447 32.761187023508135,-83.65618319896379 32.76105580840831,-83.65830629359328 32.76087726729329,-83.66042307921083 32.7606515241745,-83.66253208572374 32.760378736038,-83.66463184629896 32.76005909090909,-83.666720902951 32.75969281274174,-83.66879780351513 32.75928015456466,-83.67086110700251 32.758821403399814,-83.67290937847787 32.75831687924383,-83.67494119511315 32.75776693105163,-83.67695514665314 32.75717194084009,-83.67894983308719 32.756532323629834,-83.68092387070277 32.75584852243937,-83.68287588719608 32.755121013232745,-83.68480452667785 32.75435029997188,-83.6867084511868 32.75353691874934,-83.68858633871054 32.752681435518205,-83.69043688423329 32.75178444323992,-83.69225880474181 32.75084656496929,-83.69405083421947 32.74986845274852,-83.69581173063119 32.74885078644311,-83.69754027103403 32.74779427211197,-83.69923525541884 32.746699642822385,-83.70089550880579 32.74556766051264,-83.70251987926525 32.74439911017125,-83.70410724071183 32.74319480286376,-83.70565649104168 32.74195557654766,-83.70716655737118 32.740682290251605,-83.70863639277735 32.73937582791714,-83.71006497711272 32.738037097583764,-83.71145132142914 32.73666702917708,-83.71279446471812 32.735266572878935,-83.71409347705406 32.73383670052444,-83.71534745831372 32.73237840618403,-83.71655554062085 32.73089270080836,-83.71771688788061 32.729380616419256,-83.7188306961288 32.72784320203518,-83.71989619434675 32.7262815256503,-83.72091264550903 32.72469667027635,-83.72187934768948 32.72308973592171,-83.72279563289698 32.721461838543654,-83.72366086608594 32.71981410620665,-83.72447445225765 32.718147683855385,-83.72523582737989 32.71646372644627,-83.72594446851502 32.71476340406971,-83.72659988462323 32.713047893684596,-83.7272016266906 32.71131838726742,-83.72774927777567 32.70957608482731,-83.72824246383601 32.70782219347475,-83.72868084389114 32.70605793103041,-83.72906411790967 32.70428451962234,-83.7293920229094 32.7025031912739,-83.72966433589676 32.700715179871075,-83.7298808698651 32.69892172546988,-83.7300414788296 32.69712407208444,-83.73014605577549 32.69532346570795,-83.73019452970033 32.693521154312656,-83.73018687161033 32.691718388897606,-83.73012309050767 32.689916417551466,-83.7300032323846 32.68811649010913,-83.7298273852511 32.68631985477568,-83.72959567309675 32.684527756380156,-83.72930826092573 32.68274143695762,-83.72896535074773 32.680962133537285,-83.72856718354245 32.6791910811693,-83.72811403832833 32.67742950582342,-83.72760623312291 32.67567862846354,-83.72704412086836 32.67393966108957,-83.72642809662005 32.672213810695574,-83.72575858936847 32.670502271353506,-83.72503606605545 32.66880622898625,-83.72426102976982 32.66712685869006,-83.7234340194563 32.66546532333759,-83.72255561311698 32.66382277497487,-83.7216264197786 32.66220034969901,-83.72064708740885 32.66059917243128,-83.7196182950583 32.659020351096295,-83.71854075868117 32.65746497883392,-83.71741522729366 32.655934134581365,-83.71624248192614 32.65442887527333,-83.71502333853363 32.65295024597017,-83.71375864112719 32.65149926868198,-83.71244926771118 32.650076949469984,-83.7110961292355 32.64868427122874,-83.70970016179575 32.64732219892485,-83.70826233431666 32.64599167470751,-83.70678364482677 32.6446936215174,-83.70526511731526 32.64342893528683,-83.70370780580646 32.642198493088834,-83.70211278830624 32.64100314591942,-83.70048117076016 32.639843721724354,-83.5825305152402 32.7316823944815))": true, -} - -var skipUnion = map[string]bool{ - // Cause simplefeatures DCEL operations to fail with "no rings" error. See - // https://github.com/peterstace/simplefeatures/pull/497 for details. - "POLYGON((-83.58253051 32.73168239,-83.59843118 32.74617142,-83.70048117 32.63984372,-83.58253051 32.73168239))": true, - "POLYGON((-83.70047745 32.63984661,-83.68891846 32.5989632,-83.58253417 32.73167955,-83.70047745 32.63984661))": true, - "POINT(456567.479 3973182.99)": true, - "POINT(333673.327 6252387.751)": true, - "LINESTRING(6080642.11 1886936.97,6092335.13 1905469.04)": true, - "POINT(334368.633648097 6250948.345385009)": true, - "POINT(6080642.11 1886936.97)": true, - - // Causes incorrect snap-rounding containment detection in JTS OverlayNG. - "POLYGON((1 0,0.9807852804032304 -0.19509032201612825,0.9238795325112867 -0.3826834323650898,0.8314696123025452 -0.5555702330196022,0.7071067811865476 -0.7071067811865475,0.5555702330196023 -0.8314696123025452,0.38268343236508984 -0.9238795325112867,0.19509032201612833 -0.9807852804032304,0.00000000000000006123233995736766 -1,-0.1950903220161282 -0.9807852804032304,-0.3826834323650897 -0.9238795325112867,-0.555570233019602 -0.8314696123025455,-0.7071067811865475 -0.7071067811865476,-0.8314696123025453 -0.5555702330196022,-0.9238795325112867 -0.3826834323650899,-0.9807852804032304 -0.1950903220161286,-1 -0.00000000000000012246467991473532,-0.9807852804032304 0.19509032201612836,-0.9238795325112868 0.38268343236508967,-0.8314696123025455 0.555570233019602,-0.7071067811865477 0.7071067811865475,-0.5555702330196022 0.8314696123025452,-0.38268343236509034 0.9238795325112865,-0.19509032201612866 0.9807852804032303,-0.00000000000000018369701987210297 1,0.1950903220161283 0.9807852804032304,0.38268343236509 0.9238795325112866,0.5555702330196018 0.8314696123025455,0.7071067811865474 0.7071067811865477,0.8314696123025452 0.5555702330196022,0.9238795325112865 0.3826834323650904,0.9807852804032303 0.19509032201612872,1 0))": true, -} - -func checkDCELOperations(g1, g2 geom.Geometry, log *log.Logger) error { - // TODO: simplefeatures doesn't support GeometryCollections yet - if g1.IsGeometryCollection() || g2.IsGeometryCollection() { - return nil - } - - for _, op := range []struct { - name string - sfFunc func(g1, g2 geom.Geometry) (geom.Geometry, error) - geosFunc func(g1, g2 geom.Geometry) (geom.Geometry, error) - skip map[string]bool - }{ - { - "Union", - geom.Union, - rawgeos.Union, - skipUnion, - }, - { - "Intersection", - geom.Intersection, - rawgeos.Intersection, - skipIntersection, - }, - { - "Difference", - geom.Difference, - rawgeos.Difference, - skipDifference, - }, - { - "SymmetricDifference", - geom.SymmetricDifference, - rawgeos.SymmetricDifference, - skipSymDiff, - }, - } { - log.Println("checking", op.name) - err := checkDCELOp(op.sfFunc, op.geosFunc, g1, g2, op.skip, log) - if err != nil { - return err - } - } - - log.Println("checking Relate") - return checkRelate(g1, g2, log) -} - -func checkDCELOp( - op func(g1, g2 geom.Geometry) (geom.Geometry, error), - refImpl func(g1, g2 geom.Geometry) (geom.Geometry, error), - g1, g2 geom.Geometry, - skip map[string]bool, - log *log.Logger, -) error { - // Empty points will cause the reference impl to crash. - if hasEmptyPoint(g1) || hasEmptyPoint(g2) { - return nil - } - - // Some geometries give results that are not topologically equivalent to - // those from GEOS. These have been checked manually, and decided that the - // difference is acceptable (they typically have to do with different - // handling of numerically degenerate cases). Note that we bail out of this - // test _after_ we calculate got. That way we're at least checking that it - // doesn't crash or give an error. - if skip[g1.AsText()] || skip[g2.AsText()] { - return nil - } - - got, err := op(g1, g2) - if err != nil { - return err - } - - want, err := refImpl(g1, g2) - if err != nil { - return err - } - return checkEqualityHeuristic(want, got, log) -} - -// checkEqualityHeuristic checks some necessary but not sufficient properties -// of two geometries if they are to be equal. -func checkEqualityHeuristic(want, got geom.Geometry, log *log.Logger) error { - symDiff, err := rawgeos.SymmetricDifference(want, got) - if err != nil { - return err - } - symDiffArea := symDiff.Area() - - floatEq := float64EqualityChecker{ - absoluteThreshold: 1e-3, - relativeThreshold: 1e-3, - }.eq - - wantArea := want.Area() - gotArea := got.Area() - - if !floatEq(symDiffArea, 0) { - log.Printf("wantWKT: %v\n", want.AsText()) - log.Printf("gotWKT: %v\n", got.AsText()) - log.Printf("wantArea: %v\n", wantArea) - log.Printf("gotArea: %v\n", gotArea) - log.Printf("wantSymDiffArea: %v\n", 0) - log.Printf("gotSymDiffArea: %v\n", symDiffArea) - return errMismatch - } - return nil -} - -type float64EqualityChecker struct { - absoluteThreshold float64 - relativeThreshold float64 -} - -func (c float64EqualityChecker) eq(a, b float64) bool { - absDiff := math.Abs(a - b) - magnitude := math.Max(math.Abs(a), math.Abs(b)) - return absDiff < c.absoluteThreshold || absDiff < magnitude*c.relativeThreshold -} - -func checkRelate(g1, g2 geom.Geometry, log *log.Logger) error { - got, err := geom.Relate(g1, g2) - if err != nil { - return err - } - want, err := rawgeos.Relate(g1, g2) - if err != nil { - return err - } - - // Skip any linear and non-simple geometries. This is because GEOS has - // inconsistent behaviour with the generated relate matrix, making it hard - // to match the exact behaviour. - if linearAndNonSimple(g1) || linearAndNonSimple(g2) { - return nil - } - - if !mantissaTerminatesQuickly(g1) || !mantissaTerminatesQuickly(g2) { - // Numerical precision issues cause a large number of geometries to - // differ compared to GEOS. There aren't really any heuristics that we - // can fall back to, so we just have to skip these sorts of geometries. - return nil - } - - if got != want { - // There is a bug in JTS (https://github.com/locationtech/jts/issues/1175) - // that triggers when computing Relate involving linear geometries. The - // bug causes JTS to report F instead of 0 for the EB (position 7) or BE - // (position 5) elements of the DE-9IM matrix. Accept this known - // difference rather than failing. - if isKnownJTSRelateBug(got, want, g1, g2) { - return nil - } - log.Printf("want: %v", want) - log.Printf("got: %v", got) - return errMismatch - } - - return nil -} - -// isKnownJTSRelateBug returns true if the difference between got and want is -// due to known JTS bugs: -// -// 1. JTS reports F instead of 0 at positions 5 (BE) or 7 (EB) when linear -// geometries are involved. -// -// 2. JTS RelateNG reports incorrect values at positions involving the Interior -// of either geometry (see docs/jts_port_relate_bug.md). The DE-9IM matrix is: -// -// g2.I g2.B g2.E -// g1.I [0] [1] [2] -// g1.B [3] [4] [5] -// g1.E [6] [7] [8] -// -// The bug can affect positions 0, 1, 2 (g1.Interior row) and 0, 3, 6 -// (g2.Interior column). It occurs with linear geometries or polygons -// that have holes. -func isKnownJTSRelateBug(got, want string, g1, g2 geom.Geometry) bool { - if len(got) != 9 || len(want) != 9 { - return false - } - for i := 0; i < 9; i++ { - if got[i] == want[i] { - continue - } - // Bug 1: JTS reports F where GEOS reports 0, at positions 5 (BE) or 7 - // (EB) when linear geometries are involved. - if (i == 5 || i == 7) && got[i] == 'F' && want[i] == '0' { - if g1.Dimension() == 1 || g2.Dimension() == 1 { - continue - } - } - // Bug 2: JTS RelateNG may report incorrect values at positions - // involving the Interior: row 0 (positions 0, 1, 2) and column 0 - // (positions 0, 3, 6). This occurs with linear geometries or polygons - // that have holes. - if i == 0 || i == 1 || i == 2 || i == 3 || i == 6 { - if mayTriggerRelateNGBug(g1) || mayTriggerRelateNGBug(g2) { - continue - } - } - return false - } - return true -} - -// mayTriggerRelateNGBug returns true if the geometry has characteristics that -// may trigger the JTS RelateNG bug: linear geometries or polygons with holes. -func mayTriggerRelateNGBug(g geom.Geometry) bool { - // Linear geometries can trigger the bug. - if g.Dimension() == 1 { - return true - } - // Polygons with holes can trigger the bug. - if poly, ok := g.AsPolygon(); ok { - return poly.NumInteriorRings() > 0 - } - if mp, ok := g.AsMultiPolygon(); ok { - for i := 0; i < mp.NumPolygons(); i++ { - if mp.PolygonN(i).NumInteriorRings() > 0 { - return true - } - } - } - // GeometryCollections may contain problematic geometries. - if gc, ok := g.AsGeometryCollection(); ok { - for i := 0; i < gc.NumGeometries(); i++ { - if mayTriggerRelateNGBug(gc.GeometryN(i)) { - return true - } - } - } - return false -} - -func checkRelateMatch(log *log.Logger) error { - for i := 0; i < 1_000_000; i++ { - mat := rand9("F012") - pat := rand9("F012T*") - want, err := rawgeos.RelatePatternMatch(mat, pat) - if err != nil { - log.Printf("could not calculate want: %v", err) - return err - } - got, err := geom.RelateMatches(mat, pat) - if err != nil { - log.Printf("could not calculate got: %v", err) - return err - } - if got != want { - log.Printf("mat: %v", mat) - log.Printf("pat: %v", pat) - log.Printf("want: %v", want) - log.Printf("got: %v", got) - return errMismatch - } - } - return nil -} - -func rand9(alphabet string) string { - var buf [9]byte - for i := range buf { - buf[i] = alphabet[rand.Intn(len(alphabet))] - } - return string(buf[:]) -} diff --git a/internal/cmprefimpl/cmpgeos/main.go b/internal/cmprefimpl/cmpgeos/main.go index 2e5392ad..1f95ca19 100644 --- a/internal/cmprefimpl/cmpgeos/main.go +++ b/internal/cmprefimpl/cmpgeos/main.go @@ -37,17 +37,6 @@ func main() { forceTo2D(geoms) geoms = deduplicateGeometries(geoms) - { - var buf bytes.Buffer - lg := log.New(&buf, "", log.Lshortfile) - if err := checkRelateMatch(lg); err != nil { - fmt.Printf("Check failed: %v\n", err) - io.Copy(os.Stdout, &buf) - fmt.Println() - os.Exit(1) - } - } - var failures int var unarySkipped int for _, g := range geoms { diff --git a/internal/cmprefimpl/cmpgeos/util.go b/internal/cmprefimpl/cmpgeos/util.go index e59c6d3c..2ee52cf1 100644 --- a/internal/cmprefimpl/cmpgeos/util.go +++ b/internal/cmprefimpl/cmpgeos/util.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "math" "strings" "text/scanner" @@ -201,72 +200,6 @@ func tokenizeWKT(wkt string) []string { return tokens } -func mantissaTerminatesQuickly(g geom.Geometry) bool { - termF := func(f float64) bool { - const ( - mantissaMask = ^uint64(0) >> 12 - allowedMantissaMask = (mantissaMask >> 28) << 28 - ) - mant := math.Float64bits(f) & mantissaMask - return mant & ^allowedMantissaMask == 0 - } - termXY := func(xy geom.XY) bool { - return termF(xy.X) && termF(xy.Y) - } - - switch g.Type() { - case geom.TypePoint: - xy, ok := g.MustAsPoint().XY() - return !ok || termXY(xy) - case geom.TypeLineString: - seq := g.MustAsLineString().Coordinates() - for i := 0; i < seq.Length(); i++ { - if !termXY(seq.GetXY(i)) { - return false - } - } - return true - case geom.TypePolygon: - return g.IsEmpty() || mantissaTerminatesQuickly(g.Boundary()) - case geom.TypeMultiPoint: - mp := g.MustAsMultiPoint() - for i := 0; i < mp.NumPoints(); i++ { - pt := mp.PointN(i) - if !mantissaTerminatesQuickly(pt.AsGeometry()) { - return false - } - } - return true - case geom.TypeMultiLineString: - mls := g.MustAsMultiLineString() - for i := 0; i < mls.NumLineStrings(); i++ { - ls := mls.LineStringN(i) - if !mantissaTerminatesQuickly(ls.AsGeometry()) { - return false - } - } - return true - case geom.TypeMultiPolygon: - return g.IsEmpty() || mantissaTerminatesQuickly(g.Boundary()) - case geom.TypeGeometryCollection: - gc := g.MustAsGeometryCollection() - for i := 0; i < gc.NumGeometries(); i++ { - g := gc.GeometryN(i) - if !mantissaTerminatesQuickly(g) { - return false - } - } - return true - default: - panic(fmt.Sprintf("unknown type: %v", g.Type())) - } -} - -func linearAndNonSimple(g geom.Geometry) bool { - simple, wellDefined := g.IsSimple() - return g.Dimension() == 1 && wellDefined && !simple -} - // hasLargeCoordinates returns true if the geometry has any coordinates with // magnitude large enough to cause floating point precision issues when // comparing the results of operations performed on this geometry. The diff --git a/internal/cmprefimpl/cmpgeos/util_test.go b/internal/cmprefimpl/cmpgeos/util_test.go deleted file mode 100644 index 085bab9f..00000000 --- a/internal/cmprefimpl/cmpgeos/util_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "fmt" - "math" - "testing" - - "github.com/peterstace/simplefeatures/geom" -) - -func TestMantissaTerminatesQuickly(t *testing.T) { - // Test mantissaTerminatesQuickly function, since it's fairly complicated - // internally. - for _, tt := range []struct { - f float64 - want bool - }{ - {1.0, true}, - {1.5, true}, - {53, true}, - {100, true}, - {0.1, false}, - {-0.1, false}, - {0.7, false}, - {math.Pi, false}, - } { - t.Run(fmt.Sprintf("%v", tt.f), func(t *testing.T) { - pt := geom.XY{X: tt.f, Y: tt.f}.AsPoint() - got := mantissaTerminatesQuickly(pt.AsGeometry()) - if got != tt.want { - t.Errorf("got=%v want=%v", got, tt.want) - } - }) - } -}