PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ LWGEOM_dumpsegments()

Datum LWGEOM_dumpsegments ( PG_FUNCTION_ARGS  )

Definition at line 297 of file lwgeom_dumppoints.c.

298 {
299  FuncCallContext *funcctx;
300  MemoryContext oldcontext, newcontext;
301 
302  GSERIALIZED *pglwgeom;
303  LWCOLLECTION *lwcoll;
304  LWGEOM *lwgeom;
305  struct dumpstate *state;
306  struct dumpnode *node;
307 
308  HeapTuple tuple;
309  Datum pathpt[2]; /* used to construct the composite return value */
310  bool isnull[2] = {0, 0}; /* needed to say neither value is null */
311  Datum result; /* the actual composite return value */
312 
313  if (SRF_IS_FIRSTCALL())
314  {
315  funcctx = SRF_FIRSTCALL_INIT();
316 
317  newcontext = funcctx->multi_call_memory_ctx;
318  oldcontext = MemoryContextSwitchTo(newcontext);
319 
320  pglwgeom = PG_GETARG_GSERIALIZED_P_COPY(0);
321  lwgeom = lwgeom_from_gserialized(pglwgeom);
322 
323  /* return early if nothing to do */
324  if (!lwgeom || lwgeom_is_empty(lwgeom))
325  {
326  MemoryContextSwitchTo(oldcontext);
327  funcctx = SRF_PERCALL_SETUP();
328  SRF_RETURN_DONE(funcctx);
329  }
330 
331  /* Create function state */
332  state = lwalloc(sizeof *state);
333  state->root = lwgeom;
334  state->stacklen = 0;
335  state->pathlen = 0;
336  state->pt = 0;
337  state->ring = 0;
338 
339  funcctx->user_fctx = state;
340 
341  /*
342  * Push a struct dumpnode on the state stack
343  */
344  state->stack[0].idx = 0;
345  state->stack[0].geom = lwgeom;
346  state->stacklen++;
347 
348  /*
349  * get tuple description for return type
350  */
351  if (get_call_result_type(fcinfo, 0, &funcctx->tuple_desc) != TYPEFUNC_COMPOSITE)
352  {
353  ereport(ERROR,
354  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
355  errmsg("set-valued function called in context that cannot accept a set")));
356  }
357 
358  BlessTupleDesc(funcctx->tuple_desc);
359 
360  /* get and cache data for constructing int4 arrays */
361  get_typlenbyvalalign(INT4OID, &state->typlen, &state->byval, &state->align);
362 
363  MemoryContextSwitchTo(oldcontext);
364  }
365 
366  /* stuff done on every call of the function */
367  funcctx = SRF_PERCALL_SETUP();
368  newcontext = funcctx->multi_call_memory_ctx;
369 
370  /* get state */
371  state = funcctx->user_fctx;
372 
373  while (1)
374  {
375  POINTARRAY *points = NULL;
376  LWLINE *line;
377  LWTRIANGLE *tri;
378  LWPOLY *poly;
379  POINT4D pt_start, pt_end;
380  POINTARRAY *segment_pa;
381  LWLINE *segment;
382 
383  node = &state->stack[state->stacklen - 1];
384  lwgeom = node->geom;
385 
386  if ( !lwgeom_is_empty(lwgeom) && (lwgeom->type == LINETYPE || lwgeom->type == TRIANGLETYPE || lwgeom->type == POLYGONTYPE) )
387  {
388  if (lwgeom->type == LINETYPE)
389  {
390  line = (LWLINE *)lwgeom;
391 
392  if (state->pt < line->points->npoints - 1)
393  {
394  points = line->points;
395  }
396  }
397  if (lwgeom->type == TRIANGLETYPE)
398  {
399  tri = (LWTRIANGLE *)lwgeom;
400 
401  if (state->pt == 0)
402  {
403  state->path[state->pathlen++] = Int32GetDatum(state->ring + 1);
404  }
405 
406  if (state->pt < 3)
407  {
408  points = tri->points;
409  }
410  else
411  {
412  state->pathlen--;
413  }
414  }
415  if (lwgeom->type == POLYGONTYPE)
416  {
417  poly = (LWPOLY *)lwgeom;
418 
419  if (state->pt == poly->rings[state->ring]->npoints)
420  {
421  state->pt = 0;
422  state->ring++;
423  state->pathlen--;
424  }
425 
426  if (state->ring < poly->nrings)
427  {
428  if (state->pt == 0)
429  {
430  state->path[state->pathlen] = Int32GetDatum(state->ring + 1);
431  state->pathlen++;
432  }
433 
434  if (state->pt < poly->rings[state->ring]->npoints - 1)
435  {
436  points = poly->rings[state->ring];
437  }
438  else
439  {
440  state->pt++;
441  continue;
442  }
443  }
444  }
445 
446  if (points)
447  {
448  getPoint4d_p(points, state->pt, &pt_start);
449  getPoint4d_p(points, state->pt + 1, &pt_end);
450 
451  segment_pa = ptarray_construct(lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), 2);
452  ptarray_set_point4d(segment_pa, 0, &pt_start);
453  ptarray_set_point4d(segment_pa, 1, &pt_end);
454 
455  segment = lwline_construct(lwgeom->srid, NULL, segment_pa);
456 
457  state->pt++;
458 
459  state->path[state->pathlen] = Int32GetDatum(state->pt);
460  pathpt[0] = PointerGetDatum(construct_array(state->path,
461  state->pathlen + 1,
462  INT4OID,
463  state->typlen,
464  state->byval,
465  state->align));
466  pathpt[1] = PointerGetDatum(geometry_serialize((LWGEOM *)segment));
467 
468  tuple = heap_form_tuple(funcctx->tuple_desc, pathpt, isnull);
469  result = HeapTupleGetDatum(tuple);
470  SRF_RETURN_NEXT(funcctx, result);
471  }
472  else
473  {
474  if (--state->stacklen == 0)
475  SRF_RETURN_DONE(funcctx);
476  state->pathlen--;
477  continue;
478  }
479  }
480 
481  if (lwgeom->type == COLLECTIONTYPE || lwgeom->type == MULTILINETYPE ||
482  lwgeom->type == MULTIPOLYGONTYPE || lwgeom->type == TINTYPE)
483  {
484  lwcoll = (LWCOLLECTION *)node->geom;
485 
486  /* if a collection and we have more geoms */
487  if (node->idx < lwcoll->ngeoms)
488  {
489  /* push the next geom on the path and the stack */
490  lwgeom = lwcoll->geoms[node->idx++];
491  state->path[state->pathlen++] = Int32GetDatum(node->idx);
492 
493  node = &state->stack[state->stacklen++];
494  node->idx = 0;
495  node->geom = lwgeom;
496 
497  state->pt = 0;
498  state->ring = 0;
499 
500  /* loop back to beginning, which will then check whatever node we just pushed */
501  continue;
502  }
503  }
504 
505  /* no more geometries in the current collection */
506  if (--state->stacklen == 0)
507  SRF_RETURN_DONE(funcctx);
508  state->pathlen--;
509  }
510 }
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:262
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:239
#define COLLECTIONTYPE
Definition: liblwgeom.h:108
#define MULTILINETYPE
Definition: liblwgeom.h:106
#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
#define TINTYPE
Definition: liblwgeom.h:116
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:107
#define POLYGONTYPE
Definition: liblwgeom.h:104
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:125
#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
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:203
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, COLLECTIONTYPE, dumpnode::geom, LWCOLLECTION::geoms, getPoint4d_p(), dumpnode::idx, if(), LINETYPE, lwalloc(), lwgeom_from_gserialized(), lwgeom_has_m(), lwgeom_has_z(), lwgeom_is_empty(), lwline_construct(), MULTILINETYPE, MULTIPOLYGONTYPE, 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, TINTYPE, TRIANGLETYPE, LWGEOM::type, and dumpstate::typlen.

Here is the call graph for this function: