PostGIS  2.2.8dev-r@@SVN_REVISION@@

◆ LWGEOM_dumppoints()

Datum LWGEOM_dumppoints ( PG_FUNCTION_ARGS  )

Definition at line 51 of file lwgeom_dumppoints.c.

References dumpstate::align, dumpstate::byval, CIRCSTRINGTYPE, COLLECTIONTYPE, COMPOUNDTYPE, CURVEPOLYTYPE, POINTARRAY::flags, FLAGS_GET_M, FLAGS_GET_Z, dumpnode::geom, LWCOLLECTION::geoms, getPoint4d_p(), gserialized_from_lwgeom(), dumpnode::idx, if(), LINETYPE, lwalloc(), lwcircstring_get_lwpoint(), lwgeom_as_lwcircstring(), lwgeom_as_lwline(), lwgeom_as_lwpoint(), lwgeom_as_lwpoly(), lwgeom_as_lwtriangle(), lwgeom_from_gserialized(), lwgeom_is_collection(), lwgeom_is_empty(), lwline_get_lwpoint(), lwpoint_make(), MULTICURVETYPE, MULTILINETYPE, MULTIPOINTTYPE, MULTIPOLYGONTYPE, MULTISURFACETYPE, LWCOLLECTION::ngeoms, POINTARRAY::npoints, LWPOLY::nrings, dumpstate::path, dumpstate::pathlen, LWLINE::points, LWTRIANGLE::points, LWCIRCSTRING::points, POINTTYPE, POLYGONTYPE, POLYHEDRALSURFACETYPE, dumpstate::pt, dumpstate::ring, LWPOLY::rings, dumpstate::root, LWTRIANGLE::srid, LWPOLY::srid, dumpstate::stack, dumpstate::stacklen, TINTYPE, TRIANGLETYPE, LWGEOM::type, and dumpstate::typlen.

51  {
52  FuncCallContext *funcctx;
53  MemoryContext oldcontext, newcontext;
54 
55  GSERIALIZED *pglwgeom;
56  LWCOLLECTION *lwcoll;
57  LWGEOM *lwgeom;
58  struct dumpstate *state;
59  struct dumpnode *node;
60 
61  HeapTuple tuple;
62  Datum pathpt[2]; /* used to construct the composite return value */
63  bool isnull[2] = {0,0}; /* needed to say neither value is null */
64  Datum result; /* the actual composite return value */
65 
66  if (SRF_IS_FIRSTCALL()) {
67  funcctx = SRF_FIRSTCALL_INIT();
68 
69  newcontext = funcctx->multi_call_memory_ctx;
70  oldcontext = MemoryContextSwitchTo(newcontext);
71 
72  /* get a local copy of what we're doing a dump points on */
73  pglwgeom = PG_GETARG_GSERIALIZED_P_COPY(0);
74  lwgeom = lwgeom_from_gserialized(pglwgeom);
75 
76  /* return early if nothing to do */
77  if (!lwgeom || lwgeom_is_empty(lwgeom)) {
78  MemoryContextSwitchTo(oldcontext);
79  funcctx = SRF_PERCALL_SETUP();
80  SRF_RETURN_DONE(funcctx);
81  }
82 
83  /* Create function state */
84  state = lwalloc(sizeof *state);
85  state->root = lwgeom;
86  state->stacklen = 0;
87  state->pathlen = 0;
88  state->pt = 0;
89  state->ring = 0;
90 
91  funcctx->user_fctx = state;
92 
93  /*
94  * Push a struct dumpnode on the state stack
95  */
96 
97  state->stack[0].idx = 0;
98  state->stack[0].geom = lwgeom;
99  state->stacklen++;
100 
101  /*
102  * get tuple description for return type
103  */
104  if (get_call_result_type(fcinfo, 0, &funcctx->tuple_desc) != TYPEFUNC_COMPOSITE) {
105  ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
106  errmsg("set-valued function called in context that cannot accept a set")));
107  }
108 
109  BlessTupleDesc(funcctx->tuple_desc);
110 
111  /* get and cache data for constructing int4 arrays */
112  get_typlenbyvalalign(INT4OID, &state->typlen, &state->byval, &state->align);
113 
114  MemoryContextSwitchTo(oldcontext);
115  }
116 
117  /* stuff done on every call of the function */
118  funcctx = SRF_PERCALL_SETUP();
119  newcontext = funcctx->multi_call_memory_ctx;
120 
121  /* get state */
122  state = funcctx->user_fctx;
123 
124  while (1) {
125  node = &state->stack[state->stacklen-1];
126  lwgeom = node->geom;
127 
128  /* need to return a point from this geometry */
129  if (!lwgeom_is_collection(lwgeom)) {
130  /* either return a point, or pop the stack */
131  /* TODO use a union? would save a tiny amount of stack space.
132  * probably not worth the bother
133  */
134  LWLINE *line;
135  LWCIRCSTRING *circ;
136  LWPOLY *poly;
137  LWTRIANGLE *tri;
138  LWPOINT *lwpoint = NULL;
139  POINT4D pt;
140 
141  /*
142  * net result of switch should be to set lwpoint to the
143  * next point to return, or leave at NULL if there
144  * are no more points in the geometry
145  */
146  switch(lwgeom->type) {
147  case TRIANGLETYPE:
148  tri = lwgeom_as_lwtriangle(lwgeom);
149  if (state->pt == 0) {
150  state->path[state->pathlen++] = Int32GetDatum(state->ring+1);
151  }
152  if (state->pt <= 3) {
153  getPoint4d_p(tri->points, state->pt, &pt);
154  lwpoint = lwpoint_make(tri->srid,
155  FLAGS_GET_Z(tri->points->flags),
156  FLAGS_GET_M(tri->points->flags),
157  &pt);
158  }
159  if (state->pt > 3) {
160  state->pathlen--;
161  }
162  break;
163  case POLYGONTYPE:
164  poly = lwgeom_as_lwpoly(lwgeom);
165  if (state->pt == poly->rings[state->ring]->npoints) {
166  state->pt = 0;
167  state->ring++;
168  state->pathlen--;
169  }
170  if (state->pt == 0 && state->ring < poly->nrings) {
171  /* handle new ring */
172  state->path[state->pathlen] = Int32GetDatum(state->ring+1);
173  state->pathlen++;
174  }
175  if (state->ring == poly->nrings) {
176  } else {
177  /* TODO should be able to directly get the point
178  * into the point array of a fixed lwpoint
179  */
180  /* can't get the point directly from the ptarray because
181  * it might be aligned wrong, so at least one memcpy
182  * seems unavoidable
183  * It might be possible to pass it directly to gserialized
184  * depending how that works, it might effectively be gserialized
185  * though a brief look at the code indicates not
186  */
187  getPoint4d_p(poly->rings[state->ring], state->pt, &pt);
188  lwpoint = lwpoint_make(poly->srid,
189  FLAGS_GET_Z(poly->rings[state->ring]->flags),
190  FLAGS_GET_M(poly->rings[state->ring]->flags),
191  &pt);
192  }
193  break;
194  case POINTTYPE:
195  if (state->pt == 0) lwpoint = lwgeom_as_lwpoint(lwgeom);
196  break;
197  case LINETYPE:
198  line = lwgeom_as_lwline(lwgeom);
199  if (line->points && state->pt <= line->points->npoints) {
200  lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, state->pt);
201  }
202  break;
203  case CIRCSTRINGTYPE:
204  circ = lwgeom_as_lwcircstring(lwgeom);
205  if (circ->points && state->pt <= circ->points->npoints) {
206  lwpoint = lwcircstring_get_lwpoint((LWCIRCSTRING*)lwgeom, state->pt);
207  }
208  break;
209  default:
210  ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION),
211  errmsg("Invalid Geometry type %d passed to ST_DumpPoints()", lwgeom->type)));
212  }
213 
214  /*
215  * At this point, lwpoint is either NULL, in which case
216  * we need to pop the geometry stack and get the next
217  * geometry, if amy, or lwpoint is set and we construct
218  * a record type with the integer array of geometry
219  * indexes and the point number, and the actual point
220  * geometry itself
221  */
222 
223  if (!lwpoint) {
224  /* no point, so pop the geom and look for more */
225  if (--state->stacklen == 0) SRF_RETURN_DONE(funcctx);
226  state->pathlen--;
227  continue;
228  } else {
229  /* write address of current geom/pt */
230  state->pt++;
231 
232  state->path[state->pathlen] = Int32GetDatum(state->pt);
233  pathpt[0] = PointerGetDatum(construct_array(state->path, state->pathlen+1,
234  INT4OID, state->typlen, state->byval, state->align));
235 
236  pathpt[1] = PointerGetDatum(gserialized_from_lwgeom((LWGEOM*)lwpoint,0,0));
237 
238  tuple = heap_form_tuple(funcctx->tuple_desc, pathpt, isnull);
239  result = HeapTupleGetDatum(tuple);
240  SRF_RETURN_NEXT(funcctx, result);
241  }
242  }
243 
244  lwcoll = (LWCOLLECTION*)node->geom;
245 
246  /* if a collection and we have more geoms */
247  if (node->idx < lwcoll->ngeoms) {
248  /* push the next geom on the path and the stack */
249  lwgeom = lwcoll->geoms[node->idx++];
250  state->path[state->pathlen++] = Int32GetDatum(node->idx);
251 
252  node = &state->stack[state->stacklen++];
253  node->idx = 0;
254  node->geom = lwgeom;
255 
256  state->pt = 0;
257  state->ring = 0;
258 
259  /* loop back to beginning, which will then check whatever node we just pushed */
260  continue;
261  }
262 
263  /* no more geometries in the current collection */
264  if (--state->stacklen == 0) SRF_RETURN_DONE(funcctx);
265  state->pathlen--;
266  state->stack[state->stacklen-1].idx++;
267  }
268 }
#define LINETYPE
Definition: liblwgeom.h:71
POINTARRAY * points
Definition: liblwgeom.h:417
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:991
Datum path[34]
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int npoints
Definition: liblwgeom.h:355
#define POLYGONTYPE
Definition: liblwgeom.h:72
#define TRIANGLETYPE
Definition: liblwgeom.h:83
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:125
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwgeom.c:80
LWGEOM * geom
uint8_t flags
Definition: liblwgeom.h:353
LWGEOM ** geoms
Definition: liblwgeom.h:493
GSERIALIZED * gserialized_from_lwgeom(LWGEOM *geom, int is_geodetic, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
Definition: g_serialized.c:906
LWPOINT * lwpoint_make(int srid, int hasz, int hasm, const POINT4D *p)
Definition: lwpoint.c:175
POINTARRAY ** rings
Definition: liblwgeom.h:441
int nrings
Definition: liblwgeom.h:439
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:124
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:89
LWCIRCSTRING * lwgeom_as_lwcircstring(const LWGEOM *lwgeom)
Definition: lwgeom.c:98
LWTRIANGLE * lwgeom_as_lwtriangle(const LWGEOM *lwgeom)
Definition: lwgeom.c:134
int32_t srid
Definition: liblwgeom.h:438
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:70
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:125
LWPOINT * lwline_get_lwpoint(const LWLINE *line, int where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition: lwline.c:295
uint8_t type
Definition: liblwgeom.h:380
POINTARRAY * points
Definition: liblwgeom.h:428
struct dumpnode stack[MAXDEPTH]
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:77
void * lwalloc(size_t size)
Definition: lwutil.c:199
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1297
LWPOINT * lwcircstring_get_lwpoint(const LWCIRCSTRING *circ, int where)
Definition: lwcircstring.c:287
if(!(yy_init))
int32_t srid
Definition: liblwgeom.h:416
LWGEOM * root
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:231
POINTARRAY * points
Definition: liblwgeom.h:406
Here is the call graph for this function: