Skip to content

Commit 619bce0

Browse files
committed
ST_LocateBetween[Elevations]: Support GEOMETRYCOLLECTION
References #4155 git-svn-id: http://svn.osgeo.org/postgis/trunk@16949 b70326c6-7e19-0410-871a-916f4a2858ee
1 parent aad8424 commit 619bce0

File tree

10 files changed

+106
-106
lines changed

10 files changed

+106
-106
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ PostGIS 3.0.0
2727
Praliaskouski)
2828
- #3457, Fix raster envelope shortcut in ST_Clip (Sai-bot)
2929
- #4215, Use floating point compare in ST_DumpAsPolygons (Darafei Praliaskouski)
30+
- #4155, Support for GEOMETRYCOLLECTION in ST_LocateBetween (Darafei
31+
Praliaskouski)
3032

3133
PostGIS 2.5.0
3234
2018/09/23

configure.ac

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,11 @@ AC_SUBST([PICFLAGS])
6060

6161
AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-math-errno], [_cv_nomatherrno], [-fno-math-errno], [], [CFLAGS="$CFLAGS -fno-math-errno"], [])
6262
AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-signed-zeros], [_cv_nosignedzeros], [-fno-signed-zeros], [], [CFLAGS="$CFLAGS -fno-signed-zeros"], [])
63+
AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fopenmp], [_cv_openmp], [-fopenmp], [], [CFLAGS="$CFLAGS -fopenmp"], [])
64+
AC_LIBTOOL_LINKER_OPTION([if $compiler supports -fopenmp], [_cv_openmp], [-fopenmp], [], [LDFLAGS="-fopenmp $LDFLAGS"], [])
6365
AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -std=gnu99], [_cv_std], -std=gnu99, [], [CFLAGS="-std=gnu99 $CFLAGS"], [])
6466

67+
6568
dnl
6669
dnl For GCC enable additional warning flags -Wall and -Wmissing-prototypes (using macro included with libtool)
6770
dnl

liblwgeom/cunit/cu_algorithm.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ static void test_lwmline_clip(void)
665665
mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
666666

667667
/* Clip in the middle, mid-range. */
668-
c = lwmline_clip_to_ordinate_range(mline, 'Y', 1.5, 2.5);
668+
c = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)mline, 'Y', 1.5, 2.5);
669669
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
670670
//printf("c = %s\n", ewkt);
671671
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
@@ -680,7 +680,7 @@ static void test_lwmline_clip(void)
680680
mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 1,1 2,1 3,1 4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
681681

682682
/* Clip off the top. */
683-
c = lwmline_clip_to_ordinate_range(mline, 'Y', 3.5, 5.5);
683+
c = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)mline, 'Y', 3.5, 5.5);
684684
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
685685
//printf("c = %s\n", ewkt);
686686
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))");
@@ -695,7 +695,7 @@ static void test_lwmline_clip(void)
695695
mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 -1,1 -2,1 -3,1 -4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
696696

697697
/* Clip from 0 upwards.. */
698-
c = lwmline_clip_to_ordinate_range(mline, 'Y', 0.0, 2.5);
698+
c = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)mline, 'Y', 0.0, 2.5);
699699
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
700700
//printf("c = %s\n", ewkt);
701701
CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))");

liblwgeom/liblwgeom_internal.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,9 @@ int point_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int hasz
240240
LWCOLLECTION *lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to);
241241

242242
/**
243-
* Clip a multi-line based on the from/to range of one of its ordinates. Use for m- and z- clipping
244-
*/
245-
LWCOLLECTION *lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to);
243+
* Clip collection based on the from/to range of one of its ordinates. Use for m- and z- clipping
244+
*/
245+
LWCOLLECTION *lwcollection_clip_to_ordinate_range(const LWCOLLECTION *col, char ordinate, double from, double to);
246246

247247
/**
248248
* Clip a multi-point based on the from/to range of one of its ordinates. Use for m- and z- clipping

liblwgeom/lwgeom.c

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,22 +2190,29 @@ lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid)
21902190

21912191

21922192
/* Prototype for recursion */
2193-
static int lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxvertices, uint32_t depth, LWCOLLECTION *col);
2194-
2195-
static int
2196-
lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxvertices, uint32_t depth, LWCOLLECTION *col)
2193+
static void lwgeom_subdivide_recursive(const LWGEOM *geom,
2194+
uint8_t dimension,
2195+
uint32_t maxvertices,
2196+
uint32_t depth,
2197+
LWCOLLECTION *col);
2198+
2199+
static void
2200+
lwgeom_subdivide_recursive(const LWGEOM *geom,
2201+
uint8_t dimension,
2202+
uint32_t maxvertices,
2203+
uint32_t depth,
2204+
LWCOLLECTION *col)
21972205
{
21982206
const uint32_t maxdepth = 50;
21992207
GBOX clip, subbox1, subbox2;
22002208
uint32_t nvertices = 0;
2201-
uint32_t i, n = 0;
2209+
uint32_t i;
22022210
uint32_t split_ordinate;
22032211
double width;
22042212
double height;
22052213
double pivot = DBL_MAX;
22062214
double center = DBL_MAX;
22072215
LWPOLY *lwpoly = NULL;
2208-
LWGEOM *clipped;
22092216

22102217
gbox_duplicate(lwgeom_get_bbox(geom), &clip);
22112218
width = clip.xmax - clip.xmin;
@@ -2217,12 +2224,8 @@ lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxve
22172224
if ( width == 0.0 && height == 0.0 )
22182225
{
22192226
if ( geom->type == POINTTYPE && dimension == 0)
2220-
{
22212227
lwcollection_add_lwgeom(col, lwgeom_clone_deep(geom));
2222-
return 1;
2223-
}
2224-
else
2225-
return 0;
2228+
return;
22262229
}
22272230

22282231
if (width == 0.0)
@@ -2242,39 +2245,39 @@ lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxve
22422245
if ( lwgeom_is_collection(geom) && geom->type != MULTIPOINTTYPE )
22432246
{
22442247
LWCOLLECTION *incol = (LWCOLLECTION*)geom;
2245-
int n = 0;
22462248
/* Don't increment depth yet, since we aren't actually
22472249
* subdividing geometries yet */
22482250
for ( i = 0; i < incol->ngeoms; i++ )
2249-
n += lwgeom_subdivide_recursive(incol->geoms[i], dimension, maxvertices, depth, col);
2250-
return n;
2251+
lwgeom_subdivide_recursive(incol->geoms[i], dimension, maxvertices, depth, col);
2252+
return;
22512253
}
22522254

22532255
if (lwgeom_dimension(geom) < dimension)
22542256
{
22552257
/* We've hit a lower dimension object produced by clipping at
22562258
* a shallower recursion level. Ignore it. */
2257-
return 0;
2259+
return;
22582260
}
22592261

22602262
/* But don't go too far. 2^50 ~= 10^15, that's enough subdivision */
22612263
/* Just add what's left */
22622264
if ( depth > maxdepth )
22632265
{
22642266
lwcollection_add_lwgeom(col, lwgeom_clone_deep(geom));
2265-
return 1;
2267+
return;
22662268
}
22672269

22682270
nvertices = lwgeom_count_vertices(geom);
22692271

22702272
/* Skip empties entirely */
2271-
if (nvertices == 0) return 0;
2273+
if (nvertices == 0)
2274+
return;
22722275

22732276
/* If it is under the vertex tolerance, just add it, we're done */
22742277
if (nvertices <= maxvertices)
22752278
{
22762279
lwcollection_add_lwgeom(col, lwgeom_clone_deep(geom));
2277-
return 1;
2280+
return;
22782281
}
22792282

22802283
split_ordinate = (width > height) ? 0 : 1;
@@ -2339,27 +2342,43 @@ lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxve
23392342

23402343
++depth;
23412344

2342-
LWGEOM* subbox = (LWGEOM*) lwpoly_construct_envelope(geom->srid, subbox1.xmin, subbox1.ymin, subbox1.xmax, subbox1.ymax);
2343-
clipped = lwgeom_intersection(geom, subbox);
2344-
lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
2345-
lwgeom_free(subbox);
2346-
if (clipped)
2345+
LWCOLLECTION *col1 =
2346+
lwcollection_construct_empty(COLLECTIONTYPE, geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom));
2347+
LWCOLLECTION *col2 =
2348+
lwcollection_construct_empty(COLLECTIONTYPE, geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom));
2349+
//#pragma omp parallel sections
23472350
{
2348-
n += lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col);
2349-
lwgeom_free(clipped);
2350-
}
2351-
2352-
subbox = (LWGEOM*) lwpoly_construct_envelope(geom->srid, subbox2.xmin, subbox2.ymin, subbox2.xmax, subbox2.ymax);
2353-
clipped = lwgeom_intersection(geom, subbox);
2354-
lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
2355-
lwgeom_free(subbox);
2356-
if (clipped)
2357-
{
2358-
n += lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col);
2359-
lwgeom_free(clipped);
2351+
//#pragma omp section
2352+
{
2353+
LWGEOM *subbox = (LWGEOM *)lwpoly_construct_envelope(
2354+
geom->srid, subbox1.xmin, subbox1.ymin, subbox1.xmax, subbox1.ymax);
2355+
LWGEOM *clipped = lwgeom_intersection(geom, subbox);
2356+
lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
2357+
lwgeom_free(subbox);
2358+
if (clipped)
2359+
{
2360+
lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col1);
2361+
lwgeom_free(clipped);
2362+
}
2363+
}
2364+
//#pragma omp section
2365+
{
2366+
LWGEOM *subbox = (LWGEOM *)lwpoly_construct_envelope(
2367+
geom->srid, subbox2.xmin, subbox2.ymin, subbox2.xmax, subbox2.ymax);
2368+
LWGEOM *clipped = lwgeom_intersection(geom, subbox);
2369+
lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
2370+
lwgeom_free(subbox);
2371+
if (clipped)
2372+
{
2373+
lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col2);
2374+
lwgeom_free(clipped);
2375+
}
2376+
}
23602377
}
2361-
2362-
return n;
2378+
col = lwcollection_concat_in_place(col, col1);
2379+
lwcollection_release(col1);
2380+
col = lwcollection_concat_in_place(col, col2);
2381+
lwcollection_release(col2);
23632382
}
23642383

23652384
LWCOLLECTION *
@@ -2385,7 +2404,6 @@ lwgeom_subdivide(const LWGEOM *geom, uint32_t maxvertices)
23852404
return col;
23862405
}
23872406

2388-
23892407
int
23902408
lwgeom_is_trajectory(const LWGEOM *geom)
23912409
{

liblwgeom/lwlinearreferencing.c

Lines changed: 30 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -462,80 +462,45 @@ lwmpoint_clip_to_ordinate_range(const LWMPOINT *mpoint, char ordinate, double fr
462462
}
463463

464464
/**
465-
* Clip an input MULTILINESTRING between two values, on any ordinate input.
466-
*/
467-
LWCOLLECTION*
468-
lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to)
465+
* Clip an input COLLECTION between two values, on any ordinate input.
466+
*/
467+
LWCOLLECTION *
468+
lwcollection_clip_to_ordinate_range(const LWCOLLECTION *icol, char ordinate, double from, double to)
469469
{
470470
LWCOLLECTION *lwgeom_out = NULL;
471471

472-
if ( ! mline )
472+
if (!icol)
473473
{
474474
lwerror("Null input geometry.");
475475
return NULL;
476476
}
477477

478-
if ( mline->ngeoms == 1)
479-
{
480-
lwgeom_out = lwline_clip_to_ordinate_range(mline->geoms[0], ordinate, from, to);
481-
}
478+
if (icol->ngeoms == 1)
479+
lwgeom_out = lwgeom_clip_to_ordinate_range(icol->geoms[0], ordinate, from, to, 0);
482480
else
483481
{
484482
LWCOLLECTION *col;
485-
char hasz = lwgeom_has_z(lwmline_as_lwgeom(mline));
486-
char hasm = lwgeom_has_m(lwmline_as_lwgeom(mline));
487-
uint32_t i, j;
488-
char homogeneous = 1;
489-
size_t geoms_size = 0;
490-
lwgeom_out = lwcollection_construct_empty(MULTILINETYPE, mline->srid, hasz, hasm);
483+
char hasz = lwgeom_has_z(lwcollection_as_lwgeom(icol));
484+
char hasm = lwgeom_has_m(lwcollection_as_lwgeom(icol));
485+
uint32_t i;
486+
lwgeom_out = lwcollection_construct_empty(icol->type, icol->srid, hasz, hasm);
491487
FLAGS_SET_Z(lwgeom_out->flags, hasz);
492488
FLAGS_SET_M(lwgeom_out->flags, hasm);
493-
for ( i = 0; i < mline->ngeoms; i ++ )
489+
for (i = 0; i < icol->ngeoms; i++)
494490
{
495-
col = lwline_clip_to_ordinate_range(mline->geoms[i], ordinate, from, to);
496-
if ( col )
491+
col = lwgeom_clip_to_ordinate_range(icol->geoms[i], ordinate, from, to, 0);
492+
if (col)
497493
{
498-
/* Something was left after the clip. */
499-
if ( lwgeom_out->ngeoms + col->ngeoms > geoms_size )
500-
{
501-
geoms_size += 16;
502-
if ( lwgeom_out->geoms )
503-
{
504-
lwgeom_out->geoms = lwrealloc(lwgeom_out->geoms, geoms_size * sizeof(LWGEOM*));
505-
}
506-
else
507-
{
508-
lwgeom_out->geoms = lwalloc(geoms_size * sizeof(LWGEOM*));
509-
}
510-
}
511-
for ( j = 0; j < col->ngeoms; j++ )
512-
{
513-
lwgeom_out->geoms[lwgeom_out->ngeoms] = col->geoms[j];
514-
lwgeom_out->ngeoms++;
515-
}
516-
if ( col->type != mline->type )
517-
{
518-
homogeneous = 0;
519-
}
520-
/* Shallow free the struct, leaving the geoms behind. */
521-
if ( col->bbox ) lwfree(col->bbox);
522-
lwfree(col->geoms);
523-
lwfree(col);
494+
if (col->type != icol->type)
495+
lwgeom_out->type = COLLECTIONTYPE;
496+
lwgeom_out = lwcollection_concat_in_place(lwgeom_out, col);
497+
lwcollection_release(col);
524498
}
525499
}
526-
if ( lwgeom_out->bbox )
527-
{
528-
lwgeom_refresh_bbox((LWGEOM*)lwgeom_out);
529-
}
530-
531-
if ( ! homogeneous )
532-
{
533-
lwgeom_out->type = COLLECTIONTYPE;
534-
}
500+
if (lwgeom_out->bbox)
501+
lwgeom_refresh_bbox((LWGEOM *)lwgeom_out);
535502
}
536-
537503
return lwgeom_out;
538-
539504
}
540505

541506

@@ -789,18 +754,24 @@ lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, do
789754
case LINETYPE:
790755
out_col = lwline_clip_to_ordinate_range((LWLINE*)lwin, ordinate, from, to);
791756
break;
792-
case MULTILINETYPE:
793-
out_col = lwmline_clip_to_ordinate_range((LWMLINE*)lwin, ordinate, from, to);
794-
break;
795757
case MULTIPOINTTYPE:
796758
out_col = lwmpoint_clip_to_ordinate_range((LWMPOINT*)lwin, ordinate, from, to);
797759
break;
798760
case POINTTYPE:
799761
out_col = lwpoint_clip_to_ordinate_range((LWPOINT*)lwin, ordinate, from, to);
800762
break;
763+
// case TRIANGLETYPE:
764+
// out_col = lwtriangle_clip_to_ordinate_range((LWTRIANGLE*)lwin, ordinate, from, to);
765+
// break;
766+
case TINTYPE:
767+
case MULTILINETYPE:
768+
case MULTIPOLYGONTYPE:
769+
case COLLECTIONTYPE:
770+
out_col = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)lwin, ordinate, from, to);
771+
break;
801772
default:
802773
lwerror("This function does not accept %s geometries.", lwtype_name(lwin->type));
803-
return NULL;;
774+
return NULL;
804775
}
805776

806777
/* Stop if result is NULL */

postgis/geography_inout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ Datum geography_send(PG_FUNCTION_ARGS)
712712
result = palloc(size_result + VARHDRSZ);
713713
SET_VARSIZE(result, size_result + VARHDRSZ);
714714
memcpy(VARDATA(result), wkb, size_result);
715-
pfree(wkb);
715+
lwfree(wkb);
716716

717717
PG_RETURN_POINTER(result);
718718
}

postgis/lwgeom_functions_lrs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ Datum ST_LocateAlong(PG_FUNCTION_ARGS)
8585
GSERIALIZED *gout;
8686
LWGEOM *lwin = NULL, *lwout = NULL;
8787
double measure = PG_GETARG_FLOAT8(1);
88-
double offset = PG_GETARG_FLOAT8(2);;
88+
double offset = PG_GETARG_FLOAT8(2);
8989

9090
lwin = lwgeom_from_gserialized(gin);
9191
lwout = lwgeom_locate_along(lwin, measure, offset);
@@ -160,7 +160,7 @@ Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS)
160160

161161
if ( ! gserialized_has_z(geom_in) )
162162
{
163-
elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING with Z dimensions.");
163+
elog(ERROR, "This function only accepts geometries with Z dimensions.");
164164
PG_RETURN_NULL();
165165
}
166166

regress/core/regress_lrs.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ select '#3119a', ST_AsText(ST_LocateBetweenElevations('LINESTRING Z(0 0 0, 10 10
2929
-- Multilinestrings
3030
-- #3119 --
3131
select '#3119b', ST_AsText(ST_LocateBetweenElevations('MULTILINESTRING Z((0 0 0, 10 10 10))'::geometry, 11, 11));
32+
select '#4155.1', ST_AsText(ST_LocateBetweenElevations('GEOMETRYCOLLECTION(LINESTRING(0 0 0, 10 10 10))', 2, 5));
33+
select '#4155.2', ST_AsText(ST_LocateBetweenElevations('TIN Z EMPTY', 2, 5));
34+
select '#4155.3', ST_AsText(ST_LocateBetweenElevations('MULTIPOLYGON Z EMPTY', 2, 5));
3235

3336
--- line_locate_point
3437

0 commit comments

Comments
 (0)