]> granicus.if.org Git - postgis/commitdiff
New DumpRings(polygon) function + docs
authorSandro Santilli <strk@keybit.net>
Mon, 22 May 2006 11:02:23 +0000 (11:02 +0000)
committerSandro Santilli <strk@keybit.net>
Mon, 22 May 2006 11:02:23 +0000 (11:02 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@2361 b70326c6-7e19-0410-871a-916f4a2858ee

CHANGES
doc/postgis.xml
lwgeom/lwgeom_dump.c
lwgeom/lwpostgis.sql.in

diff --git a/CHANGES b/CHANGES
index 163ed5efd285ccf42513219cb9d09c3ef7baa0fe..29865c043c6f8122a1df870baf5cd6aeb2f3e516 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,7 @@ PostGIS 1.1.3CVS
              making those fields private later
        - Support for build Tru64 build
        - Use Jade for generating documentation
+       - New DumpRings() function
 
 PostGIS 1.1.2
 2006/03/30
index 37921c5ecebe4737c396d3c0de1361056dcc8db4..59c6bd33cee8b56ba80e69341fdb2db7c8690c6a 100644 (file)
@@ -4579,8 +4579,32 @@ FROM geometry_table;</literallayout>
                    of the component inside the collection.
                    </para>
 
-                   <para>NOTE: this function is not available for
-                   builds against PostgreSQL 7.2.x</para>
+               <para>
+                   Availability: PostGIS 1.0.0RC1.
+                   Requires PostgreSQL 7.3 or higher.
+               </para>
+
+                 </listitem>
+               </varlistentry>
+
+               <varlistentry>
+                 <term>DumpRings(geometry)</term>
+
+                 <listitem>
+                   <para>This is a set-returning function (SRF).
+                   It returns a set of geometry_dump rows, formed
+                   by a geometry (geom) and an array of integers (path).
+                   The 'path' field holds the polygon ring index, contains
+                   a single element: 0 for the shell, hole number for holes.
+                   The 'geom' field contains the corresponding ring
+                   as a polygon.
+                   </para>
+
+               <para>
+                   Availability: PostGIS 1.1.3.
+                   Requires PostgreSQL 7.3 or higher.
+               </para>
+
                  </listitem>
                </varlistentry>
 
index 0e6871629092be3e3c8a257a0df01fdd66936c3b..dbc7fb74f68f7422bb4d6a96801bd528bd569543 100644 (file)
@@ -8,6 +8,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <errno.h>
+#include <assert.h>
 
 #include "postgres.h"
 #include "fmgr.h"
@@ -24,6 +25,7 @@
 /*#define PGIS_DEBUG 1 */
 
 Datum LWGEOM_dump(PG_FUNCTION_ARGS);
+Datum LWGEOM_dump_rings(PG_FUNCTION_ARGS);
 
 typedef struct GEOMDUMPNODE_T {
        int idx;
@@ -189,5 +191,118 @@ Datum LWGEOM_dump(PG_FUNCTION_ARGS)
        SRF_RETURN_NEXT(funcctx, result);
 }
 
+struct POLYDUMPSTATE {
+       int ringnum;
+       LWPOLY *poly;
+};
+
+PG_FUNCTION_INFO_V1(LWGEOM_dump_rings);
+Datum LWGEOM_dump_rings(PG_FUNCTION_ARGS)
+{
+       PG_LWGEOM *pglwgeom;
+       LWGEOM *lwgeom;
+       FuncCallContext *funcctx;
+       struct POLYDUMPSTATE *state;
+       TupleDesc tupdesc;
+       TupleTableSlot *slot;
+       HeapTuple tuple;
+       AttInMetadata *attinmeta;
+       MemoryContext oldcontext, newcontext;
+       Datum result;
+       char address[256];
+       char *values[2];
+
+       if (SRF_IS_FIRSTCALL())
+       {
+               funcctx = SRF_FIRSTCALL_INIT();
+               newcontext = funcctx->multi_call_memory_ctx;
+
+               oldcontext = MemoryContextSwitchTo(newcontext);
+
+               pglwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
+               if ( TYPE_GETTYPE(pglwgeom->type) != POLYGONTYPE )
+               {
+                       lwerror("Input is not a polygon");
+               }
+
+               lwgeom = lwgeom_deserialize(SERIALIZED_FORM(pglwgeom));
+
+               /* Create function state */
+               state = lwalloc(sizeof(struct POLYDUMPSTATE));
+               state->poly = lwgeom_as_lwpoly(lwgeom);
+               assert (state->poly);
+               state->ringnum=0;
+
+               funcctx->user_fctx = state;
+
+               /*
+                * Build a tuple description for an
+                * geometry_dump tuple
+                */
+               tupdesc = RelationNameGetTupleDesc("geometry_dump");
+
+               /* allocate a slot for a tuple with this tupdesc */
+               slot = TupleDescGetSlot(tupdesc);
+
+               /* allocate a slot for a tuple with this tupdesc */
+               slot = TupleDescGetSlot(tupdesc);
+
+               /* assign slot to function context */
+               funcctx->slot = slot;
+
+               /*
+                * generate attribute metadata needed later to produce
+                * tuples from raw C strings
+                */
+               attinmeta = TupleDescGetAttInMetadata(tupdesc);
+               funcctx->attinmeta = attinmeta;
+
+               MemoryContextSwitchTo(oldcontext);
+       }
+
+       /* stuff done on every call of the function */
+       funcctx = SRF_PERCALL_SETUP();
+       newcontext = funcctx->multi_call_memory_ctx;
+
+       /* get state */
+       state = funcctx->user_fctx;
+
+       /* Loop trough polygon rings */
+       while (state->ringnum < state->poly->nrings )
+       {
+               LWPOLY* poly = state->poly;
+
+               /* Switch to an appropriate memory context for POINTARRAY
+                * cloning and hexwkb allocation */
+               oldcontext = MemoryContextSwitchTo(newcontext);
+
+               /* We need a copy of input ring here */
+               POINTARRAY *ring = ptarray_clone(poly->rings[state->ringnum]);
+
+               /* Construct another polygon with shell only */
+               LWGEOM* ringgeom = (LWGEOM*)lwpoly_construct(
+                       poly->SRID,
+                       NULL, /* TODO: could use input bounding box here */
+                       1, /* one ring */
+                       &ring);
+
+               /* Write path as ``{ <ringnum> }'' */
+               sprintf(address, "{%d}", state->ringnum);
+
+               values[0] = address;
+               values[1] = lwgeom_to_hexwkb(ringgeom, -1);
+
+               MemoryContextSwitchTo(oldcontext);
+
+               tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
+               result = TupleGetDatum(funcctx->slot, tuple);
+               ++state->ringnum;
+               SRF_RETURN_NEXT(funcctx, result);
+       }
+
+       SRF_RETURN_DONE(funcctx);
+
+}
+
 
 #endif /* USE_VERSION > 72 */
index c14737a4b7b5872be1d6d244b235fe9f7f22912b..98031e6095998fef1fd640da82ce121c5ba1f3cd 100644 (file)
@@ -1388,11 +1388,16 @@ CREATE AGGREGATE polygonize (
 
 CREATE TYPE geometry_dump AS (path integer[], geom geometry);
 
-CREATEFUNCTION dump(geometry)
+CREATEFUNCTION Dump(geometry)
        RETURNS SETOF geometry_dump
        AS '@MODULE_FILENAME@', 'LWGEOM_dump'
        LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
+CREATEFUNCTION DumpRings(geometry)
+       RETURNS SETOF geometry_dump
+       AS '@MODULE_FILENAME@', 'LWGEOM_dump_rings'
+       LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+
 #endif
 
 ------------------------------------------------------------------------