[postgis-tickets] r16450 - Fix invalid inputs for GEOS if it cannot process them
Darafei
komzpa at gmail.com
Wed Mar 7 05:21:46 PST 2018
Author: komzpa
Date: 2018-03-07 05:21:45 -0800 (Wed, 07 Mar 2018)
New Revision: 16450
Modified:
trunk/NEWS
trunk/liblwgeom/lwgeom_geos.c
trunk/regress/tickets.sql
trunk/regress/tickets_expected
Log:
Fix invalid inputs for GEOS if it cannot process them
Invalid input geometry is fixed with MakeValid for GEOS exceptions in
ST_Intersection, ST_Union, ST_Difference, ST_SymDifference.
Closes #4037
Closes https://github.com/postgis/postgis/pull/228
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2018-03-07 09:02:05 UTC (rev 16449)
+++ trunk/NEWS 2018-03-07 13:21:45 UTC (rev 16450)
@@ -14,7 +14,7 @@
- #3885, version number removed from address_standardize lib file
- #3893, raster support functions can only be loaded in the same schema
with core PostGIS functions.
- - #4035, remove dummy pgis_abs type from aggregate/collect routines.
+ - #4035, remove dummy pgis_abs type from aggregate/collect routines.
* Enhancements and Fixes*
- #3944, Update to EPSG register v9.2 (Even Rouault)
@@ -43,6 +43,9 @@
- #4020, Casting from box3d to geometry now returns correctly connected
PolyhedralSurface (Matthias Bay)
- #2508, ST_OffsetCurve now works with collections (Darafei Praliaskouski)
+ - #4037, Invalid input geometry is fixed with MakeValid for GEOS exceptions in
+ ST_Intersection, ST_Union, ST_Difference, ST_SymDifference (Darafei
+ Praliaskouski)
PostGIS 2.4.0
2017/09/30
Modified: trunk/liblwgeom/lwgeom_geos.c
===================================================================
--- trunk/liblwgeom/lwgeom_geos.c 2018-03-07 09:02:05 UTC (rev 16449)
+++ trunk/liblwgeom/lwgeom_geos.c 2018-03-07 13:21:45 UTC (rev 16450)
@@ -603,6 +603,24 @@
g3 = GEOSIntersection(g1, g2);
+ if (!g3)
+ {
+ GEOSGeometry *g1v, *g2v;
+ lwnotice("%s: GEOS Error: %s", __func__, lwgeom_geos_errmsg);
+
+ if (!GEOSisValid(g1) || !GEOSisValid(g2))
+ {
+ lwnotice(
+ "Your geometry dataset is not valid per OGC Specification. "
+ "Please fix it with manual review of entries that are not ST_IsValid(geom). "
+ "Retrying GEOS operation with ST_MakeValid of your input.");
+ g1v = LWGEOM_GEOS_makeValid(g1);
+ g2v = LWGEOM_GEOS_makeValid(g2);
+ g3 = GEOSIntersection(g1v, g2v);
+ geos_clean(g1v, g2v, NULL);
+ }
+ }
+
if (!g3) return geos_clean_and_fail(g1, g2, NULL, __func__);
if (!output_geos_as_lwgeom(&g3, &result, srid, is3d, __func__))
@@ -695,6 +713,24 @@
g3 = GEOSDifference(g1, g2);
+ if (!g3)
+ {
+ GEOSGeometry *g1v, *g2v;
+ lwnotice("%s: GEOS Error: %s", __func__, lwgeom_geos_errmsg);
+
+ if (!GEOSisValid(g1) || !GEOSisValid(g2))
+ {
+ lwnotice(
+ "Your geometry dataset is not valid per OGC Specification. "
+ "Please fix it with manual review of entries that are not ST_IsValid(geom). "
+ "Retrying GEOS operation with ST_MakeValid of your input.");
+ g1v = LWGEOM_GEOS_makeValid(g1);
+ g2v = LWGEOM_GEOS_makeValid(g2);
+ g3 = GEOSDifference(g1v, g2v);
+ geos_clean(g1v, g2v, NULL);
+ }
+ }
+
if (!g3) return geos_clean_and_fail(g1, g2, NULL, __func__);
if (!output_geos_as_lwgeom(&g3, &result, srid, is3d, __func__))
@@ -727,6 +763,24 @@
g3 = GEOSSymDifference(g1, g2);
+ if (!g3)
+ {
+ GEOSGeometry *g1v, *g2v;
+ lwnotice("%s: GEOS Error: %s", __func__, lwgeom_geos_errmsg);
+
+ if (!GEOSisValid(g1) || !GEOSisValid(g2))
+ {
+ lwnotice(
+ "Your geometry dataset is not valid per OGC Specification. "
+ "Please fix it with manual review of entries that are not ST_IsValid(geom). "
+ "Retrying GEOS operation with ST_MakeValid of your input.");
+ g1v = LWGEOM_GEOS_makeValid(g1);
+ g2v = LWGEOM_GEOS_makeValid(g2);
+ g3 = GEOSSymDifference(g1v, g2v);
+ geos_clean(g1v, g2v, NULL);
+ }
+ }
+
if (!g3) return geos_clean_and_fail(g1, g2, NULL, __func__);
if (!output_geos_as_lwgeom(&g3, &result, srid, is3d, __func__))
@@ -791,6 +845,24 @@
g3 = GEOSUnion(g1, g2);
+ if (!g3)
+ {
+ GEOSGeometry *g1v, *g2v;
+ lwnotice("%s: GEOS Error: %s", __func__, lwgeom_geos_errmsg);
+
+ if (!GEOSisValid(g1) || !GEOSisValid(g2))
+ {
+ lwnotice(
+ "Your geometry dataset is not valid per OGC Specification. "
+ "Please fix it with manual review of entries that are not ST_IsValid(geom). "
+ "Retrying GEOS operation with ST_MakeValid of your input.");
+ g1v = LWGEOM_GEOS_makeValid(g1);
+ g2v = LWGEOM_GEOS_makeValid(g2);
+ g3 = GEOSUnion(g1v, g2v);
+ geos_clean(g1v, g2v, NULL);
+ }
+ }
+
if (!g3) return geos_clean_and_fail(g1, g2, NULL, __func__);
if (!output_geos_as_lwgeom(&g3, &result, srid, is3d, __func__))
Modified: trunk/regress/tickets.sql
===================================================================
--- trunk/regress/tickets.sql 2018-03-07 09:02:05 UTC (rev 16449)
+++ trunk/regress/tickets.sql 2018-03-07 13:21:45 UTC (rev 16450)
@@ -1075,5 +1075,11 @@
2996311.81673704 5844916.90864168 1180471541.171)'::geometry
);
+-- a butterfly polygon in all cases
+SELECT '#4037.1', ST_AsText(ST_Intersection('POLYGON((0 0, 10 10, 0 10, 10 0, 0 0))', ST_MakeEnvelope(2,2,8,8)));
+SELECT '#4037.2', ST_AsText(ST_Difference('POLYGON((0 0, 10 10, 0 10, 10 0, 0 0))', ST_MakeEnvelope(2,2,8,8)));
+SELECT '#4037.3', ST_AsText(ST_SymDifference('POLYGON((0 0, 10 10, 0 10, 10 0, 0 0))', ST_MakeEnvelope(2,2,8,8)));
+SELECT '#4037.4', ST_AsText(ST_Union('POLYGON((0 0, 10 10, 0 10, 10 0, 0 0))', ST_MakeEnvelope(2,2,8,8)));
+
-- Clean up
DELETE FROM spatial_ref_sys;
Modified: trunk/regress/tickets_expected
===================================================================
--- trunk/regress/tickets_expected 2018-03-07 09:02:05 UTC (rev 16449)
+++ trunk/regress/tickets_expected 2018-03-07 13:21:45 UTC (rev 16450)
@@ -326,3 +326,23 @@
#4011|ST_MultiLineString|MULTILINESTRING EMPTY|t|t
#4011|ST_GeometryCollection|MULTILINESTRING((0 0,0 0))|f|f
#4025|
+NOTICE: lwgeom_intersection: GEOS Error: TopologyException: Input geom 0 is invalid: Self-intersection
+NOTICE: Self-intersection
+NOTICE: Your geometry dataset is not valid per OGC Specification. Please fix it with manual review of entries that are not ST_IsValid(geom). Retrying GEOS operation with ST_MakeValid of your input.
+NOTICE: Self-intersection
+#4037.1|MULTIPOLYGON(((2 2,5 5,8 2,2 2)),((5 5,2 8,8 8,5 5)))
+NOTICE: lwgeom_difference: GEOS Error: TopologyException: Input geom 0 is invalid: Self-intersection
+NOTICE: Self-intersection
+NOTICE: Your geometry dataset is not valid per OGC Specification. Please fix it with manual review of entries that are not ST_IsValid(geom). Retrying GEOS operation with ST_MakeValid of your input.
+NOTICE: Self-intersection
+#4037.2|MULTIPOLYGON(((0 0,2 2,8 2,10 0,0 0)),((2 8,0 10,10 10,8 8,2 8)))
+NOTICE: lwgeom_symdifference: GEOS Error: TopologyException: Input geom 0 is invalid: Self-intersection
+NOTICE: Self-intersection
+NOTICE: Your geometry dataset is not valid per OGC Specification. Please fix it with manual review of entries that are not ST_IsValid(geom). Retrying GEOS operation with ST_MakeValid of your input.
+NOTICE: Self-intersection
+#4037.3|MULTIPOLYGON(((0 0,2 2,8 2,10 0,0 0)),((5 5,2 2,2 8,5 5)),((8 2,5 5,8 8,8 2)),((2 8,0 10,10 10,8 8,2 8)))
+NOTICE: lwgeom_union: GEOS Error: TopologyException: Input geom 0 is invalid: Self-intersection
+NOTICE: Self-intersection
+NOTICE: Your geometry dataset is not valid per OGC Specification. Please fix it with manual review of entries that are not ST_IsValid(geom). Retrying GEOS operation with ST_MakeValid of your input.
+NOTICE: Self-intersection
+#4037.4|POLYGON((0 0,2 2,2 8,0 10,10 10,8 8,8 2,10 0,0 0))
More information about the postgis-tickets
mailing list