[postgis-tickets] r16954 - ST_LocateBetween[Elevations]: support TIN and TRIANGLE clipping.

Darafei komzpa at gmail.com
Sat Oct 27 03:23:04 PDT 2018


Author: komzpa
Date: 2018-10-27 03:23:03 -0700 (Sat, 27 Oct 2018)
New Revision: 16954

Modified:
   trunk/NEWS
   trunk/doc/reference_lrs.xml
   trunk/liblwgeom/cunit/cu_algorithm.c
   trunk/liblwgeom/lwlinearreferencing.c
Log:
ST_LocateBetween[Elevations]: support TIN and TRIANGLE clipping.

Triangle is converted into a TIN that has several triangles with same orientation.

Committed in Paris Airport.

Closes #4155


Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2018-10-27 10:21:00 UTC (rev 16953)
+++ trunk/NEWS	2018-10-27 10:23:03 UTC (rev 16954)
@@ -27,8 +27,8 @@
     Praliaskouski)
   - #3457, Fix raster envelope shortcut in ST_Clip (Sai-bot)
   - #4215, Use floating point compare in ST_DumpAsPolygons (Darafei Praliaskouski)
-  - #4155, Support for GEOMETRYCOLLECTION and POLYGON in ST_LocateBetween (Darafei
-    Praliaskouski)
+  - #4155, Support for GEOMETRYCOLLECTION, POLYGON, TIN, TRIANGLE in
+    ST_LocateBetween and ST_LocateBetweenElevations (Darafei Praliaskouski)
 
 PostGIS 2.5.0
 2018/09/23

Modified: trunk/doc/reference_lrs.xml
===================================================================
--- trunk/doc/reference_lrs.xml	2018-10-27 10:21:00 UTC (rev 16953)
+++ trunk/doc/reference_lrs.xml	2018-10-27 10:23:03 UTC (rev 16954)
@@ -426,8 +426,7 @@
 		<refname>ST_LocateBetween</refname>
 
 		<refpurpose>Return a derived geometry collection value with elements
-			that match the specified range of measures inclusively. Polygonal
-			elements are not supported.</refpurpose>
+			that match the specified range of measures inclusively.</refpurpose>
 	  </refnamediv>
 
 	  <refsynopsisdiv>
@@ -434,7 +433,7 @@
 		<funcsynopsis>
 		  <funcprototype>
 			<funcdef>geometry <function>ST_LocateBetween</function></funcdef>
-			<paramdef><type>geometry </type> <parameter>geomA</parameter></paramdef>
+			<paramdef><type>geometry </type> <parameter>geom</parameter></paramdef>
 			<paramdef><type>float8 </type> <parameter>measure_start</parameter></paramdef>
 			<paramdef><type>float8 </type> <parameter>measure_end</parameter></paramdef>
 			<paramdef choice="opt"><type>float8 </type> <parameter>offset</parameter></paramdef>
@@ -447,8 +446,10 @@
 		<title>Description</title>
 
 		<para>Return a derived geometry collection with elements that match the specified range of
-		measures inclusively. Polygonal elements are not supported.</para>
+		measures inclusively.</para>
 
+		<para>Clipping a non-convex POLYGON may produce invalid geometry.</para>
+
 		<para>If an offset is provided, the resultant will be offset to the left or right of the
 		input line by the specified number of units. A positive offset will be to the left, and
                 a negative one to the right.</para>
@@ -458,6 +459,7 @@
 
 		<para>Availability: 1.1.0 by old name ST_Locate_Between_Measures. </para>
 		<para>Changed: 2.0.0 - in prior versions this used to be called ST_Locate_Between_Measures.  The old name has been deprecated and will be removed in the future but is still available for backward compatibility.</para>
+		<para>Enhanced: 3.0.0 - added support for POLYGON, TIN, TRIANGLE.</para>
 
 		<para>&M_support;</para>
 	  </refsection>
@@ -465,11 +467,15 @@
 	  <refsection>
 		<title>Examples</title>
 
-		<programlisting>SELECT ST_AsText(the_geom)
-		FROM
-		(SELECT ST_LocateBetween(
-			ST_GeomFromText('MULTILINESTRING M ((1 2 3, 3 4 2, 9 4 3),
-		(1 2 3, 5 4 5))'),1.5, 3) As the_geom) As foo;
+		<programlisting>
+SELECT ST_AsText(the_geom)
+FROM (
+    SELECT ST_LocateBetween(
+       'MULTILINESTRING M ((1 2 3, 3 4 2, 9 4 3),(1 2 3, 5 4 5))'),
+       1.5,
+       3
+    ) as the_geom
+) As foo;
 
 							 st_asewkt
 ------------------------------------------------------------------------
@@ -478,10 +484,13 @@
 --Geometry collections are difficult animals so dump them
 --to make them more digestable
 SELECT ST_AsText((ST_Dump(the_geom)).geom)
-		FROM
-		(SELECT ST_LocateBetween(
-			ST_GeomFromText('MULTILINESTRING M ((1 2 3, 3 4 2, 9 4 3),
-		(1 2 3, 5 4 5))'),1.5, 3) As the_geom) As foo;
+FROM (
+    SELECT ST_LocateBetween(
+	'MULTILINESTRING M ((1 2 3, 3 4 2, 9 4 3),(1 2 3, 5 4 5))'),
+	1.5,
+	3
+    ) As the_geom
+) As foo;
 
 		   st_asewkt
 --------------------------------
@@ -502,8 +511,7 @@
 		<refname>ST_LocateBetweenElevations</refname>
 
 		<refpurpose>Return a derived geometry (collection) value with elements
-			that intersect the specified range of elevations inclusively. Only 3D, 4D LINESTRINGS and MULTILINESTRINGS
-			are supported.</refpurpose>
+			that intersect the specified range of elevations inclusively.</refpurpose>
 	  </refnamediv>
 
 	  <refsynopsisdiv>
@@ -510,7 +518,7 @@
 		<funcsynopsis>
 		  <funcprototype>
 			<funcdef>geometry <function>ST_LocateBetweenElevations</function></funcdef>
-			<paramdef><type>geometry </type> <parameter>geom_mline</parameter></paramdef>
+			<paramdef><type>geometry </type> <parameter>geom</parameter></paramdef>
 			<paramdef><type>float8 </type> <parameter>elevation_start</parameter></paramdef>
 			<paramdef><type>float8 </type> <parameter>elevation_end</parameter></paramdef>
 		  </funcprototype>
@@ -521,12 +529,14 @@
 	  <refsection>
 		<title>Description</title>
 
-		   <para>Return a derived geometry (collection) value with elements
-			that intersect the specified range of elevations inclusively. Only 3D, 3DM LINESTRINGS and MULTILINESTRINGS
-			are supported.</para>
+		<para>Return a derived geometry (collection) value with elements
+		that intersect the specified range of elevations inclusively.</para>
 
-			<para>Availability: 1.4.0</para>
+		<para>Clipping a non-convex POLYGON may produce invalid geometry.</para>
 
+		<para>Availability: 1.4.0</para>
+		<para>Enhanced: 3.0.0 - added support for POLYGON, TIN, TRIANGLE.</para>
+
 		<para>&Z_support;</para>
 	  </refsection>
 
@@ -534,24 +544,22 @@
 		<title>Examples</title>
 
 		<programlisting>SELECT ST_AsEWKT(ST_LocateBetweenElevations(
-			ST_GeomFromEWKT('LINESTRING(1 2 3, 4 5 6)'),2,4)) As ewelev;
+			ST_GeomFromEWKT('LINESTRING(1 2 3, 4 5 6)'), 2, 4)) As ewelev;
 								   ewelev
 ----------------------------------------------------------------
 	MULTILINESTRING((1 2 3,2 3 4))
 
-SELECT ST_AsEWKT(ST_LocateBetweenElevations(
-			ST_GeomFromEWKT('LINESTRING(1 2 6, 4 5 -1, 7 8 9)'),6,9)) As ewelev;
+SELECT ST_AsEWKT(ST_LocateBetweenElevations('LINESTRING(1 2 6, 4 5 -1, 7 8 9)', 6, 9)) As ewelev;
 
 				ewelev
 ----------------------------------------------------------------
 GEOMETRYCOLLECTION(POINT(1 2 6),LINESTRING(6.1 7.1 6,7 8 9))
 
---Geometry collections are difficult animals so dump them
---to make them more digestable
+-- Geometry collections are difficult animals so dump them
+-- to make them more digestable
 SELECT ST_AsEWKT((ST_Dump(the_geom)).geom)
-		FROM
-		(SELECT ST_LocateBetweenElevations(
-			ST_GeomFromEWKT('LINESTRING(1 2 6, 4 5 -1, 7 8 9)'),6,9) As the_geom) As foo;
+	FROM
+	(SELECT ST_LocateBetweenElevations('LINESTRING(1 2 6, 4 5 -1, 7 8 9)', 6, 9) as the_geom) As foo;
 
 		   st_asewkt
 --------------------------------
@@ -564,7 +572,7 @@
 	  <refsection>
 		<title>See Also</title>
 
-		<para><xref linkend="ST_Dump" /></para>
+		<para><xref linkend="ST_Dump" />, <xref linkend="ST_LocateBetween" /></para>
 	  </refsection>
 	</refentry>
 

Modified: trunk/liblwgeom/cunit/cu_algorithm.c
===================================================================
--- trunk/liblwgeom/cunit/cu_algorithm.c	2018-10-27 10:21:00 UTC (rev 16953)
+++ trunk/liblwgeom/cunit/cu_algorithm.c	2018-10-27 10:23:03 UTC (rev 16954)
@@ -557,7 +557,7 @@
 	c = lwgeom_clip_to_ordinate_range(l51, 'Y', 1.5, 2.5, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -565,7 +565,7 @@
 	c = lwgeom_clip_to_ordinate_range(l51, 'Y', 3.5, 5.5, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 3.5,0 4))");
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 3.5,0 4))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -573,7 +573,7 @@
 	c = lwgeom_clip_to_ordinate_range(l51, 'Y', -1.5, 2.5, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 2.5))" );
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 2.5))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -581,7 +581,7 @@
 	c = lwgeom_clip_to_ordinate_range(l51, 'Y', -1.5, 5.5, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))" );
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -589,7 +589,7 @@
 	c = lwgeom_clip_to_ordinate_range(l51, 'Y', 1.0, 2.0, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1,0 2))" );
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1,0 2))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -597,7 +597,7 @@
 	c = lwgeom_clip_to_ordinate_range(l51, 'Y', -1.0, 2.0, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2))" );
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -605,7 +605,7 @@
 	c = lwgeom_clip_to_ordinate_range(l51, 'Y', -1.0, 0.0, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(0 0))" );
+	ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(0 0))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -613,7 +613,7 @@
 	line = lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE);
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 1.0, 2.0, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" );
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 	lwgeom_free(line);
@@ -623,7 +623,7 @@
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 1.0, 2.0, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("a = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" );
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 	lwgeom_free(line);
@@ -633,7 +633,7 @@
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 1.0, 1.0, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("b = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" );
+	ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 	lwgeom_free(line);
@@ -643,7 +643,7 @@
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 1.0, 1.0, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" );
+	ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 	lwgeom_free(line);
@@ -665,7 +665,7 @@
 
 	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
 	// printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(
+	ASSERT_STRING_EQUAL(
 	    ewkt,
 	    "MULTIPOLYGON(((0.51 -0.25,1 -0.179078947368,1 0.270149253731,0.6 0.3,0.7 0.7,1 0.7,1 0.6,0.8 0.5,1 0.46,1 1.2,0.5 1.2,0.5 -0.1,0.3 -0.1,0.3 1.3,0 1.26875,0 -0.25,0.51 -0.25)))");
 	lwfree(ewkt);
@@ -679,7 +679,7 @@
 
 	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(
+	ASSERT_STRING_EQUAL(
 	    ewkt,
 	    "MULTIPOLYGON(((1 0,1 0.270149253731,0.6 0.3,0.7 0.7,1 0.7,1 0.6,0.8 0.5,1 0.46,1 1,0.5 1,0.5 0,0.3 0,0.3 1,0 1,0 0,1 0)))");
 	lwfree(ewkt);
@@ -687,6 +687,46 @@
 	lwgeom_free(g);
 }
 
+static void
+test_lwtriangle_clip(void)
+{
+	LWCOLLECTION *c;
+	LWGEOM *g = NULL;
+	char *ewkt;
+
+	g = lwgeom_from_wkt("TRIANGLE((0 0 0, 1 1 1, 3 2 2, 0 0 0))", LW_PARSER_CHECK_NONE);
+	c = lwgeom_clip_to_ordinate_range(g, 'Z', -10.0, 4.0, 0);
+
+	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
+	// printf("c = %s\n", ewkt);
+	ASSERT_STRING_EQUAL(ewkt, "TIN(((0 0 0,1 1 1,3 2 2,0 0 0)))");
+	lwfree(ewkt);
+	lwcollection_free(c);
+	lwgeom_free(g);
+
+	g = lwgeom_from_wkt("TRIANGLE((0 0 0, 1 1 1, 3 2 2, 0 0 0))", LW_PARSER_CHECK_NONE);
+	c = lwgeom_clip_to_ordinate_range(g, 'Z', 0.0, 1.0, 0);
+
+	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
+	// printf("c = %s\n", ewkt);
+	ASSERT_STRING_EQUAL(ewkt, "TIN(((0 0 0,1 1 1,1.5 1 1,0 0 0)))");
+	lwfree(ewkt);
+	lwcollection_free(c);
+	lwgeom_free(g);
+
+	g = lwgeom_from_wkt("TRIANGLE((0 0 0, 1 1 1, 3 2 3, 0 0 0))", LW_PARSER_CHECK_NONE);
+	c = lwgeom_clip_to_ordinate_range(g, 'Z', 1.0, 2.0, 0);
+
+	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
+	// printf("c = %s\n", ewkt);
+	ASSERT_STRING_EQUAL(
+	    ewkt,
+	    "TIN(((1 1 1,2 1.5 2,2 1.333333333333 2,1 1 1)),((1 1 1,2 1.333333333333 2,1 0.666666666667 1,1 1 1)))");
+	lwfree(ewkt);
+	lwcollection_free(c);
+	lwgeom_free(g);
+}
+
 static void test_lwmline_clip(void)
 {
 	LWCOLLECTION *c;
@@ -703,7 +743,7 @@
 	c = lwgeom_clip_to_ordinate_range(mline, 'Y', 1.5, 2.5, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -718,7 +758,7 @@
 	c = lwgeom_clip_to_ordinate_range(mline, 'Y', 3.5, 5.5, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))");
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -734,7 +774,7 @@
 	c = lwgeom_clip_to_ordinate_range(mline, 'Y', 0.0, 2.5, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))");
+	ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -750,7 +790,7 @@
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 3.0, 3.5, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5))");
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -758,7 +798,8 @@
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 2.0, 3.5, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5,2 2 2 6))");
+	ASSERT_STRING_EQUAL(ewkt,
+			    "MULTILINESTRING((2 2 2 2,3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5,2 2 2 6))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -766,7 +807,7 @@
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 3.0, 4.0, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,4 4 4 4,3 3 3 5))");
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,4 4 4 4,3 3 3 5))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -774,7 +815,7 @@
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 2.0, 3.0, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3),(3 3 3 5,2 2 2 6))");
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3),(3 3 3 5,2 2 2 6))");
 	lwfree(ewkt);
 	lwcollection_free(c);
 
@@ -807,7 +848,7 @@
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 0.5, 1.5, 0);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0.5 0.5 0.5,1 1 1,1.5 1.5 1.5))" );
+	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0.5 0.5 0.5,1 1 1,1.5 1.5 1.5))");
 
 	lwfree(ewkt);
 	lwcollection_free(c);
@@ -854,17 +895,17 @@
 
 	geohash = geohash_point(0, 0, 16);
 	//printf("\ngeohash %s\n",geohash);
-	CU_ASSERT_STRING_EQUAL(geohash, "s000000000000000");
+	ASSERT_STRING_EQUAL(geohash, "s000000000000000");
 	lwfree(geohash);
 
 	geohash = geohash_point(90, 0, 16);
 	//printf("\ngeohash %s\n",geohash);
-	CU_ASSERT_STRING_EQUAL(geohash, "w000000000000000");
+	ASSERT_STRING_EQUAL(geohash, "w000000000000000");
 	lwfree(geohash);
 
 	geohash = geohash_point(20.012345, -20.012345, 15);
 	//printf("\ngeohash %s\n",geohash);
-	CU_ASSERT_STRING_EQUAL(geohash, "kkqnpkue9ktbpe5");
+	ASSERT_STRING_EQUAL(geohash, "kkqnpkue9ktbpe5");
 	lwfree(geohash);
 
 }
@@ -879,7 +920,7 @@
 	lwpoint = (LWPOINT*)lwgeom_from_wkt("POINT(23.0 25.2)", LW_PARSER_CHECK_NONE);
 	geohash = lwgeom_geohash((LWGEOM*)lwpoint,0);
 	//printf("\ngeohash %s\n",geohash);
-	CU_ASSERT_STRING_EQUAL(geohash, "ss2r77s0du7p2ewb8hmx");
+	ASSERT_STRING_EQUAL(geohash, "ss2r77s0du7p2ewb8hmx");
 	lwpoint_free(lwpoint);
 	lwfree(geohash);
 
@@ -886,7 +927,7 @@
 	lwpoint = (LWPOINT*)lwgeom_from_wkt("POINT(23.0 25.2 2.0)", LW_PARSER_CHECK_NONE);
 	geohash = lwgeom_geohash((LWGEOM*)lwpoint,0);
 	//printf("geohash %s\n",geohash);
-	CU_ASSERT_STRING_EQUAL(geohash, "ss2r77s0du7p2ewb8hmx");
+	ASSERT_STRING_EQUAL(geohash, "ss2r77s0du7p2ewb8hmx");
 	lwpoint_free(lwpoint);
 	lwfree(geohash);
 
@@ -893,7 +934,7 @@
 	lwline = (LWLINE*)lwgeom_from_wkt("LINESTRING(23.0 23.0,23.1 23.1)", LW_PARSER_CHECK_NONE);
 	geohash = lwgeom_geohash((LWGEOM*)lwline,0);
 	//printf("geohash %s\n",geohash);
-	CU_ASSERT_STRING_EQUAL(geohash, "ss0");
+	ASSERT_STRING_EQUAL(geohash, "ss0");
 	lwline_free(lwline);
 	lwfree(geohash);
 
@@ -900,7 +941,7 @@
 	lwline = (LWLINE*)lwgeom_from_wkt("LINESTRING(23.0 23.0,23.001 23.001)", LW_PARSER_CHECK_NONE);
 	geohash = lwgeom_geohash((LWGEOM*)lwline,0);
 	//printf("geohash %s\n",geohash);
-	CU_ASSERT_STRING_EQUAL(geohash, "ss06g7h");
+	ASSERT_STRING_EQUAL(geohash, "ss06g7h");
 	lwline_free(lwline);
 	lwfree(geohash);
 
@@ -907,7 +948,7 @@
 	lwmline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((23.0 23.0,23.1 23.1),(23.0 23.0,23.1 23.1))", LW_PARSER_CHECK_NONE);
 	geohash = lwgeom_geohash((LWGEOM*)lwmline,0);
 	//printf("geohash %s\n",geohash);
-	CU_ASSERT_STRING_EQUAL(geohash, "ss0");
+	ASSERT_STRING_EQUAL(geohash, "ss0");
 	lwmline_free(lwmline);
 	lwfree(geohash);
 }
@@ -1045,7 +1086,7 @@
 	g = lwgeom_from_wkt("MULTIPOINT(0 0, 10 0, 10 10, 10 10, 0 10, 0 10, 0 10, 0 0, 0 0, 0 0, 5 5, 0 0, 5 5)", LW_PARSER_CHECK_NONE);
 	lwgeom_remove_repeated_points_in_place(g, 1);
 	ewkt = lwgeom_to_ewkt(g);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTIPOINT(0 0,10 0,10 10,0 10,5 5)");
+	ASSERT_STRING_EQUAL(ewkt, "MULTIPOINT(0 0,10 0,10 10,0 10,5 5)");
 	lwgeom_free(g);
 	lwfree(ewkt);
 
@@ -1052,7 +1093,7 @@
 	g = lwgeom_from_wkt("LINESTRING(1612830.15445 4841287.12672,1612830.15824 4841287.12674,1612829.98813 4841274.56198)", LW_PARSER_CHECK_NONE);
 	lwgeom_remove_repeated_points_in_place(g, 0.01);
 	ewkt = lwgeom_to_ewkt(g);
-	CU_ASSERT_STRING_EQUAL(ewkt, "LINESTRING(1612830.15445 4841287.12672,1612829.98813 4841274.56198)");
+	ASSERT_STRING_EQUAL(ewkt, "LINESTRING(1612830.15445 4841287.12672,1612829.98813 4841274.56198)");
 	lwgeom_free(g);
 	lwfree(ewkt);
 
@@ -1059,7 +1100,8 @@
 	g = lwgeom_from_wkt("MULTIPOINT(0 0,10 0,10 10,10 10,0 10,0 10,0 10,0 0,0 0,0 0,5 5,5 5,5 8,8 8,8 8,8 8,8 5,8 5,5 5,5 5,5 5,5 5,5 5,50 50,50 50,50 50,50 60,50 60,50 60,60 60,60 50,60 50,50 50,55 55,55 58,58 58,58 55,58 55,55 55)", LW_PARSER_CHECK_NONE);
 	lwgeom_remove_repeated_points_in_place(g, 1);
 	ewkt = lwgeom_to_ewkt(g);
-	CU_ASSERT_STRING_EQUAL(ewkt, "MULTIPOINT(0 0,10 0,10 10,0 10,5 5,5 8,8 8,8 5,50 50,50 60,60 60,60 50,55 55,55 58,58 58,58 55)");
+	ASSERT_STRING_EQUAL(
+	    ewkt, "MULTIPOINT(0 0,10 0,10 10,0 10,5 5,5 8,8 8,8 5,50 50,50 60,60 60,60 50,55 55,55 58,58 58,58 55)");
 	lwgeom_free(g);
 	lwfree(ewkt);
 
@@ -1066,7 +1108,7 @@
 	g = lwgeom_from_wkt("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))", LW_PARSER_CHECK_NONE);
 	lwgeom_remove_repeated_points_in_place(g, 10000);
 	ewkt = lwgeom_to_ewkt(g);
-	CU_ASSERT_STRING_EQUAL(ewkt, "POLYGON((0 0,1 1,1 0,0 0))");
+	ASSERT_STRING_EQUAL(ewkt, "POLYGON((0 0,1 1,1 0,0 0))");
 	lwgeom_free(g);
 	lwfree(ewkt);
 }
@@ -1081,7 +1123,7 @@
 	g = lwgeom_from_wkt("LINESTRING(0 0, 1 0, 1 1, 0 1, 0 0)", LW_PARSER_CHECK_NONE);
 	l = lwgeom_simplify(g, 10, LW_TRUE);
 	ewkt = lwgeom_to_ewkt(l);
-	CU_ASSERT_STRING_EQUAL(ewkt, "LINESTRING(0 0,0 0)");
+	ASSERT_STRING_EQUAL(ewkt, "LINESTRING(0 0,0 0)");
 	lwgeom_free(g);
 	lwgeom_free(l);
 	lwfree(ewkt);
@@ -1090,7 +1132,7 @@
 	g = lwgeom_from_wkt("POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))", LW_PARSER_CHECK_NONE);
 	l = lwgeom_simplify(g, 10, LW_TRUE);
 	ewkt = lwgeom_to_ewkt(l);
-	CU_ASSERT_STRING_EQUAL(ewkt, "POLYGON((0 0,1 0,1 1,0 0))");
+	ASSERT_STRING_EQUAL(ewkt, "POLYGON((0 0,1 0,1 1,0 0))");
 	lwgeom_free(g);
 	lwgeom_free(l);
 	lwfree(ewkt);
@@ -1113,7 +1155,7 @@
 	g = lwgeom_from_wkt("LINESTRING(0 0, 50 1.00001, 100 0)", LW_PARSER_CHECK_NONE);
 	l = lwgeom_simplify(g, 1.0, LW_FALSE);
 	ewkt = lwgeom_to_ewkt(l);
-	CU_ASSERT_STRING_EQUAL(ewkt, "LINESTRING(0 0,50 1.00001,100 0)");
+	ASSERT_STRING_EQUAL(ewkt, "LINESTRING(0 0,50 1.00001,100 0)");
 	lwgeom_free(g);
 	lwgeom_free(l);
 	lwfree(ewkt);
@@ -1122,7 +1164,7 @@
 	g = lwgeom_from_wkt("LINESTRING(0 0,50 0.99999,100 0)", LW_PARSER_CHECK_NONE);
 	l = lwgeom_simplify(g, 1.0, LW_FALSE);
 	ewkt = lwgeom_to_ewkt(l);
-	CU_ASSERT_STRING_EQUAL(ewkt, "LINESTRING(0 0,100 0)");
+	ASSERT_STRING_EQUAL(ewkt, "LINESTRING(0 0,100 0)");
 	lwgeom_free(g);
 	lwgeom_free(l);
 	lwfree(ewkt);
@@ -1531,6 +1573,7 @@
 	PG_ADD_TEST(suite,test_lwline_interpolate_points);
 	PG_ADD_TEST(suite,test_lwline_clip);
 	PG_ADD_TEST(suite, test_lwpoly_clip);
+	PG_ADD_TEST(suite, test_lwtriangle_clip);
 	PG_ADD_TEST(suite,test_lwline_clip_big);
 	PG_ADD_TEST(suite,test_lwmline_clip);
 	PG_ADD_TEST(suite,test_geohash_point);

Modified: trunk/liblwgeom/lwlinearreferencing.c
===================================================================
--- trunk/liblwgeom/lwlinearreferencing.c	2018-10-27 10:21:00 UTC (rev 16953)
+++ trunk/liblwgeom/lwlinearreferencing.c	2018-10-27 10:23:03 UTC (rev 16954)
@@ -440,7 +440,7 @@
 }
 
 static inline POINTARRAY *
-ptarray_clamp_to_ordinate_range(const POINTARRAY *ipa, char ordinate, double from, double to)
+ptarray_clamp_to_ordinate_range(const POINTARRAY *ipa, char ordinate, double from, double to, uint8_t is_closed)
 {
 	POINT4D p1, p2;
 	POINTARRAY *opa;
@@ -524,7 +524,7 @@
 		LW_ON_INTERRUPT(ptarray_free(opa); return NULL);
 	}
 
-	if (ptarray_is_closed(ipa) && opa->npoints > 0)
+	if (is_closed && opa->npoints > 2)
 	{
 		getPoint4d_p(opa, 0, &p1);
 		ptarray_append_point(opa, &p1, LW_FALSE);
@@ -769,7 +769,7 @@
 	for (i = 0; i < nrings; i++)
 	{
 		/* Ret number of points */
-		POINTARRAY *pa = ptarray_clamp_to_ordinate_range(poly->rings[i], ordinate, from, to);
+		POINTARRAY *pa = ptarray_clamp_to_ordinate_range(poly->rings[i], ordinate, from, to, LW_TRUE);
 
 		if (pa->npoints >= 4)
 			lwpoly_add_ring(poly_res, pa);
@@ -786,6 +786,41 @@
 }
 
 /**
+ * Clip an input LWTRIANGLE between two values, on any ordinate input.
+ */
+static inline LWCOLLECTION *
+lwtriangle_clip_to_ordinate_range(const LWTRIANGLE *tri, char ordinate, double from, double to)
+{
+	LWCOLLECTION *lwgeom_out = NULL;
+	char hasz = FLAGS_GET_Z(tri->flags), hasm = FLAGS_GET_M(tri->flags);
+
+	assert(tri);
+	lwgeom_out = lwcollection_construct_empty(TINTYPE, tri->srid, hasz, hasm);
+
+	POINTARRAY *pa = ptarray_clamp_to_ordinate_range(tri->points, ordinate, from, to, LW_TRUE);
+
+	if (pa->npoints >= 4)
+	{
+		POINT4D first = getPoint4d(pa, 0);
+		for (uint32_t i = 1; i < pa->npoints - 2; i++)
+		{
+			POINT4D p;
+			POINTARRAY *tpa = ptarray_construct_empty(hasz, hasm, 4);
+			ptarray_append_point(tpa, &first, LW_TRUE);
+			getPoint4d_p(pa, i, &p);
+			ptarray_append_point(tpa, &p, LW_TRUE);
+			getPoint4d_p(pa, i + 1, &p);
+			ptarray_append_point(tpa, &p, LW_TRUE);
+			ptarray_append_point(tpa, &first, LW_TRUE);
+			LWTRIANGLE *otri = lwtriangle_construct(tri->srid, NULL, tpa);
+			lwgeom_out = lwcollection_add_lwgeom(lwgeom_out, (LWGEOM *)otri);
+		}
+	}
+	ptarray_free(pa);
+	return lwgeom_out;
+}
+
+/**
  * Clip an input COLLECTION between two values, on any ordinate input.
  */
 static inline LWCOLLECTION *
@@ -859,9 +894,9 @@
 	case POLYGONTYPE:
 		out_col = lwpoly_clip_to_ordinate_range((LWPOLY *)lwin, ordinate, from, to);
 		break;
-	// case TRIANGLETYPE:
-	// 	out_col = lwtriangle_clip_to_ordinate_range((LWTRIANGLE*)lwin, ordinate, from, to);
-	// 	break;
+	case TRIANGLETYPE:
+		out_col = lwtriangle_clip_to_ordinate_range((LWTRIANGLE *)lwin, ordinate, from, to);
+		break;
 	case TINTYPE:
 	case MULTILINETYPE:
 	case MULTIPOLYGONTYPE:



More information about the postgis-tickets mailing list