**POLY Valid-Invalids** vanOosterom/Delft {{{ 1 blue Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260)) 2 blue Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (160 210, 220 210, 220 170, 160 170, 160 210)) 3 blue Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (160 210, 220 210, 220 170, 160 170, 160 210), (180 160, 210 160, 212 135, 181 135, 180 160)) 4 blue Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (130 211, 220 211, 220 170, 130 170, 130 211)) 5 blue Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (170 210, 220 210, 220 170, 170 170, 170 210), (140 170, 170 170, 170 150, 140 150, 140 170)) 6 blue Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (130 211, 170 211, 170 170, 130 170, 130 211), (170 170, 200 170, 200 150, 170 150, 170 170), (200 200, 230 200, 230 170, 200 170, 200 200)) 7 blue Valid POLYGON ((200 260, 171 241, 188 226, 227 226, 227 201, 188 201, 188 223, 170 240, 100 190, 196 66, 270 210, 200 260)) 8 blue Valid POLYGON ((200 260, 171 241, 188 226, 227 226, 227 201, 188 201, 188 223, 162 245, 100 190, 196 66, 270 210, 200 260)) 9 red Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (132 211, 220 170, 116 200, 132 211)) 10 red Invalid POLYGON ((200 260, 100 190, 196 66, 270 210 )) 11 red Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 240 230, 250 260, 239 231, 200 260)) 12 blue Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 240 230, 223 194, 239 231, 200 260)) 13 red Invalid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (130 232, 220 232, 220 170, 130 170, 130 232)) # another integers version, for convenience POLYGON ((200 261, 100 190, 196 66, 270 210, 200 261), (210 236, 210 210, 163 210, 163 235, 210 236)) 14 red Invalid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (130 292, 220 292, 130 230, 130 292)) 15 red Valid POLYGON ((200 260, 108 190, 138 230, 180 292, 108 292, 132 230, 100 190, 196 66, 270 210, 200 260)) 16 red Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 240 230, 169.678 100, 150.0907 125.3, 210 250, 200 260, 200 260)) 17 red Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 240 230, 170 100, 210 250, 200 260, 200 260)) 18 red Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (157.15 230, 242 230, 242 200, 157 200, 157.15 230)) 19 red Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (170 210, 242 230, 220 170, 170 170, 170 210), (131 170, 170 170, 170 150, 131 150, 131 170)) 20 red Invalid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (130 211, 200 200, 170 170, 130 211), (170 170, 200 170, 200 150, 170 150, 170 170), (200 200, 230 200, 230 170, 200 170, 200 200)) 21 red Invalid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (160 211, 200 200, 170 170, 160 211), (170 170, 200 170, 200 150, 170 150, 170 170), (200 200, 230 200, 230 170, 200 170, 200 200)) 22 red Invalid POLYGON ((200 260, 100 190, 270 210, 200 66, 200 260)) 23 red Invalid POLYGON ((200 260, 100 190, 200 202, 270 210, 200 66, 200 202, 200 260)) 24 red Invalid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (160 210, 220 210, 220 170, 160 170, 160 210), (180 200, 210 200, 212 185, 188 185, 180 200)) 25 red Invalid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260),(160 210, 220 210, 220 170, 160 170, 160 210),(200 210, 212 185, 188 185, 200 210)) 26 blue Valid POLYGON ((200 260, 110 197, 100 190, 196 66, 270 210, 200 260)) 27 green Valid POLYGON ((200 260, 110 197, 109.9999999999999 196.9999999999999, 100 190, 196 66, 270 210, 200 260)) 28 green Valid POLYGON ((200 260, 110 197, 100 222, 109.9999999999999 196.9999999999999, 100 190, 196 66, 270 210, 200 260)) 29 green Valid POLYGON ((200 260, 110 197, 140 170, 109.9999999999999 196.9999999999999, 100 190, 196 66, 270 210, 200 260)) 30 green Invalid POLYGON ((200 260, 110 197, 248 90, 109.9999999999999 196.9999999999999, 100 190, 196 66, 270 210, 200 260)) 31 green Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (130.0000000000001 210.9999999999999, 220 210.9999999999999, 220 170, 130.0000000000001 170, 130.0000000000001 210.9999999999999)) 32 green Invalid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260),(129.9999999999999 211.0000000000001, 220 211.0000000000001, 220 170, 129.9999999999999 170, 129.9999999999999 211.0000000000001)) 33 green Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 240 230, 169.9 99.8, 150.333 125, 210 250, 200 260, 200 260)) 34 green Valid POLYGON ((200 260, 110 197, 212.95800000000003 99, 103 192.1, 100 190, 196 66, 270 210, 200 260)) 35 green Invalid POLYGON ((200 260, 110 197, 212.95848 99.0000000000001, 103 192.1, 100 190, 196 66, 270 210, 200 260)) 36 green Valid POLYGON ((200 260, 100 190, 196 66, 270 210, 200 260), (157.1432 230, 241.9999999999952 230, 242 190, 157.142 190, 157.1432 230)) }}} defined Error Conditions {{{ BS=boundary selfintersects CR=crossing rings EN=edge not connected to interior FI=floating inner ring NA=no area NC=not closed NH=not one homogenous portion NO=not orientable NS=no surface Rn=rule n (n=1,3,4,5) RC=ring crosses ring RO=rings overlap RT=rings touch SR=self crossing ring TE=two exterior rings TS=two separate areas WO=wrong orientation }}} note that outer shells are COUNTER-CLOCKWISE, inner polygons are CLOCKWISE, unless otherwise noted ---- **About Invalid, Valid and Clean Polygons** 2004 Delft university, NL ; peter van oosterom, theo tijssen [[Image(ticket:987:valids-delft_ovr16a.png)]] [[Image(ticket:987:valids-delft_ovr16b.png)]] [[Image(ticket:987:valids-delft_ovr16c.png)]] ---- Ex. 13 -- Self-intersection [[Image(ticket:987:valids-delft_13a.png)]] [[Image(ticket:987:valids-delft_13b.png)]] GEOS 3.8 MakeValid(geom) [[Image(ticket:987:valids-delft_13c.png)]] (larger POLY result shown. there is also a small triangle POLY not shown) ---- Ex. 14 -- disjoint shells [[Image(ticket:987:valids-delft_14a.png)]] MakeValid(geom) changes POLYGON to MULTIPOLYGON , the two parts are valid. ---- Ex. 20 -- interior is disconnected POLYGON ( outer large diamond, inner triangle, lower inner rect, upper inner rect ) POLYGON ( (200 260, 100 190, 196 66, 270 210, 200 260), (130 211, 200 200, 170 170, 130 211), (170 170, 200 170, 200 150, 170 150, 170 170), (200 200, 230 200, 230 170, 200 170, 200 200)) ; [[Image(ticket:987:valids-delft_20a.png)]] GEOS 3.8 MakeValid(geom) [[Image(ticket:987:valids-delft_20b.png)]] [[Image(ticket:987:valids-delft_20rd.png)]] MULTIPOLYGON( ( (130 211, 200 260, 270 210, 196 66, 100 190, 130 211), (130 211, 170 170, 170 150, 200 150, 200 170, 230 170, 230 200, 200 200, 130 211) ), ((170 170, 200 200, 200 170, 170 170)) ) (outer diamond, inner hole ), triangle ---- Ex. 22 -- bowtie [[Image(ticket:987:valids-delft_22a.png)]] GEOS 3.8 MakeValid(geom) [[Image(ticket:987:valids-delft_22b.png)]] ---- Ex. 24 -- holes are nested [[Image(ticket:987:valids-delft_24a.png)]] GEOS 3.8 MakeValid(geom) [[Image(ticket:987:valids-delft_24b.png)]] POLYGON( outer diamond, hole_A, hole_B ) => MULTIPOLYGON ( outer diamond, hole_A ), poly_B ---- Ex. 25 -- self-intersection [[Image(ticket:987:valids-delft_25a.png)]] [[Image(ticket:987:valids-delft_25c.png)]] [[Image(ticket:987:valids-delft_25p.png)]] ---- Ex. 32 -- a regular hole corner is offset by a tiny constant [[Image(ticket:987:valids-delft_32a.png)]] [[Image(ticket:987:valids-delft_32b.png)]] The result of ST_MakeValid(geom) is difficult to illustrate here. The MULTIPOLYGON result has two parts: a large POLY that is the diamond shape, but then includes four segments making a sharp concave interior; the second POLY is smaller than the default precision of text floating point can show. The valid solution here is nearly the same as Ex. 13 . ---- Ex. 35 -- cross exterior shell [[Image(ticket:987:valid-delft35.png)]] [[Image(ticket:987:valids-delft_35b.png)]] GEOS 3.8 MakeValid(geom) [[Image(ticket:987:valids-delft_35c.png)]] [[Image(ticket:987:valids-delft_35d.png)]] ---- **Valids-Delft Lab** {{{ Table "public.valids_delft" Column | Type | Collation | Nullable | Default -----------+----------+-----------+----------+--------- pkey | integer | | not null | groupname | text | | | refvalid | text | | | wkt_base | text | | | geom | geometry | | | Indexes: "valids_delft_pkey" PRIMARY KEY, btree (pkey) note: entry ten is not a closed POLYGON, and does not load into PostGIS }}} **Postgis 2.5 | GEOS 3.7.1 |** refvalid **MATCH** {{{ PostgreSQL 10.10 (Ubuntu 10.10-0ubuntu0.18.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0, 64-bit POSTGIS="2.5.2 r17328" [EXTENSION] PGSQL="100" GEOS="3.7.1-CAPI-1.11.1 27a5e771" PROJ="Rel. 5.2.0, September 15th, 2018" GDAL="GDAL 2.4.2, released 2019/06/28" LIBXML="2.9.4" LIBJSON="0.12.1" LIBPROTOBUF="1.2.1" RASTER }}} **PostGIS 2.3 | GEOS 3.8dev |** refvalid **MATCH** {{{ user=# select pkey, refvalid, st_isValid(geom) from valids_delft ; NOTICE: Self-intersection at or near point 163.39202965708989 235.00834105653382 NOTICE: Hole lies outside shell at or near point 130 292 NOTICE: Interior is disconnected at or near point 170 170 NOTICE: Interior is disconnected at or near point 170 170 NOTICE: Self-intersection at or near point 200 201.76470588235293 NOTICE: Self-intersection at or near point 200 202 NOTICE: Holes are nested at or near point 180 200 NOTICE: Self-intersection at or near point 200 210 NOTICE: Self-intersection at or near point 219.6352644836272 111.99294710327453 NOTICE: Self-intersection at or near point 129.99999999999989 210.99999999999991 NOTICE: Self-intersection at or near point 212.95837780046392 99.000086530632473 pkey | refvalid | st_isvalid ------+----------+------------ 1 | Valid | t 2 | Valid | t 3 | Valid | t 4 | Valid | t 5 | Valid | t 7 | Valid | t 6 | Valid | t 8 | Valid | t 9 | Valid | t 11 | Valid | t 12 | Valid | t 13 | Invalid | f 14 | Invalid | f 15 | Valid | t 16 | Valid | t 17 | Valid | t 18 | Valid | t 19 | Valid | t 20 | Invalid | f 21 | Invalid | f 22 | Invalid | f 23 | Invalid | f 24 | Invalid | f 25 | Invalid | f 26 | Valid | t 27 | Valid | t 28 | Valid | t 29 | Valid | t 30 | Invalid | f 31 | Valid | t 32 | Invalid | f 33 | Valid | t 34 | Valid | t 35 | Invalid | f 36 | Valid | t (35 rows) -- PostgreSQL 9.5.14 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609, 64-bit POSTGIS="2.3.2 r15302" GEOS="3.8.0dev-CAPI-1.12.0 " PROJ="Rel. 4.9.2, 08 September 2015" GDAL="GDAL 2.1.3, released 2017/20/01" LIBXML="2.9.3" LIBJSON="0.11.99" RASTER }}} **PostGIS 2.4 | GEOS 3.7.2 |** refvalid **MATCH** {{{ dbb=# select pkey, refvalid, st_isValid(geom) from valids_delft ; NOTICE: Self-intersection at or near point 163.39202965708989 235.00834105653382 NOTICE: Hole lies outside shell at or near point 130 292 NOTICE: Interior is disconnected at or near point 170 170 NOTICE: Interior is disconnected at or near point 170 170 NOTICE: Self-intersection at or near point 200 201.76470588235293 NOTICE: Self-intersection at or near point 200 202 NOTICE: Holes are nested at or near point 180 200 NOTICE: Self-intersection at or near point 200 210 NOTICE: Self-intersection at or near point 219.6352644836272 111.99294710327453 NOTICE: Self-intersection at or near point 129.99999999999989 210.99999999999991 NOTICE: Self-intersection at or near point 212.95837780046392 99.000086530632473 pkey | refvalid | st_isvalid ------+----------+------------ 1 | Valid | t 2 | Valid | t 3 | Valid | t 4 | Valid | t 5 | Valid | t 7 | Valid | t 6 | Valid | t 8 | Valid | t 9 | Valid | t 11 | Valid | t 12 | Valid | t 13 | Invalid | f 14 | Invalid | f 15 | Valid | t 16 | Valid | t 17 | Valid | t 18 | Valid | t 19 | Valid | t 20 | Invalid | f 21 | Invalid | f 22 | Invalid | f 23 | Invalid | f 24 | Invalid | f 25 | Invalid | f 26 | Valid | t 27 | Valid | t 28 | Valid | t 29 | Valid | t 30 | Invalid | f 31 | Valid | t 32 | Invalid | f 33 | Valid | t 34 | Valid | t 35 | Invalid | f 36 | Valid | t (35 rows) -- PostgreSQL 10.10 (Ubuntu 10.10-1.pgdg16.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609, 64-bit POSTGIS="2.4.3" PGSQL="100" GEOS="3.7.2-CAPI-1.11.2 0" PROJ="Rel. 4.9.2, 08 September 2015" GDAL="GDAL 2.3.2, released 2018/09/21" LIBXML="2.9.3" LIBJSON="0.11.99" LIBPROTOBUF="1.2.1" }}} **PostGIS 2.4 | GEOS 3.6.2 |** refvalid **MATCH** {{{ PostgreSQL 10.10 (Ubuntu 10.10-1.pgdg16.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609, 64-bit POSTGIS="2.4.3" PGSQL="100" GEOS="3.6.2-CAPI-1.10.2 4d2925d6" SFCGAL="1.3.0" PROJ="Rel. 4.9.3, 15 August 2016" LIBXML="2.9.3" LIBJSON="0.11.99" LIBPROTOBUF="1.2.1" }}}