PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ 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.
Definition: gserialized.c:268
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:339
#define LINETYPE
Definition: liblwgeom.h:103
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
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:934
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:1097
#define POLYGONTYPE
Definition: liblwgeom.h:104
#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:314
#define TRIANGLETYPE
Definition: liblwgeom.h:115
void * lwalloc(size_t size)
Definition: lwutil.c:227
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:941
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition: lwgeom_api.c:369
LWCIRCSTRING * lwcircstring_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwcircstring.c:50
#define MAXDEPTH
if(!(yy_init))
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
uint32_t idx
LWGEOM * geom
Datum path[34]
LWGEOM * root
struct dumpnode stack[MAXDEPTH]
uint32_t ring

References dumpstate::align, dumpstate::byval, CIRCSTRINGTYPE, dumpnode::geom, LWCOLLECTION::geoms, getPoint4d_p(), dumpnode::idx, if(), 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: