From: Sandro Santilli Date: Fri, 15 Oct 2004 11:42:36 +0000 (+0000) Subject: Added makeline() aggregate and make_lwline() API method. X-Git-Tag: pgis_1_0_0RC1~277 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e604af53ea47004740ae2f608816c07fb4dd8150;p=postgis Added makeline() aggregate and make_lwline() API method. git-svn-id: http://svn.osgeo.org/postgis/trunk@1008 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h index 2e0fe8311..72c215647 100644 --- a/lwgeom/liblwgeom.h +++ b/lwgeom/liblwgeom.h @@ -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); diff --git a/lwgeom/lwgeom.h b/lwgeom/lwgeom.h index 55590be1d..30e992723 100644 --- a/lwgeom/lwgeom.h +++ b/lwgeom/lwgeom.h @@ -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); diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index f2f5e8915..325065ebc 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -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; itype) != 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); diff --git a/lwgeom/lwline.c b/lwgeom/lwline.c index 15225a80d..a45add9c0 100644 --- a/lwgeom/lwline.c +++ b/lwgeom/lwline.c @@ -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; itype); + 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; ipoint, 0, + (POINT2D *)getPoint(pa, i)); + case 1: // 3dm + for (i=0; ipoint, 0, + (POINT3DM *)getPoint(pa, i)); + case 2: // 3dz + for (i=0; ipoint, 0, + (POINT3DZ *)getPoint(pa, i)); + default: // 4d + for (i=0; ipoint, 0, + (POINT4D *)getPoint(pa, i)); + } + + return lwline_construct(SRID, NULL, pa); +} + diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index 2f0b3586a..f8ddc5cd2 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -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 + ); + ------------------------------------------------------------------------ -- diff --git a/lwgeom/ptarray.c b/lwgeom/ptarray.c index 2bea2baba..2d17236dc 100644 --- a/lwgeom/ptarray.c +++ b/lwgeom/ptarray.c @@ -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; ix = 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; ix = 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; ix = 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) {