PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ LWGEOM_dumpsegments()

Datum LWGEOM_dumpsegments ( PG_FUNCTION_ARGS  )

Definition at line 301 of file lwgeom_dumppoints.c.

302{
303 FuncCallContext *funcctx;
304 MemoryContext oldcontext, newcontext;
305
306 GSERIALIZED *pglwgeom;
307 LWCOLLECTION *lwcoll;
308 LWGEOM *lwgeom;
309 struct dumpstate *state;
310 struct dumpnode *node;
311
312 HeapTuple tuple;
313 Datum pathpt[2]; /* used to construct the composite return value */
314 bool isnull[2] = {0, 0}; /* needed to say neither value is null */
315 Datum result; /* the actual composite return value */
316
317 if (SRF_IS_FIRSTCALL())
318 {
319 funcctx = SRF_FIRSTCALL_INIT();
320
321 newcontext = funcctx->multi_call_memory_ctx;
322 oldcontext = MemoryContextSwitchTo(newcontext);
323
324 pglwgeom = PG_GETARG_GSERIALIZED_P_COPY(0);
325 lwgeom = lwgeom_from_gserialized(pglwgeom);
326
327 /* return early if nothing to do */
328 if (!lwgeom || lwgeom_is_empty(lwgeom))
329 {
330 MemoryContextSwitchTo(oldcontext);
331 funcctx = SRF_PERCALL_SETUP();
332 SRF_RETURN_DONE(funcctx);
333 }
334
335 /* Create function state */
336 state = lwalloc(sizeof *state);
337 state->root = lwgeom;
338 state->stacklen = 0;
339 state->pathlen = 0;
340 state->pt = 0;
341 state->ring = 0;
342
343 funcctx->user_fctx = state;
344
345 /*
346 * Push a struct dumpnode on the state stack
347 */
348 state->stack[0].idx = 0;
349 state->stack[0].geom = lwgeom;
350 state->stacklen++;
351
352 /*
353 * get tuple description for return type
354 */
355 if (get_call_result_type(fcinfo, 0, &funcctx->tuple_desc) != TYPEFUNC_COMPOSITE)
356 {
357 ereport(ERROR,
358 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
359 errmsg("set-valued function called in context that cannot accept a set")));
360 }
361
362 BlessTupleDesc(funcctx->tuple_desc);
363
364 /* get and cache data for constructing int4 arrays */
365 get_typlenbyvalalign(INT4OID, &state->typlen, &state->byval, &state->align);
366
367 MemoryContextSwitchTo(oldcontext);
368 }
369
370 /* stuff done on every call of the function */
371 funcctx = SRF_PERCALL_SETUP();
372 newcontext = funcctx->multi_call_memory_ctx;
373
374 /* get state */
375 state = funcctx->user_fctx;
376
377 while (1)
378 {
379 POINTARRAY *points = NULL;
380 LWLINE *line;
381 LWTRIANGLE *tri;
382 LWPOLY *poly;
383 POINT4D pts_out[3];
384 POINTARRAY *segment_pa;
385 LWGEOM *segment;
386 uint8_t stride = 1;
387
388 node = &state->stack[state->stacklen - 1];
389 lwgeom = node->geom;
390
391 if (lwgeom->type == CIRCSTRINGTYPE)
392 stride =2 ;
393
394 if ( !lwgeom_is_empty(lwgeom) && (lwgeom->type == LINETYPE || lwgeom->type == TRIANGLETYPE || lwgeom->type == POLYGONTYPE || lwgeom->type == CIRCSTRINGTYPE) )
395 {
396 if (lwgeom->type == LINETYPE || lwgeom->type == CIRCSTRINGTYPE)
397 {
398 line = (LWLINE *)lwgeom;
399
400 if (state->pt < (line->points->npoints - stride))
401 {
402 points = line->points;
403 }
404 }
405 else if (lwgeom->type == TRIANGLETYPE)
406 {
407 tri = (LWTRIANGLE *)lwgeom;
408
409 if (state->pt == 0)
410 {
411 state->path[state->pathlen++] = Int32GetDatum(state->ring + 1);
412 }
413
414 if (state->pt < 3)
415 {
416 points = tri->points;
417 }
418 else
419 {
420 state->pathlen--;
421 }
422 }
423 else if (lwgeom->type == POLYGONTYPE)
424 {
425 poly = (LWPOLY *)lwgeom;
426
427 if (state->pt == poly->rings[state->ring]->npoints)
428 {
429 state->pt = 0;
430 state->ring++;
431 state->pathlen--;
432 }
433
434 if (state->ring < poly->nrings)
435 {
436 if (state->pt == 0)
437 {
438 state->path[state->pathlen] = Int32GetDatum(state->ring + 1);
439 state->pathlen++;
440 }
441
442 if (state->pt < poly->rings[state->ring]->npoints - 1)
443 {
444 points = poly->rings[state->ring];
445 }
446 else
447 {
448 state->pt += stride;
449 continue;
450 }
451 }
452 }
453
454 if (points && ((state->pt % stride) == 0))
455 {
456 segment_pa = ptarray_construct(lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), stride+1);
457 for (uint8_t i = 0; i < stride+1; i++)
458 {
459 getPoint4d_p(points, state->pt+i, &pts_out[i]);
460 ptarray_set_point4d(segment_pa, i, &pts_out[i]);
461 }
462
463 if (stride == 1)
464 segment = lwline_as_lwgeom(lwline_construct(lwgeom->srid, NULL, segment_pa));
465 else if (stride == 2)
466 segment = lwcircstring_as_lwgeom(lwcircstring_construct(lwgeom->srid, NULL, segment_pa));
467 else
468 elog(ERROR, "%s got unexpected strid", __func__);
469
470 state->pt += stride;
471
472 state->path[state->pathlen] = Int32GetDatum(state->pt / stride);
473 pathpt[0] = PointerGetDatum(construct_array(state->path,
474 state->pathlen + 1,
475 INT4OID,
476 state->typlen,
477 state->byval,
478 state->align));
479 pathpt[1] = PointerGetDatum(geometry_serialize((LWGEOM *)segment));
480
481 tuple = heap_form_tuple(funcctx->tuple_desc, pathpt, isnull);
482 result = HeapTupleGetDatum(tuple);
483 SRF_RETURN_NEXT(funcctx, result);
484 }
485 else
486 {
487 if (--state->stacklen == 0)
488 SRF_RETURN_DONE(funcctx);
489 state->pathlen--;
490 continue;
491 }
492 }
493
494 if (lwgeom_is_collection(lwgeom))
495 {
496 lwcoll = (LWCOLLECTION *)node->geom;
497
498 /* if a collection and we have more geoms */
499 if (node->idx < lwcoll->ngeoms)
500 {
501 if (state->stacklen > MAXDEPTH)
502 elog(ERROR, "Unable to dump overly nested collection");
503
504 /* push the next geom on the path and the stack */
505 lwgeom = lwcoll->geoms[node->idx++];
506 state->path[state->pathlen++] = Int32GetDatum(node->idx);
507
508 node = &state->stack[state->stacklen++];
509 node->idx = 0;
510 node->geom = lwgeom;
511
512 state->pt = 0;
513 state->ring = 0;
514
515 /* loop back to beginning, which will then check whatever node we just pushed */
516 continue;
517 }
518 }
519
520 /* no more geometries in the current collection */
521 if (--state->stacklen == 0)
522 SRF_RETURN_DONE(funcctx);
523 state->pathlen--;
524 }
525}
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition cu_print.c:267
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
#define LINETYPE
Definition liblwgeom.h:103
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition lwgeom.c:962
void * lwalloc(size_t size)
Definition lwutil.c:227
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM contains sub-geometries or not This basically just checks that the struct ...
Definition lwgeom.c:1125
#define POLYGONTYPE
Definition liblwgeom.h:104
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
#define CIRCSTRINGTYPE
Definition liblwgeom.h:109
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition lwgeom_api.c:125
LWGEOM * lwcircstring_as_lwgeom(const LWCIRCSTRING *obj)
Definition lwgeom.c:342
#define TRIANGLETYPE
Definition liblwgeom.h:115
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition lwgeom.c:969
LWCIRCSTRING * lwcircstring_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition lwgeom_api.c:369
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition ptarray.c:51
#define MAXDEPTH
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition lwinline.h:199
uint32_t ngeoms
Definition liblwgeom.h:580
LWGEOM ** geoms
Definition liblwgeom.h:575
uint8_t type
Definition liblwgeom.h:462
int32_t srid
Definition liblwgeom.h:460
POINTARRAY * points
Definition liblwgeom.h:483
POINTARRAY ** rings
Definition liblwgeom.h:519
uint32_t nrings
Definition liblwgeom.h:524
POINTARRAY * points
Definition liblwgeom.h:495
uint32_t npoints
Definition liblwgeom.h:427
LWGEOM * geom
Datum path[34]
struct dumpnode stack[MAXDEPTH]

References dumpstate::align, dumpstate::byval, CIRCSTRINGTYPE, dumpnode::geom, LWCOLLECTION::geoms, getPoint4d_p(), dumpnode::idx, LINETYPE, lwalloc(), lwcircstring_as_lwgeom(), lwcircstring_construct(), lwgeom_from_gserialized(), lwgeom_has_m(), lwgeom_has_z(), lwgeom_is_collection(), lwgeom_is_empty(), lwline_as_lwgeom(), lwline_construct(), MAXDEPTH, LWCOLLECTION::ngeoms, POINTARRAY::npoints, LWPOLY::nrings, dumpstate::path, dumpstate::pathlen, LWLINE::points, LWTRIANGLE::points, POLYGONTYPE, dumpstate::pt, ptarray_construct(), ptarray_set_point4d(), result, dumpstate::ring, LWPOLY::rings, dumpstate::root, LWGEOM::srid, dumpstate::stack, dumpstate::stacklen, TRIANGLETYPE, LWGEOM::type, and dumpstate::typlen.

Here is the call graph for this function: