From 799ac1b619da1819aa5458bd5ab5cb3d0a53f104 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Tue, 24 Aug 2004 15:05:34 +0000 Subject: [PATCH] Added NumInteriorRings() and InteriorRingN() git-svn-id: http://svn.osgeo.org/postgis/trunk@737 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/MISSING_OBJECTS | 2 - lwgeom/lwgeom_ogc.c | 90 ++++++++++++++++++++++++++++++++++++++++- lwgeom/lwpostgis.sql.in | 24 ++++++++--- 3 files changed, 107 insertions(+), 9 deletions(-) diff --git a/lwgeom/MISSING_OBJECTS b/lwgeom/MISSING_OBJECTS index fb8b8679f..661a298f2 100644 --- a/lwgeom/MISSING_OBJECTS +++ b/lwgeom/MISSING_OBJECTS @@ -29,8 +29,6 @@ FUNC: KEEPING FUNCTION: [x(geometry)] FUNC: KEEPING FUNCTION: [y(geometry)] FUNC: KEEPING FUNCTION: [z(geometry)] FUNC: KEEPING FUNCTION: [pointn(geometry, integer)] -FUNC: KEEPING FUNCTION: [numinteriorrings(geometry)] -FUNC: KEEPING FUNCTION: [interiorringn(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_ogc.c b/lwgeom/lwgeom_ogc.c index 9fb27adc7..fd0d3c2a5 100644 --- a/lwgeom/lwgeom_ogc.c +++ b/lwgeom/lwgeom_ogc.c @@ -37,6 +37,10 @@ Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS); Datum LWGEOM_dimension(PG_FUNCTION_ARGS); // ---- ExteriorRing(geometry) Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS); +// ---- InteriorRingN(geometry, integer) +Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS); +// ---- NumInteriorRings(geometry) +Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS); // internal @@ -279,8 +283,8 @@ Datum LWGEOM_dimension(PG_FUNCTION_ARGS) // exteriorRing(GEOMETRY) -- find the first polygon in GEOMETRY, return -// its exterior ring (as a linestring). Return NULL if there is no -// POLYGON(..) in GEOMETRY. +// its exterior ring (as a linestring). +// Return NULL if there is no POLYGON(..) in (first level of) GEOMETRY. PG_FUNCTION_INFO_V1(LWGEOM_exteriorring_polygon); Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS) { @@ -320,3 +324,85 @@ Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } +// NumInteriorRings(GEOMETRY) -- find the first polygon in GEOMETRY, return +// the number of its interior rings (holes). +// Return NULL if there is no POLYGON(..) in (first level of) GEOMETRY. +PG_FUNCTION_INFO_V1(LWGEOM_numinteriorrings_polygon); +Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS) +{ + LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM_INSPECTED *inspected = lwgeom_inspect(SERIALIZED_FORM(geom)); + LWPOLY *poly = NULL; + int32 result; + int i; + + for (i=0; ingeometries; i++) + { + poly = lwgeom_getpoly_inspected(inspected, i); + if ( poly ) break; + } + + if ( poly == NULL ) PG_RETURN_NULL(); + + // Ok, now we have a polygon. Here is its number of holes + result = poly->nrings-1; + + PG_RETURN_INT32(result); +} + +// InteriorRingN(GEOMETRY) -- find the first polygon in GEOMETRY, return +// its Nth interior ring (as a linestring). +// Return NULL if there is no POLYGON(..) in (first level of) GEOMETRY. +PG_FUNCTION_INFO_V1(LWGEOM_interiorringn_polygon); +Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS) +{ + LWGEOM *geom; + int32 wanted_index; + LWGEOM_INSPECTED *inspected; + LWPOLY *poly = NULL; + POINTARRAY *ring; + LWLINE *line; + char *serializedline; + LWGEOM *result; + int i; + + wanted_index = PG_GETARG_INT32(1); + if ( wanted_index < 0 ) + PG_RETURN_NULL(); // index out of range + + geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + inspected = lwgeom_inspect(SERIALIZED_FORM(geom)); + + for (i=0; ingeometries; i++) + { + poly = lwgeom_getpoly_inspected(inspected, i); + if ( poly ) break; + } + + if ( poly == NULL ) PG_RETURN_NULL(); + + // Ok, now we have a polygon. Let's see if it has enough holes + if ( wanted_index > poly->nrings-2 ) + { + pfree_inspected(inspected); + PG_RETURN_NULL(); + } + + ring = poly->rings[wanted_index+1]; + + // This is a LWLINE constructed by exterior ring POINTARRAY + line = lwline_construct(poly->ndims, poly->SRID, ring); + + // Now we serialized it (copying data) + serializedline = lwline_serialize(line); + + // And we construct the line (copy again) + result = LWGEOM_construct(serializedline, poly->SRID, + lwgeom_hasBBOX(geom->type)); + + pfree(serializedline); + pfree(line); + + PG_RETURN_POINTER(result); +} + diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index 40202ac3b..a72e77e76 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -11,6 +11,9 @@ -- -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- $Log$ +-- Revision 1.12 2004/08/24 15:05:34 strk +-- Added NumInteriorRings() and InteriorRingN() +-- -- Revision 1.11 2004/08/24 14:48:58 strk -- Added dimension() and exteriorring() -- @@ -847,31 +850,42 @@ CREATEFUNCTION npoints(geometry) ------------------------------------------------------------------------ -CREATEFUNCTION numpoints(geometry) +CREATEFUNCTION NumPoints(geometry) RETURNS int4 AS '@MODULE_FILENAME@', 'LWGEOM_numpoints_linestring' LANGUAGE 'C' WITH (isstrict); -CREATEFUNCTION numgeometries(geometry) +CREATEFUNCTION NumGeometries(geometry) RETURNS int4 AS '@MODULE_FILENAME@', 'LWGEOM_numgeometries_collection' LANGUAGE 'C' WITH (isstrict); -CREATEFUNCTION geometryn(geometry,integer) +CREATEFUNCTION GeometryN(geometry,integer) RETURNS geometry AS '@MODULE_FILENAME@', 'LWGEOM_geometryn_collection' LANGUAGE 'C' WITH (isstrict); -CREATEFUNCTION dimension(geometry) +CREATEFUNCTION Dimension(geometry) RETURNS int4 AS '@MODULE_FILENAME@', 'LWGEOM_dimension' LANGUAGE 'C' WITH (isstrict); -CREATEFUNCTION exteriorring(geometry) +CREATEFUNCTION ExterioRring(geometry) RETURNS geometry AS '@MODULE_FILENAME@','LWGEOM_exteriorring_polygon' LANGUAGE 'C' WITH (isstrict); +CREATEFUNCTION NumInteriorRings(geometry) + RETURNS integer + AS '@MODULE_FILENAME@','LWGEOM_numinteriorrings_polygon' + LANGUAGE 'C' WITH (isstrict); + +CREATEFUNCTION InteriorRingN(geometry,integer) + RETURNS geometry + AS '@MODULE_FILENAME@','LWGEOM_interiorringn_polygon' + LANGUAGE 'C' WITH (isstrict); + + ------------------------------------------------------------------------ CREATEFUNCTION geometrytype(geometry) -- 2.40.0