]> granicus.if.org Git - postgis/commitdiff
ST_LocateBetween[Elevations]: Support GEOMETRYCOLLECTION
authorDarafei Praliaskouski <me@komzpa.net>
Wed, 24 Oct 2018 21:56:42 +0000 (21:56 +0000)
committerDarafei Praliaskouski <me@komzpa.net>
Wed, 24 Oct 2018 21:56:42 +0000 (21:56 +0000)
References #4155

git-svn-id: http://svn.osgeo.org/postgis/trunk@16949 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
configure.ac
liblwgeom/cunit/cu_algorithm.c
liblwgeom/liblwgeom_internal.h
liblwgeom/lwgeom.c
liblwgeom/lwlinearreferencing.c
postgis/geography_inout.c
postgis/lwgeom_functions_lrs.c
regress/core/regress_lrs.sql
regress/core/regress_lrs_expected

diff --git a/NEWS b/NEWS
index 82a24099eb91a17ccde34a15822902f3416e20ff..292fd421ddeedb9d75db72f75b8259beff6cd4a9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,8 @@ PostGIS 3.0.0
     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
index 88f6dbacc0e237fd3f8bc033957a8ee981676cc5..5369d6a929416d81b1d33e504e193f14549cccf0 100644 (file)
@@ -60,8 +60,11 @@ AC_SUBST([PICFLAGS])
 
 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
index 3e9741c6ba4a348639ffb511f0da9898db951a71..02d1812362fc0cb446a0a9f1efc21e8515db3bae 100644 (file)
@@ -665,7 +665,7 @@ static void test_lwmline_clip(void)
        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))");
@@ -680,7 +680,7 @@ static void test_lwmline_clip(void)
        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))");
@@ -695,7 +695,7 @@ static void test_lwmline_clip(void)
        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))");
index e92ba7974626f65e25ab136cd901c4145fc400bb..a8cba10032580601196a5a7d6cb638967c13e4b0 100644 (file)
@@ -240,9 +240,9 @@ int point_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int hasz
 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
index f632dabb7697933f331e34a5f6bcac4f166ea291..9ad889f4f700b9fc49291a4e2bda15e9acfdba9a 100644 (file)
@@ -2190,22 +2190,29 @@ lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid)
 
 
 /* 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;
@@ -2217,12 +2224,8 @@ lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxve
        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)
@@ -2242,19 +2245,18 @@ lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxve
        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 */
@@ -2262,19 +2264,20 @@ lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxve
        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;
@@ -2339,27 +2342,43 @@ lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxve
 
        ++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 *
@@ -2385,7 +2404,6 @@ lwgeom_subdivide(const LWGEOM *geom, uint32_t maxvertices)
        return col;
 }
 
-
 int
 lwgeom_is_trajectory(const LWGEOM *geom)
 {
index 6f627de209beee8e21459fc3495eca353cccf58b..3d9b8e99d05feda8a6ef5ab3284aa692da0fe01d 100644 (file)
@@ -462,80 +462,45 @@ lwmpoint_clip_to_ordinate_range(const LWMPOINT *mpoint, char ordinate, double fr
 }
 
 /**
-* 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;
-
 }
 
 
@@ -789,18 +754,24 @@ lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, do
        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 */
index 87a449f5be628068fa0509d7198790caed20db09..844e828d8bfa8f6d2219d375a34b69c7e89a1535 100644 (file)
@@ -712,7 +712,7 @@ Datum geography_send(PG_FUNCTION_ARGS)
        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);
 }
index d5170c3daf6747109d0bd3bd88bbe60b028b67c0..d6dac837ea45857b7e31817f827391754c4f75b4 100644 (file)
@@ -85,7 +85,7 @@ Datum ST_LocateAlong(PG_FUNCTION_ARGS)
        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);
@@ -160,7 +160,7 @@ Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS)
 
        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();
        }
 
index f504b9f702d2600f03d3460d6a2da66f0c85c2f8..b9aac3204aacb8c42c4761ec914c723b42a73354 100644 (file)
@@ -29,6 +29,9 @@ select '#3119a', ST_AsText(ST_LocateBetweenElevations('LINESTRING Z(0 0 0, 10 10
 -- 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
 
index b6a54268e997c6019340c6e76c063e0f2617396a..90b724f301b3fc6c1c41d2e72396ef24bcb5fef0 100644 (file)
@@ -17,6 +17,9 @@ LINEZM_5|MULTILINESTRING ZM ((0 9 90 2,0 1 10 18),(5.5 4.5 4.5 18,9.5 0.5 0.5 2)
 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