[postgis-tickets] [SCM] PostGIS branch stable-2.5 updated. 2.5.5-30-gad333941d

git at osgeo.org git at osgeo.org
Mon Feb 7 19:24:36 PST 2022


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, stable-2.5 has been updated
       via  ad333941d847141219f753e49a2ff468339a4acc (commit)
      from  506d2a03be88e74b3390ba43b2aa6013e3d15bcc (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit ad333941d847141219f753e49a2ff468339a4acc
Author: Regina Obe <lr at pcorp.us>
Date:   Mon Feb 7 22:23:02 2022 -0500

    Items
    1. Stop trying to createlang in regress. Closes #4457 for PostGIS 2.5.6
    2. Regress cleanly with GEOS 3.9. Closes #5086

diff --git a/NEWS b/NEWS
index b404ba2fd..af99abdc7 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,5 @@
 PostGIS 2.5.6
-2022/02/03
+2022/02/06
 
  * Bug fixes *
 
@@ -13,6 +13,11 @@ PostGIS 2.5.6
   - #4971, Cunit fixes for newer CUnit (Raúl Marín, Regina Obe)
   - #5069, search_path vulnerabilty during install/upgrade
            (Regina Obe)
+  - #5086, regress cleanly (clip by box, make valid)
+           with GEOS 3.8+. For GEOS 3.8+
+           use native GEOS makevalid, buildarea, clipbybox (Regina Obe)
+  - #4457, Stop trying to createlang in regress
+           plpgsql is always installed (Regina Obe)
 
 
 PostGIS 2.5.5
diff --git a/doc/release_notes.xml b/doc/release_notes.xml
index 76303f38d..2efb86930 100644
--- a/doc/release_notes.xml
+++ b/doc/release_notes.xml
@@ -17,6 +17,11 @@
         <para>4971, Cunit fixes for newer CUnit (Raúl Marín, Regina Obe)</para>
         <para>5069, search_path vulnerabilty during install/upgrade
                   (Regina Obe)</para>
+        <para>5086, regress cleanly (clip by box, make valid)
+           with GEOS 3.8+. For GEOS 3.8+
+           use native GEOS makevalid, buildarea, clipbybox (Regina Obe)</para>
+        <para>4457, Stop trying to createlang in regress
+           plpgsql is always installed (Regina Obe)</para>
       </simplesect>
     </sect1>
 
diff --git a/liblwgeom/cunit/cu_geos.c b/liblwgeom/cunit/cu_geos.c
index ec3cedc0b..0af75f6eb 100644
--- a/liblwgeom/cunit/cu_geos.c
+++ b/liblwgeom/cunit/cu_geos.c
@@ -130,15 +130,27 @@ test_geos_makevalid(void)
 	char* out_ewkt;
 	LWGEOM* geom1;
 	LWGEOM* geom2;
+	LWGEOM* geom3;
 
 	wkb = (uint8_t*) "\001\003\000\000\000\001\000\000\000\011\000\000\000b\020X9 }\366 at 7\211A\340\235I\034A\316\326t18}\366@\306g\347\323\230I\034Ay\351&18}\366@\331\316\367\323\230I\034A\372~j\274\370}\366@\315\314\314LpI\034A\343\245\233\304R}\366 at R\270\036\005?I\034A\315\314\314\314Z~\366@\343\245\233\304\007I\034A\004V\016-\242}\366@\252\361\322M\323H\034A\351&1\010\306{\366 at H\341z\0247I\034Ab\020X9 }\366 at 7\211A\340\235I\034A";
 	geom1 = lwgeom_from_wkb(wkb, 157, LW_PARSER_CHECK_NONE);
 	geom2 = lwgeom_make_valid(geom1);
-	out_ewkt = lwgeom_to_ewkt((LWGEOM*)geom2);
-	ASSERT_STRING_EQUAL(out_ewkt, "GEOMETRYCOLLECTION(POLYGON((92114.014 463463.469,92115.5120743 463462.206937,92115.512 463462.207,92127.546 463452.075,92117.173 463439.755,92133.675 463425.942,92122.136 463412.826,92092.377 463437.77,92114.014 463463.469)),MULTIPOINT(92115.5120743 463462.206937,92122.136 463412.826))");
+	geom3 = lwgeom_normalize(geom2); //so GEOS 3.9 and 3.10 agree
+	out_ewkt = lwgeom_to_ewkt((LWGEOM*)geom3);
+
+	#if POSTGIS_GEOS_VERSION < 39
+	ASSERT_STRING_EQUAL(
+	    out_ewkt,
+	    "GEOMETRYCOLLECTION(POLYGON((92092.377 463437.77,92114.014 463463.469,92115.5120743 463462.206937,92115.512 463462.207,92127.546 463452.075,92117.173 463439.755,92133.675 463425.942,92122.136 463412.826,92092.377 463437.77)),MULTIPOINT(92122.136 463412.826,92115.5120743 463462.206937))");
+#else
+	ASSERT_STRING_EQUAL(
+	    out_ewkt,
+	    "POLYGON((92092.377 463437.77,92114.014 463463.469,92115.512 463462.207,92115.5120743 463462.206937,92127.546 463452.075,92117.173 463439.755,92133.675 463425.942,92122.136 463412.826,92092.377 463437.77))");
+#endif
 	lwfree(out_ewkt);
 	lwgeom_free(geom1);
 	lwgeom_free(geom2);
+	lwgeom_free(geom3);
 }
 
 
diff --git a/liblwgeom/cunit/cu_wrapx.c b/liblwgeom/cunit/cu_wrapx.c
index 9f246f353..a5ca09a28 100644
--- a/liblwgeom/cunit/cu_wrapx.c
+++ b/liblwgeom/cunit/cu_wrapx.c
@@ -15,10 +15,11 @@
 
 #include "liblwgeom.h"
 #include "liblwgeom_internal.h"
+#include "../lwgeom_geos.h"
 
 static void test_lwgeom_wrapx(void)
 {
-	LWGEOM *geom, *ret;
+	LWGEOM *geom, *ret, *tmp, *tmp2;
 	char *exp_wkt, *obt_wkt;
 
 	geom = lwgeom_from_wkt(
@@ -77,12 +78,21 @@ static void test_lwgeom_wrapx(void)
 		"LINESTRING(0 0,10 0)",
 		LW_PARSER_CHECK_NONE);
 	CU_ASSERT_FATAL(geom != NULL);
-	ret = lwgeom_wrapx(geom, 8, -10);
+	tmp = lwgeom_wrapx(geom, 8, -10);
+	ret = lwgeom_normalize(tmp);
+	lwgeom_free(tmp);
 	CU_ASSERT_FATAL(ret != NULL);
 	obt_wkt = lwgeom_to_ewkt(ret);
-	exp_wkt = "MULTILINESTRING((0 0,8 0),(-2 0,0 0))";
+	tmp = lwgeom_from_wkt(
+					"MULTILINESTRING((0 0,8 0),(-2 0,0 0))",
+					LW_PARSER_CHECK_NONE);
+	tmp2 = lwgeom_normalize(tmp);
+	lwgeom_free(tmp);
+	exp_wkt = lwgeom_to_ewkt(tmp2);
+	lwgeom_free(tmp2);
 	ASSERT_STRING_EQUAL(obt_wkt, exp_wkt);
 	lwfree(obt_wkt);
+	lwfree(exp_wkt);
 	lwgeom_free(ret);
 	lwgeom_free(geom);
 
@@ -90,12 +100,19 @@ static void test_lwgeom_wrapx(void)
 		"MULTILINESTRING((-5 -2,0 0),(0 0,10 10))",
 		LW_PARSER_CHECK_NONE);
 	CU_ASSERT_FATAL(geom != NULL);
-	ret = lwgeom_wrapx(geom, 0, 20);
+	tmp = lwgeom_wrapx(geom, 0, 20);
+	ret = lwgeom_normalize(tmp);
+	lwgeom_free(tmp);
 	CU_ASSERT_FATAL(ret != NULL);
 	obt_wkt = lwgeom_to_ewkt(ret);
-	exp_wkt = "MULTILINESTRING((15 -2,20 0),(0 0,10 10))";
+	tmp = lwgeom_from_wkt("MULTILINESTRING((15 -2,20 0),(0 0,10 10))", LW_PARSER_CHECK_NONE);
+	tmp2 = lwgeom_normalize(tmp);
+	lwgeom_free(tmp);
+	exp_wkt = lwgeom_to_ewkt(tmp2);
+	lwgeom_free(tmp2);
 	ASSERT_STRING_EQUAL(obt_wkt, exp_wkt);
 	lwfree(obt_wkt);
+	lwfree(exp_wkt);
 	lwgeom_free(ret);
 	lwgeom_free(geom);
 
@@ -106,21 +123,29 @@ static void test_lwgeom_wrapx(void)
 		")",
 		LW_PARSER_CHECK_NONE);
 	CU_ASSERT_FATAL(geom != NULL);
-	ret = lwgeom_wrapx(geom, 2, 20);
+	tmp = lwgeom_wrapx(geom, 2, 20);
+	ret = lwgeom_normalize(tmp);
+	lwgeom_free(tmp);
 	CU_ASSERT_FATAL(ret != NULL);
 	obt_wkt = lwgeom_to_ewkt(ret);
-	exp_wkt = "GEOMETRYCOLLECTION("
-						"MULTIPOLYGON("
-						"((22 0,20 0,20 10,22 10,22 4,22 2,22 0)),"
-						"((2 10,10 10,10 0,2 0,2 2,4 2,4 4,2 4,2 10))"
-						"),"
-						"MULTIPOLYGON("
-						"((22 11,20 11,20 21,22 21,22 15,22 13,22 11)),"
-						"((2 21,10 21,10 11,2 11,2 13,4 13,4 15,2 15,2 21))"
-						")"
-						")";
+	tmp = lwgeom_from_wkt("GEOMETRYCOLLECTION("
+							    "MULTIPOLYGON("
+							    "((22 0,20 0,20 10,22 10,22 4,22 2,22 0)),"
+							    "((2 10,10 10,10 0,2 0,2 2,4 2,4 4,2 4,2 10))"
+							    "),"
+							    "MULTIPOLYGON("
+							    "((22 11,20 11,20 21,22 21,22 15,22 13,22 11)),"
+							    "((2 21,10 21,10 11,2 11,2 13,4 13,4 15,2 15,2 21))"
+							    ")"
+							    ")",
+							    LW_PARSER_CHECK_NONE);
+	tmp2 = lwgeom_normalize(tmp);
+	lwgeom_free(tmp);
+	exp_wkt = lwgeom_to_ewkt(tmp2);
+	lwgeom_free(tmp2);
 	ASSERT_STRING_EQUAL(obt_wkt, exp_wkt);
 	lwfree(obt_wkt);
+	lwfree(exp_wkt);
 	lwgeom_free(ret);
 	lwgeom_free(geom);
 
@@ -132,21 +157,35 @@ static void test_lwgeom_wrapx(void)
 		")",
 		LW_PARSER_CHECK_NONE);
 	CU_ASSERT_FATAL(geom != NULL);
-	ret = lwgeom_wrapx(geom, 0, 20);
+	tmp = lwgeom_wrapx(geom, 0, 20);
+	ret = lwgeom_normalize(tmp);
+	lwgeom_free(tmp);
 	CU_ASSERT_FATAL(ret != NULL);
 	obt_wkt = lwgeom_to_ewkt(ret);
-	exp_wkt = "GEOMETRYCOLLECTION("
-						"MULTILINESTRING((15 -2,20 0),(0 0,10 10)),"
-						"POINT(15 0),"
-						"POLYGON EMPTY"
-						")";
+	tmp = lwgeom_from_wkt(
+	    "GEOMETRYCOLLECTION("
+	    "MULTILINESTRING((15 -2,20 0),(0 0,10 10)),"
+	    "POINT(15 0),"
+	    "POLYGON EMPTY"
+	    ")",
+	    LW_PARSER_CHECK_NONE);
+	tmp2 = lwgeom_normalize(tmp);
+	lwgeom_free(tmp);
+	exp_wkt = lwgeom_to_ewkt(tmp2);
+	lwgeom_free(tmp2);
 	ASSERT_STRING_EQUAL(obt_wkt, exp_wkt);
 	lwfree(obt_wkt);
+	lwfree(exp_wkt);
 	lwgeom_free(ret);
 	lwgeom_free(geom);
-
 }
 
+static int
+clean_geos_wrapx_suite(void)
+{
+	finishGEOS();
+	return 0;
+}
 
 /*
 ** Used by test harness to register the tests in this file.
@@ -154,6 +193,6 @@ static void test_lwgeom_wrapx(void)
 void wrapx_suite_setup(void);
 void wrapx_suite_setup(void)
 {
-	CU_pSuite suite = CU_add_suite("wrapx", NULL, NULL);
+	CU_pSuite suite = CU_add_suite("wrapx", NULL, clean_geos_wrapx_suite);
 	PG_ADD_TEST(suite, test_lwgeom_wrapx);
 }
diff --git a/liblwgeom/lwgeom_geos.c b/liblwgeom/lwgeom_geos.c
index ab8b3143e..e51d1ec3d 100644
--- a/liblwgeom/lwgeom_geos.c
+++ b/liblwgeom/lwgeom_geos.c
@@ -145,9 +145,16 @@ ptarray_from_GEOSCoordSeq(const GEOSCoordSequence* cs, uint8_t want3d)
 
 	for (i = 0; i < size; i++)
 	{
+#if POSTGIS_GEOS_VERSION < 38
 		GEOSCoordSeq_getX(cs, i, &(point.x));
 		GEOSCoordSeq_getY(cs, i, &(point.y));
 		if (dims >= 3) GEOSCoordSeq_getZ(cs, i, &(point.z));
+#else
+		if (dims >= 3)
+			GEOSCoordSeq_getXYZ(cs, i, &(point.x), &(point.y), &(point.z));
+		else
+			GEOSCoordSeq_getXY(cs, i, &(point.x), &(point.y));
+#endif
 		ptarray_set_point4d(pa, i, &point);
 	}
 
@@ -283,10 +290,17 @@ ptarray_to_GEOSCoordSeq(const POINTARRAY* pa, uint8_t fix_ring)
 			LWDEBUGF(4, "Point: %g,%g", p2d->x, p2d->y);
 		}
 
+#if POSTGIS_GEOS_VERSION < 38
 		GEOSCoordSeq_setX(sq, i, p2d->x);
 		GEOSCoordSeq_setY(sq, i, p2d->y);
-
 		if (dims == 3) GEOSCoordSeq_setZ(sq, i, p3d->z);
+#else
+		if (dims == 3)
+			GEOSCoordSeq_setXYZ(sq, i, p2d->x, p2d->y, p3d->z);
+		else
+			GEOSCoordSeq_setXY(sq, i, p2d->x, p2d->y);
+#endif
+
 	}
 
 	if (append_points)
@@ -300,8 +314,12 @@ ptarray_to_GEOSCoordSeq(const POINTARRAY* pa, uint8_t fix_ring)
 			p2d = getPoint2d_cp(pa, 0);
 		for (i = pa->npoints; i < pa->npoints + append_points; i++)
 		{
+#if POSTGIS_GEOS_VERSION < 38
 			GEOSCoordSeq_setX(sq, i, p2d->x);
 			GEOSCoordSeq_setY(sq, i, p2d->y);
+#else
+			GEOSCoordSeq_setXY(sq, i, p2d->x, p2d->y);
+#endif
 
 			if (dims == 3) GEOSCoordSeq_setZ(sq, i, p3d->z);
 		}
@@ -328,6 +346,7 @@ GBOX2GEOS(const GBOX* box)
 	GEOSCoordSequence* seq = GEOSCoordSeq_create(5, 2);
 	if (!seq) return NULL;
 
+#if POSTGIS_GEOS_VERSION < 38
 	GEOSCoordSeq_setX(seq, 0, box->xmin);
 	GEOSCoordSeq_setY(seq, 0, box->ymin);
 
@@ -342,6 +361,13 @@ GBOX2GEOS(const GBOX* box)
 
 	GEOSCoordSeq_setX(seq, 4, box->xmin);
 	GEOSCoordSeq_setY(seq, 4, box->ymin);
+#else
+	GEOSCoordSeq_setXY(seq, 0, box->xmin, box->ymin);
+	GEOSCoordSeq_setXY(seq, 1, box->xmax, box->ymin);
+	GEOSCoordSeq_setXY(seq, 2, box->xmax, box->ymax);
+	GEOSCoordSeq_setXY(seq, 3, box->xmin, box->ymax);
+	GEOSCoordSeq_setXY(seq, 4, box->xmin, box->ymin);
+#endif
 
 	ring = GEOSGeom_createLinearRing(seq);
 	if (!ring)
@@ -403,8 +429,21 @@ LWGEOM2GEOS(const LWGEOM* lwgeom, uint8_t autofix)
 			g = GEOSGeom_createEmptyPolygon();
 		else
 		{
+#if POSTGIS_GEOS_VERSION < 38
 			sq = ptarray_to_GEOSCoordSeq(lwp->point, 0);
 			g = GEOSGeom_createPoint(sq);
+#else
+			if (lwgeom_has_z(lwgeom))
+			{
+				sq = ptarray_to_GEOSCoordSeq(lwp->point, 0);
+				g = GEOSGeom_createPoint(sq);
+			}
+			else
+			{
+				const POINT2D* p = getPoint2d_cp(lwp->point, 0);
+				g = GEOSGeom_createPointFromXY(p->x, p->y);
+			}
+#endif
 		}
 		if (!g) return NULL;
 		break;
@@ -519,8 +558,12 @@ make_geos_point(double x, double y)
 
 	if (!seq) return NULL;
 
+#if POSTGIS_GEOS_VERSION < 38
 	GEOSCoordSeq_setX(seq, 0, x);
 	GEOSCoordSeq_setY(seq, 0, y);
+#else
+	GEOSCoordSeq_setXY(seq, 0, x, y);
+#endif
 
 	geom = GEOSGeom_createPoint(seq);
 	if (!geom) GEOSCoordSeq_destroy(seq);
@@ -535,10 +578,15 @@ make_geos_segment(double x1, double y1, double x2, double y2)
 
 	if (!seq) return NULL;
 
+#if POSTGIS_GEOS_VERSION < 38
 	GEOSCoordSeq_setX(seq, 0, x1);
 	GEOSCoordSeq_setY(seq, 0, y1);
 	GEOSCoordSeq_setX(seq, 1, x2);
 	GEOSCoordSeq_setY(seq, 1, y2);
+#else
+	GEOSCoordSeq_setXY(seq, 0, x1, y1);
+	GEOSCoordSeq_setXY(seq, 1, x2, y2);
+#endif
 
 	geom = GEOSGeom_createLineString(seq);
 	if (!geom) GEOSCoordSeq_destroy(seq);
@@ -903,7 +951,7 @@ lwgeom_clip_by_rect(const LWGEOM *geom1, double x1, double y1, double x2, double
 }
 
 /* ------------ BuildArea stuff ---------------------------------------------------------------------{ */
-
+#if POSTGIS_GEOS_VERSION < 38
 typedef struct Face_t
 {
 	const GEOSGeometry* geom;
@@ -1149,6 +1197,7 @@ LWGEOM_GEOS_buildArea(const GEOSGeometry* geom_in)
 
 	return shp;
 }
+#endif
 
 LWGEOM*
 lwgeom_buildarea(const LWGEOM* geom)
@@ -1167,7 +1216,11 @@ lwgeom_buildarea(const LWGEOM* geom)
 
 	if (!(g1 = LWGEOM2GEOS(geom, AUTOFIX))) GEOS_FAIL();
 
+#if POSTGIS_GEOS_VERSION < 38
 	g3 = LWGEOM_GEOS_buildArea(g1);
+#else
+	g3 = GEOSBuildArea(g1);
+#endif
 
 	if (!g3) GEOS_FREE_AND_FAIL(g1);
 	GEOSSetSRID(g3, srid);
@@ -1558,8 +1611,12 @@ lwpoly_to_points(const LWPOLY* lwpoly, uint32_t npoints)
 			if (x >= bbox.xmax || y >= bbox.ymax) continue;
 
 			gseq = GEOSCoordSeq_create(1, 2);
+#if POSTGIS_GEOS_VERSION < 38
 			GEOSCoordSeq_setX(gseq, 0, x);
 			GEOSCoordSeq_setY(gseq, 0, y);
+#else
+			GEOSCoordSeq_setXY(gseq, 0, x, y);
+#endif
 			gpt = GEOSGeom_createPoint(gseq);
 
 			contains = GEOSPreparedIntersects(gprep, gpt);
@@ -1794,7 +1851,11 @@ lwgeom_get_geos_coordseq_2d(const LWGEOM* g, uint32_t num_points)
 			return NULL;
 		}
 
+#if POSTGIS_GEOS_VERSION < 38
 		if (!GEOSCoordSeq_setX(coords, i, tmp.x) || !GEOSCoordSeq_setY(coords, i, tmp.y))
+#else
+		if (!GEOSCoordSeq_setXY(coords, i, tmp.x, tmp.y))
+#endif
 		{
 			GEOSCoordSeq_destroy(coords);
 			lwpointiterator_destroy(it);
diff --git a/liblwgeom/lwgeom_geos.h b/liblwgeom/lwgeom_geos.h
index 9845cff11..ae21aef79 100644
--- a/liblwgeom/lwgeom_geos.h
+++ b/liblwgeom/lwgeom_geos.h
@@ -34,8 +34,10 @@
 LWGEOM* GEOS2LWGEOM(const GEOSGeometry* geom, uint8_t want3d);
 GEOSGeometry* LWGEOM2GEOS(const LWGEOM* g, uint8_t autofix);
 GEOSGeometry* GBOX2GEOS(const GBOX* g);
+#if POSTGIS_GEOS_VERSION < 38
 GEOSGeometry* LWGEOM_GEOS_buildArea(const GEOSGeometry* geom_in);
 GEOSGeometry* LWGEOM_GEOS_makeValid(const GEOSGeometry*);
+#endif
 
 GEOSGeometry* make_geos_point(double x, double y);
 GEOSGeometry* make_geos_segment(double x1, double y1, double x2, double y2);
diff --git a/liblwgeom/lwgeom_geos_clean.c b/liblwgeom/lwgeom_geos_clean.c
index 7cc9c76d5..9ef310875 100644
--- a/liblwgeom/lwgeom_geos_clean.c
+++ b/liblwgeom/lwgeom_geos_clean.c
@@ -35,6 +35,7 @@
 /* #define PARANOIA_LEVEL 2 */
 #undef LWGEOM_PROFILE_MAKEVALID
 
+#if POSTGIS_GEOS_VERSION < 38
 /*
  * Return Nth vertex in GEOSGeometry as a POINT.
  * May return NULL if the geometry has NO vertex.
@@ -108,6 +109,7 @@ LWGEOM_GEOS_getPointN(const GEOSGeometry* g_in, uint32_t n)
 
 	return GEOSGeom_createPoint(seq_out);
 }
+#endif
 
 LWGEOM* lwcollection_make_geos_friendly(LWCOLLECTION* g);
 LWGEOM* lwline_make_geos_friendly(LWLINE* line);
@@ -314,6 +316,8 @@ lwcollection_make_geos_friendly(LWCOLLECTION* g)
 	return (LWGEOM*)ret;
 }
 
+#if POSTGIS_GEOS_VERSION < 38
+
 /*
  * Fully node given linework
  */
@@ -843,6 +847,7 @@ LWGEOM_GEOS_makeValid(const GEOSGeometry* gin)
 
 	return gout;
 }
+#endif
 
 /* Exported. Uses GEOS internally */
 LWGEOM*
@@ -889,7 +894,11 @@ lwgeom_make_valid(LWGEOM* lwgeom_in)
 		lwgeom_out = lwgeom_in;
 	}
 
+#if POSTGIS_GEOS_VERSION < 38
 	geosout = LWGEOM_GEOS_makeValid(geosgeom);
+#else
+	geosout = GEOSMakeValid(geosgeom);
+#endif
 	GEOSGeom_destroy(geosgeom);
 	if (!geosout) return NULL;
 
diff --git a/postgis/mvt.c b/postgis/mvt.c
index 333db09c4..83e25cb49 100644
--- a/postgis/mvt.c
+++ b/postgis/mvt.c
@@ -998,7 +998,11 @@ mvt_grid_and_validate_geos(LWGEOM *ng, uint8_t basic_type)
 
 		while (!valid && iterations < max_iterations)
 		{
+#if POSTGIS_GEOS_VERSION < 38
 			GEOSGeometry *geo_valid = LWGEOM_GEOS_makeValid(geo);
+#else
+			GEOSGeometry *geo_valid = GEOSMakeValid(geo);
+#endif
 			GEOSGeom_destroy(geo);
 			if (!geo_valid)
 				return NULL;
diff --git a/regress/clean.sql b/regress/clean.sql
index 5ddc33e48..d641075b9 100644
--- a/regress/clean.sql
+++ b/regress/clean.sql
@@ -42,10 +42,11 @@ SELECT origin,caseno,
        st_equals(st_collectionextract(st_makevalid(orig),3), st_collectionextract(valid,3)),
        st_isvalid(st_makevalid(orig)), -- paranoia
        (st_isvaliddetail(orig)).valid
-  FROM clean_cases;
+  FROM clean_cases
+ORDER BY 1, 2;
 
 SELECT '#1719.1', ST_AsEWKT(ST_MakeValid('POINT(0 0)'));
-SELECT '#1719.2', ST_AsEWKT(ST_MakeValid('GEOMETRYCOLLECTION(POINT(0 0),MULTIPOINT(3 4,5 2),LINESTRING(4 4, 4 4),POLYGON((0 0,10 10,0 10,10 0,0 0)))'));
+SELECT '#1719.2', ST_AsEWKT(ST_Normalize(ST_MakeValid('GEOMETRYCOLLECTION(POINT(0 0),MULTIPOINT(3 4,5 2),LINESTRING(4 4, 4 4),POLYGON((0 0,10 10,0 10,10 0,0 0)))')));
 SELECT '#1719.3', ST_AsEWKT(ST_MakeValid('MULTIPOINT(3 4,5 2)'));
 
 DROP TABLE clean_cases;
diff --git a/regress/clean_expected b/regress/clean_expected
index d3159135f..307d75b61 100644
--- a/regress/clean_expected
+++ b/regress/clean_expected
@@ -1,3 +1,8 @@
+PG|1|t|t|f
+PG|2|t|t|f
+PG|3|t|t|f
+PG|4|t|t|f
+PG|5|t|t|f
 RT|1|t|t|f
 RT|2|t|t|f
 RT|3|t|t|f
@@ -21,11 +26,6 @@ RT|16.2|t|t|f
 RT|16.3|t|t|f
 RT|16.4|t|t|f
 RT|17.1|t|t|f
-PG|1|t|t|f
-PG|2|t|t|f
-PG|3|t|t|f
-PG|4|t|t|f
-PG|5|t|t|f
 #1719.1|POINT(0 0)
-#1719.2|GEOMETRYCOLLECTION(POINT(0 0),MULTIPOINT(3 4,5 2),POINT(4 4),MULTIPOLYGON(((0 0,5 5,10 0,0 0)),((5 5,0 10,10 10,5 5))))
+#1719.2|GEOMETRYCOLLECTION(MULTIPOLYGON(((0 10,10 10,5 5,0 10)),((0 0,5 5,10 0,0 0))),MULTIPOINT(5 2,3 4),POINT(4 4),POINT(0 0))
 #1719.3|MULTIPOINT(3 4,5 2)
diff --git a/regress/concave_hull_hard.sql b/regress/concave_hull_hard.sql
index 7076d1243..085e8fac6 100644
--- a/regress/concave_hull_hard.sql
+++ b/regress/concave_hull_hard.sql
@@ -1,60 +1,69 @@
--- Tests to confirm the concave hull area is <= convex hull and
--- covers the original geometry (can't use covers because always gives topo errors with 3.3
-SELECT
-	'ST_ConcaveHull MultiPolygon 0.95', ST_Area(ST_Intersection(geom,ST_ConcaveHull(
-		geom, 0.95) )) = ST_Area(geom) As encloses_geom,
-		(ST_Area(ST_ConvexHull(geom))
-		- ST_Area(ST_ConcaveHull(geom, 0.95))) < (0.95 * ST_Area(ST_ConvexHull(geom) ) ) As reached_target
-FROM ST_Union(ST_GeomFromText('POLYGON((175 150, 20 40,
-			50 60, 125 100, 175 150))'),
-		ST_Buffer(ST_GeomFromText('POINT(110 170)'), 20)
-		) As geom;
-
-SELECT
-	'ST_ConcaveHull Lines 0.80', ST_Within(geom,ST_ConcaveHull(
-		geom, 0.80) ) As encloses_geom,
-		(ST_Area(ST_ConvexHull(geom))
-		- ST_Area(ST_ConcaveHull(geom, 0.80))) < (0.80 * ST_Area(ST_ConvexHull(geom) ) ) As reached_target
-
-FROM ST_GeomFromText('MULTILINESTRING((106 164,30 112,74 70,82 112,130 94,
-	130 62,122 40,156 32,162 76,172 88),
-(132 178,134 148,128 136,96 128,132 108,150 130,
-170 142,174 110,156 96,158 90,158 88),
-(22 64,66 28,94 38,94 68,114 76,112 30,
-132 10,168 18,178 34,186 52,184 74,190 100,
-190 122,182 148,178 170,176 184,156 164,146 178,
-132 186,92 182,56 158,36 150,62 150,76 128,88 118))') As geom;
-
--- test holes vs. no holes - holes should still enclose but have smaller area than no holes --
-SELECT
-	'ST_ConcaveHull Lines 0.80 holes', ST_Within(geom,ST_ConcaveHull(
-		geom, 0.80, true) ) As encloses_geom,
-		ST_Area(ST_ConcaveHull(geom, 0.80, true)) < ST_Area(ST_ConcaveHull(geom, 0.80)) As reached_target
-
-FROM ST_GeomFromText('MULTILINESTRING((106 164,30 112,74 70,82 112,130 94,
-	130 62,122 40,156 32,162 76,172 88),
-(132 178,134 148,128 136,96 128,132 108,150 130,
-170 142,174 110,156 96,158 90,158 88),
-(22 64,66 28,94 38,94 68,114 76,112 30,
-132 10,168 18,178 34,186 52,184 74,190 100,
-190 122,182 148,178 170,176 184,156 164,146 178,
-132 186,92 182,56 158,36 150,62 150,76 128,88 118))') As geom;
-
-SELECT '#3638', abs(ST_Area(ST_Intersection(geom, ST_ConcaveHull(geom, 0.999) )) - ST_Area(geom)) < 1 As encloses_geom,
-(ST_Area(ST_ConvexHull(geom)) - ST_Area(ST_ConcaveHull(geom, 0.999))) < (0.999 * ST_Area(ST_ConvexHull(geom) ) ) As reached_target
-FROM ST_GeomFromText('MULTIPOLYGON(((2224400 6861690,2226160 6865040,2226430 6867030,2225110 6867930,2224550 6868140,2222860 6868290,2224200 6870520,2224140 6871610,2224400 6871920,2224100 6872050,2223140 6873060,2223190 6873150,2222810 6873290,2222400 6873900,2221890 6875900,2222910 6876200,2223970 6876510,2224210 6875470,2225600 6872970,2226880 6872060,2227360 6871910,2228120 6870830,2228190 6870260,2229210 6869450,2229980 6869320,2233190 6870260,2233940 6870200,2236570 6869190,2238080 6869450,2239770 6870300,2240580 6870450,2242530 6870230,2243570 6869480,2244190 6869320,2246720 6869460,2248040 6869250,2249830 6869940,2250120 6869640,2251060 6869630,2253500 6870910,2254340 6870800,2258060 6871250,2259470 6871140,2260580 6871370,2263080 6871040,2263880 6871220,2265420 6870890,2266880 6870990,2267830 6870880,2268480 6870640,2269680 6869860,2270470 6869570,2270700 6869880,2271370 6870100,2271250 6870020,2271340 6868300,2270340 6867850,2270750 6867310,2271670 6867510,2272200 6867270,
 2272860 6867290,2272900 6867140,2272770 6866040,2273190 6865860,2273380 6861740,2272880 6861660,2272770 6861350,2272850 6860930,2273060 6860960,2273120 6860390,2272990 6860380,2272180 6859940,2271690 6860140,2271190 6859990,2270050 6859210,2269380 6859250,2269140 6858320,2268520 6858490,2268260 6857030,2268370 6855880,2269980 6855600,2270020 6855910,2270200 6855880,2270540 6855400,2270560 6855400,2270330 6854840,2269130 6855330,2269040 6854000,2268770 6854040,2268800 6853770,2267050 6853410,2264990 6853780,2264820 6852290,2263930 6852640,2263870 6852490,2262620 6852580,2262270 6851950,2261370 6851900,2260840 6850950,2262280 6850740,2263030 6850540,2263460 6850900,2263950 6850880,2263470 6846320,2263940 6846290,2264470 6845790,2264080 6844800,2263350 6845130,2262920 6844190,2263890 6843570,2263900 6843290,2264390 6843280,2264750 6843050,2267580 6843130,2267770 6841660,2268520 6841380,2269290 6843720,2270390 6843200,2270740 6844460,2272070 6844140,2272570 6843850,2271910 6841700,22723
 10 6841620,2271920 6839660,2274110 6839550,2273830 6840050,2273930 6840710,2273780 6841680,2273880 6842480,2274700 6842440,2274710 6842470,2274860 6842360,2275820 6843640,2277060 6843170,2277560 6843180,2278450 6842340,2280650 6843010,2280460 6841890,2280720 6841910,2280630 6841380,2280660 6841300,2280350 6841280,2279800 6840940,2279400 6840910,2278970 6840290,2279390 6839440,2279840 6839590,2280640 6839550,2280580 6838610,2280420 6838460,2280440 6837540,2280780 6835350,2279600 6835380,2280130 6833540,2280100 6833530,2280180 6833360,2280240 6833150,2280280 6833170,2280340 6833020,2280280 6832200,2279750 6832550,2278910 6833410,2277720 6834160,2275760 6834770,2273730 6834900,2273700 6834600,2273090 6834760,2272900 6835060,2273030 6835640,2272360 6835700,2271630 6834440,2271300 6832800,2270770 6831480,2270430 6831170,2270060 6829650,2272180 6829220,2271960 6825760,2270980 6825900,2271120 6825460,2269680 6825130,2269960 6824210,2268800 6823880,2268490 6824880,2265240 6824150,2265060 68
 25050,2265230 6828090,2264720 6827640,2262680 6827420,2262460 6829170,2261680 6827390,2261300 6827330,2261630 6826400,2261380 6826380,2261300 6825770,2260880 6825470,2260890 6825200,2258820 6826220,2256110 6826820,2256000 6826170,2256240 6824400,2256110 6823070,2255600 6822830,2255020 6821780,2254200 6821510,2254290 6821180,2254090 6821140,2250160 6821360,2249430 6820740,2248860 6820690,2247300 6821910,2246100 6823920,2244620 6825100,2244150 6825940,2244360 6826540,2244120 6827280,2242860 6826970,2241510 6826250,2239300 6825950,2238920 6826090,2239140 6826530,2236380 6827620,2235840 6828780,2235820 6829940,2236020 6830230,2235940 6830520,2235320 6831610,2234070 6832950,2233720 6833920,2233090 6834050,2233220 6836220,2235120 6842320,2234390 6843060,2233600 6843480,2230340 6844740,2230830 6846700,2229830 6846880,2228380 6847430,2225950 6847340,2224770 6847510,2222350 6848640,2222130 6849400,2221570 6850340,2221630 6851510,2221280 6851290,2219450 6852470,2219120 6854260,2219460 6854340
 ,2219570 6855400,2220210 6856120,2220350 6856590,2220420 6856570,2224880 6860850,2224840 6861280,2224400 6861690)),((2270830 6855440,2272020 6855640,2271620 6854660,2270830 6855440)))') as geom;
-
-\set QUIET on
-SET client_min_messages TO WARNING;
-drop table if exists big_polygon;
-create table big_polygon(geom geometry);
-alter table big_polygon alter column geom set storage main;
-\copy big_polygon from 'ticket_3697.wkt'
-\set QUIET off
-SET client_min_messages TO NOTICE;
-
-SELECT '#3697', ST_Area(ST_Intersection(geom,ST_ConcaveHull(geom, 0.8) )) = ST_Area(geom) As encloses_geom,
-(ST_Area(ST_ConvexHull(geom)) - ST_Area(ST_ConcaveHull(geom, 0.8))) < (0.8 * ST_Area(ST_ConvexHull(geom) ) ) As reached_target
-FROM big_polygon;
-
-drop table big_polygon;
+-- Tests to confirm the concave hull area is <= convex hull and
+-- covers the original geometry (can't use covers because always gives topo errors with 3.3
+SELECT
+	'ST_ConcaveHull MultiPolygon 0.95', ST_Area(ST_Intersection(geom,ST_ConcaveHull(
+		geom, 0.95) )) = ST_Area(geom) As encloses_geom,
+		(ST_Area(ST_ConvexHull(geom))
+		- ST_Area(ST_ConcaveHull(geom, 0.95))) < (0.95 * ST_Area(ST_ConvexHull(geom) ) ) As reached_target
+FROM ST_Union(ST_GeomFromText('POLYGON((175 150, 20 40,
+			50 60, 125 100, 175 150))'),
+		ST_Buffer(ST_GeomFromText('POINT(110 170)'), 20)
+		) As geom;
+
+SELECT
+	'ST_ConcaveHull Lines 0.80', ST_Within(geom,ST_ConcaveHull(
+		geom, 0.80) ) As encloses_geom,
+		(ST_Area(ST_ConvexHull(geom))
+		- ST_Area(ST_ConcaveHull(geom, 0.80))) < (0.80 * ST_Area(ST_ConvexHull(geom) ) ) As reached_target
+
+FROM ST_GeomFromText('MULTILINESTRING((106 164,30 112,74 70,82 112,130 94,
+	130 62,122 40,156 32,162 76,172 88),
+(132 178,134 148,128 136,96 128,132 108,150 130,
+170 142,174 110,156 96,158 90,158 88),
+(22 64,66 28,94 38,94 68,114 76,112 30,
+132 10,168 18,178 34,186 52,184 74,190 100,
+190 122,182 148,178 170,176 184,156 164,146 178,
+132 186,92 182,56 158,36 150,62 150,76 128,88 118))') As geom;
+
+-- test holes vs. no holes - holes should still enclose but have smaller area than no holes --
+SELECT
+	'ST_ConcaveHull Lines 0.80 holes', ST_Within(geom,ST_ConcaveHull(
+		geom, 0.80, true) ) As encloses_geom,
+		ST_Area(ST_ConcaveHull(geom, 0.80, true)) < ST_Area(ST_ConcaveHull(geom, 0.80)) As reached_target
+
+FROM ST_GeomFromText('MULTILINESTRING((106 164,30 112,74 70,82 112,130 94,
+	130 62,122 40,156 32,162 76,172 88),
+(132 178,134 148,128 136,96 128,132 108,150 130,
+170 142,174 110,156 96,158 90,158 88),
+(22 64,66 28,94 38,94 68,114 76,112 30,
+132 10,168 18,178 34,186 52,184 74,190 100,
+190 122,182 148,178 170,176 184,156 164,146 178,
+132 186,92 182,56 158,36 150,62 150,76 128,88 118))') As geom;
+
+SELECT '#3638', abs(ST_Area(ST_Intersection(geom, ST_ConcaveHull(geom, 0.999) )) - ST_Area(geom)) < 1 As encloses_geom,
+(ST_Area(ST_ConvexHull(geom)) - ST_Area(ST_ConcaveHull(geom, 0.999))) < (0.999 * ST_Area(ST_ConvexHull(geom) ) ) As reached_target
+FROM ST_GeomFromText('MULTIPOLYGON(((2224400 6861690,2226160 6865040,2226430 6867030,2225110 6867930,2224550 6868140,2222860 6868290,2224200 6870520,2224140 6871610,2224400 6871920,2224100 6872050,2223140 6873060,2223190 6873150,2222810 6873290,2222400 6873900,2221890 6875900,2222910 6876200,2223970 6876510,2224210 6875470,2225600 6872970,2226880 6872060,2227360 6871910,2228120 6870830,2228190 6870260,2229210 6869450,2229980 6869320,2233190 6870260,2233940 6870200,2236570 6869190,2238080 6869450,2239770 6870300,2240580 6870450,2242530 6870230,2243570 6869480,2244190 6869320,2246720 6869460,2248040 6869250,2249830 6869940,2250120 6869640,2251060 6869630,2253500 6870910,2254340 6870800,2258060 6871250,2259470 6871140,2260580 6871370,2263080 6871040,2263880 6871220,2265420 6870890,2266880 6870990,2267830 6870880,2268480 6870640,2269680 6869860,2270470 6869570,2270700 6869880,2271370 6870100,2271250 6870020,2271340 6868300,2270340 6867850,2270750 6867310,2271670 6867510,2272200 6867270,
 2272860 6867290,2272900 6867140,2272770 6866040,2273190 6865860,2273380 6861740,2272880 6861660,2272770 6861350,2272850 6860930,2273060 6860960,2273120 6860390,2272990 6860380,2272180 6859940,2271690 6860140,2271190 6859990,2270050 6859210,2269380 6859250,2269140 6858320,2268520 6858490,2268260 6857030,2268370 6855880,2269980 6855600,2270020 6855910,2270200 6855880,2270540 6855400,2270560 6855400,2270330 6854840,2269130 6855330,2269040 6854000,2268770 6854040,2268800 6853770,2267050 6853410,2264990 6853780,2264820 6852290,2263930 6852640,2263870 6852490,2262620 6852580,2262270 6851950,2261370 6851900,2260840 6850950,2262280 6850740,2263030 6850540,2263460 6850900,2263950 6850880,2263470 6846320,2263940 6846290,2264470 6845790,2264080 6844800,2263350 6845130,2262920 6844190,2263890 6843570,2263900 6843290,2264390 6843280,2264750 6843050,2267580 6843130,2267770 6841660,2268520 6841380,2269290 6843720,2270390 6843200,2270740 6844460,2272070 6844140,2272570 6843850,2271910 6841700,22723
 10 6841620,2271920 6839660,2274110 6839550,2273830 6840050,2273930 6840710,2273780 6841680,2273880 6842480,2274700 6842440,2274710 6842470,2274860 6842360,2275820 6843640,2277060 6843170,2277560 6843180,2278450 6842340,2280650 6843010,2280460 6841890,2280720 6841910,2280630 6841380,2280660 6841300,2280350 6841280,2279800 6840940,2279400 6840910,2278970 6840290,2279390 6839440,2279840 6839590,2280640 6839550,2280580 6838610,2280420 6838460,2280440 6837540,2280780 6835350,2279600 6835380,2280130 6833540,2280100 6833530,2280180 6833360,2280240 6833150,2280280 6833170,2280340 6833020,2280280 6832200,2279750 6832550,2278910 6833410,2277720 6834160,2275760 6834770,2273730 6834900,2273700 6834600,2273090 6834760,2272900 6835060,2273030 6835640,2272360 6835700,2271630 6834440,2271300 6832800,2270770 6831480,2270430 6831170,2270060 6829650,2272180 6829220,2271960 6825760,2270980 6825900,2271120 6825460,2269680 6825130,2269960 6824210,2268800 6823880,2268490 6824880,2265240 6824150,2265060 68
 25050,2265230 6828090,2264720 6827640,2262680 6827420,2262460 6829170,2261680 6827390,2261300 6827330,2261630 6826400,2261380 6826380,2261300 6825770,2260880 6825470,2260890 6825200,2258820 6826220,2256110 6826820,2256000 6826170,2256240 6824400,2256110 6823070,2255600 6822830,2255020 6821780,2254200 6821510,2254290 6821180,2254090 6821140,2250160 6821360,2249430 6820740,2248860 6820690,2247300 6821910,2246100 6823920,2244620 6825100,2244150 6825940,2244360 6826540,2244120 6827280,2242860 6826970,2241510 6826250,2239300 6825950,2238920 6826090,2239140 6826530,2236380 6827620,2235840 6828780,2235820 6829940,2236020 6830230,2235940 6830520,2235320 6831610,2234070 6832950,2233720 6833920,2233090 6834050,2233220 6836220,2235120 6842320,2234390 6843060,2233600 6843480,2230340 6844740,2230830 6846700,2229830 6846880,2228380 6847430,2225950 6847340,2224770 6847510,2222350 6848640,2222130 6849400,2221570 6850340,2221630 6851510,2221280 6851290,2219450 6852470,2219120 6854260,2219460 6854340
 ,2219570 6855400,2220210 6856120,2220350 6856590,2220420 6856570,2224880 6860850,2224840 6861280,2224400 6861690)),((2270830 6855440,2272020 6855640,2271620 6854660,2270830 6855440)))') as geom;
+
+\set QUIET on
+SET client_min_messages TO WARNING;
+drop table if exists big_polygon;
+create table big_polygon(geom geometry);
+alter table big_polygon alter column geom set storage main;
+\copy big_polygon from 'ticket_3697.wkt'
+\set QUIET off
+SET client_min_messages TO NOTICE;
+
+WITH intermediate AS
+(
+    SELECT ST_ConcaveHull(geom, 0.8)    as concave,
+           ST_Area(ST_ConvexHull(geom)) as convex_area,
+           geom                         as geom
+    FROM big_polygon
+)
+SELECT '#3697',
+				-- for some reason area difference is 3e-13 on GEOS 3.9.2dev, not worth sweating over
+        abs(ST_Area(ST_Intersection(geom,concave)) - ST_Area(geom)) < 0.0001 As encloses_geom,
+        (convex_area - ST_Area(concave) < (0.8 * convex_area)) As reached_target
+FROM intermediate;
+
+drop table big_polygon;
diff --git a/regress/mvt.sql b/regress/mvt.sql
index c09fab9b8..344b9e9f8 100644
--- a/regress/mvt.sql
+++ b/regress/mvt.sql
@@ -11,10 +11,10 @@ select 'PG3', ST_AsText(ST_AsMVTGeom(
 	ST_Point(1, 2),
 	ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096/2, 4096/2)),
 	4096, 0, false));
-select 'PG4', ST_AsText(ST_AsMVTGeom(
+select 'PG4', ST_AsText(ST_Normalize(ST_AsMVTGeom(
 	ST_GeomFromText('POLYGON ((0 0, 10 0, 10 5, 0 -5, 0 0))'),
 	ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)),
-	4096, 0, false));
+	4096, 0, false)));
 select 'PG5', ST_AsText(ST_AsMVTGeom(
 	ST_GeomFromText('POLYGON ((0 0, 10 0, 10 5, 0 -5, 0 0))'),
 	ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096*4096, 4096*4096)),
@@ -34,10 +34,10 @@ SELECT 'PG7', ST_Area(COALESCE(ST_AsMVTGeom(
 	ST_MakeBox2D(ST_Point(-20037508.34, -20037508.34), ST_Point(20037508.34, 20037508.34)),
 	4096, 10, true), 'POLYGON EMPTY'::geometry)) <= 2;
 
-select 'PG8', ST_AsText(ST_AsMVTGeom(
+select 'PG8', ST_AsText(ST_Normalize(ST_AsMVTGeom(
 	ST_GeomFromText('GEOMETRYCOLLECTION(MULTIPOLYGON (((0 0, 10 0, 10 5, 0 -5, 0 0))))'),
 	ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)),
-	4096, 0, false));
+	4096, 0, false)));
 select 'PG9', ST_Area(ST_AsMVTGeom(
 	ST_GeomFromText('POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))'),
 	ST_MakeBox2D(ST_Point(0, 0), ST_Point(5, 5)),
@@ -267,10 +267,10 @@ SELECT 'PG43 - ON ', ST_AsText(ST_AsMVTGeom(
 	ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
 	10, 0, true));
 
-SELECT 'PG43 - OFF', ST_AsText(ST_AsMVTGeom(
+SELECT 'PG43 - OFF', ST_AsText(ST_Normalize(ST_AsMVTGeom(
 	ST_GeomFromText('POLYGON((-10 -10, 110 110, -10 110, 110 -10, -10 -10))'),
 	ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
-	10, 0, false));
+	10, 0, false)));
 
 -- Geometry type change
 SELECT 'PG44', ST_AsEWKT(ST_AsMVTGeom(
@@ -358,13 +358,13 @@ SELECT 'PG56', ST_AsText(ST_AsMVTGeom(
 -- Different round behaviour between geos and wagyu
 WITH geometry AS
 (
-    SELECT ST_AsText(ST_AsMVTGeom(
+    SELECT ST_AsText(ST_Normalize(ST_AsMVTGeom(
 	ST_GeomFromText('POLYGON((0 0, 0 99, 1 101, 100 100, 100 0, 0 0))'),
 	ST_MakeBox2D(ST_Point(0, 0), ST_Point(100, 100)),
-	100, 0, true)) as g
+	100, 0, true))) as g
 )
 SELECT 'PG57',
-        g = 'POLYGON((100 0,100 100,0 100,0 1,1 0,100 0))' OR g = 'POLYGON((0 1,0 0,100 0,100 100,0 100,0 1))'
+        g = 'POLYGON((0 1,0 100,100 100,100 0,1 0,0 1))' OR g = 'POLYGON((0 0,0 1,0 100,100 100,100 0,0 0))'
 FROM geometry;
 
 -- Geometrycollection test
diff --git a/regress/mvt_expected b/regress/mvt_expected
index a24fb4b5c..addc525da 100644
--- a/regress/mvt_expected
+++ b/regress/mvt_expected
@@ -1,11 +1,11 @@
 PG1|POINT(1 4094)
 PG2|POINT(0 4095)
 PG3|POINT(2 4092)
-PG4|MULTIPOLYGON(((5 4096,10 4091,10 4096,5 4096)),((5 4096,0 4101,0 4096,5 4096)))
+PG4|MULTIPOLYGON(((5 4096,10 4096,10 4091,5 4096)),((0 4096,0 4101,5 4096,0 4096)))
 PG5|
 PG6|POLYGON((2791 594,894 2704,600 594,2791 594))
 PG7|t
-PG8|MULTIPOLYGON(((5 4096,10 4091,10 4096,5 4096)),((5 4096,0 4101,0 4096,5 4096)))
+PG8|MULTIPOLYGON(((5 4096,10 4096,10 4091,5 4096)),((0 4096,0 4101,5 4096,0 4096)))
 PG9|16777216
 PG9.1|2|12.5|f
 PG10|
@@ -45,7 +45,7 @@ PG41 - OFF|LINESTRING(0 10,0 4,0 2,0 0,1 0)
 PG42 - ON |LINESTRING(0 10,0 0,1 0)
 PG42 - OFF|LINESTRING(0 10,0 0,1 0)
 PG43 - ON |MULTIPOLYGON(((5 5,0 0,10 0,5 5)),((5 5,10 10,0 10,5 5)))
-PG43 - OFF|MULTIPOLYGON(((5 5,-1 -1,11 -1,5 5)),((5 5,11 11,-1 11,5 5)))
+PG43 - OFF|MULTIPOLYGON(((-1 11,11 11,5 5,-1 11)),((-1 -1,5 5,11 -1,-1 -1)))
 PG44|
 PG45|
 PG46|SRID=3857;POLYGON((3262 2030,3253 2158,3245 2224,3262 2030))
diff --git a/regress/regress_ogc.sql b/regress/regress_ogc.sql
index e53e373ad..1f8ae1efc 100644
--- a/regress/regress_ogc.sql
+++ b/regress/regress_ogc.sql
@@ -158,9 +158,9 @@ SELECT 'isvalid', ST_isvalid('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry)
 SELECT 'isvalid', ST_isvalid('POLYGON((0 0, 0 10, 10 10, -5 10, 10 0, 0 0))'::geometry);
 SELECT 'isvalid', ST_isvalid('GEOMETRYCOLLECTION EMPTY'::geometry);
 SELECT 'intersection', ST_astext(ST_intersection('LINESTRING(0 10, 0 -10)'::geometry, 'LINESTRING(0 0, 1 1)'::geometry));
-SELECT 'difference', ST_astext(ST_difference('LINESTRING(0 10, 0 -10)'::GEOMETRY, 'LINESTRING(0 2, 0 -2)'::GEOMETRY));
+SELECT 'difference', ST_astext(ST_Normalize(ST_difference('LINESTRING(0 10, 0 -10)'::GEOMETRY, 'LINESTRING(0 2, 0 -2)'::GEOMETRY)));
 SELECT 'boundary', ST_astext(ST_boundary('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0),(2 2, 2 4, 4 4, 4 2, 2 2))'::geometry));
-SELECT 'symdifference', ST_astext(ST_symdifference('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0),(2 2, 2 4, 4 4, 4 2, 2 2))'::geometry, 'LINESTRING(0 0, 20 20)'::geometry));
+SELECT 'symdifference', ST_astext(ST_Normalize(ST_symdifference('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0),(2 2, 2 4, 4 4, 4 2, 2 2))'::geometry, 'LINESTRING(0 0, 20 20)'::geometry)));
 SELECT 'issimple', ST_issimple('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0),(2 2, 2 4, 4 4, 4 2, 2 2))'::geometry);
 SELECT 'equals', ST_equals('LINESTRING(0 0, 1 1)'::geometry, 'LINESTRING(1 1, 0 0)'::geometry);
 WITH inp AS ( SELECT
@@ -188,7 +188,7 @@ select 'intersects', ST_intersects(
 
 select 'ST_GeometryN', ST_asewkt(ST_GeometryN('LINESTRING(0 0, 1 1)'::geometry, 1));
 select 'ST_NumGeometries', ST_NumGeometries('LINESTRING(0 0, 1 1)'::geometry);
-select 'ST_Union1', ST_AsText(ST_Union(ARRAY['POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'::geometry, 'POLYGON((0.5 0.5, 1.5 0.5, 1.5 1.5, 0.5 1.5, 0.5 0.5))'::geometry]));
+select 'ST_Union1', ST_AsText(ST_Normalize(ST_Union(ARRAY['POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'::geometry, 'POLYGON((0.5 0.5, 1.5 0.5, 1.5 1.5, 0.5 1.5, 0.5 0.5))'::geometry])));
 select 'ST_StartPoint1',ST_AsText(ST_StartPoint('LINESTRING(0 0, 1 1, 2 2)'::geometry));
 select 'ST_EndPoint1', ST_AsText(ST_Endpoint('LINESTRING(0 0, 1 1, 2 2)'::geometry));
 select 'ST_PointN1', ST_AsText(ST_PointN('LINESTRING(0 0, 1 1, 2 2)'::geometry,2));
diff --git a/regress/regress_ogc_expected b/regress/regress_ogc_expected
index 5ab5f91e6..2e972565b 100644
--- a/regress/regress_ogc_expected
+++ b/regress/regress_ogc_expected
@@ -89,9 +89,9 @@ NOTICE:  Self-intersection
 isvalid|f
 isvalid|t
 intersection|POINT(0 0)
-difference|MULTILINESTRING((0 10,0 2),(0 -2,0 -10))
+difference|MULTILINESTRING((0 2,0 10),(0 -10,0 -2))
 boundary|MULTILINESTRING((0 0,0 10,10 10,10 0,0 0),(2 2,2 4,4 4,4 2,2 2))
-symdifference|GEOMETRYCOLLECTION(LINESTRING(2 2,4 4),LINESTRING(10 10,20 20),POLYGON((0 0,0 10,10 10,10 0,0 0),(4 4,2 4,2 2,4 2,4 4)))
+symdifference|GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2)),LINESTRING(10 10,20 20),LINESTRING(2 2,4 4))
 issimple|t
 equals|t
 pointonsurface|t
diff --git a/regress/run_test.pl b/regress/run_test.pl
index 65886753f..e95f1534c 100755
--- a/regress/run_test.pl
+++ b/regress/run_test.pl
@@ -1247,8 +1247,6 @@ sub create_spatial
 
   $rv = create_db();
 
-	$cmd = "createlang plpgsql $DB >> $REGRESS_LOG 2>&1";
-	$rv = system($cmd);
 
 	# Count database objects before installing anything
 	$OBJ_COUNT_PRE = count_db_objects();
diff --git a/regress/sfcgal/regress_ogc_expected b/regress/sfcgal/regress_ogc_expected
index a8cfab4f8..2e972565b 100644
--- a/regress/sfcgal/regress_ogc_expected
+++ b/regress/sfcgal/regress_ogc_expected
@@ -89,9 +89,9 @@ NOTICE:  Self-intersection
 isvalid|f
 isvalid|t
 intersection|POINT(0 0)
-difference|MULTILINESTRING((0 -2,0 -10),(0 10,0 2))
+difference|MULTILINESTRING((0 2,0 10),(0 -10,0 -2))
 boundary|MULTILINESTRING((0 0,0 10,10 10,10 0,0 0),(2 2,2 4,4 4,4 2,2 2))
-symdifference|GEOMETRYCOLLECTION(LINESTRING(2 2,4 4),LINESTRING(10 10,20 20),POLYGON((0 0,0 10,10 10,10 0,0 0),(4 4,2 4,2 2,4 2,4 4)))
+symdifference|GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2)),LINESTRING(10 10,20 20),LINESTRING(2 2,4 4))
 issimple|t
 equals|t
 pointonsurface|t
diff --git a/regress/sfcgal/tickets.sql b/regress/sfcgal/tickets.sql
index b67ce2c17..ef3d9daf7 100644
--- a/regress/sfcgal/tickets.sql
+++ b/regress/sfcgal/tickets.sql
@@ -18,7 +18,7 @@ INSERT INTO spatial_ref_sys ( srid, proj4text ) VALUES ( 3395, '+proj=merc +lon_
 INSERT INTO spatial_ref_sys (srid,proj4text) VALUES (32707,'+proj=utm +zone=7 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ');
 
 -- #2 --
-SELECT '#2', ST_AsText(ST_Union(g)) FROM
+SELECT '#2', ST_AsText(ST_Normalize(ST_Union(g)) ) FROM
 ( VALUES
 ('SRID=4326;MULTIPOLYGON(((1 1,1 2,2 2,2 1,1 1)))'),
 ('SRID=4326;MULTIPOLYGON(((2 1,3 1,3 2,2 2,2 1)))')
diff --git a/regress/tickets.sql b/regress/tickets.sql
index a560c0256..aac984a74 100644
--- a/regress/tickets.sql
+++ b/regress/tickets.sql
@@ -16,7 +16,7 @@ INSERT INTO spatial_ref_sys ( srid, proj4text ) VALUES ( 3395, '+proj=merc +lon_
 INSERT INTO spatial_ref_sys (srid,proj4text) VALUES (32707,'+proj=utm +zone=7 +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs ');
 
 -- #2 --
-SELECT '#2', ST_AsText(ST_Union(g)) FROM
+SELECT '#2', ST_AsText(ST_Normalize(ST_Union(g)) ) FROM
 ( VALUES
 ('SRID=4326;MULTIPOLYGON(((1 1,1 2,2 2,2 1,1 1)))'),
 ('SRID=4326;MULTIPOLYGON(((2 1,3 1,3 2,2 2,2 1)))')
@@ -397,7 +397,7 @@ SELECT '#804', ST_AsGML(3, 'SRID=4326;POINT(0 0)'::geometry, 0, 1);
 SELECT '#845', ST_Intersects('POINT(169.69960846592 -46.5061209281002)'::geometry, 'POLYGON((169.699607857174 -46.5061218662,169.699607857174 -46.5061195965597,169.699608806526 -46.5061195965597,169.699608806526 -46.5061218662,169.699607857174 -46.5061218662))'::geometry);
 
 -- #834
-SELECT '#834', ST_AsEWKT(ST_Intersection('LINESTRING(0 0,0 10,10 10,10 0)', 'LINESTRING(10 10 4,10 0 5,0 0 5)'));
+SELECT '#834', ST_AsEWKT(ST_Normalize(ST_Force2D(ST_Intersection('LINESTRING(0 0,0 10,10 10,10 0)', 'LINESTRING(10 10 4,10 0 5,0 0 5)'))));
 
 -- #884 --
 CREATE TABLE foo (id integer, the_geom geometry);
@@ -786,7 +786,7 @@ round(ST_Length(St_Segmentize(ST_GeographyFromText('LINESTRING(-89.3000030518 28
 SELECT '#2232', ST_AsSVG('LINESTRING(0 0, 0.4 0, 0.8 0, 1.2 0,1.6 0, 2 0)'::geometry,1,0);
 
 -- #2307 --
-SELECT '#2307', ST_AsText(ST_SnapToGrid(ST_MakeValid('0106000020E6100000010000000103000000010000000A0000004B7DA956B99844C0DB0790FE8B4D1DC010BA74A9AF9444C049AFFC5B8C4D1DC03FC6CC690D9844C0DD67E5628C4D1DC07117B56B0D9844C0C80ABA67C45E1DC0839166ABAF9444C0387D4568C45E1DC010BA74A9AF9444C049AFFC5B8C4D1DC040C3CD74169444C0362EC0608C4D1DC07C1A3B77169444C0DC3ADB40B2641DC03AAE5F68B99844C0242948DEB1641DC04B7DA956B99844C0DB0790FE8B4D1DC0'::geometry),0.0001));
+SELECT '#2307', ST_AsText(ST_Normalize(ST_SnapToGrid(ST_MakeValid('0106000020E6100000010000000103000000010000000A0000004B7DA956B99844C0DB0790FE8B4D1DC010BA74A9AF9444C049AFFC5B8C4D1DC03FC6CC690D9844C0DD67E5628C4D1DC07117B56B0D9844C0C80ABA67C45E1DC0839166ABAF9444C0387D4568C45E1DC010BA74A9AF9444C049AFFC5B8C4D1DC040C3CD74169444C0362EC0608C4D1DC07C1A3B77169444C0DC3ADB40B2641DC03AAE5F68B99844C0242948DEB1641DC04B7DA956B99844C0DB0790FE8B4D1DC0'::geometry),0.0001)));
 
 SELECT '#2409', ST_Summary('GEOMETRYCOLLECTION(MULTISURFACE(POLYGON((0 0, 0 1, 1 1, 1 0, 0 0)),CURVEPOLYGON(COMPOUNDCURVE((0 0, 0 1, 1 1, 1 0, 0 0),CIRCULARSTRING(0 0, 0 1, 1 1, 1 2, 0 0)))),TIN(((0 0, 0 1, 1 1, 0 0))))'::geometry);
 
@@ -803,8 +803,8 @@ SELECT '#2420.1', ST_AsText(ST_LineToCurve('LINESTRING(0 0,10 0,10 10,0 10,0 0)'
 SELECT '#2420.2', ST_AsText(ST_LineToCurve('LINESTRING(0 0,10 0,10 10,0 10)'));
 
 SELECT '#2423', ST_AsText(ST_SnapToGrid(ST_CurveToLine(ST_LineToCurve(
-  ST_Intersection(ST_Buffer(ST_Point(0,0),10),ST_MakeEnvelope(-10,0,10,10))
-), 4), 1e-5));
+    ST_Normalize(ST_Intersection(ST_Buffer(ST_Point(0,0),10),ST_MakeEnvelope(-10,0,10,10)))
+), 4), 0.0001), 3);
 
 SELECT '#2424', ST_AsText(ST_SnapToGrid(ST_CurveToLine(
   'MULTICURVE(COMPOUNDCURVE((0 0, 10 0),CIRCULARSTRING(10 0, 20 1, 30 10)))',
diff --git a/regress/tickets_expected b/regress/tickets_expected
index cf76f6f06..88e3525f0 100644
--- a/regress/tickets_expected
+++ b/regress/tickets_expected
@@ -130,7 +130,7 @@ ERROR:  First argument must be a LINESTRING
 #723|f
 #804|<gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos srsDimension="2">0 0</gml:pos></gml:Point>
 #845|t
-#834|GEOMETRYCOLLECTION(POINT(0 0 5),LINESTRING(10 10 5,10 0 5))
+#834|GEOMETRYCOLLECTION(LINESTRING(10 0,10 10),POINT(0 0))
 #884|1|f
 #884|2|t
 #938|
@@ -238,7 +238,7 @@ ERROR:  invalid GML representation
 #2110.3|t
 #2145|6792004
 #2232|M 0 0 l 0 0 1 0 0 0 1 0 0 0
-#2307|MULTIPOLYGON(((-41.1932 -7.3257,-41.1616 -7.3257,-41.1569 -7.3257,-41.1569 -7.3483,-41.1932 -7.3483,-41.1932 -7.3257),(-41.1616 -7.3257,-41.1879 -7.3257,-41.1879 -7.3425,-41.1616 -7.3425,-41.1616 -7.3257)))
+#2307|MULTIPOLYGON(((-41.1932 -7.3483,-41.1932 -7.3257,-41.1616 -7.3257,-41.1569 -7.3257,-41.1569 -7.3483,-41.1932 -7.3483),(-41.1879 -7.3425,-41.1616 -7.3425,-41.1616 -7.3257,-41.1879 -7.3257,-41.1879 -7.3425)))
 #2409|GeometryCollection[B] with 2 elements
   MultiSurface[] with 2 elements
     Polygon[] with 1 rings
@@ -254,7 +254,7 @@ ERROR:  invalid GML representation
 #2412|LINESTRING(0 0,10 0,20 0)
 #2420.1|LINESTRING(0 0,10 0,10 10,0 10,0 0)
 #2420.2|LINESTRING(0 0,10 0,10 10,0 10)
-#2423|POLYGON((-10 0,-9.2388 3.82683,-7.07107 7.07107,-3.82683 9.2388,0 10,3.82683 9.2388,7.07107 7.07107,9.2388 3.82683,10 0,-10 0))
+#2423|POLYGON((-10 0,-9.239 3.827,-7.071 7.071,-3.827 9.239,0 10,3.827 9.239,7.071 7.071,9.239 3.827,10 0,-10 0))
 #2424|MULTILINESTRING((0 0,10 0,24 3,30 10))
 #2427|POINT(-1 0)
 #2168|5340.76237395|5340.76237395|0
diff --git a/regress/unaryunion.sql b/regress/unaryunion.sql
index 78826731c..a14ec4359 100644
--- a/regress/unaryunion.sql
+++ b/regress/unaryunion.sql
@@ -1,10 +1,8 @@
-
 -- Noding a multilinestring
-SELECT 1, ST_AsText(ST_UnaryUnion('MULTILINESTRING((0 0, 10 0), (5 -5, 5 5))'));
+SELECT 1, ST_AsText(ST_Normalize(ST_UnaryUnion('MULTILINESTRING((0 0, 10 0), (5 -5, 5 5))')) );
 
 -- Unioning a set of polygons (CascadedUnion)
-SELECT 2, ST_AsText(ST_UnaryUnion('GEOMETRYCOLLECTION(POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)),POLYGON((5 5, 15 5, 15 15, 5 15, 5 5)))'));
+SELECT 2, ST_AsText(ST_Normalize(ST_UnaryUnion('GEOMETRYCOLLECTION(POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)),POLYGON((5 5, 15 5, 15 15, 5 15, 5 5)))')));
 
 -- Unioning an heterogeneous collection of geometries
-SELECT 3, ST_AsText(ST_UnaryUnion('GEOMETRYCOLLECTION(POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)),POLYGON((5 5, 15 5, 15 15, 5 15, 5 5)), MULTIPOINT(5 4, -5 4),LINESTRING(2 -10, 2 20))'));
-
+SELECT 3, ST_AsText(ST_Normalize(ST_UnaryUnion('GEOMETRYCOLLECTION(POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)),POLYGON((5 5, 15 5, 15 15, 5 15, 5 5)), MULTIPOINT(5 4, -5 4),LINESTRING(2 -10, 2 20))')));
diff --git a/regress/unaryunion_expected b/regress/unaryunion_expected
index 074bc6c84..815f73b41 100644
--- a/regress/unaryunion_expected
+++ b/regress/unaryunion_expected
@@ -1,3 +1,3 @@
-1|MULTILINESTRING((0 0,5 0),(5 0,10 0),(5 -5,5 0),(5 0,5 5))
-2|POLYGON((10 5,10 0,0 0,0 10,5 10,5 15,15 15,15 5,10 5))
-3|GEOMETRYCOLLECTION(POINT(-5 4),LINESTRING(2 -10,2 0),LINESTRING(2 10,2 20),POLYGON((10 5,10 0,2 0,0 0,0 10,2 10,5 10,5 15,15 15,15 5,10 5)))
+1|MULTILINESTRING((5 0,10 0),(5 0,5 5),(5 -5,5 0),(0 0,5 0))
+2|POLYGON((0 0,0 10,5 10,5 15,15 15,15 5,10 5,10 0,0 0))
+3|GEOMETRYCOLLECTION(POLYGON((0 0,0 10,2 10,5 10,5 15,15 15,15 5,10 5,10 0,2 0,0 0)),LINESTRING(2 10,2 20),LINESTRING(2 -10,2 0),POINT(-5 4))

-----------------------------------------------------------------------

Summary of changes:
 NEWS                                |   7 +-
 doc/release_notes.xml               |   5 ++
 liblwgeom/cunit/cu_geos.c           |  16 ++++-
 liblwgeom/cunit/cu_wrapx.c          |  87 +++++++++++++++++-------
 liblwgeom/lwgeom_geos.c             |  65 +++++++++++++++++-
 liblwgeom/lwgeom_geos.h             |   2 +
 liblwgeom/lwgeom_geos_clean.c       |   9 +++
 postgis/mvt.c                       |   4 ++
 regress/clean.sql                   |   5 +-
 regress/clean_expected              |  12 ++--
 regress/concave_hull_hard.sql       | 129 +++++++++++++++++++-----------------
 regress/mvt.sql                     |  18 ++---
 regress/mvt_expected                |   6 +-
 regress/regress_ogc.sql             |   6 +-
 regress/regress_ogc_expected        |   4 +-
 regress/run_test.pl                 |   2 -
 regress/sfcgal/regress_ogc_expected |   4 +-
 regress/sfcgal/tickets.sql          |   2 +-
 regress/tickets.sql                 |  10 +--
 regress/tickets_expected            |   6 +-
 regress/unaryunion.sql              |   8 +--
 regress/unaryunion_expected         |   6 +-
 22 files changed, 278 insertions(+), 135 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list