Skip to content

Commit 1a4ab8d

Browse files
committed
Tidy lwline_clip_to_ordinate_range
Fix memory leak. Closes #4218 Closes postgis#324 git-svn-id: http://svn.osgeo.org/postgis/trunk@16961 b70326c6-7e19-0410-871a-916f4a2858ee
1 parent 8b5b079 commit 1a4ab8d

File tree

2 files changed

+61
-99
lines changed

2 files changed

+61
-99
lines changed

liblwgeom/cunit/cu_algorithm.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -741,8 +741,7 @@ static void test_lwmline_clip(void)
741741

742742
/* Clip in the middle, mid-range. */
743743
c = lwgeom_clip_to_ordinate_range(mline, 'Y', 1.5, 2.5, 0);
744-
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
745-
//printf("c = %s\n", ewkt);
744+
ewkt = lwgeom_to_ewkt((LWGEOM *)c);
746745
ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
747746
lwfree(ewkt);
748747
lwcollection_free(c);
@@ -756,8 +755,7 @@ static void test_lwmline_clip(void)
756755

757756
/* Clip off the top. */
758757
c = lwgeom_clip_to_ordinate_range(mline, 'Y', 3.5, 5.5, 0);
759-
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
760-
//printf("c = %s\n", ewkt);
758+
ewkt = lwgeom_to_ewkt((LWGEOM *)c);
761759
ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))");
762760
lwfree(ewkt);
763761
lwcollection_free(c);
@@ -772,8 +770,7 @@ static void test_lwmline_clip(void)
772770

773771
/* Clip from 0 upwards.. */
774772
c = lwgeom_clip_to_ordinate_range(mline, 'Y', 0.0, 2.5, 0);
775-
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
776-
//printf("c = %s\n", ewkt);
773+
ewkt = lwgeom_to_ewkt((LWGEOM *)c);
777774
ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))");
778775
lwfree(ewkt);
779776
lwcollection_free(c);
@@ -788,33 +785,29 @@ static void test_lwmline_clip(void)
788785

789786
/* Clip from 3 to 3.5 */
790787
c = lwgeom_clip_to_ordinate_range(line, 'Z', 3.0, 3.5, 0);
791-
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
792-
//printf("c = %s\n", ewkt);
788+
ewkt = lwgeom_to_ewkt((LWGEOM *)c);
793789
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))");
794790
lwfree(ewkt);
795791
lwcollection_free(c);
796792

797793
/* Clip from 2 to 3.5 */
798794
c = lwgeom_clip_to_ordinate_range(line, 'Z', 2.0, 3.5, 0);
799-
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
800-
//printf("c = %s\n", ewkt);
795+
ewkt = lwgeom_to_ewkt((LWGEOM *)c);
801796
ASSERT_STRING_EQUAL(ewkt,
802797
"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))");
803798
lwfree(ewkt);
804799
lwcollection_free(c);
805800

806801
/* Clip from 3 to 4 */
807802
c = lwgeom_clip_to_ordinate_range(line, 'Z', 3.0, 4.0, 0);
808-
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
809-
//printf("c = %s\n", ewkt);
803+
ewkt = lwgeom_to_ewkt((LWGEOM *)c);
810804
ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,4 4 4 4,3 3 3 5))");
811805
lwfree(ewkt);
812806
lwcollection_free(c);
813807

814808
/* Clip from 2 to 3 */
815809
c = lwgeom_clip_to_ordinate_range(line, 'Z', 2.0, 3.0, 0);
816-
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
817-
//printf("c = %s\n", ewkt);
810+
ewkt = lwgeom_to_ewkt((LWGEOM *)c);
818811
ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3),(3 3 3 5,2 2 2 6))");
819812
lwfree(ewkt);
820813
lwcollection_free(c);

liblwgeom/lwlinearreferencing.c

Lines changed: 54 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,6 @@ ptarray_clamp_to_ordinate_range(const POINTARRAY *ipa, char ordinate, double fro
541541
static inline LWCOLLECTION *
542542
lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to)
543543
{
544-
545544
POINTARRAY *pa_in = NULL;
546545
LWCOLLECTION *lwgeom_out = NULL;
547546
POINTARRAY *dp = NULL;
@@ -551,22 +550,15 @@ lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, do
551550
double ordinate_value_p = 0.0, ordinate_value_q = 0.0;
552551
char hasz, hasm;
553552
char dims;
554-
#if POSTGIS_DEBUG_LEVEL >= 4
555-
char *geom_ewkt;
556-
#endif
557553

558554
/* Null input, nothing we can do. */
559-
if ( ! line )
560-
{
561-
lwerror("Null input geometry.");
562-
return NULL;
563-
}
555+
assert(line);
564556
hasz = lwgeom_has_z(lwline_as_lwgeom(line));
565557
hasm = lwgeom_has_m(lwline_as_lwgeom(line));
566558
dims = FLAGS_NDIMS(line->flags);
567559

568560
/* Asking for an ordinate we don't have. Error. */
569-
if ( (ordinate == 'Z' && ! hasz) || (ordinate == 'M' && ! hasm) )
561+
if ((ordinate == 'Z' && !hasz) || (ordinate == 'M' && !hasm))
570562
{
571563
lwerror("Cannot clip on ordinate %d in a %d-d geometry.", ordinate, dims);
572564
return NULL;
@@ -583,93 +575,81 @@ lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, do
583575
/* Get our input point array */
584576
pa_in = line->points;
585577

586-
for ( i = 0; i < pa_in->npoints; i++ )
578+
for (i = 0; i < pa_in->npoints; i++)
587579
{
588-
LWDEBUGF(4, "Point #%d", i);
589-
LWDEBUGF(4, "added_last_point %d", added_last_point);
590-
if ( i > 0 )
580+
if (i > 0)
591581
{
592582
*q = *p;
593583
ordinate_value_q = ordinate_value_p;
594584
}
595585
getPoint4d_p(pa_in, i, p);
596586
ordinate_value_p = lwpoint_get_ordinate(p, ordinate);
597-
LWDEBUGF(4, " ordinate_value_p %g (current)", ordinate_value_p);
598-
LWDEBUGF(4, " ordinate_value_q %g (previous)", ordinate_value_q);
599587

600588
/* Is this point inside the ordinate range? Yes. */
601-
if ( ordinate_value_p >= from && ordinate_value_p <= to )
589+
if (ordinate_value_p >= from && ordinate_value_p <= to)
602590
{
603-
LWDEBUGF(4, " inside ordinate range (%g, %g)", from, to);
604591

605592
if ( ! added_last_point )
606593
{
607-
LWDEBUG(4," new ptarray required");
608594
/* We didn't add the previous point, so this is a new segment.
609-
* Make a new point array. */
595+
* Make a new point array. */
610596
dp = ptarray_construct_empty(hasz, hasm, 32);
611597

612598
/* We're transiting into the range so add an interpolated
613-
* point at the range boundary.
614-
* If we're on a boundary and crossing from the far side,
615-
* we also need an interpolated point. */
616-
if ( i > 0 && ( /* Don't try to interpolate if this is the first point */
617-
( ordinate_value_p > from && ordinate_value_p < to ) || /* Inside */
618-
( ordinate_value_p == from && ordinate_value_q > to ) || /* Hopping from above */
619-
( ordinate_value_p == to && ordinate_value_q < from ) ) ) /* Hopping from below */
599+
* point at the range boundary.
600+
* If we're on a boundary and crossing from the far side,
601+
* we also need an interpolated point. */
602+
if (i > 0 &&
603+
(/* Don't try to interpolate if this is the first point */
604+
(ordinate_value_p > from && ordinate_value_p < to) || /* Inside */
605+
(ordinate_value_p == from && ordinate_value_q > to) || /* Hopping from above */
606+
(ordinate_value_p == to && ordinate_value_q < from))) /* Hopping from below */
620607
{
621608
double interpolation_value;
622-
(ordinate_value_q > to) ? (interpolation_value = to) : (interpolation_value = from);
609+
(ordinate_value_q > to) ? (interpolation_value = to)
610+
: (interpolation_value = from);
623611
point_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
624612
ptarray_append_point(dp, r, LW_FALSE);
625-
LWDEBUGF(4, "[0] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
626613
}
627614
}
628615
/* Add the current vertex to the point array. */
629616
ptarray_append_point(dp, p, LW_FALSE);
630-
if ( ordinate_value_p == from || ordinate_value_p == to )
631-
{
617+
if (ordinate_value_p == from || ordinate_value_p == to)
632618
added_last_point = 2; /* Added on boundary. */
633-
}
634619
else
635-
{
636620
added_last_point = 1; /* Added inside range. */
637-
}
638621
}
639622
/* Is this point inside the ordinate range? No. */
640623
else
641624
{
642-
LWDEBUGF(4, " added_last_point (%d)", added_last_point);
643-
if ( added_last_point == 1 )
625+
if (added_last_point == 1)
644626
{
645627
/* We're transiting out of the range, so add an interpolated point
646-
* to the point array at the range boundary. */
628+
* to the point array at the range boundary. */
647629
double interpolation_value;
648630
(ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
649631
point_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
650632
ptarray_append_point(dp, r, LW_FALSE);
651-
LWDEBUGF(4, " [1] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
652633
}
653-
else if ( added_last_point == 2 )
634+
else if (added_last_point == 2)
654635
{
655636
/* We're out and the last point was on the boundary.
656-
* If the last point was the near boundary, nothing to do.
657-
* If it was the far boundary, we need an interpolated point. */
658-
if ( from != to && (
659-
(ordinate_value_q == from && ordinate_value_p > from) ||
660-
(ordinate_value_q == to && ordinate_value_p < to) ) )
637+
* If the last point was the near boundary, nothing to do.
638+
* If it was the far boundary, we need an interpolated point. */
639+
if (from != to && ((ordinate_value_q == from && ordinate_value_p > from) ||
640+
(ordinate_value_q == to && ordinate_value_p < to)))
661641
{
662642
double interpolation_value;
663-
(ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
643+
(ordinate_value_p > to) ? (interpolation_value = to)
644+
: (interpolation_value = from);
664645
point_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
665646
ptarray_append_point(dp, r, LW_FALSE);
666-
LWDEBUGF(4, " [2] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
667647
}
668648
}
669-
else if ( i && ordinate_value_q < from && ordinate_value_p > to )
649+
else if (i && ordinate_value_q < from && ordinate_value_p > to)
670650
{
671651
/* We just hopped over the whole range, from bottom to top,
672-
* so we need to add *two* interpolated points! */
652+
* so we need to add *two* interpolated points! */
673653
dp = ptarray_construct(hasz, hasm, 2);
674654
/* Interpolate lower point. */
675655
point_interpolate(p, q, r, hasz, hasm, ordinate, from);
@@ -678,10 +658,10 @@ lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, do
678658
point_interpolate(p, q, r, hasz, hasm, ordinate, to);
679659
ptarray_set_point4d(dp, 1, r);
680660
}
681-
else if ( i && ordinate_value_q > to && ordinate_value_p < from )
661+
else if (i && ordinate_value_q > to && ordinate_value_p < from)
682662
{
683663
/* We just hopped over the whole range, from top to bottom,
684-
* so we need to add *two* interpolated points! */
664+
* so we need to add *two* interpolated points! */
685665
dp = ptarray_construct(hasz, hasm, 2);
686666
/* Interpolate upper point. */
687667
point_interpolate(p, q, r, hasz, hasm, ordinate, to);
@@ -691,18 +671,15 @@ lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, do
691671
ptarray_set_point4d(dp, 1, r);
692672
}
693673
/* We have an extant point-array, save it out to a multi-line. */
694-
if ( dp )
674+
if (dp)
695675
{
696-
LWDEBUG(4, "saving pointarray to multi-line (1)");
697-
698676
/* Only one point, so we have to make an lwpoint to hold this
699-
* and set the overall output type to a generic collection. */
700-
if ( dp->npoints == 1 )
677+
* and set the overall output type to a generic collection. */
678+
if (dp->npoints == 1)
701679
{
702680
LWPOINT *opoint = lwpoint_construct(line->srid, NULL, dp);
703681
lwgeom_out->type = COLLECTIONTYPE;
704682
lwgeom_out = lwcollection_add_lwgeom(lwgeom_out, lwpoint_as_lwgeom(opoint));
705-
706683
}
707684
else
708685
{
@@ -714,39 +691,33 @@ lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, do
714691
dp = NULL;
715692
}
716693
added_last_point = 0;
717-
718694
}
719695
}
720696

721697
/* Still some points left to be saved out. */
722-
if ( dp && dp->npoints > 0 )
698+
if (dp)
723699
{
724-
LWDEBUG(4, "saving pointarray to multi-line (2)");
725-
LWDEBUGF(4, "dp->npoints == %d", dp->npoints);
726-
LWDEBUGF(4, "lwgeom_out->ngeoms == %d", lwgeom_out->ngeoms);
727-
728-
if ( dp->npoints == 1 )
700+
if (dp->npoints == 1)
729701
{
730702
LWPOINT *opoint = lwpoint_construct(line->srid, NULL, dp);
731703
lwgeom_out->type = COLLECTIONTYPE;
732704
lwgeom_out = lwcollection_add_lwgeom(lwgeom_out, lwpoint_as_lwgeom(opoint));
733705
}
734-
else
706+
else if (dp->npoints > 1)
735707
{
736708
LWLINE *oline = lwline_construct(line->srid, NULL, dp);
737709
lwgeom_out = lwcollection_add_lwgeom(lwgeom_out, lwline_as_lwgeom(oline));
738710
}
739-
740-
/* Pointarray is now owned by lwgeom_out, so drop reference to it */
741-
dp = NULL;
711+
else
712+
ptarray_free(dp);
742713
}
743714

744715
lwfree(p);
745716
lwfree(q);
746717
lwfree(r);
747718

748719
if (line->bbox && lwgeom_out->ngeoms > 0)
749-
lwgeom_refresh_bbox((LWGEOM*)lwgeom_out);
720+
lwgeom_refresh_bbox((LWGEOM *)lwgeom_out);
750721

751722
return lwgeom_out;
752723
}
@@ -826,22 +797,9 @@ lwtriangle_clip_to_ordinate_range(const LWTRIANGLE *tri, char ordinate, double f
826797
static inline LWCOLLECTION *
827798
lwcollection_clip_to_ordinate_range(const LWCOLLECTION *icol, char ordinate, double from, double to)
828799
{
829-
LWCOLLECTION *lwgeom_out = NULL;
830-
831-
if (!icol)
832-
{
833-
lwerror("Null input geometry.");
834-
return NULL;
835-
}
836-
837-
/* Ensure 'from' is less than 'to'. */
838-
if (to < from)
839-
{
840-
double t = from;
841-
from = to;
842-
to = t;
843-
}
800+
LWCOLLECTION *lwgeom_out;
844801

802+
assert(icol);
845803
if (icol->ngeoms == 1)
846804
lwgeom_out = lwgeom_clip_to_ordinate_range(icol->geoms[0], ordinate, from, to, 0);
847805
else
@@ -861,12 +819,15 @@ lwcollection_clip_to_ordinate_range(const LWCOLLECTION *icol, char ordinate, dou
861819
if (col->type != icol->type)
862820
lwgeom_out->type = COLLECTIONTYPE;
863821
lwgeom_out = lwcollection_concat_in_place(lwgeom_out, col);
822+
lwfree(col->geoms);
864823
lwcollection_release(col);
865824
}
866825
}
867-
if (icol->bbox)
868-
lwgeom_refresh_bbox((LWGEOM *)lwgeom_out);
869826
}
827+
828+
if (icol->bbox)
829+
lwgeom_refresh_bbox((LWGEOM *)lwgeom_out);
830+
870831
return lwgeom_out;
871832
}
872833

@@ -877,6 +838,14 @@ lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, do
877838
LWCOLLECTION *out_offset;
878839
uint32_t i;
879840

841+
/* Ensure 'from' is less than 'to'. */
842+
if (to < from)
843+
{
844+
double t = from;
845+
from = to;
846+
to = t;
847+
}
848+
880849
if ( ! lwin )
881850
lwerror("lwgeom_clip_to_ordinate_range: null input geometry!");
882851

0 commit comments

Comments
 (0)