]> granicus.if.org Git - postgis/commitdiff
Initial import
authorSandro Santilli <strk@keybit.net>
Fri, 7 Jan 2005 00:58:13 +0000 (00:58 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 7 Jan 2005 00:58:13 +0000 (00:58 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@1238 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/lwgeom_dump.c [new file with mode: 0644]

diff --git a/lwgeom/lwgeom_dump.c b/lwgeom/lwgeom_dump.c
new file mode 100644 (file)
index 0000000..ea4588c
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+
+-- To enable the dump() function copy this SQL into lwpostgis.sql.in
+-- and run make, then open lwpostgis.sql and feed the corresponding
+-- queries to your spatial db
+--
+-- Also, add lwgeom_dump.o to OBJS variable in Makefile
+
+CREATE TYPE geometry_dump AS (path integer[], geom geometry);
+
+CREATEFUNCTION dump(geometry)
+       RETURNS SETOF geometry_dump
+       AS '@MODULE_FILENAME@', 'LWGEOM_dump'
+       LANGUAGE 'C' WITH (isstrict,iscachable);
+
+*/
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "postgres.h"
+#include "fmgr.h"
+#include "utils/elog.h"
+#include "utils/array.h"
+#include "utils/geo_decls.h"
+#include "funcapi.h"
+
+#include "liblwgeom.h"
+#include "lwgeom_pg.h"
+#include "profile.h"
+#include "wktparse.h"
+
+typedef struct GEOMDUMPNODE_T {
+       int idx;
+       LWCOLLECTION *geom;
+} GEOMDUMPNODE;
+
+#define MAXDEPTH 32
+typedef struct GEOMDUMPSTATE {
+       int stacklen;
+       GEOMDUMPNODE *stack[MAXDEPTH];
+       LWGEOM *root;
+       LWGEOM *geom;
+} GEOMDUMPSTATE;
+
+#define PUSH(x,y) ((x)->stack[(x)->stacklen++]=(y))
+#define LAST(x) ((x)->stack[(x)->stacklen-1])
+#define POP(x) (--((x)->stacklen))
+
+PG_FUNCTION_INFO_V1(LWGEOM_dump);
+Datum LWGEOM_dump(PG_FUNCTION_ARGS)
+{
+       PG_LWGEOM *pglwgeom;
+       LWCOLLECTION *lwcoll;
+       LWGEOM *lwgeom;
+       FuncCallContext *funcctx;
+       GEOMDUMPSTATE *state;
+       GEOMDUMPNODE *node;
+       TupleDesc tupdesc;
+       TupleTableSlot *slot;
+       HeapTuple tuple;
+       AttInMetadata *attinmeta;
+       MemoryContext oldcontext;
+       Datum result;
+       char address[256];
+       char *ptr;
+       unsigned int i;
+       char *values[2];
+
+       if (SRF_IS_FIRSTCALL())
+       {
+               funcctx = SRF_FIRSTCALL_INIT();
+
+               oldcontext = MemoryContextSwitchTo(
+                       funcctx->multi_call_memory_ctx);
+
+               pglwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
+               if ( TYPE_GETTYPE(pglwgeom->type) < MULTIPOINTTYPE )
+               {
+                       lwgeom = lwgeom_deserialize(
+                               SERIALIZED_FORM(pglwgeom));
+                       /*
+                        * Write state the user context
+                        */
+                       state = lwalloc(sizeof(GEOMDUMPSTATE));
+                       state->stacklen=0;
+                       state->root = lwgeom;
+                       funcctx->user_fctx = state;
+               }
+               else
+               {
+                       lwcoll = lwcollection_deserialize(
+                               SERIALIZED_FORM(pglwgeom));
+
+                       /*
+                        * Write state the user context
+                        */
+                       node = lwalloc(sizeof(GEOMDUMPNODE));
+                       node->idx=0;
+                       node->geom = lwcoll;
+                       state = lwalloc(sizeof(GEOMDUMPSTATE));
+                       state->root = (LWGEOM *)lwcoll;
+                       state->stacklen=0;
+                       PUSH(state, node);
+                       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();
+
+       /* get state */
+       state = funcctx->user_fctx;
+
+       /* Handled simple geometries */
+       if ( ! state->root ) SRF_RETURN_DONE(funcctx);
+       if ( TYPE_GETTYPE(state->root->type) < MULTIPOINTTYPE )
+       {
+               values[0] = "{}";
+               values[1] = lwgeom_to_hexwkb(lwgeom, -1);
+               tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
+               result = TupleGetDatum(funcctx->slot, tuple);
+
+               //lwnotice("%s", address);
+               //pglwgeom = pglwgeom_serialize(lwgeom);
+               //result = PointerGetDatum(pglwgeom);
+               state->root = NULL;
+               SRF_RETURN_NEXT(funcctx, result);
+       }
+
+       while (1)
+       {
+               node = LAST(state);
+               lwcoll = node->geom;
+
+               if ( node->idx < lwcoll->ngeoms )
+               {
+                       lwgeom = lwcoll->geoms[node->idx];
+                       if ( TYPE_GETTYPE(lwgeom->type) < MULTIPOINTTYPE )
+                       {
+       /* write address of current geom */
+       ptr=address; *ptr++='{';
+       for (i=0; i<state->stacklen; i++)
+       {
+               if ( i ) ptr += sprintf(ptr, ",");
+               ptr += sprintf(ptr, "%d", state->stack[i]->idx+1);
+       }
+       *ptr++='}'; *ptr='\0';
+
+                               break;
+                       }
+
+                       /*
+                        * It's a collection, increment index
+                        * of current node, push a new one on the
+                        * stack
+                        */
+                       node->idx;
+                       node = lwalloc(sizeof(GEOMDUMPNODE));
+                       node->idx=0;
+                       node->geom = (LWCOLLECTION *)lwgeom;
+                       PUSH(state, node);
+                       continue;
+               }
+
+               if ( ! POP(state) ) SRF_RETURN_DONE(funcctx);
+               LAST(state)->idx++;
+       }
+
+       lwgeom->SRID = state->root->SRID;
+
+       //pglwgeom = pglwgeom_serialize(lwgeom);
+       //result = PointerGetDatum(pglwgeom);
+       //lwnotice("%s", address);
+       values[0] = address;
+       values[1] = lwgeom_to_hexwkb(lwgeom, -1);
+       tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
+       result = TupleGetDatum(funcctx->slot, tuple);
+       node->idx++;
+       SRF_RETURN_NEXT(funcctx, result);
+}
+
+