From: Sandro Santilli Date: Fri, 15 Oct 2004 16:21:33 +0000 (+0000) Subject: makeline_from_multipoint() implemented and exposed. X-Git-Tag: pgis_1_0_0RC1~269 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c69644c1c65c25f3f78b4fc19229b186b1bba226;p=postgis makeline_from_multipoint() implemented and exposed. git-svn-id: http://svn.osgeo.org/postgis/trunk@1017 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/lwgeom/TODO b/lwgeom/TODO index 5c05e028c..ec12de518 100644 --- a/lwgeom/TODO +++ b/lwgeom/TODO @@ -1,5 +1,5 @@ - have lwgeom_collect (or lwcollection_construct) use widest dimensions - based on input dimensions. + based on input dimensions (really?). - makeline, makepoly: aggregates on single types or functions on multitypes ? diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h index 72c215647..ecd5e6bf8 100644 --- a/lwgeom/liblwgeom.h +++ b/lwgeom/liblwgeom.h @@ -990,7 +990,8 @@ 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); +extern LWLINE *lwline_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points); +extern LWLINE *lwline_from_lwmpoint(int SRID, LWMPOINT *mpoint); // Return a char string with ASCII versionf of type flags extern const char *lwgeom_typeflags(unsigned char type); diff --git a/lwgeom/lwgeom.h b/lwgeom/lwgeom.h index 30e992723..55590be1d 100644 --- a/lwgeom/lwgeom.h +++ b/lwgeom/lwgeom.h @@ -38,7 +38,6 @@ 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 6254cbbef..1f445f7cb 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -53,6 +53,7 @@ Datum LWGEOM_zmflag(PG_FUNCTION_ARGS); Datum LWGEOM_makepoint(PG_FUNCTION_ARGS); Datum LWGEOM_makepoint3dm(PG_FUNCTION_ARGS); Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS); +Datum LWGEOM_makeline(PG_FUNCTION_ARGS); /*------------------------------------------------------------------*/ @@ -1757,6 +1758,53 @@ Datum LWGEOM_collect_garray(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } +/* + * makeline ( GEOMETRY ) returns a LINE formed by + * all the points in the in given multipoint. + */ +PG_FUNCTION_INFO_V1(LWGEOM_makeline); +Datum LWGEOM_makeline(PG_FUNCTION_ARGS) +{ + PG_LWGEOM *ingeom, *result; + LWLINE *lwline; + LWMPOINT *mpoint; + size_t size; + +#ifdef DEBUG + elog(NOTICE, "LWGEOM_makeline called"); +#endif + + /* Get input PG_LWGEOM and deserialize it */ + ingeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + + if ( TYPE_GETTYPE(ingeom->type) != MULTIPOINTTYPE ) + { + elog(ERROR, "makeline: input must be a multipoint"); + PG_RETURN_NULL(); // input is not a multipoint + } + + mpoint = lwmpoint_deserialize(SERIALIZED_FORM(ingeom)); + lwline = lwline_from_lwmpoint(-1, mpoint); + if ( ! lwline ) + { + elog(ERROR, "makeline: lwline_from_lwmpoint returned NULL"); + PG_RETURN_NULL(); + } + + size = lwline_serialize_size(lwline); + result = palloc(size+4); + result->size = (size+4); + lwline_serialize_buf(lwline, 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); +} + /* * makeline_garray ( GEOMETRY[] ) returns a LINE formed by * all the point geometries in given array. @@ -1845,7 +1893,7 @@ Datum LWGEOM_makeline_garray(PG_FUNCTION_ARGS) elog(NOTICE, "LWGEOM_makeline_garray: point elements: %d", npoints); #endif - outlwg = (LWGEOM *)make_lwline(-1, npoints, lwpoints); + outlwg = (LWGEOM *)lwline_from_lwpointarray(-1, npoints, lwpoints); size = lwgeom_serialize_size(outlwg); //lwnotice("lwgeom_serialize_size returned %d", size); diff --git a/lwgeom/lwline.c b/lwgeom/lwline.c index f167f097b..f0ec7084d 100644 --- a/lwgeom/lwline.c +++ b/lwgeom/lwline.c @@ -376,10 +376,10 @@ lwline_same(const LWLINE *l1, const LWLINE *l2) /* * Construct a LWLINE from an array of LWPOINTs - * LWLINE dimensions are large enought to host all input dimensions. + * LWLINE dimensions are large enough to host all input dimensions. */ LWLINE * -make_lwline(int SRID, unsigned int npoints, LWPOINT **points) +lwline_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points) { int zmflag=0; unsigned int i; @@ -392,7 +392,7 @@ make_lwline(int SRID, unsigned int npoints, LWPOINT **points) { if ( TYPE_GETTYPE(points[i]->type) != POINTTYPE ) { - lwerror("make_lwline: invalid input type: %s", + lwerror("lwline_from_lwpointarray: invalid input type: %s", lwgeom_typename(TYPE_GETTYPE(points[i]->type))); return NULL; } @@ -405,7 +405,7 @@ make_lwline(int SRID, unsigned int npoints, LWPOINT **points) pa = ptarray_construct(zmflag&2, zmflag&1, npoints); #ifdef DEBUG - lwnotice("make_lwline: constructed pointarray for %d points, %d zmflag", + lwnotice("lwline_from_lwpointarray: constructed pointarray for %d points, %d zmflag", npoints, zmflag); #endif @@ -439,7 +439,62 @@ make_lwline(int SRID, unsigned int npoints, LWPOINT **points) break; default: - lwerror ("make_lwline: unespected ZMflag: %d", zmflag); + lwerror ("lwline_from_lwpointarray: unespected ZMflag: %d", zmflag); + return NULL; + } + + return lwline_construct(SRID, NULL, pa); +} + +/* + * Construct a LWLINE from a LWMPOINT + */ +LWLINE * +lwline_from_lwmpoint(int SRID, LWMPOINT *mpoint) +{ + unsigned int i; + POINTARRAY *pa; + char zmflag = TYPE_GETZM(mpoint->type); + + /* Allocate space for output pointarray */ + pa = ptarray_construct(TYPE_HASZ(mpoint->type), + TYPE_HASM(mpoint->type), mpoint->ngeoms); + +#ifdef DEBUG + lwnotice("lwline_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag); +#endif + + /* + * Fill pointarray + */ + switch (zmflag) + { + case 0: // 2d + for (i=0; ingeoms; i++) + getPoint2d_p(mpoint->geoms[i]->point, 0, + (POINT2D *)getPoint(pa, i)); + break; + + case 1: // 3dm + for (i=0; ingeoms; i++) + getPoint3dm_p(mpoint->geoms[i]->point, 0, + (POINT3DM *)getPoint(pa, i)); + break; + + case 2: // 3dz + for (i=0; ingeoms; i++) + getPoint3dz_p(mpoint->geoms[i]->point, 0, + (POINT3DZ *)getPoint(pa, i)); + break; + + case 3: // 4d + for (i=0; ingeoms; i++) + getPoint4d_p(mpoint->geoms[i]->point, 0, + (POINT4D *)getPoint(pa, i)); + break; + + default: + lwerror ("lwline_from_lwmpoint: unespected ZMflag: %d", zmflag); return NULL; } diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index f8ddc5cd2..3f47cb3a3 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -1677,7 +1677,12 @@ CREATEFUNCTION makeline_garray (geometry[]) AS '@MODULE_FILENAME@', 'LWGEOM_makeline_garray' LANGUAGE 'C'; -CREATE AGGREGATE makeLine ( +CREATEFUNCTION makeline_from_multipoint(geometry) + RETURNS geometry + AS '@MODULE_FILENAME@', 'LWGEOM_makeline' + LANGUAGE 'C'; + +CREATE AGGREGATE makeline ( sfunc = geom_accum, basetype = geometry, stype = geometry[],