From: Sandro Santilli Date: Thu, 28 Oct 2004 09:00:11 +0000 (+0000) Subject: Added AddPoint(line, point, [position]) and support API functions. X-Git-Tag: pgis_1_0_0RC1~233 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4c2a5c676a44bb566b274669c0b01f06c35ea87a;p=postgis Added AddPoint(line, point, [position]) and support API functions. git-svn-id: http://svn.osgeo.org/postgis/trunk@1059 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/doc/postgis.xml b/doc/postgis.xml index f28dea72a..71595142e 100644 --- a/doc/postgis.xml +++ b/doc/postgis.xml @@ -3718,20 +3718,31 @@ FROM geometry_table; - Polygonize(geometry set) + LineFromMultiPoint(multipoint) - Aggregate. Creates a MultiPolygon from the costituent - linework of a set of geometries. - Only available when compiled against GEOS >= 2.1.0. + Creates a LineString from a MultiPoint geometry. - LineFromMultiPoint(multipoint) + AddPoint(linestring, point, [<position>]) - Creates a LineString from a MultiPoint geometry. + Adds a point to a LineString at position <pos>. + Third parameter can be omitted or set to -1 for appending. + + + + + + + Polygonize(geometry set) + + + Aggregate. Creates a MultiPolygon from the costituent + linework of a set of geometries. + Only available when compiled against GEOS >= 2.1.0. diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h index b425f0aee..f25547a1a 100644 --- a/lwgeom/liblwgeom.h +++ b/lwgeom/liblwgeom.h @@ -993,6 +993,7 @@ 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 *lwline_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points); extern LWLINE *lwline_from_lwmpoint(int SRID, LWMPOINT *mpoint); +extern LWLINE *lwline_addpoint(LWLINE *line, LWPOINT *point, unsigned int where); // Return a char string with ASCII versionf of type flags extern const char *lwgeom_typeflags(unsigned char type); @@ -1003,6 +1004,7 @@ 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 POINTARRAY *ptarray_addPoint(POINTARRAY *pa, char *p, size_t pdims, unsigned int where); extern int32 lwgeom_nrings_recursive(char *serialized); extern void dump_lwexploded(LWGEOM_EXPLODED *exploded); diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index 69f67869b..37de87ea9 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -55,6 +55,7 @@ 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); +Datum LWGEOM_addpoint(PG_FUNCTION_ARGS); /*------------------------------------------------------------------*/ @@ -2372,3 +2373,39 @@ Datum LWGEOM_makepoint3dm(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } +PG_FUNCTION_INFO_V1(LWGEOM_addpoint); +Datum LWGEOM_addpoint(PG_FUNCTION_ARGS) +{ + PG_LWGEOM *pglwg1, *pglwg2, *result; + LWPOINT *point; + LWLINE *line, *outline; + int where = -1; + + pglwg1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + pglwg2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + + if ( PG_NARGS() > 2 ) { + where = PG_GETARG_INT32(2); + } + + if ( ! TYPE_GETTYPE(pglwg1->type) == LINETYPE ) + { + elog(ERROR, "First argument must be a LINESTRING"); + PG_RETURN_NULL(); + } + + if ( ! TYPE_GETTYPE(pglwg2->type) == POINTTYPE ) + { + elog(ERROR, "Second argument must be a POINT"); + PG_RETURN_NULL(); + } + + line = lwline_deserialize(SERIALIZED_FORM(pglwg1)); + point = lwpoint_deserialize(SERIALIZED_FORM(pglwg2)); + + outline = lwline_addpoint(line, point, where); + + result = pglwgeom_serialize(outline); + PG_RETURN_POINTER(result); + +} diff --git a/lwgeom/lwgeom_pg.c b/lwgeom/lwgeom_pg.c index bc06e2886..90439d511 100644 --- a/lwgeom/lwgeom_pg.c +++ b/lwgeom/lwgeom_pg.c @@ -100,3 +100,23 @@ init_pg_func() lwnotice = pg_notice; } +PG_LWGEOM * +pglwgeom_serialize(LWGEOM *in) +{ + size_t size; + PG_LWGEOM *result; + + size = lwgeom_serialize_size(in); + //lwnotice("lwgeom_serialize_size returned %d", size); + result = palloc(size+4); + result->size = (size+4); + lwgeom_serialize_buf(in, SERIALIZED_FORM(result), &size); + if ( size != result->size-4 ) + { + lwerror("lwgeom_serialize size:%d, lwgeom_serialize_size:%d", + size, result->size-4); + return NULL; + } + + return result; +} diff --git a/lwgeom/lwgeom_pg.h b/lwgeom/lwgeom_pg.h index 382cf68db..62a94a676 100644 --- a/lwgeom/lwgeom_pg.h +++ b/lwgeom/lwgeom_pg.h @@ -16,6 +16,9 @@ void pg_free(void *ptr); void pg_error(const char *msg, ...); void pg_notice(const char *msg, ...); +// Serialize an LWGEOM into a PG_LWGEOM (postgis datatype) +PG_LWGEOM *pglwgeom_serialize(LWGEOM *lwgeom); + // call this as first thing of any PG function void init_pg_func(void); diff --git a/lwgeom/lwline.c b/lwgeom/lwline.c index eeec2ad78..f0ce27836 100644 --- a/lwgeom/lwline.c +++ b/lwgeom/lwline.c @@ -528,3 +528,17 @@ lwline_from_lwmpoint(int SRID, LWMPOINT *mpoint) return lwline_construct(SRID, NULL, pa); } + +LWLINE * +lwline_addpoint(LWLINE *line, LWPOINT *point, unsigned int where) +{ + POINTARRAY *newpa; + LWLINE *ret; + + newpa = ptarray_addPoint(line->points, getPoint(point->point, 0), + TYPE_NDIMS(point->type), where); + + ret = lwline_construct(line->SRID, NULL, newpa); + + return ret; +} diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index bb6eb981d..8fb88f220 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -1695,7 +1695,17 @@ CREATEFUNCTION makeline_garray (geometry[]) CREATEFUNCTION LineFromMultiPoint(geometry) RETURNS geometry AS '@MODULE_FILENAME@', 'LWGEOM_makeline' - LANGUAGE 'C'; + LANGUAGE 'C' WITH (iscachable,isstrict); + +CREATEFUNCTION AddPoint(geometry, geometry) + RETURNS geometry + AS '@MODULE_FILENAME@', 'LWGEOM_addpoint' + LANGUAGE 'C' WITH (iscachable,isstrict); + +CREATEFUNCTION AddPoint(geometry, geometry, integer) + RETURNS geometry + AS '@MODULE_FILENAME@', 'LWGEOM_addpoint' + LANGUAGE 'C' WITH (iscachable,isstrict); CREATE AGGREGATE makeline ( sfunc = geom_accum, diff --git a/lwgeom/ptarray.c b/lwgeom/ptarray.c index 2d17236dc..9a27c3b99 100644 --- a/lwgeom/ptarray.c +++ b/lwgeom/ptarray.c @@ -3,6 +3,8 @@ #include "liblwgeom.h" +//#define DEBUG 1 + POINTARRAY * ptarray_construct(char hasz, char hasm, unsigned int npoints) { @@ -260,3 +262,54 @@ ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2) return 1; } + +/* + * Add a point in a pointarray. + * 'where' is the offset (starting at 0) + * if 'where' == -1 append is required. + */ +POINTARRAY * +ptarray_addPoint(POINTARRAY *pa, char *p, size_t pdims, unsigned int where) +{ + POINTARRAY *ret; + POINT4D pbuf; + size_t ptsize = pointArray_ptsize(pa); + + if ( pdims < 2 || pdims > 4 ) + { + lwerror("ptarray_addPoint: point dimension out of range (%d)", + pdims); + return NULL; + } + +#if DEBUG + lwnotice("ptarray_addPoint: called with a %dD point"); +#endif + + pbuf.x = pbuf.y = pbuf.z = pbuf.m = 0.0; + memcpy((char *)&pbuf, p, pdims*sizeof(double)); + +#if DEBUG + lwnotice("ptarray_addPoint: initialized point buffer"); +#endif + + ret = ptarray_construct(TYPE_HASZ(pa->dims), + TYPE_HASM(pa->dims), pa->npoints+1); + + if ( where == -1 ) where = pa->npoints; + + if ( where ) + { + memcpy(getPoint(ret, 0), getPoint(pa, 0), ptsize*where); + } + + memcpy(getPoint(ret, where), (char *)&pbuf, ptsize); + + if ( where+1 != ret->npoints ) + { + memcpy(getPoint(ret, where+1), getPoint(pa, where), + ptsize*(pa->npoints-where)); + } + + return ret; +}