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 in ST_LocateBetween (Darafei
+ Praliaskouski)
PostGIS 2.5.0
2018/09/23
AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-math-errno], [_cv_nomatherrno], [-fno-math-errno], [], [CFLAGS="$CFLAGS -fno-math-errno"], [])
AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-signed-zeros], [_cv_nosignedzeros], [-fno-signed-zeros], [], [CFLAGS="$CFLAGS -fno-signed-zeros"], [])
+AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fopenmp], [_cv_openmp], [-fopenmp], [], [CFLAGS="$CFLAGS -fopenmp"], [])
+AC_LIBTOOL_LINKER_OPTION([if $compiler supports -fopenmp], [_cv_openmp], [-fopenmp], [], [LDFLAGS="-fopenmp $LDFLAGS"], [])
AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -std=gnu99], [_cv_std], -std=gnu99, [], [CFLAGS="-std=gnu99 $CFLAGS"], [])
+
dnl
dnl For GCC enable additional warning flags -Wall and -Wmissing-prototypes (using macro included with libtool)
dnl
mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
/* Clip in the middle, mid-range. */
- c = lwmline_clip_to_ordinate_range(mline, 'Y', 1.5, 2.5);
+ c = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)mline, 'Y', 1.5, 2.5);
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))");
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);
/* Clip off the top. */
- c = lwmline_clip_to_ordinate_range(mline, 'Y', 3.5, 5.5);
+ c = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)mline, 'Y', 3.5, 5.5);
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))");
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);
/* Clip from 0 upwards.. */
- c = lwmline_clip_to_ordinate_range(mline, 'Y', 0.0, 2.5);
+ c = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)mline, 'Y', 0.0, 2.5);
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))");
LWCOLLECTION *lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to);
/**
-* Clip a multi-line based on the from/to range of one of its ordinates. Use for m- and z- clipping
-*/
-LWCOLLECTION *lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to);
+ * Clip collection based on the from/to range of one of its ordinates. Use for m- and z- clipping
+ */
+LWCOLLECTION *lwcollection_clip_to_ordinate_range(const LWCOLLECTION *col, char ordinate, double from, double to);
/**
* Clip a multi-point based on the from/to range of one of its ordinates. Use for m- and z- clipping
/* Prototype for recursion */
-static int lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxvertices, uint32_t depth, LWCOLLECTION *col);
-
-static int
-lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxvertices, uint32_t depth, LWCOLLECTION *col)
+static void lwgeom_subdivide_recursive(const LWGEOM *geom,
+ uint8_t dimension,
+ uint32_t maxvertices,
+ uint32_t depth,
+ LWCOLLECTION *col);
+
+static void
+lwgeom_subdivide_recursive(const LWGEOM *geom,
+ uint8_t dimension,
+ uint32_t maxvertices,
+ uint32_t depth,
+ LWCOLLECTION *col)
{
const uint32_t maxdepth = 50;
GBOX clip, subbox1, subbox2;
uint32_t nvertices = 0;
- uint32_t i, n = 0;
+ uint32_t i;
uint32_t split_ordinate;
double width;
double height;
double pivot = DBL_MAX;
double center = DBL_MAX;
LWPOLY *lwpoly = NULL;
- LWGEOM *clipped;
gbox_duplicate(lwgeom_get_bbox(geom), &clip);
width = clip.xmax - clip.xmin;
if ( width == 0.0 && height == 0.0 )
{
if ( geom->type == POINTTYPE && dimension == 0)
- {
lwcollection_add_lwgeom(col, lwgeom_clone_deep(geom));
- return 1;
- }
- else
- return 0;
+ return;
}
if (width == 0.0)
if ( lwgeom_is_collection(geom) && geom->type != MULTIPOINTTYPE )
{
LWCOLLECTION *incol = (LWCOLLECTION*)geom;
- int n = 0;
/* Don't increment depth yet, since we aren't actually
* subdividing geometries yet */
for ( i = 0; i < incol->ngeoms; i++ )
- n += lwgeom_subdivide_recursive(incol->geoms[i], dimension, maxvertices, depth, col);
- return n;
+ lwgeom_subdivide_recursive(incol->geoms[i], dimension, maxvertices, depth, col);
+ return;
}
if (lwgeom_dimension(geom) < dimension)
{
/* We've hit a lower dimension object produced by clipping at
* a shallower recursion level. Ignore it. */
- return 0;
+ return;
}
/* But don't go too far. 2^50 ~= 10^15, that's enough subdivision */
if ( depth > maxdepth )
{
lwcollection_add_lwgeom(col, lwgeom_clone_deep(geom));
- return 1;
+ return;
}
nvertices = lwgeom_count_vertices(geom);
/* Skip empties entirely */
- if (nvertices == 0) return 0;
+ if (nvertices == 0)
+ return;
/* If it is under the vertex tolerance, just add it, we're done */
if (nvertices <= maxvertices)
{
lwcollection_add_lwgeom(col, lwgeom_clone_deep(geom));
- return 1;
+ return;
}
split_ordinate = (width > height) ? 0 : 1;
++depth;
- LWGEOM* subbox = (LWGEOM*) lwpoly_construct_envelope(geom->srid, subbox1.xmin, subbox1.ymin, subbox1.xmax, subbox1.ymax);
- clipped = lwgeom_intersection(geom, subbox);
- lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
- lwgeom_free(subbox);
- if (clipped)
+ LWCOLLECTION *col1 =
+ lwcollection_construct_empty(COLLECTIONTYPE, geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom));
+ LWCOLLECTION *col2 =
+ lwcollection_construct_empty(COLLECTIONTYPE, geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom));
+ //#pragma omp parallel sections
{
- n += lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col);
- lwgeom_free(clipped);
- }
-
- subbox = (LWGEOM*) lwpoly_construct_envelope(geom->srid, subbox2.xmin, subbox2.ymin, subbox2.xmax, subbox2.ymax);
- clipped = lwgeom_intersection(geom, subbox);
- lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
- lwgeom_free(subbox);
- if (clipped)
- {
- n += lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col);
- lwgeom_free(clipped);
+ //#pragma omp section
+ {
+ LWGEOM *subbox = (LWGEOM *)lwpoly_construct_envelope(
+ geom->srid, subbox1.xmin, subbox1.ymin, subbox1.xmax, subbox1.ymax);
+ LWGEOM *clipped = lwgeom_intersection(geom, subbox);
+ lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
+ lwgeom_free(subbox);
+ if (clipped)
+ {
+ lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col1);
+ lwgeom_free(clipped);
+ }
+ }
+ //#pragma omp section
+ {
+ LWGEOM *subbox = (LWGEOM *)lwpoly_construct_envelope(
+ geom->srid, subbox2.xmin, subbox2.ymin, subbox2.xmax, subbox2.ymax);
+ LWGEOM *clipped = lwgeom_intersection(geom, subbox);
+ lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
+ lwgeom_free(subbox);
+ if (clipped)
+ {
+ lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col2);
+ lwgeom_free(clipped);
+ }
+ }
}
-
- return n;
+ col = lwcollection_concat_in_place(col, col1);
+ lwcollection_release(col1);
+ col = lwcollection_concat_in_place(col, col2);
+ lwcollection_release(col2);
}
LWCOLLECTION *
return col;
}
-
int
lwgeom_is_trajectory(const LWGEOM *geom)
{
}
/**
-* Clip an input MULTILINESTRING between two values, on any ordinate input.
-*/
-LWCOLLECTION*
-lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to)
+ * Clip an input COLLECTION between two values, on any ordinate input.
+ */
+LWCOLLECTION *
+lwcollection_clip_to_ordinate_range(const LWCOLLECTION *icol, char ordinate, double from, double to)
{
LWCOLLECTION *lwgeom_out = NULL;
- if ( ! mline )
+ if (!icol)
{
lwerror("Null input geometry.");
return NULL;
}
- if ( mline->ngeoms == 1)
- {
- lwgeom_out = lwline_clip_to_ordinate_range(mline->geoms[0], ordinate, from, to);
- }
+ if (icol->ngeoms == 1)
+ lwgeom_out = lwgeom_clip_to_ordinate_range(icol->geoms[0], ordinate, from, to, 0);
else
{
LWCOLLECTION *col;
- char hasz = lwgeom_has_z(lwmline_as_lwgeom(mline));
- char hasm = lwgeom_has_m(lwmline_as_lwgeom(mline));
- uint32_t i, j;
- char homogeneous = 1;
- size_t geoms_size = 0;
- lwgeom_out = lwcollection_construct_empty(MULTILINETYPE, mline->srid, hasz, hasm);
+ char hasz = lwgeom_has_z(lwcollection_as_lwgeom(icol));
+ char hasm = lwgeom_has_m(lwcollection_as_lwgeom(icol));
+ uint32_t i;
+ lwgeom_out = lwcollection_construct_empty(icol->type, icol->srid, hasz, hasm);
FLAGS_SET_Z(lwgeom_out->flags, hasz);
FLAGS_SET_M(lwgeom_out->flags, hasm);
- for ( i = 0; i < mline->ngeoms; i ++ )
+ for (i = 0; i < icol->ngeoms; i++)
{
- col = lwline_clip_to_ordinate_range(mline->geoms[i], ordinate, from, to);
- if ( col )
+ col = lwgeom_clip_to_ordinate_range(icol->geoms[i], ordinate, from, to, 0);
+ if (col)
{
- /* Something was left after the clip. */
- if ( lwgeom_out->ngeoms + col->ngeoms > geoms_size )
- {
- geoms_size += 16;
- if ( lwgeom_out->geoms )
- {
- lwgeom_out->geoms = lwrealloc(lwgeom_out->geoms, geoms_size * sizeof(LWGEOM*));
- }
- else
- {
- lwgeom_out->geoms = lwalloc(geoms_size * sizeof(LWGEOM*));
- }
- }
- for ( j = 0; j < col->ngeoms; j++ )
- {
- lwgeom_out->geoms[lwgeom_out->ngeoms] = col->geoms[j];
- lwgeom_out->ngeoms++;
- }
- if ( col->type != mline->type )
- {
- homogeneous = 0;
- }
- /* Shallow free the struct, leaving the geoms behind. */
- if ( col->bbox ) lwfree(col->bbox);
- lwfree(col->geoms);
- lwfree(col);
+ if (col->type != icol->type)
+ lwgeom_out->type = COLLECTIONTYPE;
+ lwgeom_out = lwcollection_concat_in_place(lwgeom_out, col);
+ lwcollection_release(col);
}
}
- if ( lwgeom_out->bbox )
- {
- lwgeom_refresh_bbox((LWGEOM*)lwgeom_out);
- }
-
- if ( ! homogeneous )
- {
- lwgeom_out->type = COLLECTIONTYPE;
- }
+ if (lwgeom_out->bbox)
+ lwgeom_refresh_bbox((LWGEOM *)lwgeom_out);
}
-
return lwgeom_out;
-
}
case LINETYPE:
out_col = lwline_clip_to_ordinate_range((LWLINE*)lwin, ordinate, from, to);
break;
- case MULTILINETYPE:
- out_col = lwmline_clip_to_ordinate_range((LWMLINE*)lwin, ordinate, from, to);
- break;
case MULTIPOINTTYPE:
out_col = lwmpoint_clip_to_ordinate_range((LWMPOINT*)lwin, ordinate, from, to);
break;
case POINTTYPE:
out_col = lwpoint_clip_to_ordinate_range((LWPOINT*)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:
+ case COLLECTIONTYPE:
+ out_col = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)lwin, ordinate, from, to);
+ break;
default:
lwerror("This function does not accept %s geometries.", lwtype_name(lwin->type));
- return NULL;;
+ return NULL;
}
/* Stop if result is NULL */
result = palloc(size_result + VARHDRSZ);
SET_VARSIZE(result, size_result + VARHDRSZ);
memcpy(VARDATA(result), wkb, size_result);
- pfree(wkb);
+ lwfree(wkb);
PG_RETURN_POINTER(result);
}
GSERIALIZED *gout;
LWGEOM *lwin = NULL, *lwout = NULL;
double measure = PG_GETARG_FLOAT8(1);
- double offset = PG_GETARG_FLOAT8(2);;
+ double offset = PG_GETARG_FLOAT8(2);
lwin = lwgeom_from_gserialized(gin);
lwout = lwgeom_locate_along(lwin, measure, offset);
if ( ! gserialized_has_z(geom_in) )
{
- elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING with Z dimensions.");
+ elog(ERROR, "This function only accepts geometries with Z dimensions.");
PG_RETURN_NULL();
}
-- Multilinestrings
-- #3119 --
select '#3119b', ST_AsText(ST_LocateBetweenElevations('MULTILINESTRING Z((0 0 0, 10 10 10))'::geometry, 11, 11));
+select '#4155.1', ST_AsText(ST_LocateBetweenElevations('GEOMETRYCOLLECTION(LINESTRING(0 0 0, 10 10 10))', 2, 5));
+select '#4155.2', ST_AsText(ST_LocateBetweenElevations('TIN Z EMPTY', 2, 5));
+select '#4155.3', ST_AsText(ST_LocateBetweenElevations('MULTIPOLYGON Z EMPTY', 2, 5));
--- line_locate_point
LINEZM_6|MULTIPOINT ZM (9.5 0.5 0.5 2)
#3119a|MULTILINESTRING Z EMPTY
#3119b|MULTILINESTRING Z EMPTY
+#4155.1|MULTILINESTRING Z ((2 2 2,5 5 5))
+#4155.2|TIN Z EMPTY
+#4155.3|MULTIPOLYGON Z EMPTY
line_locate_point_1|0.528602749909894
line_locate_point_2|1
line_locate_point_3|0