[postgis-tickets] r16961 - Tidy lwline_clip_to_ordinate_range

Darafei komzpa at gmail.com
Mon Oct 29 07:57:55 PDT 2018


Author: komzpa
Date: 2018-10-29 19:57:55 -0700 (Mon, 29 Oct 2018)
New Revision: 16961

Modified:
   trunk/liblwgeom/cunit/cu_algorithm.c
   trunk/liblwgeom/lwlinearreferencing.c
Log:
Tidy lwline_clip_to_ordinate_range

Fix memory leak.

Closes #4218
Closes https://github.com/postgis/postgis/pull/324


Modified: trunk/liblwgeom/cunit/cu_algorithm.c
===================================================================
--- trunk/liblwgeom/cunit/cu_algorithm.c	2018-10-29 22:20:48 UTC (rev 16960)
+++ trunk/liblwgeom/cunit/cu_algorithm.c	2018-10-30 02:57:55 UTC (rev 16961)
@@ -741,8 +741,7 @@
 
 	/* Clip in the middle, mid-range. */
 	c = lwgeom_clip_to_ordinate_range(mline, 'Y', 1.5, 2.5, 0);
-	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
-	//printf("c = %s\n", ewkt);
+	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
 	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
 	lwfree(ewkt);
 	lwcollection_free(c);
@@ -756,8 +755,7 @@
 
 	/* Clip off the top. */
 	c = lwgeom_clip_to_ordinate_range(mline, 'Y', 3.5, 5.5, 0);
-	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
-	//printf("c = %s\n", ewkt);
+	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
 	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))");
 	lwfree(ewkt);
 	lwcollection_free(c);
@@ -772,8 +770,7 @@
 
 	/* Clip from 0 upwards.. */
 	c = lwgeom_clip_to_ordinate_range(mline, 'Y', 0.0, 2.5, 0);
-	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
-	//printf("c = %s\n", ewkt);
+	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
 	ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))");
 	lwfree(ewkt);
 	lwcollection_free(c);
@@ -788,8 +785,7 @@
 
 	/* Clip from 3 to 3.5 */
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 3.0, 3.5, 0);
-	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
-	//printf("c = %s\n", ewkt);
+	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
 	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);
@@ -796,8 +792,7 @@
 
 	/* Clip from 2 to 3.5 */
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 2.0, 3.5, 0);
-	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
-	//printf("c = %s\n", ewkt);
+	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
 	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);
@@ -805,8 +800,7 @@
 
 	/* Clip from 3 to 4 */
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 3.0, 4.0, 0);
-	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
-	//printf("c = %s\n", ewkt);
+	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
 	ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,4 4 4 4,3 3 3 5))");
 	lwfree(ewkt);
 	lwcollection_free(c);
@@ -813,8 +807,7 @@
 
 	/* Clip from 2 to 3 */
 	c = lwgeom_clip_to_ordinate_range(line, 'Z', 2.0, 3.0, 0);
-	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
-	//printf("c = %s\n", ewkt);
+	ewkt = lwgeom_to_ewkt((LWGEOM *)c);
 	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);

Modified: trunk/liblwgeom/lwlinearreferencing.c
===================================================================
--- trunk/liblwgeom/lwlinearreferencing.c	2018-10-29 22:20:48 UTC (rev 16960)
+++ trunk/liblwgeom/lwlinearreferencing.c	2018-10-30 02:57:55 UTC (rev 16961)
@@ -541,7 +541,6 @@
 static inline LWCOLLECTION *
 lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to)
 {
-
 	POINTARRAY *pa_in = NULL;
 	LWCOLLECTION *lwgeom_out = NULL;
 	POINTARRAY *dp = NULL;
@@ -551,22 +550,15 @@
 	double ordinate_value_p = 0.0, ordinate_value_q = 0.0;
 	char hasz, hasm;
 	char dims;
-#if POSTGIS_DEBUG_LEVEL >= 4
-	char *geom_ewkt;
-#endif
 
 	/* Null input, nothing we can do. */
-	if ( ! line )
-	{
-		lwerror("Null input geometry.");
-		return NULL;
-	}
+	assert(line);
 	hasz = lwgeom_has_z(lwline_as_lwgeom(line));
 	hasm = lwgeom_has_m(lwline_as_lwgeom(line));
 	dims = FLAGS_NDIMS(line->flags);
 
 	/* Asking for an ordinate we don't have. Error. */
-	if ( (ordinate == 'Z' && ! hasz) || (ordinate == 'M' && ! hasm) )
+	if ((ordinate == 'Z' && !hasz) || (ordinate == 'M' && !hasm))
 	{
 		lwerror("Cannot clip on ordinate %d in a %d-d geometry.", ordinate, dims);
 		return NULL;
@@ -583,11 +575,9 @@
 	/* Get our input point array */
 	pa_in = line->points;
 
-	for ( i = 0; i < pa_in->npoints; i++ )
+	for (i = 0; i < pa_in->npoints; i++)
 	{
-		LWDEBUGF(4, "Point #%d", i);
-		LWDEBUGF(4, "added_last_point %d", added_last_point);
-		if ( i > 0 )
+		if (i > 0)
 		{
 			*q = *p;
 			ordinate_value_q = ordinate_value_p;
@@ -594,82 +584,72 @@
 		}
 		getPoint4d_p(pa_in, i, p);
 		ordinate_value_p = lwpoint_get_ordinate(p, ordinate);
-		LWDEBUGF(4, " ordinate_value_p %g (current)", ordinate_value_p);
-		LWDEBUGF(4, " ordinate_value_q %g (previous)", ordinate_value_q);
 
 		/* Is this point inside the ordinate range? Yes. */
-		if ( ordinate_value_p >= from && ordinate_value_p <= to )
+		if (ordinate_value_p >= from && ordinate_value_p <= to)
 		{
-			LWDEBUGF(4, " inside ordinate range (%g, %g)", from, to);
 
 			if ( ! added_last_point )
 			{
-				LWDEBUG(4,"  new ptarray required");
 				/* We didn't add the previous point, so this is a new segment.
-				*  Make a new point array. */
+				 *  Make a new point array. */
 				dp = ptarray_construct_empty(hasz, hasm, 32);
 
 				/* We're transiting into the range so add an interpolated
-				*  point at the range boundary.
-				*  If we're on a boundary and crossing from the far side,
-				*  we also need an interpolated point. */
-				if ( i > 0 && ( /* Don't try to interpolate if this is the first point */
-				            ( ordinate_value_p > from && ordinate_value_p < to ) || /* Inside */
-				            ( ordinate_value_p == from && ordinate_value_q > to ) || /* Hopping from above */
-				            ( ordinate_value_p == to && ordinate_value_q < from ) ) ) /* Hopping from below */
+				 *  point at the range boundary.
+				 *  If we're on a boundary and crossing from the far side,
+				 *  we also need an interpolated point. */
+				if (i > 0 &&
+				    (/* Don't try to interpolate if this is the first point */
+				     (ordinate_value_p > from && ordinate_value_p < to) ||  /* Inside */
+				     (ordinate_value_p == from && ordinate_value_q > to) || /* Hopping from above */
+				     (ordinate_value_p == to && ordinate_value_q < from)))  /* Hopping from below */
 				{
 					double interpolation_value;
-					(ordinate_value_q > to) ? (interpolation_value = to) : (interpolation_value = from);
+					(ordinate_value_q > to) ? (interpolation_value = to)
+								: (interpolation_value = from);
 					point_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
 					ptarray_append_point(dp, r, LW_FALSE);
-					LWDEBUGF(4, "[0] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
 				}
 			}
 			/* Add the current vertex to the point array. */
 			ptarray_append_point(dp, p, LW_FALSE);
-			if ( ordinate_value_p == from || ordinate_value_p == to )
-			{
+			if (ordinate_value_p == from || ordinate_value_p == to)
 				added_last_point = 2; /* Added on boundary. */
-			}
 			else
-			{
 				added_last_point = 1; /* Added inside range. */
-			}
 		}
 		/* Is this point inside the ordinate range? No. */
 		else
 		{
-			LWDEBUGF(4, "  added_last_point (%d)", added_last_point);
-			if ( added_last_point == 1 )
+			if (added_last_point == 1)
 			{
 				/* We're transiting out of the range, so add an interpolated point
-				*  to the point array at the range boundary. */
+				 *  to the point array at the range boundary. */
 				double interpolation_value;
 				(ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
 				point_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
 				ptarray_append_point(dp, r, LW_FALSE);
-				LWDEBUGF(4, " [1] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
 			}
-			else if ( added_last_point == 2 )
+			else if (added_last_point == 2)
 			{
 				/* We're out and the last point was on the boundary.
-				*  If the last point was the near boundary, nothing to do.
-				*  If it was the far boundary, we need an interpolated point. */
-				if ( from != to && (
-				            (ordinate_value_q == from && ordinate_value_p > from) ||
-				            (ordinate_value_q == to && ordinate_value_p < to) ) )
+				 *  If the last point was the near boundary, nothing to do.
+				 *  If it was the far boundary, we need an interpolated point. */
+				if (from != to && ((ordinate_value_q == from && ordinate_value_p > from) ||
+						   (ordinate_value_q == to && ordinate_value_p < to)))
 				{
 					double interpolation_value;
-					(ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
+					(ordinate_value_p > to) ? (interpolation_value = to)
+								: (interpolation_value = from);
 					point_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
 					ptarray_append_point(dp, r, LW_FALSE);
-					LWDEBUGF(4, " [2] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
 				}
 			}
-			else if ( i && ordinate_value_q < from && ordinate_value_p > to )
+			else if (i && ordinate_value_q < from && ordinate_value_p > to)
 			{
 				/* We just hopped over the whole range, from bottom to top,
-				*  so we need to add *two* interpolated points! */
+				 *  so we need to add *two* interpolated points! */
 				dp = ptarray_construct(hasz, hasm, 2);
 				/* Interpolate lower point. */
 				point_interpolate(p, q, r, hasz, hasm, ordinate, from);
@@ -678,10 +658,10 @@
 				point_interpolate(p, q, r, hasz, hasm, ordinate, to);
 				ptarray_set_point4d(dp, 1, r);
 			}
-			else if ( i && ordinate_value_q > to && ordinate_value_p < from )
+			else if (i && ordinate_value_q > to && ordinate_value_p < from)
 			{
 				/* We just hopped over the whole range, from top to bottom,
-				*  so we need to add *two* interpolated points! */
+				 *  so we need to add *two* interpolated points! */
 				dp = ptarray_construct(hasz, hasm, 2);
 				/* Interpolate upper point. */
 				point_interpolate(p, q, r, hasz, hasm, ordinate, to);
@@ -691,18 +671,15 @@
 				ptarray_set_point4d(dp, 1, r);
 			}
 			/* We have an extant point-array, save it out to a multi-line. */
-			if ( dp )
+			if (dp)
 			{
-				LWDEBUG(4, "saving pointarray to multi-line (1)");
-
 				/* Only one point, so we have to make an lwpoint to hold this
-				*  and set the overall output type to a generic collection. */
-				if ( dp->npoints == 1 )
+				 *  and set the overall output type to a generic collection. */
+				if (dp->npoints == 1)
 				{
 					LWPOINT *opoint = lwpoint_construct(line->srid, NULL, dp);
 					lwgeom_out->type = COLLECTIONTYPE;
 					lwgeom_out = lwcollection_add_lwgeom(lwgeom_out, lwpoint_as_lwgeom(opoint));
-
 				}
 				else
 				{
@@ -714,31 +691,25 @@
 				dp = NULL;
 			}
 			added_last_point = 0;
-
 		}
 	}
 
 	/* Still some points left to be saved out. */
-	if ( dp && dp->npoints > 0 )
+	if (dp)
 	{
-		LWDEBUG(4, "saving pointarray to multi-line (2)");
-		LWDEBUGF(4, "dp->npoints == %d", dp->npoints);
-		LWDEBUGF(4, "lwgeom_out->ngeoms == %d", lwgeom_out->ngeoms);
-
-		if ( dp->npoints == 1 )
+		if (dp->npoints == 1)
 		{
 			LWPOINT *opoint = lwpoint_construct(line->srid, NULL, dp);
 			lwgeom_out->type = COLLECTIONTYPE;
 			lwgeom_out = lwcollection_add_lwgeom(lwgeom_out, lwpoint_as_lwgeom(opoint));
 		}
-		else
+		else if (dp->npoints > 1)
 		{
 			LWLINE *oline = lwline_construct(line->srid, NULL, dp);
 			lwgeom_out = lwcollection_add_lwgeom(lwgeom_out, lwline_as_lwgeom(oline));
 		}
-
-		/* Pointarray is now owned by lwgeom_out, so drop reference to it */
-		dp = NULL;
+		else
+			ptarray_free(dp);
 	}
 
 	lwfree(p);
@@ -746,7 +717,7 @@
 	lwfree(r);
 
 	if (line->bbox && lwgeom_out->ngeoms > 0)
-		lwgeom_refresh_bbox((LWGEOM*)lwgeom_out);
+		lwgeom_refresh_bbox((LWGEOM *)lwgeom_out);
 
 	return lwgeom_out;
 }
@@ -826,22 +797,9 @@
 static inline LWCOLLECTION *
 lwcollection_clip_to_ordinate_range(const LWCOLLECTION *icol, char ordinate, double from, double to)
 {
-	LWCOLLECTION *lwgeom_out = NULL;
+	LWCOLLECTION *lwgeom_out;
 
-	if (!icol)
-	{
-		lwerror("Null input geometry.");
-		return NULL;
-	}
-
-	/* Ensure 'from' is less than 'to'. */
-	if (to < from)
-	{
-		double t = from;
-		from = to;
-		to = t;
-	}
-
+	assert(icol);
 	if (icol->ngeoms == 1)
 		lwgeom_out = lwgeom_clip_to_ordinate_range(icol->geoms[0], ordinate, from, to, 0);
 	else
@@ -861,12 +819,15 @@
 				if (col->type != icol->type)
 					lwgeom_out->type = COLLECTIONTYPE;
 				lwgeom_out = lwcollection_concat_in_place(lwgeom_out, col);
+				lwfree(col->geoms);
 				lwcollection_release(col);
 			}
 		}
-		if (icol->bbox)
-			lwgeom_refresh_bbox((LWGEOM *)lwgeom_out);
 	}
+
+	if (icol->bbox)
+		lwgeom_refresh_bbox((LWGEOM *)lwgeom_out);
+
 	return lwgeom_out;
 }
 
@@ -877,6 +838,14 @@
 	LWCOLLECTION *out_offset;
 	uint32_t i;
 
+	/* Ensure 'from' is less than 'to'. */
+	if (to < from)
+	{
+		double t = from;
+		from = to;
+		to = t;
+	}
+
 	if ( ! lwin )
 		lwerror("lwgeom_clip_to_ordinate_range: null input geometry!");
 



More information about the postgis-tickets mailing list