]> granicus.if.org Git - postgis/commitdiff
Add support for linestrings in ST_MakeLine (#1500)
authorSandro Santilli <strk@keybit.net>
Thu, 26 Jan 2012 13:00:08 +0000 (13:00 +0000)
committerSandro Santilli <strk@keybit.net>
Thu, 26 Jan 2012 13:00:08 +0000 (13:00 +0000)
Affects both the aggregate and the 2-parameters function.
Regression testing included.
Documentation was updated, but lacks examples.

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

doc/reference_constructor.xml
postgis/lwgeom_functions_basic.c
regress/ctors.sql
regress/ctors_expected

index 5417f7d4d4033a22bf535a57964674acf8323f47..67eaf33beacd9e396850f513ae782c99e446f073 100644 (file)
@@ -1226,25 +1226,25 @@ BOX3D(-989502.1875 528439.5625 10,-987121.375 529933.1875 10)
                <refnamediv>
                <refname>ST_MakeLine</refname>
 
-               <refpurpose>Creates a Linestring from point geometries.</refpurpose>
+               <refpurpose>Creates a Linestring from point or line geometries.</refpurpose>
                </refnamediv>
 
                <refsynopsisdiv>
                <funcsynopsis>
                        <funcprototype>
                                <funcdef>geometry <function>ST_MakeLine</function></funcdef>
-                               <paramdef><type>geometry set</type> <parameter>pointfield</parameter></paramdef>
+                               <paramdef><type>geometry set</type> <parameter>geoms</parameter></paramdef>
                        </funcprototype>
 
                        <funcprototype>
                                <funcdef>geometry <function>ST_MakeLine</function></funcdef>
-                               <paramdef><type>geometry</type> <parameter>point1</parameter></paramdef>
-                               <paramdef><type>geometry</type> <parameter>point2</parameter></paramdef>
+                               <paramdef><type>geometry</type> <parameter>geom1</parameter></paramdef>
+                               <paramdef><type>geometry</type> <parameter>geom2</parameter></paramdef>
                        </funcprototype>
 
                        <funcprototype>
                                <funcdef>geometry <function>ST_MakeLine</function></funcdef>
-                               <paramdef><type>geometry[]</type> <parameter>point_array</parameter></paramdef>
+                               <paramdef><type>geometry[]</type> <parameter>geoms_array</parameter></paramdef>
                        </funcprototype>
                </funcsynopsis>
                </refsynopsisdiv>
@@ -1253,12 +1253,17 @@ BOX3D(-989502.1875 528439.5625 10,-987121.375 529933.1875 10)
                <title>Description</title>
 
                <para>ST_MakeLine comes in 3 forms: a spatial aggregate that takes
-                       rows of point geometries and returns a line string, a function that takes an array of points, and a regular function that takes two point geometries. You
+                       rows of point-or-line geometries and returns a line string, a function that takes an array of point-or-lines, and a regular function that takes two point-or-line geometries. You
                        might want to use a subselect to order points before feeding them
                        to  the aggregate version of this function.</para>
 
+               <para>
+                       When adding line components a common node is removed from the output.
+               </para>
+
                <para>&Z_support;</para>
                <para>Availability: 1.4.0 -  ST_MakeLine(geomarray) was introduced. ST_MakeLine aggregate functions was enhanced to handle more points faster.</para>
+               <para>Availability: 2.0.0 -  Support for linestring input elements was introduced</para>
                </refsection>
 
                <refsection>
@@ -1319,6 +1324,9 @@ SELECT ST_AsEWKT(ST_MakeLine(ARRAY[ST_MakePoint(1,2,3),
 LINESTRING(1 2 3,3 4 5,6 6 6)
                        </programlisting>
                </refsection>
+
+       <!-- TODO: add an example using lines -->
+
                <refsection>
                        <title>See Also</title>
                        <para><xref linkend="ST_AsEWKT" />, <xref linkend="ST_AsText" />, <xref linkend="ST_GeomFromText" />, <xref linkend="ST_MakePoint" /></para>
index a3680763fcf99651bfae729a8eee8578c7da8827..9fdfcc8f0762573f2e58167405fe2ca860e20bd9 100644 (file)
@@ -1326,9 +1326,9 @@ Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS)
        ArrayType *array;
        int nelems;
        GSERIALIZED *result=NULL;
-       LWPOINT **lwpoints;
+       LWGEOM **geoms;
        LWGEOM *outlwg;
-       uint32 npoints;
+       uint32 ngeoms;
        int i;
        size_t offset;
        int srid=SRID_UNKNOWN;
@@ -1367,13 +1367,13 @@ Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS)
 
        /*
         * Deserialize all point geometries in array into the
-        * lwpoints pointers array.
+        * geoms pointers array.
         * Count actual number of points.
         */
 
        /* possibly more then required */
-       lwpoints = palloc(sizeof(LWGEOM *)*nelems);
-       npoints = 0;
+       geoms = palloc(sizeof(LWGEOM *)*nelems);
+       ngeoms = 0;
        offset = 0;
        bitmap = ARR_NULLBITMAP(array);
        bitmask = 1;
@@ -1385,20 +1385,21 @@ Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS)
                        GSERIALIZED *geom = (GSERIALIZED *)(ARR_DATA_PTR(array)+offset);
                        offset += INTALIGN(VARSIZE(geom));
 
-                       if ( gserialized_get_type(geom) != POINTTYPE ) continue;
+                       if ( gserialized_get_type(geom) != POINTTYPE && gserialized_get_type(geom) != LINETYPE ) continue;
 
-                       lwpoints[npoints++] =
-                           lwgeom_as_lwpoint(lwgeom_from_gserialized(geom));
+                       geoms[ngeoms++] =
+                           lwgeom_from_gserialized(geom);
 
                        /* Check SRID homogeneity */
-                       if ( npoints == 1 )
+                       if ( ngeoms == 1 )
                        {
                                /* Get first geometry SRID */
-                               srid = lwpoints[npoints-1]->srid;
+                               srid = geoms[ngeoms-1]->srid;
+                               /* TODO: also get ZMflags */
                        }
                        else
                        {
-                               if ( lwpoints[npoints-1]->srid != srid )
+                               if ( geoms[ngeoms-1]->srid != srid )
                                {
                                        elog(ERROR,
                                             "Operation on mixed SRID geometries");
@@ -1422,15 +1423,16 @@ Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS)
        }
 
        /* Return null on 0-points input array */
-       if ( npoints == 0 )
+       if ( ngeoms == 0 )
        {
-               elog(NOTICE, "No points in input array");
+               /* TODO: should we return LINESTRING EMPTY here ? */
+               elog(NOTICE, "No points or linestrings in input array");
                PG_RETURN_NULL();
        }
 
-       POSTGIS_DEBUGF(3, "LWGEOM_makeline_garray: point elements: %d", npoints);
+       POSTGIS_DEBUGF(3, "LWGEOM_makeline_garray: elements: %d", ngeoms);
 
-       outlwg = (LWGEOM *)lwline_from_ptarray(srid, npoints, lwpoints);
+       outlwg = (LWGEOM *)lwline_from_lwgeom_array(srid, ngeoms, geoms);
 
        result = geometry_serialize(outlwg);
 
@@ -1446,7 +1448,7 @@ Datum LWGEOM_makeline(PG_FUNCTION_ARGS)
 {
        GSERIALIZED *pglwg1, *pglwg2;
        GSERIALIZED *result=NULL;
-       LWPOINT *lwpoints[2];
+       LWGEOM *lwgeoms[2];
        LWLINE *outline;
 
        POSTGIS_DEBUG(2, "LWGEOM_makeline called.");
@@ -1455,26 +1457,26 @@ Datum LWGEOM_makeline(PG_FUNCTION_ARGS)
        pglwg1 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
        pglwg2 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
 
-       if ( gserialized_get_type(pglwg1) != POINTTYPE ||
-            gserialized_get_type(pglwg2) != POINTTYPE )
+       if ( (gserialized_get_type(pglwg1) != POINTTYPE && gserialized_get_type(pglwg1) != LINETYPE) ||
+            (gserialized_get_type(pglwg2) != POINTTYPE && gserialized_get_type(pglwg2) != LINETYPE) )
        {
-               elog(ERROR, "Input geometries must be points");
+               elog(ERROR, "Input geometries must be points or lines");
                PG_RETURN_NULL();
        }
 
        error_if_srid_mismatch(gserialized_get_srid(pglwg1), gserialized_get_srid(pglwg2));
 
-       lwpoints[0] = lwgeom_as_lwpoint(lwgeom_from_gserialized(pglwg1));
-       lwpoints[1] = lwgeom_as_lwpoint(lwgeom_from_gserialized(pglwg2));
+       lwgeoms[0] = lwgeom_from_gserialized(pglwg1);
+       lwgeoms[1] = lwgeom_from_gserialized(pglwg2);
 
-       outline = lwline_from_ptarray(lwpoints[0]->srid, 2, lwpoints);
+       outline = lwline_from_lwgeom_array(lwgeoms[0]->srid, 2, lwgeoms);
 
        result = geometry_serialize((LWGEOM *)outline);
 
        PG_FREE_IF_COPY(pglwg1, 0);
        PG_FREE_IF_COPY(pglwg2, 1);
-       lwgeom_release((LWGEOM *)lwpoints[0]);
-       lwgeom_release((LWGEOM *)lwpoints[1]);
+       lwgeom_release((LWGEOM *)lwgeoms[0]);
+       lwgeom_release((LWGEOM *)lwgeoms[1]);
 
        PG_RETURN_POINTER(result);
 }
index da6f289d2db540cf16f31aa50e0c93af801acb1f..84084ebf73249a6dc1b6e26a237ec9373b687bf3 100644 (file)
@@ -7,6 +7,18 @@ SELECT ST_Collect('SRID=32749;POINT(0 0)', 'SRID=32740;POINT(1 1)');
 select ST_asewkt(ST_makeline('SRID=3;POINT(0 0)', 'SRID=3;POINT(1 1)'));
 select ST_makeline('POINT(0 0)', 'SRID=3;POINT(1 1)');
 
+select 'ST_MakeLine1', ST_AsText(ST_MakeLine(
+ 'POINT(0 0)'::geometry,
+ 'LINESTRING(1 1, 10 0)'::geometry
+));
+
+select 'ST_MakeLine_agg1', ST_AsText(ST_MakeLine(g)) from (
+ values ('POINT(0 0)'),
+        ('LINESTRING(1 1, 10 0)'),
+        ('LINESTRING(10 0, 20 20)'),
+        ('POINT(40 4)')
+) as foo(g);
+
 -- postgis-users/2006-July/012788.html
 select ST_makebox2d('SRID=3;POINT(0 0)', 'SRID=3;POINT(1 1)');
 select ST_makebox2d('POINT(0 0)', 'SRID=3;POINT(1 1)');
index 84ca34adabd42f96b941dcbcbfd645eaddfdd689..cbb39882c73878381ffdce0334d24a94d5aa71c3 100644 (file)
@@ -2,6 +2,8 @@
 ERROR:  Operation on mixed SRID geometries
 SRID=3;LINESTRING(0 0,1 1)
 ERROR:  Operation on mixed SRID geometries
+ST_MakeLine1|LINESTRING(0 0,1 1,10 0)
+ST_MakeLine_agg1|LINESTRING(0 0,1 1,10 0,20 20,40 4)
 BOX(0 0,1 1)
 ERROR:  Operation on mixed SRID geometries
 BOX3D(0 0 0,1 1 0)