34 #include "utils/elog.h"
35 #include "utils/array.h"
36 #include "utils/geo_decls.h"
39 #include "../postgis_config.h"
41 #include "lwgeom_pg.h"
64 #define PUSH(x,y) ((x)->stack[(x)->stacklen++]=(y))
65 #define LAST(x) ((x)->stack[(x)->stacklen-1])
66 #define POP(x) (--((x)->stacklen))
75 FuncCallContext *funcctx;
80 AttInMetadata *attinmeta;
81 MemoryContext oldcontext, newcontext;
88 if (SRF_IS_FIRSTCALL())
90 funcctx = SRF_FIRSTCALL_INIT();
91 newcontext = funcctx->multi_call_memory_ctx;
93 oldcontext = MemoryContextSwitchTo(newcontext);
95 pglwgeom = PG_GETARG_GSERIALIZED_P_COPY(0);
100 state->
root = lwgeom;
114 funcctx->user_fctx = state;
120 get_call_result_type(fcinfo, 0, &tupdesc);
121 BlessTupleDesc(tupdesc);
127 attinmeta = TupleDescGetAttInMetadata(tupdesc);
128 funcctx->attinmeta = attinmeta;
130 MemoryContextSwitchTo(oldcontext);
134 funcctx = SRF_PERCALL_SETUP();
135 newcontext = funcctx->multi_call_memory_ctx;
138 state = funcctx->user_fctx;
141 if ( ! state->
root ) SRF_RETURN_DONE(funcctx);
148 tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
149 result = HeapTupleGetDatum(tuple);
152 SRF_RETURN_NEXT(funcctx,
result);
170 if ( i ) ptr += sprintf(ptr,
",");
171 ptr += sprintf(ptr,
"%d", state->
stack[i]->
idx+1);
186 elog(ERROR,
"Unable to dump overly nested collection.");
188 oldcontext = MemoryContextSwitchTo(newcontext);
195 MemoryContextSwitchTo(oldcontext);
200 if ( !
POP(state) ) SRF_RETURN_DONE(funcctx);
208 tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
209 result = TupleGetDatum(funcctx->slot, tuple);
211 SRF_RETURN_NEXT(funcctx,
result);
225 FuncCallContext *funcctx;
229 AttInMetadata *attinmeta;
230 MemoryContext oldcontext, newcontext;
235 if (SRF_IS_FIRSTCALL())
237 funcctx = SRF_FIRSTCALL_INIT();
238 newcontext = funcctx->multi_call_memory_ctx;
240 oldcontext = MemoryContextSwitchTo(newcontext);
242 pglwgeom = PG_GETARG_GSERIALIZED_P_COPY(0);
245 elog(ERROR,
"Input is not a polygon");
253 assert (state->
poly);
256 funcctx->user_fctx = state;
262 get_call_result_type(fcinfo, 0, &tupdesc);
263 BlessTupleDesc(tupdesc);
269 attinmeta = TupleDescGetAttInMetadata(tupdesc);
270 funcctx->attinmeta = attinmeta;
272 MemoryContextSwitchTo(oldcontext);
276 funcctx = SRF_PERCALL_SETUP();
277 newcontext = funcctx->multi_call_memory_ctx;
280 state = funcctx->user_fctx;
291 oldcontext = MemoryContextSwitchTo(newcontext);
304 sprintf(address,
"{%d}", state->
ringnum);
309 MemoryContextSwitchTo(oldcontext);
311 tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
312 result = HeapTupleGetDatum(tuple);
314 SRF_RETURN_NEXT(funcctx,
result);
317 SRF_RETURN_DONE(funcctx);
341 FuncCallContext *funcctx;
342 collection_fctx *fctx;
343 MemoryContext oldcontext;
346 if (SRF_IS_FIRSTCALL())
352 int maxvertices = 128;
353 double gridSize = -1;
356 funcctx = SRF_FIRSTCALL_INIT();
361 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
366 gser = PG_GETARG_GSERIALIZED_P(0);
372 if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
373 maxvertices = PG_GETARG_INT32(1);
378 if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
379 gridSize = PG_GETARG_FLOAT8(2);
387 SRF_RETURN_DONE(funcctx);
390 fctx = (collection_fctx *) palloc(
sizeof(collection_fctx));
394 fctx->numgeoms = col->
ngeoms;
398 funcctx->user_fctx = fctx;
399 MemoryContextSwitchTo(oldcontext);
403 funcctx = SRF_PERCALL_SETUP();
404 fctx = funcctx->user_fctx;
406 if (fctx->nextgeom < fctx->numgeoms)
408 GSERIALIZED *gpart = geometry_serialize(fctx->col->geoms[fctx->nextgeom]);
410 SRF_RETURN_NEXT(funcctx, PointerGetDatum(gpart));
415 SRF_RETURN_DONE(funcctx);
char result[OUT_DOUBLE_BUFFER_SIZE]
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
POINTARRAY * ptarray_clone_deep(const POINTARRAY *ptarray)
Deep clone a pointarray (also clones serialized pointlist)
char * lwgeom_to_hexwkb_buffer(const LWGEOM *geom, uint8_t variant)
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
void * lwalloc(size_t size)
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
LWCOLLECTION * lwgeom_subdivide_prec(const LWGEOM *geom, uint32_t maxvertices, double gridSize)
LWPOLY * lwpoly_construct(int32_t srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
This library is the generic geometry handling section of PostGIS.
Datum ST_Subdivide(PG_FUNCTION_ARGS)
struct GEOMDUMPNODE_T GEOMDUMPNODE
Datum LWGEOM_dump_rings(PG_FUNCTION_ARGS)
struct GEOMDUMPSTATE GEOMDUMPSTATE
PG_FUNCTION_INFO_V1(LWGEOM_dump)
Datum LWGEOM_dump(PG_FUNCTION_ARGS)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
GEOMDUMPNODE * stack[MAXDEPTH]