]> granicus.if.org Git - postgis/commitdiff
Added makeline() aggregate and make_lwline() API method.
authorSandro Santilli <strk@keybit.net>
Fri, 15 Oct 2004 11:42:36 +0000 (11:42 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 15 Oct 2004 11:42:36 +0000 (11:42 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@1008 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/liblwgeom.h
lwgeom/lwgeom.h
lwgeom/lwgeom_functions_basic.c
lwgeom/lwline.c
lwgeom/lwpostgis.sql.in
lwgeom/ptarray.c

index 2e0fe83115fb5434a87de362e0e64577ef4265c4..72c2156474c0b565dbfd32aea7a3ddfa237ee3f9 100644 (file)
@@ -990,6 +990,7 @@ extern LWPOINT *make_lwpoint2d(int SRID, double x, double y);
 extern LWPOINT *make_lwpoint3dz(int SRID, double x, double y, double z);
 extern LWPOINT *make_lwpoint3dm(int SRID, double x, double y, double m);
 extern LWPOINT *make_lwpoint4d(int SRID, double x, double y, double z, double m);
+extern LWLINE *make_lwline(int SRID, unsigned int npoints, LWPOINT **points);
 
 // Return a char string with ASCII versionf of type flags
 extern const char *lwgeom_typeflags(unsigned char type);
@@ -997,6 +998,9 @@ extern const char *lwgeom_typeflags(unsigned char type);
 // Construct an empty pointarray
 extern POINTARRAY *ptarray_construct(char hasz, char hasm, unsigned int npoints);
 extern POINTARRAY *ptarray_construct2d(uint32 npoints, const POINT2D *pts);
+extern POINTARRAY *ptarray_construct3dz(uint32 npoints, const POINT3DZ *pts);
+extern POINTARRAY *ptarray_construct3dm(uint32 npoints, const POINT3DM *pts);
+extern POINTARRAY *ptarray_construct4d(uint32 npoints, const POINT4D *pts);
 
 extern int32 lwgeom_nrings_recursive(char *serialized);
 extern void dump_lwexploded(LWGEOM_EXPLODED *exploded);
index 55590be1d8317abf4a84a58f50bee43650d66790..30e99272345962e0fb54f53a4d99a9136617ae30 100644 (file)
@@ -38,6 +38,7 @@ extern LWGEOM make_lwpoint2d(int SRID, double x, double y);
 extern LWGEOM make_lwpoint3dz(int SRID, double x, double y, double z);
 extern LWGEOM make_lwpoint3dm(int SRID, double x, double y, double m);
 extern LWGEOM make_lwpoint4d(int SRID, double x, double y, double z, double m);
+extern LWGEOM make_lwline(int SRID, unsigned int npoints, LWGEOM *points);
 
 // Spatial functions
 extern void lwgeom_reverse(LWGEOM lwgeom);
index f2f5e8915526f7fe3723ec839a02054fb843d48d..325065ebc07e03d16540938ba79846dcf463b171 100644 (file)
@@ -51,7 +51,8 @@ Datum LWGEOM_forceRHR_poly(PG_FUNCTION_ARGS);
 Datum LWGEOM_noop(PG_FUNCTION_ARGS);
 Datum LWGEOM_zmflag(PG_FUNCTION_ARGS);
 Datum LWGEOM_makepoint(PG_FUNCTION_ARGS);
-Datum LWGEOM_makepointm(PG_FUNCTION_ARGS);
+Datum LWGEOM_makepoint3dm(PG_FUNCTION_ARGS);
+Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS);
 
 
 /*------------------------------------------------------------------*/
@@ -1736,6 +1737,93 @@ Datum LWGEOM_collect_garray(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(result);
 }
 
+/*
+ * makeline_garray ( GEOMETRY[] ) returns a LINE formed by
+ * all the point geometries in given array.
+ * array elements that are NOT points are discarded..
+ */
+PG_FUNCTION_INFO_V1(LWGEOM_makeline_garray);
+Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS)
+{
+       Datum datum;
+       ArrayType *array;
+       int nelems;
+       PG_LWGEOM **geoms;
+       PG_LWGEOM *result=NULL;
+       LWPOINT **lwpoints;
+       LWGEOM *outlwg;
+       size_t size;
+       unsigned int npoints;
+       int i;
+
+//elog(NOTICE, "LWGEOM_makeline_garray called");
+
+       /* Get input datum */
+       datum = PG_GETARG_DATUM(0);
+
+       /* Return null on null input */
+       if ( (Pointer *)datum == NULL )
+       {
+               elog(NOTICE, "NULL input");
+               PG_RETURN_NULL();
+       }
+
+       /* Get actual ArrayType */
+       array = (ArrayType *) PG_DETOAST_DATUM(datum);
+
+       /* Get number of geometries in array */
+       nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
+
+       /* Return null on 0-elements input array */
+       if ( nelems == 0 )
+       {
+               elog(NOTICE, "0 elements input array");
+               PG_RETURN_NULL();
+       }
+
+       /* Get pointer to GEOMETRY pointers array */
+       geoms = (PG_LWGEOM **)ARR_DATA_PTR(array);
+
+       /*
+        * Deserialize all point geometries in array into the
+        * lwpoints pointers array.
+        * Count actual number of points.
+        */
+       
+       // possibly more then required
+       lwpoints = palloc(sizeof(LWGEOM *)*nelems);
+       npoints = 0;
+       for (i=0; i<nelems; i++)
+       {
+               if ( TYPE_GETTYPE(geoms[i]->type) != POINTTYPE ) continue;
+               lwpoints[npoints++] =
+                       lwpoint_deserialize(SERIALIZED_FORM(geoms[i]));
+       }
+
+       /* Return null on 0-points input array */
+       if ( npoints == 0 )
+       {
+               elog(NOTICE, "No points in input array");
+               PG_RETURN_NULL();
+       }
+
+       outlwg = (LWGEOM *)make_lwline(-1, npoints, lwpoints);
+
+       size = lwgeom_serialize_size(outlwg);
+       //lwnotice("lwgeom_serialize_size returned %d", size);
+       result = palloc(size+4);
+       result->size = (size+4);
+       lwgeom_serialize_buf(outlwg, SERIALIZED_FORM(result), &size);
+       if ( size != result->size-4 )
+       {
+               lwerror("lwgeom_serialize size:%d, lwgeom_serialize_size:%d",
+                       size, result->size-4);
+               PG_RETURN_NULL();
+       }
+
+       PG_RETURN_POINTER(result);
+}
+
 // makes a polygon of the expanded features bvol - 1st point = LL 3rd=UR
 // 2d only. (3d might be worth adding).
 // create new geometry of type polygon, 1 ring, 5 points
@@ -2117,7 +2205,6 @@ PG_FUNCTION_INFO_V1(LWGEOM_makepoint3dm);
 Datum LWGEOM_makepoint3dm(PG_FUNCTION_ARGS)
 {
        double x,y,m;
-       int SRID;
        LWPOINT *point;
        PG_LWGEOM *result;
        size_t size;
@@ -2126,7 +2213,7 @@ Datum LWGEOM_makepoint3dm(PG_FUNCTION_ARGS)
        y = PG_GETARG_FLOAT8(1);
        m = PG_GETARG_FLOAT8(2);
 
-       point = make_lwpoint3dm(SRID, x, y, m);
+       point = make_lwpoint3dm(-1, x, y, m);
 
        size = lwpoint_serialize_size(point);
        result = (PG_LWGEOM *)palloc(size+4);
index 15225a80d537d5ab599cd24124a9d25422f2ef52..a45add9c01f7a3383b1a879df3eec8e603506cd9 100644 (file)
@@ -373,3 +373,52 @@ lwline_same(const LWLINE *l1, const LWLINE *l2)
        return ptarray_same(l1->points, l2->points);
 }
 
+/*
+ * Construct a LWLINE from an array of LWPOINTs
+ * LWLINE dimensions are large enought to host all input dimensions.
+ */
+LWLINE *
+make_lwline(int SRID, unsigned int npoints, LWPOINT **points)
+{
+       int zmflag=0;
+       unsigned int i;
+       POINTARRAY *pa;
+
+       /*
+        * Find output dimensions
+        */
+       for (i=0; i<npoints; i++)
+       {
+               zmflag = TYPE_GETZM(points[i]->type);
+               if ( zmflag == 3 ) break;
+       }
+
+       /* Allocate space for output pointarray */
+       pa = ptarray_construct(zmflag&2, zmflag&1, npoints);
+
+       /*
+        * Fill pointarray
+        */
+       switch (zmflag)
+       {
+               case 0: // 2d
+                       for (i=0; i<npoints; i++)
+                               getPoint2d_p(points[i]->point, 0,
+                                       (POINT2D *)getPoint(pa, i));
+               case 1: // 3dm
+                       for (i=0; i<npoints; i++)
+                               getPoint3dm_p(points[i]->point, 0,
+                                       (POINT3DM *)getPoint(pa, i));
+               case 2: // 3dz
+                       for (i=0; i<npoints; i++)
+                               getPoint3dz_p(points[i]->point, 0,
+                                       (POINT3DZ *)getPoint(pa, i));
+               default: // 4d
+                       for (i=0; i<npoints; i++)
+                               getPoint4d_p(points[i]->point, 0,
+                                       (POINT4D *)getPoint(pa, i));
+       }
+
+       return lwline_construct(SRID, NULL, pa);
+}
+
index 2f0b3586ac077ef1dc919126b705c346b39b5636..f8ddc5cd23bee706a3302802678de7bc18d06d04 100644 (file)
@@ -1652,17 +1652,17 @@ CREATEFUNCTION zmflag(geometry)
 -- CONSTRUCTORS
 ------------------------------------------------------------------------
 
-CREATEFUNCTION makepoint(float8, float8)
+CREATEFUNCTION makePoint(float8, float8)
        RETURNS geometry
        AS '@MODULE_FILENAME@', 'LWGEOM_makepoint'
        LANGUAGE 'C' WITH (iscachable,isstrict);
 
-CREATEFUNCTION makepoint(float8, float8, float8)
+CREATEFUNCTION makePoint(float8, float8, float8)
        RETURNS geometry
        AS '@MODULE_FILENAME@', 'LWGEOM_makepoint'
        LANGUAGE 'C' WITH (iscachable,isstrict);
 
-CREATEFUNCTION makepoint(float8, float8, float8, float8)
+CREATEFUNCTION makePoint(float8, float8, float8, float8)
        RETURNS geometry
        AS '@MODULE_FILENAME@', 'LWGEOM_makepoint'
        LANGUAGE 'C' WITH (iscachable,isstrict);
@@ -1672,6 +1672,18 @@ CREATEFUNCTION makePointM(float8, float8, float8)
        AS '@MODULE_FILENAME@', 'LWGEOM_makepoint3dm'
        LANGUAGE 'C' WITH (iscachable,isstrict);
 
+CREATEFUNCTION makeline_garray (geometry[])
+       RETURNS geometry
+       AS '@MODULE_FILENAME@', 'LWGEOM_makeline_garray'
+       LANGUAGE 'C';
+
+CREATE AGGREGATE makeLine (
+       sfunc = geom_accum,
+       basetype = geometry,
+       stype = geometry[],
+       finalfunc = makeline_garray
+       );
+
 ------------------------------------------------------------------------
 
 --
index 2bea2baba4a4cd3ada9d655bd5ea35705a0c6e0a..2d17236dc71aa38259969ee498e33b911a032e0e 100644 (file)
@@ -39,6 +39,58 @@ ptarray_construct2d(uint32 npoints, const POINT2D *pts)
        return pa;
 }
 
+POINTARRAY *
+ptarray_construct3dz(uint32 npoints, const POINT3DZ *pts)
+{
+       POINTARRAY *pa = ptarray_construct(1, 0, npoints);
+       uint32 i;
+
+       for (i=0; i<npoints; i++)
+       {
+               POINT3DZ *pap = (POINT3DZ *)getPoint(pa, i);
+               pap->x = pts[i].x;
+               pap->y = pts[i].y;
+               pap->z = pts[i].z;
+       }
+       
+       return pa;
+}
+
+POINTARRAY *
+ptarray_construct3dm(uint32 npoints, const POINT3DM *pts)
+{
+       POINTARRAY *pa = ptarray_construct(0, 1, npoints);
+       uint32 i;
+
+       for (i=0; i<npoints; i++)
+       {
+               POINT3DM *pap = (POINT3DM *)getPoint(pa, i);
+               pap->x = pts[i].x;
+               pap->y = pts[i].y;
+               pap->m = pts[i].m;
+       }
+       
+       return pa;
+}
+
+POINTARRAY *
+ptarray_construct4d(uint32 npoints, const POINT4D *pts)
+{
+       POINTARRAY *pa = ptarray_construct(0, 1, npoints);
+       uint32 i;
+
+       for (i=0; i<npoints; i++)
+       {
+               POINT4D *pap = (POINT4D *)getPoint(pa, i);
+               pap->x = pts[i].x;
+               pap->y = pts[i].y;
+               pap->z = pts[i].z;
+               pap->m = pts[i].m;
+       }
+       
+       return pa;
+}
+
 void
 ptarray_reverse(POINTARRAY *pa)
 {