From 840e565470e583c727ba2c17e72e237ed0d7a4da Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Tue, 24 Aug 2004 09:34:33 +0000 Subject: [PATCH] Added npoints,numpoints,numgeometries,geometryn git-svn-id: http://svn.osgeo.org/postgis/trunk@729 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/MISSING_OBJECTS | 5 +- lwgeom/lwgeom_functions_basic.c | 181 ++++++++++++++++++++++++++++++++ lwgeom/lwpostgis.sql.in | 27 ++++- 3 files changed, 208 insertions(+), 5 deletions(-) diff --git a/lwgeom/MISSING_OBJECTS b/lwgeom/MISSING_OBJECTS index d049ce08e..bc8c72b24 100644 --- a/lwgeom/MISSING_OBJECTS +++ b/lwgeom/MISSING_OBJECTS @@ -19,9 +19,9 @@ FUNC: KEEPING FUNCTION: [box3d(geometry)] FUNC: KEEPING FUNCTION: [box(geometry)] FUNC: KEEPING FUNCTION: [geometry(box3d)] FUNC: KEEPING FUNCTION: [expand(box3d, double precision)] + FUNC: KEEPING FUNCTION: [asbinary(geometry)] FUNC: KEEPING FUNCTION: [asbinary(geometry, text)] -FUNC: KEEPING FUNCTION: [npoints(geometry)] FUNC: KEEPING FUNCTION: [nrings(geometry)] FUNC: KEEPING FUNCTION: [translate(geometry, double precision, double precision, double precision)] FUNC: KEEPING FUNCTION: [dimension(geometry)] @@ -29,13 +29,10 @@ FUNC: KEEPING FUNCTION: [envelope(geometry)] FUNC: KEEPING FUNCTION: [x(geometry)] FUNC: KEEPING FUNCTION: [y(geometry)] FUNC: KEEPING FUNCTION: [z(geometry)] -FUNC: KEEPING FUNCTION: [numpoints(geometry)] FUNC: KEEPING FUNCTION: [pointn(geometry, integer)] FUNC: KEEPING FUNCTION: [exteriorring(geometry)] FUNC: KEEPING FUNCTION: [numinteriorrings(geometry)] FUNC: KEEPING FUNCTION: [interiorringn(geometry, integer)] -FUNC: KEEPING FUNCTION: [numgeometries(geometry)] -FUNC: KEEPING FUNCTION: [geometryn(geometry, integer)] FUNC: KEEPING FUNCTION: [max_distance(geometry, geometry)] FUNC: KEEPING FUNCTION: [optimistic_overlap(geometry, geometry, double precision)] FUNC: KEEPING FUNCTION: [segmentize(geometry, double precision)] diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index 4776aa441..d4631615c 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -33,8 +33,13 @@ Datum lwgeom_summary(PG_FUNCTION_ARGS); Datum postgis_uses_stats(PG_FUNCTION_ARGS); Datum postgis_scripts_released(PG_FUNCTION_ARGS); Datum postgis_lib_version(PG_FUNCTION_ARGS); +Datum lwgeom_npoints(PG_FUNCTION_ARGS); +Datum lwgeom_numpoints_linestring(PG_FUNCTION_ARGS); +Datum lwgeom_numgeometries_collection(PG_FUNCTION_ARGS); char * lwgeom_summary_recursive(char *serialized, int offset); +int32 lwgeom_npoints_recursive(char *serialized); +int32 lwgeom_numpoints_linestring_recursive(char *serialized); // getSRID(lwgeom) :: int4 PG_FUNCTION_INFO_V1(LWGEOM_getSRID); @@ -303,3 +308,179 @@ Datum postgis_uses_stats(PG_FUNCTION_ARGS) PG_RETURN_BOOL(FALSE); #endif } + +/* + * Recursively count points in a SERIALIZED lwgeom + */ +int32 +lwgeom_npoints_recursive(char *serialized) +{ + LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized); + int i, j; + int npoints=0; + + //now have to do a scan of each object + for (i=0; ingeometries; i++) + { + LWLINE *line=NULL; + LWPOINT *point=NULL; + LWPOLY *poly=NULL; + char *subgeom=NULL; + + point = lwgeom_getpoint_inspected(inspected, i); + if (point !=NULL) + { + npoints++; + continue; + } + + poly = lwgeom_getpoly_inspected(inspected, i); + if (poly !=NULL) + { + for (j=0; jnrings; j++) + { + npoints += poly->rings[j]->npoints; + } + continue; + } + + line = lwgeom_getline_inspected(inspected, i); + if (line != NULL) + { + npoints += line->points->npoints; + continue; + } + + subgeom = lwgeom_getsubgeometry_inspected(inspected, i); + if ( subgeom != NULL ) + { + npoints += lwgeom_npoints_recursive(subgeom); + } + else + { + elog(ERROR, "What ? lwgeom_getsubgeometry_inspected returned NULL??"); + } + } + return npoints; +} + +//number of points in an object +PG_FUNCTION_INFO_V1(lwgeom_npoints); +Datum lwgeom_npoints(PG_FUNCTION_ARGS) +{ + LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + int32 npoints = 0; + + npoints = lwgeom_npoints_recursive(SERIALIZED_FORM(geom)); + + PG_RETURN_INT32(npoints); +} + +// Find first linestring in serialized geometry and return +// the number of points in it. If no linestrings are found +// return -1. +int32 +lwgeom_numpoints_linestring_recursive(char *serialized) +{ + LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized); + int i; + + for (i=0; ingeometries; i++) + { + int32 npoints; + int type; + LWLINE *line=NULL; + char *subgeom; + + line = lwgeom_getline_inspected(inspected, i); + if (line != NULL) + { + return line->points->npoints; + } + + subgeom = lwgeom_getsubgeometry_inspected(inspected, i); + if ( subgeom == NULL ) + { + elog(ERROR, "What ? lwgeom_getsubgeometry_inspected returned NULL??"); + } + + type = lwgeom_getType(subgeom[0]); + + // MULTILINESTRING && GEOMETRYCOLLECTION are worth checking + if ( type != 7 && type != 5 ) continue; + + npoints = lwgeom_numpoints_linestring_recursive(subgeom); + if ( npoints == -1 ) continue; + return npoints; + } + + return -1; +} + +//numpoints(GEOMETRY) -- find the first linestring in GEOMETRY, return +//the number of points in it. Return NULL if there is no LINESTRING(..) +//in GEOMETRY +PG_FUNCTION_INFO_V1(lwgeom_numpoints_linestring); +Datum lwgeom_numpoints_linestring(PG_FUNCTION_ARGS) +{ + LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + int32 ret; + ret = lwgeom_numpoints_linestring_recursive(SERIALIZED_FORM(geom)); + if ( ret == -1 ) PG_RETURN_NULL(); + PG_RETURN_INT32(ret); +} + +PG_FUNCTION_INFO_V1(lwgeom_numgeometries_collection); +Datum lwgeom_numgeometries_collection(PG_FUNCTION_ARGS) +{ + LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + int type; + char *serialized = SERIALIZED_FORM(geom); + + type = lwgeom_getType(geom->type); + if ( type >= 4 ) + { + PG_RETURN_INT32(lwgeom_getnumgeometries(serialized)); + } + else + { + PG_RETURN_NULL(); + } +} + +PG_FUNCTION_INFO_V1(lwgeom_geometryn_collection); +Datum lwgeom_geometryn_collection(PG_FUNCTION_ARGS) +{ + LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *result; + int size; + int type = lwgeom_getType(geom->type); + int32 idx; + char *serialized; + char *subgeom; + + // call is valid on multi* geoms only + if ( type < 4 ) + { + //elog(NOTICE, "geometryn: geom is of type %d, requires >=4", type); + PG_RETURN_NULL(); + } + + idx = PG_GETARG_INT32(1); + serialized = SERIALIZED_FORM(geom); + + subgeom = lwgeom_getsubgeometry(serialized, idx); + if ( subgeom == NULL ) + { + //elog(NOTICE, "geometryn: subgeom %d does not exist", idx); + PG_RETURN_NULL(); + } + + // we have it, not it's time to make an LWGEOM + size = lwgeom_seralizedformlength_simple(subgeom); + result = palloc(size); + memcpy(result, &size, 4); + memcpy(SERIALIZED_FORM(result), subgeom, size); + PG_RETURN_POINTER(result); + +} diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index ee2d11ac4..5cac17f4a 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -11,6 +11,9 @@ -- -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- $Log$ +-- Revision 1.9 2004/08/24 09:34:33 strk +-- Added npoints,numpoints,numgeometries,geometryn +-- -- Revision 1.8 2004/08/23 15:57:56 strk -- versioning functions completed -- @@ -808,7 +811,6 @@ CREATEFUNCTION setSRID(geometry,int4) AS '@MODULE_FILENAME@','LWGEOM_setSRID' LANGUAGE 'C' WITH (isstrict,iscachable); - CREATEFUNCTION asText(geometry) RETURNS TEXT AS '@MODULE_FILENAME@','LWGEOM_asText' @@ -829,6 +831,29 @@ CREATEFUNCTION summary(geometry) AS '@MODULE_FILENAME@', 'lwgeom_summary' LANGUAGE 'C' WITH (isstrict); +CREATEFUNCTION npoints(geometry) + RETURNS int4 + AS '@MODULE_FILENAME@', 'lwgeom_npoints' + LANGUAGE 'C' WITH (isstrict); + +-- OGC +CREATEFUNCTION numpoints(geometry) + RETURNS int4 + AS '@MODULE_FILENAME@', 'lwgeom_numpoints_linestring' + LANGUAGE 'C' WITH (isstrict); + +-- OGC +CREATEFUNCTION numgeometries(geometry) + RETURNS int4 + AS '@MODULE_FILENAME@', 'lwgeom_numgeometries_collection' + LANGUAGE 'C' WITH (isstrict); + +-- OGC +CREATEFUNCTION geometryn(geometry,integer) + RETURNS geometry + AS '@MODULE_FILENAME@', 'lwgeom_geometryn_collection' + LANGUAGE 'C' WITH (isstrict); + CREATEFUNCTION geometrytype(geometry) RETURNS text -- 2.40.0