[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0rc1-447-ge35fbe1

git at osgeo.org git at osgeo.org
Sat Aug 28 09:17:17 PDT 2021


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, master has been updated
       via  e35fbe16677ecdc052a25f6b358f76575eb3a008 (commit)
       via  e843371cd8ee10a8f494b3802a8e8eb0e27c9391 (commit)
       via  5bedb5bed1da630753afdf14b1c2f1683f71f0b5 (commit)
       via  afabfd55a949720e8e279a2683a1b0bc6a6c1d45 (commit)
       via  401d3c542ff60a9ea40576a09cbb00982acf63af (commit)
       via  d7b83d6e5a713f8e2649ea57b231933de8e54d13 (commit)
       via  dc3499df75713551858d882ff41921c93d382a25 (commit)
       via  0d995095118db4b87d0c1fc1dce00fc6b01d79df (commit)
       via  88256b672e3ca1f025c2b80ff962d2a22b76ec76 (commit)
       via  65a00865adc37bd759b0bdfd80aed7b340574154 (commit)
       via  cce909b3fb809f2bf58bf7fd569564f4727e5b4f (commit)
       via  4f93bdf208d53bead51f4824f26988feb225622c (commit)
       via  24d6752cc6b6c74ee49c5012150ec0115e88f9a2 (commit)
      from  f5bbe5655b1416420711d8b61adf5cf4b54a5e62 (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 e35fbe16677ecdc052a25f6b358f76575eb3a008
Author: Darafei Praliaskouski <me at komzpa.net>
Date:   Sat Aug 28 19:17:04 2021 +0300

    Merge and format lwgeom_boundary tests
    
    Thanks Aliaksandr Kalenik and Sandro Santilli for the work on it.
    
    Closes #4956
    Closes #4960
    Closes #4961
    Closes https://github.com/postgis/postgis/pull/626

diff --git a/liblwgeom/cunit/cu_boundary.c b/liblwgeom/cunit/cu_boundary.c
index 4bec730..3088f91 100644
--- a/liblwgeom/cunit/cu_boundary.c
+++ b/liblwgeom/cunit/cu_boundary.c
@@ -4,6 +4,7 @@
  * http://postgis.net
  *
  * Copyright (C) 2021 Sandro Santilli <strk at kbt.io>
+ * Copyright (C) 2021 Aliaksandr Kalinik <kalenik.aliaksandr at gmail.com>
  *
  * This is free software; you can redistribute and/or modify it under
  * the terms of the GNU General Public Licence. See the COPYING file.
@@ -16,22 +17,25 @@
 #include "liblwgeom.h"
 #include "liblwgeom_internal.h"
 
-#define BOUNDARY_TEST(wkt_in, wkt_exp) do {\
-	LWGEOM *gin, *gout, *gexp; \
-	cu_error_msg_reset(); \
-	gin = lwgeom_from_wkt( wkt_in, LW_PARSER_CHECK_NONE);  \
-	CU_ASSERT_PTR_NOT_NULL_FATAL(gin); \
-	gexp = lwgeom_from_wkt( wkt_exp, LW_PARSER_CHECK_NONE);  \
-	CU_ASSERT_PTR_NOT_NULL_FATAL(gexp); \
-	gout = lwgeom_boundary(gin);  \
-	CU_ASSERT_PTR_NOT_NULL_FATAL(gout); \
-	ASSERT_NORMALIZED_GEOM_SAME(gout, gexp);  \
-	lwgeom_free(gout);  \
-	lwgeom_free(gexp);  \
-	lwgeom_free(gin);  \
-} while (0)
-
-static void boundary_point(void)
+#define BOUNDARY_TEST(wkt_in, wkt_exp) \
+	do \
+	{ \
+		LWGEOM *gin, *gout, *gexp; \
+		cu_error_msg_reset(); \
+		gin = lwgeom_from_wkt(wkt_in, LW_PARSER_CHECK_NONE); \
+		CU_ASSERT_PTR_NOT_NULL_FATAL(gin); \
+		gexp = lwgeom_from_wkt(wkt_exp, LW_PARSER_CHECK_NONE); \
+		CU_ASSERT_PTR_NOT_NULL_FATAL(gexp); \
+		gout = lwgeom_boundary(gin); \
+		CU_ASSERT_PTR_NOT_NULL_FATAL(gout); \
+		ASSERT_NORMALIZED_GEOM_SAME(gout, gexp); \
+		lwgeom_free(gout); \
+		lwgeom_free(gexp); \
+		lwgeom_free(gin); \
+	} while (0)
+
+static void
+boundary_point(void)
 {
 	BOUNDARY_TEST(
 		"POINT EMPTY",
@@ -54,7 +58,8 @@ static void boundary_point(void)
 	);
 }
 
-static void boundary_line(void)
+static void
+boundary_line(void)
 {
 	BOUNDARY_TEST(
 		"LINESTRING EMPTY",
@@ -93,7 +98,8 @@ static void boundary_line(void)
 
 }
 
-static void boundary_polygon(void)
+static void
+boundary_polygon(void)
 {
 	BOUNDARY_TEST(
 		"POLYGON EMPTY",
@@ -128,7 +134,8 @@ static void boundary_polygon(void)
 
 }
 
-static void boundary_triangle(void)
+static void
+boundary_triangle(void)
 {
 	BOUNDARY_TEST(
 		"TRIANGLE EMPTY",
@@ -141,7 +148,8 @@ static void boundary_triangle(void)
 	);
 }
 
-static void boundary_tin(void)
+static void
+boundary_tin(void)
 {
 	BOUNDARY_TEST(
 		"TIN EMPTY",
@@ -159,7 +167,8 @@ static void boundary_tin(void)
 	);
 }
 
-static void boundary_collection(void)
+static void
+boundary_collection(void)
 {
 	BOUNDARY_TEST(
 		"GEOMETRYCOLLECTION EMPTY",
@@ -193,19 +202,15 @@ static void boundary_collection(void)
 	);
 }
 
-
 void boundary_suite_setup(void);
-void boundary_suite_setup(void)
+void
+boundary_suite_setup(void)
 {
 	CU_pSuite suite = CU_add_suite("boundary", NULL, NULL);
-	PG_ADD_TEST(suite,boundary_point);
-	PG_ADD_TEST(suite,boundary_line);
-	PG_ADD_TEST(suite,boundary_polygon);
-	PG_ADD_TEST(suite,boundary_triangle);
-	PG_ADD_TEST(suite,boundary_tin);
-	PG_ADD_TEST(suite,boundary_collection);
-#if 0 /* write these */
-	PG_ADD_TEST(suite,boundary_tin);
-#endif
-	//PG_ADD_TEST(suite,boundary_collection);
+	PG_ADD_TEST(suite, boundary_point);
+	PG_ADD_TEST(suite, boundary_line);
+	PG_ADD_TEST(suite, boundary_polygon);
+	PG_ADD_TEST(suite, boundary_triangle);
+	PG_ADD_TEST(suite, boundary_tin);
+	PG_ADD_TEST(suite, boundary_collection);
 }
diff --git a/liblwgeom/cunit/cu_tester.c b/liblwgeom/cunit/cu_tester.c
index 08de8d6..2aa1f6a 100644
--- a/liblwgeom/cunit/cu_tester.c
+++ b/liblwgeom/cunit/cu_tester.c
@@ -82,61 +82,58 @@ extern void wrapx_suite_setup(void);
 
 
 /* AND ADD YOUR SUITE SETUP FUNCTION HERE (2 of 2) */
-PG_SuiteSetup setupfuncs[] =
-{
-	algorithms_suite_setup,
-	boundary_suite_setup,
-	buildarea_suite_setup,
-	clean_suite_setup,
-	clip_by_rect_suite_setup,
-	force_dims_suite_setup,
-	force_sfs_suite_setup,
-	geodetic_suite_setup,
-	geos_suite_setup,
-	geos_cluster_suite_setup,
-	unionfind_suite_setup,
-	homogenize_suite_setup,
-	in_encoded_polyline_suite_setup,
+PG_SuiteSetup setupfuncs[] = {algorithms_suite_setup,
+			      boundary_suite_setup,
+			      buildarea_suite_setup,
+			      clean_suite_setup,
+			      clip_by_rect_suite_setup,
+			      force_dims_suite_setup,
+			      force_sfs_suite_setup,
+			      geodetic_suite_setup,
+			      geos_suite_setup,
+			      geos_cluster_suite_setup,
+			      unionfind_suite_setup,
+			      homogenize_suite_setup,
+			      in_encoded_polyline_suite_setup,
 #if HAVE_LIBJSON
-	in_geojson_suite_setup,
+			      in_geojson_suite_setup,
 #endif
-    iterator_suite_setup,
-	twkb_in_suite_setup,
-	gserialized1_suite_setup,
-	gserialized2_suite_setup,
-	lwstroke_suite_setup,
-	measures_suite_setup,
-	effectivearea_suite_setup,
-	chaikin_suite_setup,
-	filterm_suite_setup,
-	minimum_bounding_circle_suite_setup,
-	misc_suite_setup,
-	node_suite_setup,
-	out_encoded_polyline_suite_setup,
-	out_geojson_suite_setup,
-	out_gml_suite_setup,
-	out_kml_suite_setup,
-	out_svg_suite_setup,
-	out_x3d_suite_setup,
-	ptarray_suite_setup,
-	print_suite_setup,
+			      iterator_suite_setup,
+			      twkb_in_suite_setup,
+			      gserialized1_suite_setup,
+			      gserialized2_suite_setup,
+			      lwstroke_suite_setup,
+			      measures_suite_setup,
+			      effectivearea_suite_setup,
+			      chaikin_suite_setup,
+			      filterm_suite_setup,
+			      minimum_bounding_circle_suite_setup,
+			      misc_suite_setup,
+			      node_suite_setup,
+			      out_encoded_polyline_suite_setup,
+			      out_geojson_suite_setup,
+			      out_gml_suite_setup,
+			      out_kml_suite_setup,
+			      out_svg_suite_setup,
+			      out_x3d_suite_setup,
+			      ptarray_suite_setup,
+			      print_suite_setup,
 #if HAVE_SFCGAL
-	sfcgal_suite_setup,
+			      sfcgal_suite_setup,
 #endif
-	split_suite_setup,
-	stringbuffer_suite_setup,
-	surface_suite_setup,
-	tree_suite_setup,
-	triangulate_suite_setup,
-	twkb_out_suite_setup,
-	varint_suite_setup,
-	wkb_in_suite_setup,
-	wkb_out_suite_setup,
-	wkt_in_suite_setup,
-	wkt_out_suite_setup,
-	wrapx_suite_setup,
-	NULL
-};
+			      split_suite_setup,
+			      stringbuffer_suite_setup,
+			      surface_suite_setup,
+			      tree_suite_setup,
+			      triangulate_suite_setup,
+			      twkb_out_suite_setup,
+			      varint_suite_setup,
+			      wkb_in_suite_setup,
+			      wkb_out_suite_setup,
+			      wkt_in_suite_setup,
+			      wkt_out_suite_setup,
+			      wrapx_suite_setup,
+			      NULL};
 
 
 #define MAX_CUNIT_MSG_LENGTH 256
diff --git a/liblwgeom/cunit/cu_tester.h b/liblwgeom/cunit/cu_tester.h
index 2212355..ebc1681 100644
--- a/liblwgeom/cunit/cu_tester.h
+++ b/liblwgeom/cunit/cu_tester.h
@@ -41,23 +41,31 @@ typedef void (*PG_SuiteSetup)(void);
   CU_ASSERT_EQUAL(o,e); \
 } while (0);
 
-#define ASSERT_NORMALIZED_GEOM_SAME(gobt, gexp) do { \
-	char *obt, *exp; \
-	LWGEOM *ngobt, *ngexp; \
-	ngobt = lwgeom_normalize(gobt); \
-	ngexp = lwgeom_normalize(gexp); \
-	if ( ! lwgeom_same((ngobt), (ngexp)) ) { \
- 		obt = lwgeom_to_wkt((ngobt), WKT_ISO, 8, NULL); \
- 		exp = lwgeom_to_wkt((ngexp), WKT_ISO, 8, NULL); \
-    fprintf(stderr, "[%s:%d]\n Expected: %s\n Obtained: %s\n", __FILE__, __LINE__, exp, obt); \
-		free(obt); free(exp); \
-    lwgeom_free(ngobt); lwgeom_free(ngexp); \
-		CU_ASSERT(0); \
-	} else { \
-    lwgeom_free(ngobt); lwgeom_free(ngexp); \
-    CU_ASSERT(1); \
-  } \
-} while (0)
+#define ASSERT_NORMALIZED_GEOM_SAME(gobt, gexp) \
+	do \
+	{ \
+		char *obt, *exp; \
+		LWGEOM *ngobt, *ngexp; \
+		ngobt = lwgeom_normalize(gobt); \
+		ngexp = lwgeom_normalize(gexp); \
+		if (!lwgeom_same((ngobt), (ngexp))) \
+		{ \
+			obt = lwgeom_to_wkt((ngobt), WKT_ISO, 8, NULL); \
+			exp = lwgeom_to_wkt((ngexp), WKT_ISO, 8, NULL); \
+			fprintf(stderr, "[%s:%d]\n Expected: %s\n Obtained: %s\n", __FILE__, __LINE__, exp, obt); \
+			free(obt); \
+			free(exp); \
+			lwgeom_free(ngobt); \
+			lwgeom_free(ngexp); \
+			CU_ASSERT(0); \
+		} \
+		else \
+		{ \
+			lwgeom_free(ngobt); \
+			lwgeom_free(ngexp); \
+			CU_ASSERT(1); \
+		} \
+	} while (0)
 
 static inline void
 assert_string_equal_impl(const char *obtained, const char *expected, const char *file, int line)
diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c
index 597e477..95f94f1 100644
--- a/liblwgeom/lwgeom.c
+++ b/liblwgeom/lwgeom.c
@@ -2628,9 +2628,9 @@ lwgeom_boundary(LWGEOM *lwgeom)
 			lwmline_add_lwline(lwmline, lwline_construct(srid, 0, ring));
 		}
 
+		/* Homogenize the multilinestring to hopefully get a single LINESTRING */
 		LWGEOM *lwout = lwgeom_homogenize((LWGEOM *)lwmline);
 		lwgeom_free((LWGEOM *)lwmline);
-
 		return lwout;
 	}
 	case CURVEPOLYTYPE: {
diff --git a/liblwgeom/lwhomogenize.c b/liblwgeom/lwhomogenize.c
index ac20ab7..1d52ed9 100644
--- a/liblwgeom/lwhomogenize.c
+++ b/liblwgeom/lwhomogenize.c
@@ -247,7 +247,7 @@ lwgeom_homogenize(const LWGEOM *geom)
 			/* Strip single-entry multi-geometries down to singletons */
 			if ( col->ngeoms == 1 )
 			{
-				hgeom = lwgeom_clone_deep((LWGEOM*)(col->geoms[0]));
+				hgeom = lwgeom_clone_deep((LWGEOM *)(col->geoms[0]));
 				hgeom->srid = geom->srid;
 				if (geom->bbox)
 					hgeom->bbox = gbox_copy(geom->bbox);

commit e843371cd8ee10a8f494b3802a8e8eb0e27c9391
Merge: f5bbe56 5bedb5b
Author: kalenikaliaksandr <kalenik.aliaksandr at gmail.com>
Date:   Sat Aug 28 18:49:27 2021 +0300

    Merge 5bedb5bed1da630753afdf14b1c2f1683f71f0b5 into f5bbe5655b1416420711d8b61adf5cf4b54a5e62


commit 5bedb5bed1da630753afdf14b1c2f1683f71f0b5
Author: kalenikaliaksandr <kalenik.aliaksandr at gmail.com>
Date:   Wed Aug 11 19:36:02 2021 +0300

    update lwgeom_homogenize comment documentation to indicate that deep clone of geometry is returned

diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in
index f2a148c..98ccbdf 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -1193,10 +1193,7 @@ extern LWCURVEPOLY* lwcurvepoly_construct_from_lwpoly(LWPOLY *lwpoly);
 extern int lwcollection_ngeoms(const LWCOLLECTION *col);
 
 /* Given a generic geometry/collection, return the "simplest" form.
- * The elements of the homogenized collection are references to the
- * input geometry; a deep clone is not performed.
- * TODO: consider returning a geometry that does not reference the
- * input
+ * The elements of the homogenized collection are deeply cloned
  * */
 extern LWGEOM *lwgeom_homogenize(const LWGEOM *geom);
 

commit afabfd55a949720e8e279a2683a1b0bc6a6c1d45
Author: kalenikaliaksandr <kalenik.aliaksandr at gmail.com>
Date:   Tue Aug 10 20:49:49 2021 +0300

    lwgeom_boundary: increase test coverage

diff --git a/liblwgeom/cunit/cu_boundary.c b/liblwgeom/cunit/cu_boundary.c
index 355e991..4bec730 100644
--- a/liblwgeom/cunit/cu_boundary.c
+++ b/liblwgeom/cunit/cu_boundary.c
@@ -171,6 +171,26 @@ static void boundary_collection(void)
 		"GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2)),POLYGON((2 2,2 4,4 4,4 2,2 2)))",
 		"MULTILINESTRING((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2),(2 2,2 4,4 4,4 2,2 2))"
 	);
+
+	BOUNDARY_TEST(
+		"GEOMETRYCOLLECTION(TIN(((0 0,0 -1,-1 1,0 0)),((0 0,1 0,0 -1,0 0))),TIN(((10 10,10 20,20 20,10 10))))",
+		"MULTILINESTRING((0 0,0 -1,-1 1,0 0),(0 0,1 0,0 -1,0 0),(10 10,10 20,20 20,10 10))"
+	);
+
+	BOUNDARY_TEST(
+		"GEOMETRYCOLLECTION(TRIANGLE((1 1, 0 0, -1 1, 1 1)))",
+		"LINESTRING(1 1, 0 0, -1 1, 1 1)"
+	);
+
+	BOUNDARY_TEST(
+		"GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(TRIANGLE((0 0,0 -1,-1 1,0 0)),TRIANGLE((0 0,1 0,0 -1,0 0))),MULTILINESTRING((0 0, 5 0, 10 0),(20 5, 20 6, 20 10)))",
+		"GEOMETRYCOLLECTION(MULTILINESTRING((0 0,0 -1,1 0,0 0),(0 0,-1 1,0 -1,0 0)),MULTIPOINT(20 10,20 5,10 0,0 0))"
+	);
+
+	BOUNDARY_TEST(
+		"GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(0 0)),POINT(1 1),MULTIPOINT(2 2,3 3))",
+		"GEOMETRYCOLLECTION EMPTY"
+	);
 }
 
 
diff --git a/regress/core/boundary.sql b/regress/core/boundary.sql
index 806de1a..e9c7a50 100644
--- a/regress/core/boundary.sql
+++ b/regress/core/boundary.sql
@@ -14,3 +14,7 @@ SELECT 'boundary13', ST_AsText(ST_Boundary(ST_GeomFromEWKT('TIN(((0 0,0 -1,-1 1,
 SELECT 'boundary14', ST_AsText(ST_Boundary(ST_GeomFromEWKT('TIN(((0 0,0 -1,-1 1,0 0)))')));
 SELECT 'boundary15', ST_AsText(ST_Boundary(ST_GeomFromEWKT('CURVEPOLYGON(CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0),(1 1, 3 3, 3 1, 1 1))')));
 SELECT 'boundary16', ST_AsEWKT(ST_Boundary(ST_GeomFromEWKT('MULTICURVE((1 1 1,0 0 0.5, -1 1 1),(1 1 0.5,0 0 0.5, -1 1 0.5, 1 1 0.5) )')));
+SELECT 'boundary17', ST_AsEWKT(ST_Boundary(ST_GeomFromEWKT('GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2)),POLYGON((2 2,2 4,4 4,4 2,2 2)))')));
+SELECT 'boundary18', ST_AsEWKT(ST_Boundary(ST_GeomFromEWKT('GEOMETRYCOLLECTION(TIN(((0 0,0 -1,-1 1,0 0)),((0 0,1 0,0 -1,0 0))),TIN(((10 10,10 20,20 20,10 10))))')));
+SELECT 'boundary19', ST_AsEWKT(ST_Boundary(ST_GeomFromEWKT('MULTIPOLYGON(((0 0, 5 5, 10 0, 0 0),(3 1,7 1,5 2,3 1)),((20 0,20 5,25 5,20 0)))')));
+SELECT 'boundary20', ST_AsEWKT(ST_Boundary(ST_GeomFromEWKT('LINESTRING EMPTY')));
diff --git a/regress/core/boundary_expected b/regress/core/boundary_expected
index 30bbfd0..1e01f1b 100644
--- a/regress/core/boundary_expected
+++ b/regress/core/boundary_expected
@@ -14,3 +14,7 @@ boundary13|MULTILINESTRING((0 0,0 -1,-1 1,0 0),(0 0,1 0,0 -1,0 0))
 boundary14|LINESTRING(0 0,0 -1,-1 1,0 0)
 boundary15|MULTICURVE(CIRCULARSTRING(0 0,4 0,4 4,0 4,0 0),(1 1,3 3,3 1,1 1))
 boundary16|MULTIPOINT(1 1 1,-1 1 1)
+boundary17|MULTILINESTRING((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2),(2 2,2 4,4 4,4 2,2 2))
+boundary18|MULTILINESTRING((0 0,0 -1,-1 1,0 0),(0 0,1 0,0 -1,0 0),(10 10,10 20,20 20,10 10))
+boundary19|MULTILINESTRING((0 0,5 5,10 0,0 0),(3 1,7 1,5 2,3 1),(20 0,20 5,25 5,20 0))
+boundary20|MULTIPOINT EMPTY

commit 401d3c542ff60a9ea40576a09cbb00982acf63af
Author: kalenikaliaksandr <kalenik.aliaksandr at gmail.com>
Date:   Fri Aug 6 02:51:10 2021 +0300

    st_boundary: fix integration tests

diff --git a/regress/core/boundary_expected b/regress/core/boundary_expected
index 973bf46..30bbfd0 100644
--- a/regress/core/boundary_expected
+++ b/regress/core/boundary_expected
@@ -11,6 +11,6 @@ boundary10|MULTIPOINT EMPTY
 boundary11|LINESTRING(1 1,0 0,-1 1,1 1)
 boundary12|MULTILINESTRING((30 20,45 40,10 40,30 20),(15 5,40 10,10 20,5 10,15 5),(30 20,45 40,10 40,30 20),(15 5,40 10,10 20,5 10,15 5))
 boundary13|MULTILINESTRING((0 0,0 -1,-1 1,0 0),(0 0,1 0,0 -1,0 0))
-boundary14|MULTILINESTRING((0 0,0 -1,-1 1,0 0))
+boundary14|LINESTRING(0 0,0 -1,-1 1,0 0)
 boundary15|MULTICURVE(CIRCULARSTRING(0 0,4 0,4 4,0 4,0 0),(1 1,3 3,3 1,1 1))
 boundary16|MULTIPOINT(1 1 1,-1 1 1)

commit d7b83d6e5a713f8e2649ea57b231933de8e54d13
Author: kalenikaliaksandr <kalenik.aliaksandr at gmail.com>
Date:   Fri Aug 6 02:36:53 2021 +0300

    lwgeom_boundary: fix memory leak introduced by using lwgeom_homogenize

diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c
index e928e10..597e477 100644
--- a/liblwgeom/lwgeom.c
+++ b/liblwgeom/lwgeom.c
@@ -2628,7 +2628,10 @@ lwgeom_boundary(LWGEOM *lwgeom)
 			lwmline_add_lwline(lwmline, lwline_construct(srid, 0, ring));
 		}
 
-		return lwgeom_homogenize((LWGEOM *)lwmline);
+		LWGEOM *lwout = lwgeom_homogenize((LWGEOM *)lwmline);
+		lwgeom_free((LWGEOM *)lwmline);
+
+		return lwout;
 	}
 	case CURVEPOLYTYPE: {
 		LWCURVEPOLY *lwcurvepoly = (LWCURVEPOLY *)lwgeom;
@@ -2648,7 +2651,10 @@ lwgeom_boundary(LWGEOM *lwgeom)
 		for (uint32_t i = 0; i < lwcol->ngeoms; i++)
 			lwcollection_add_lwgeom(lwcol_boundary, lwgeom_boundary(lwcol->geoms[i]));
 
-		return lwgeom_homogenize((LWGEOM *)lwcol_boundary);
+		LWGEOM *lwout = lwgeom_homogenize((LWGEOM *)lwcol_boundary);
+		lwgeom_free((LWGEOM *)lwcol_boundary);
+
+		return lwout;
 	}
 	default:
 		lwerror("%s: unsupported geometry type: %s", __func__, lwtype_name(lwgeom->type));
diff --git a/liblwgeom/lwhomogenize.c b/liblwgeom/lwhomogenize.c
index 8bc9faf..ac20ab7 100644
--- a/liblwgeom/lwhomogenize.c
+++ b/liblwgeom/lwhomogenize.c
@@ -101,7 +101,7 @@ lwcollection_build_buffer(const LWCOLLECTION *col, HomogenizeBuffer *buffer)
 				buffer->buf[geom->type] = bufcol;
 			}
 			/* Add sub-geom to buffer */
-			lwcollection_add_lwgeom(buffer->buf[geom->type], lwgeom_clone(geom));
+			lwcollection_add_lwgeom(buffer->buf[geom->type], lwgeom_clone_deep(geom));
 			/* Increment count for this singleton type */
 			buffer->cnt[geom->type]++;
 			break;
@@ -217,7 +217,7 @@ lwgeom_homogenize(const LWGEOM *geom)
 			return lwcollection_as_lwgeom(lwcollection_construct_empty(geom->type, geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom)));
 		}
 
-		return lwgeom_clone(geom);
+		return lwgeom_clone_deep(geom);
 	}
 
 	switch (geom->type)
@@ -231,7 +231,7 @@ lwgeom_homogenize(const LWGEOM *geom)
 		case TRIANGLETYPE:
 		case CURVEPOLYTYPE:
 		case POLYGONTYPE:
-			return lwgeom_clone(geom);
+			return lwgeom_clone_deep(geom);
 
 		/* Process homogeneous geometries lightly */
 		case MULTIPOINTTYPE:
@@ -247,7 +247,7 @@ lwgeom_homogenize(const LWGEOM *geom)
 			/* Strip single-entry multi-geometries down to singletons */
 			if ( col->ngeoms == 1 )
 			{
-				hgeom = lwgeom_clone((LWGEOM*)(col->geoms[0]));
+				hgeom = lwgeom_clone_deep((LWGEOM*)(col->geoms[0]));
 				hgeom->srid = geom->srid;
 				if (geom->bbox)
 					hgeom->bbox = gbox_copy(geom->bbox);
@@ -255,7 +255,7 @@ lwgeom_homogenize(const LWGEOM *geom)
 			}
 
 			/* Return proper multigeometry untouched */
-			return lwgeom_clone(geom);
+			return lwgeom_clone_deep(geom);
 		}
 
 		/* Work on anonymous collections separately */

commit dc3499df75713551858d882ff41921c93d382a25
Author: kalenikaliaksandr <kalenik.aliaksandr at gmail.com>
Date:   Wed Aug 4 20:41:12 2021 +0300

    increase boundary unit test coverage

diff --git a/liblwgeom/cunit/cu_boundary.c b/liblwgeom/cunit/cu_boundary.c
index 4de5c3c..355e991 100644
--- a/liblwgeom/cunit/cu_boundary.c
+++ b/liblwgeom/cunit/cu_boundary.c
@@ -62,11 +62,21 @@ static void boundary_line(void)
 	);
 
 	BOUNDARY_TEST(
+		"CIRCULARSTRING EMPTY",
+		"MULTIPOINT EMPTY"
+	);
+
+	BOUNDARY_TEST(
 		"LINESTRING(0 0, 5 5, 10 0, 0 0)",
 		"MULTIPOINT EMPTY"
 	);
 
 	BOUNDARY_TEST(
+		"CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0)",
+		"MULTIPOINT EMPTY"
+	);
+
+	BOUNDARY_TEST(
 		"LINESTRING(0 0, 5 0, 10 0)",
 		"MULTIPOINT(0 0, 10 0)"
 	);
@@ -76,6 +86,11 @@ static void boundary_line(void)
 		"MULTIPOINT(0 0, 10 0, 20 5, 20 10)"
 	);
 
+	BOUNDARY_TEST(
+		"MULTICURVE((1 1 1,0 0 0.5, -1 1 1),(1 1 0.5,0 0 0.5, -1 1 0.5, 1 1 0.5))",
+		"MULTIPOINT(1 1 1,-1 1 1)"
+	);
+
 }
 
 static void boundary_polygon(void)
@@ -95,19 +110,66 @@ static void boundary_polygon(void)
 		"MULTILINESTRING((0 0, 5 5, 10 0, 0 0),(3 1,7 1,5 2,3 1))"
 	);
 
+	/* See https://trac.osgeo.org/postgis/ticket/4961 */
 	BOUNDARY_TEST(
 		"MULTIPOLYGON(((0 0, 5 5, 10 0, 0 0),(3 1,7 1,5 2,3 1)),((20 0,20 5,25 5,20 0)))",
 		"MULTILINESTRING((0 0, 5 5, 10 0, 0 0),(3 1,7 1,5 2,3 1),(20 0,20 5,25 5,20 0))"
 	);
 
+	BOUNDARY_TEST(
+		"CURVEPOLYGON(CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0))",
+		"MULTICURVE(CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0))"
+	);
+
+	BOUNDARY_TEST(
+		"CURVEPOLYGON(CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0),(1 1, 3 3, 3 1, 1 1))",
+		"MULTICURVE(CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0),(1 1, 3 3, 3 1, 1 1))"
+	);
+
+}
+
+static void boundary_triangle(void)
+{
+	BOUNDARY_TEST(
+		"TRIANGLE EMPTY",
+		"LINESTRING EMPTY"
+	);
+
+	BOUNDARY_TEST(
+		"TRIANGLE((1 1, 0 0, -1 1, 1 1))",
+		"LINESTRING(1 1, 0 0, -1 1, 1 1)"
+	);
+}
+
+static void boundary_tin(void)
+{
+	BOUNDARY_TEST(
+		"TIN EMPTY",
+		"GEOMETRYCOLLECTION EMPTY"
+	);
+
+	BOUNDARY_TEST(
+		"TIN(((0 0,0 -1,-1 1,0 0)))",
+		"LINESTRING(0 0,0 -1,-1 1,0 0)"
+	);
+
+	BOUNDARY_TEST(
+		"TIN(((0 0,0 -1,-1 1,0 0)),((0 0,1 0,0 -1,0 0)))",
+		"MULTILINESTRING((0 0,0 -1,-1 1,0 0),(0 0,1 0,0 -1,0 0))"
+	);
 }
 
 static void boundary_collection(void)
 {
+	BOUNDARY_TEST(
+		"GEOMETRYCOLLECTION EMPTY",
+		"GEOMETRYCOLLECTION EMPTY"
+	);
+
 	/* See https://trac.osgeo.org/postgis/ticket/4956 */
 	BOUNDARY_TEST(
-"GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2)),POLYGON((2 2,2 4,4 4,4 2,2 2)))",
-"MULTILINESTRING((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2),(2 2,2 4,4 4,4 2,2 2))"
+		"GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2)),POLYGON((2 2,2 4,4 4,4 2,2 2)))",
+		"MULTILINESTRING((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2),(2 2,2 4,4 4,4 2,2 2))"
 	);
 }
 
@@ -119,6 +181,9 @@ void boundary_suite_setup(void)
 	PG_ADD_TEST(suite,boundary_point);
 	PG_ADD_TEST(suite,boundary_line);
 	PG_ADD_TEST(suite,boundary_polygon);
+	PG_ADD_TEST(suite,boundary_triangle);
+	PG_ADD_TEST(suite,boundary_tin);
+	PG_ADD_TEST(suite,boundary_collection);
 #if 0 /* write these */
 	PG_ADD_TEST(suite,boundary_tin);
 #endif

commit 0d995095118db4b87d0c1fc1dce00fc6b01d79df
Author: kalenikaliaksandr <kalenik.aliaksandr at gmail.com>
Date:   Wed Aug 4 20:39:42 2021 +0300

    fix 4961

diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c
index 356203e..e928e10 100644
--- a/liblwgeom/lwgeom.c
+++ b/liblwgeom/lwgeom.c
@@ -2550,20 +2550,16 @@ lwgeom_boundary(LWGEOM *lwgeom)
 
 	switch (lwgeom->type)
 	{
-	case POINTTYPE: {
-		return (LWGEOM *)lwpoint_construct_empty(srid, hasz, hasm);
-	}
+	case POINTTYPE:
 	case MULTIPOINTTYPE: {
-		return (LWGEOM *)lwmpoint_construct_empty(srid, hasz, hasm);
+		return lwgeom_construct_empty(lwgeom->type, srid, hasz, hasm);
 	}
 	case LINETYPE:
 	case CIRCSTRINGTYPE: {
-		if (lwgeom_is_closed(lwgeom))
+		if (lwgeom_is_closed(lwgeom) || lwgeom_is_empty(lwgeom))
 			return (LWGEOM *)lwmpoint_construct_empty(srid, hasz, hasm);
 		else
 		{
-			if ( lwgeom_is_empty(lwgeom) )
-				return (LWGEOM *)lwmpoint_construct_empty(srid, hasz, hasm);
 			LWLINE *lwline = (LWLINE *)lwgeom;
 			LWMPOINT *lwmpoint = lwmpoint_construct_empty(srid, hasz, hasm);
 			POINT4D pt;
@@ -2625,22 +2621,14 @@ lwgeom_boundary(LWGEOM *lwgeom)
 	case POLYGONTYPE: {
 		LWPOLY *lwpoly = (LWPOLY *)lwgeom;
 
-		if (lwpoly->nrings == 1)
+		LWMLINE *lwmline = lwmline_construct_empty(srid, hasz, hasm);
+		for (uint32_t i = 0; i < lwpoly->nrings; i++)
 		{
-			POINTARRAY *ring = ptarray_clone_deep(lwpoly->rings[0]);
-			return (LWGEOM *)lwline_construct(srid, 0, ring);
+			POINTARRAY *ring = ptarray_clone_deep(lwpoly->rings[i]);
+			lwmline_add_lwline(lwmline, lwline_construct(srid, 0, ring));
 		}
-		else
-		{
-			LWMLINE *lwmline = lwmline_construct_empty(srid, hasz, hasm);
-			for (uint32_t i = 0; i < lwpoly->nrings; i++)
-			{
-				POINTARRAY *ring = ptarray_clone_deep(lwpoly->rings[i]);
-				lwmline_add_lwline(lwmline, lwline_construct(srid, 0, ring));
-			}
 
-			return (LWGEOM *)lwmline;
-		}
+		return lwgeom_homogenize((LWGEOM *)lwmline);
 	}
 	case CURVEPOLYTYPE: {
 		LWCURVEPOLY *lwcurvepoly = (LWCURVEPOLY *)lwgeom;
@@ -2652,17 +2640,9 @@ lwgeom_boundary(LWGEOM *lwgeom)
 		return (LWGEOM *)lwcol;
 	}
 	case MULTIPOLYGONTYPE:
+	case COLLECTIONTYPE:
 	case TINTYPE: {
 		LWCOLLECTION *lwcol = (LWCOLLECTION *)lwgeom;
-		LWCOLLECTION *lwcol_boundary = lwcollection_construct_empty(MULTILINETYPE, srid, hasz, hasm);
-
-		for (uint32_t i = 0; i < lwcol->ngeoms; i++)
-			lwcollection_add_lwgeom(lwcol_boundary, lwgeom_boundary(lwcol->geoms[i]));
-
-		return (LWGEOM *)lwcol_boundary;
-	}
-	case COLLECTIONTYPE: {
-		LWCOLLECTION *lwcol = (LWCOLLECTION *)lwgeom;
 		LWCOLLECTION *lwcol_boundary = lwcollection_construct_empty(COLLECTIONTYPE, srid, hasz, hasm);
 
 		for (uint32_t i = 0; i < lwcol->ngeoms; i++)

commit 88256b672e3ca1f025c2b80ff962d2a22b76ec76
Author: Sandro Santilli <strk at kbt.io>
Date:   Thu Jul 29 21:55:27 2021 +0200

    Stub test for ST_Boundary(polygon)
    
    Fails for a MULTIPOLYGON

diff --git a/liblwgeom/cunit/cu_boundary.c b/liblwgeom/cunit/cu_boundary.c
index 34ed2d2..4de5c3c 100644
--- a/liblwgeom/cunit/cu_boundary.c
+++ b/liblwgeom/cunit/cu_boundary.c
@@ -20,11 +20,11 @@
 	LWGEOM *gin, *gout, *gexp; \
 	cu_error_msg_reset(); \
 	gin = lwgeom_from_wkt( wkt_in, LW_PARSER_CHECK_NONE);  \
-	CU_ASSERT(gin != NULL);  \
+	CU_ASSERT_PTR_NOT_NULL_FATAL(gin); \
 	gexp = lwgeom_from_wkt( wkt_exp, LW_PARSER_CHECK_NONE);  \
-	CU_ASSERT(gexp != NULL);  \
+	CU_ASSERT_PTR_NOT_NULL_FATAL(gexp); \
 	gout = lwgeom_boundary(gin);  \
-	CU_ASSERT(gout != NULL);  \
+	CU_ASSERT_PTR_NOT_NULL_FATAL(gout); \
 	ASSERT_NORMALIZED_GEOM_SAME(gout, gexp);  \
 	lwgeom_free(gout);  \
 	lwgeom_free(gexp);  \
@@ -78,6 +78,30 @@ static void boundary_line(void)
 
 }
 
+static void boundary_polygon(void)
+{
+	BOUNDARY_TEST(
+		"POLYGON EMPTY",
+		"MULTILINESTRING EMPTY"
+	);
+
+	BOUNDARY_TEST(
+		"POLYGON((0 0, 5 5, 10 0, 0 0))",
+		"LINESTRING(0 0, 5 5, 10 0, 0 0)"
+	);
+
+	BOUNDARY_TEST(
+		"POLYGON((0 0, 5 5, 10 0, 0 0),(3 1,7 1,5 2,3 1))",
+		"MULTILINESTRING((0 0, 5 5, 10 0, 0 0),(3 1,7 1,5 2,3 1))"
+	);
+
+	BOUNDARY_TEST(
+		"MULTIPOLYGON(((0 0, 5 5, 10 0, 0 0),(3 1,7 1,5 2,3 1)),((20 0,20 5,25 5,20 0)))",
+		"MULTILINESTRING((0 0, 5 5, 10 0, 0 0),(3 1,7 1,5 2,3 1),(20 0,20 5,25 5,20 0))"
+	);
+
+}
+
 static void boundary_collection(void)
 {
 	/* See https://trac.osgeo.org/postgis/ticket/4956 */
@@ -94,8 +118,8 @@ void boundary_suite_setup(void)
 	CU_pSuite suite = CU_add_suite("boundary", NULL, NULL);
 	PG_ADD_TEST(suite,boundary_point);
 	PG_ADD_TEST(suite,boundary_line);
-#if 0 /* write these */
 	PG_ADD_TEST(suite,boundary_polygon);
+#if 0 /* write these */
 	PG_ADD_TEST(suite,boundary_tin);
 #endif
 	//PG_ADD_TEST(suite,boundary_collection);

commit 65a00865adc37bd759b0bdfd80aed7b340574154
Author: Sandro Santilli <strk at kbt.io>
Date:   Thu Jul 29 21:49:02 2021 +0200

    Add more linear tests for lwgeom_boundary

diff --git a/liblwgeom/cunit/cu_boundary.c b/liblwgeom/cunit/cu_boundary.c
index f8b7008..34ed2d2 100644
--- a/liblwgeom/cunit/cu_boundary.c
+++ b/liblwgeom/cunit/cu_boundary.c
@@ -61,6 +61,21 @@ static void boundary_line(void)
 		"MULTIPOINT EMPTY"
 	);
 
+	BOUNDARY_TEST(
+		"LINESTRING(0 0, 5 5, 10 0, 0 0)",
+		"MULTIPOINT EMPTY"
+	);
+
+	BOUNDARY_TEST(
+		"LINESTRING(0 0, 5 0, 10 0)",
+		"MULTIPOINT(0 0, 10 0)"
+	);
+
+	BOUNDARY_TEST(
+		"MULTILINESTRING((0 0, 5 0, 10 0),(20 5, 20 6, 20 10))",
+		"MULTIPOINT(0 0, 10 0, 20 5, 20 10)"
+	);
+
 }
 
 static void boundary_collection(void)

commit cce909b3fb809f2bf58bf7fd569564f4727e5b4f
Author: Sandro Santilli <strk at kbt.io>
Date:   Thu Jul 29 21:46:52 2021 +0200

    Fix ST_Boundary('LINESTRING EMPTY')
    
    Closes #4960
    Includes unit test

diff --git a/liblwgeom/cunit/cu_boundary.c b/liblwgeom/cunit/cu_boundary.c
index 6f32e4d..f8b7008 100644
--- a/liblwgeom/cunit/cu_boundary.c
+++ b/liblwgeom/cunit/cu_boundary.c
@@ -58,7 +58,7 @@ static void boundary_line(void)
 {
 	BOUNDARY_TEST(
 		"LINESTRING EMPTY",
-		"POINT EMPTY"
+		"MULTIPOINT EMPTY"
 	);
 
 }
diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c
index 2eef44e..356203e 100644
--- a/liblwgeom/lwgeom.c
+++ b/liblwgeom/lwgeom.c
@@ -2562,6 +2562,8 @@ lwgeom_boundary(LWGEOM *lwgeom)
 			return (LWGEOM *)lwmpoint_construct_empty(srid, hasz, hasm);
 		else
 		{
+			if ( lwgeom_is_empty(lwgeom) )
+				return (LWGEOM *)lwmpoint_construct_empty(srid, hasz, hasm);
 			LWLINE *lwline = (LWLINE *)lwgeom;
 			LWMPOINT *lwmpoint = lwmpoint_construct_empty(srid, hasz, hasm);
 			POINT4D pt;

commit 4f93bdf208d53bead51f4824f26988feb225622c
Author: Sandro Santilli <strk at kbt.io>
Date:   Thu Jul 29 12:54:35 2021 +0200

    Stub unit test for lwgeom_boundary
    
    NOTE: reveals memory issues

diff --git a/liblwgeom/cunit/Makefile.in b/liblwgeom/cunit/Makefile.in
index a228a3d..59201d0 100644
--- a/liblwgeom/cunit/Makefile.in
+++ b/liblwgeom/cunit/Makefile.in
@@ -26,8 +26,9 @@ endif
 # ADD YOUR NEW TEST FILE HERE (1/1)
 OBJS=	\
 	cu_algorithm.o \
-	cu_bytebuffer.o \
+	cu_boundary.o \
 	cu_buildarea.o \
+	cu_bytebuffer.o \
 	cu_clean.o \
 	cu_print.o \
 	cu_minimum_bounding_circle.o \
diff --git a/liblwgeom/cunit/cu_boundary.c b/liblwgeom/cunit/cu_boundary.c
new file mode 100644
index 0000000..6f32e4d
--- /dev/null
+++ b/liblwgeom/cunit/cu_boundary.c
@@ -0,0 +1,87 @@
+/**********************************************************************
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.net
+ *
+ * Copyright (C) 2021 Sandro Santilli <strk at kbt.io>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+#include "liblwgeom.h"
+#include "liblwgeom_internal.h"
+
+#define BOUNDARY_TEST(wkt_in, wkt_exp) do {\
+	LWGEOM *gin, *gout, *gexp; \
+	cu_error_msg_reset(); \
+	gin = lwgeom_from_wkt( wkt_in, LW_PARSER_CHECK_NONE);  \
+	CU_ASSERT(gin != NULL);  \
+	gexp = lwgeom_from_wkt( wkt_exp, LW_PARSER_CHECK_NONE);  \
+	CU_ASSERT(gexp != NULL);  \
+	gout = lwgeom_boundary(gin);  \
+	CU_ASSERT(gout != NULL);  \
+	ASSERT_NORMALIZED_GEOM_SAME(gout, gexp);  \
+	lwgeom_free(gout);  \
+	lwgeom_free(gexp);  \
+	lwgeom_free(gin);  \
+} while (0)
+
+static void boundary_point(void)
+{
+	BOUNDARY_TEST(
+		"POINT EMPTY",
+		"POINT EMPTY"
+	);
+
+	BOUNDARY_TEST(
+		"POINT(0 0)",
+		"POINT EMPTY"
+	);
+
+	BOUNDARY_TEST(
+		"MULTIPOINT EMPTY",
+		"MULTIPOINT EMPTY" /* debatable return type */
+	);
+
+	BOUNDARY_TEST(
+		"MULTIPOINT(0 0,10 0)",
+		"MULTIPOINT EMPTY" /* debatable return type */
+	);
+}
+
+static void boundary_line(void)
+{
+	BOUNDARY_TEST(
+		"LINESTRING EMPTY",
+		"POINT EMPTY"
+	);
+
+}
+
+static void boundary_collection(void)
+{
+	/* See https://trac.osgeo.org/postgis/ticket/4956 */
+	BOUNDARY_TEST(
+"GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2)),POLYGON((2 2,2 4,4 4,4 2,2 2)))",
+"MULTILINESTRING((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2),(2 2,2 4,4 4,4 2,2 2))"
+	);
+}
+
+
+void boundary_suite_setup(void);
+void boundary_suite_setup(void)
+{
+	CU_pSuite suite = CU_add_suite("boundary", NULL, NULL);
+	PG_ADD_TEST(suite,boundary_point);
+	PG_ADD_TEST(suite,boundary_line);
+#if 0 /* write these */
+	PG_ADD_TEST(suite,boundary_polygon);
+	PG_ADD_TEST(suite,boundary_tin);
+#endif
+	//PG_ADD_TEST(suite,boundary_collection);
+}
diff --git a/liblwgeom/cunit/cu_tester.c b/liblwgeom/cunit/cu_tester.c
index ac979da..08de8d6 100644
--- a/liblwgeom/cunit/cu_tester.c
+++ b/liblwgeom/cunit/cu_tester.c
@@ -32,6 +32,7 @@ cu_debuglogger(int level, const char *fmt, va_list ap);
 /* ADD YOUR SUITE SETUP FUNCTION HERE (1 of 2) */
 extern void print_suite_setup();
 extern void algorithms_suite_setup();
+extern void boundary_suite_setup();
 extern void buildarea_suite_setup();
 extern void clean_suite_setup();
 extern void clip_by_rect_suite_setup();
@@ -84,6 +85,7 @@ extern void wrapx_suite_setup(void);
 PG_SuiteSetup setupfuncs[] =
 {
 	algorithms_suite_setup,
+	boundary_suite_setup,
 	buildarea_suite_setup,
 	clean_suite_setup,
 	clip_by_rect_suite_setup,
diff --git a/liblwgeom/cunit/cu_tester.h b/liblwgeom/cunit/cu_tester.h
index 6c253d5..2212355 100644
--- a/liblwgeom/cunit/cu_tester.h
+++ b/liblwgeom/cunit/cu_tester.h
@@ -41,6 +41,24 @@ typedef void (*PG_SuiteSetup)(void);
   CU_ASSERT_EQUAL(o,e); \
 } while (0);
 
+#define ASSERT_NORMALIZED_GEOM_SAME(gobt, gexp) do { \
+	char *obt, *exp; \
+	LWGEOM *ngobt, *ngexp; \
+	ngobt = lwgeom_normalize(gobt); \
+	ngexp = lwgeom_normalize(gexp); \
+	if ( ! lwgeom_same((ngobt), (ngexp)) ) { \
+ 		obt = lwgeom_to_wkt((ngobt), WKT_ISO, 8, NULL); \
+ 		exp = lwgeom_to_wkt((ngexp), WKT_ISO, 8, NULL); \
+    fprintf(stderr, "[%s:%d]\n Expected: %s\n Obtained: %s\n", __FILE__, __LINE__, exp, obt); \
+		free(obt); free(exp); \
+    lwgeom_free(ngobt); lwgeom_free(ngexp); \
+		CU_ASSERT(0); \
+	} else { \
+    lwgeom_free(ngobt); lwgeom_free(ngexp); \
+    CU_ASSERT(1); \
+  } \
+} while (0)
+
 static inline void
 assert_string_equal_impl(const char *obtained, const char *expected, const char *file, int line)
 {

commit 24d6752cc6b6c74ee49c5012150ec0115e88f9a2
Author: Sandro Santilli <strk at kbt.io>
Date:   Thu Jul 29 12:39:05 2021 +0200

    Don't assume boundary of collection is linear
    
    Closes #4956
    
    Still needs a regression test

diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c
index ad85fa8..2eef44e 100644
--- a/liblwgeom/lwgeom.c
+++ b/liblwgeom/lwgeom.c
@@ -2650,8 +2650,7 @@ lwgeom_boundary(LWGEOM *lwgeom)
 		return (LWGEOM *)lwcol;
 	}
 	case MULTIPOLYGONTYPE:
-	case TINTYPE:
-	case COLLECTIONTYPE: {
+	case TINTYPE: {
 		LWCOLLECTION *lwcol = (LWCOLLECTION *)lwgeom;
 		LWCOLLECTION *lwcol_boundary = lwcollection_construct_empty(MULTILINETYPE, srid, hasz, hasm);
 
@@ -2660,6 +2659,15 @@ lwgeom_boundary(LWGEOM *lwgeom)
 
 		return (LWGEOM *)lwcol_boundary;
 	}
+	case COLLECTIONTYPE: {
+		LWCOLLECTION *lwcol = (LWCOLLECTION *)lwgeom;
+		LWCOLLECTION *lwcol_boundary = lwcollection_construct_empty(COLLECTIONTYPE, srid, hasz, hasm);
+
+		for (uint32_t i = 0; i < lwcol->ngeoms; i++)
+			lwcollection_add_lwgeom(lwcol_boundary, lwgeom_boundary(lwcol->geoms[i]));
+
+		return lwgeom_homogenize((LWGEOM *)lwcol_boundary);
+	}
 	default:
 		lwerror("%s: unsupported geometry type: %s", __func__, lwtype_name(lwgeom->type));
 		return NULL;

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

Summary of changes:
 liblwgeom/cunit/Makefile.in    |   3 +-
 liblwgeom/cunit/cu_boundary.c  | 216 +++++++++++++++++++++++++++++++++++++++++
 liblwgeom/cunit/cu_tester.c    |  99 ++++++++++---------
 liblwgeom/cunit/cu_tester.h    |  26 +++++
 liblwgeom/liblwgeom.h.in       |   5 +-
 liblwgeom/lwgeom.c             |  40 ++++----
 liblwgeom/lwhomogenize.c       |  10 +-
 regress/core/boundary.sql      |   4 +
 regress/core/boundary_expected |   6 +-
 9 files changed, 326 insertions(+), 83 deletions(-)
 create mode 100644 liblwgeom/cunit/cu_boundary.c


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list