PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ ST_ShapeGrid()

Datum ST_ShapeGrid ( PG_FUNCTION_ARGS  )

Definition at line 233 of file lwgeom_generate_grid.c.

234 {
235  FuncCallContext *funcctx;
236 
237  GSERIALIZED *gbounds;
238  GeometryGridState *state;
239 
240  LWGEOM *lwgeom;
241  bool isnull[3] = {0,0,0}; /* needed to say no value is null */
242  Datum tuple_arr[3]; /* used to construct the composite return value */
243  HeapTuple tuple;
244  Datum result; /* the actual composite return value */
245 
246  if (SRF_IS_FIRSTCALL())
247  {
248  MemoryContext oldcontext;
249  const char *func_name;
250  char gbounds_is_empty;
251  GBOX bounds;
252  double size;
253  funcctx = SRF_FIRSTCALL_INIT();
254 
255  /* Get a local copy of the bounds we are going to fill with shapes */
256  gbounds = PG_GETARG_GSERIALIZED_P(1);
257  size = PG_GETARG_FLOAT8(0);
258 
259  gbounds_is_empty = (gserialized_get_gbox_p(gbounds, &bounds) == LW_FAILURE);
260 
261  /* quick opt-out if we get nonsensical inputs */
262  if (size <= 0.0 || gbounds_is_empty)
263  {
264  funcctx = SRF_PERCALL_SETUP();
265  SRF_RETURN_DONE(funcctx);
266  }
267 
268  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
269 
270  /*
271  * Support both hexagon and square grids with one function,
272  * by checking the calling signature up front.
273  */
274  func_name = get_func_name(fcinfo->flinfo->fn_oid);
275  if (strcmp(func_name, "st_hexagongrid") == 0)
276  {
277  state = (GeometryGridState*)hexagon_grid_state(size, &bounds, gserialized_get_srid(gbounds));
278  }
279  else if (strcmp(func_name, "st_squaregrid") == 0)
280  {
281  state = (GeometryGridState*)square_grid_state(size, &bounds, gserialized_get_srid(gbounds));
282  }
283  else
284  {
285  ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
286  errmsg("%s called from unsupported functional context '%s'", __func__, func_name)));
287  }
288 
289  funcctx->user_fctx = state;
290 
291  /* get tuple description for return type */
292  if (get_call_result_type(fcinfo, 0, &funcctx->tuple_desc) != TYPEFUNC_COMPOSITE)
293  {
294  ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
295  errmsg("set-valued function called in context that cannot accept a set")));
296  }
297 
298  BlessTupleDesc(funcctx->tuple_desc);
299  MemoryContextSwitchTo(oldcontext);
300  }
301 
302  /* stuff done on every call of the function */
303  funcctx = SRF_PERCALL_SETUP();
304 
305  /* get state */
306  state = funcctx->user_fctx;
307 
308  /* Stop when we've used up all the grid squares */
309  if (state->done)
310  {
311  SRF_RETURN_DONE(funcctx);
312  }
313 
314  /* Store grid cell coordinates */
315  tuple_arr[1] = Int32GetDatum(state->i);
316  tuple_arr[2] = Int32GetDatum(state->j);
317 
318  /* Generate geometry */
319  switch (state->cell_shape)
320  {
321  case SHAPE_HEXAGON:
322  lwgeom = hexagon(0.0, 0.0, state->size, state->i, state->j, state->srid);
323  /* Increment to next cell */
325  break;
326  case SHAPE_SQUARE:
327  lwgeom = square(0.0, 0.0, state->size, state->i, state->j, state->srid);
328  /* Increment to next cell */
330  break;
331  default:
332  ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
333  errmsg("%s called from with unsupported shape '%d'", __func__, state->cell_shape)));
334  }
335 
336  tuple_arr[0] = PointerGetDatum(geometry_serialize(lwgeom));
337  lwfree(lwgeom);
338 
339  /* Form tuple and return */
340  tuple = heap_form_tuple(funcctx->tuple_desc, tuple_arr, isnull);
341  result = HeapTupleGetDatum(tuple);
342  SRF_RETURN_NEXT(funcctx, result);
343 }
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:262
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: gserialized.c:126
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
Definition: gserialized.c:65
#define LW_FAILURE
Definition: liblwgeom.h:96
void lwfree(void *mem)
Definition: lwutil.c:242
@ SHAPE_SQUARE
@ SHAPE_HEXAGON
static void square_state_next(SquareGridState *state)
static void hexagon_state_next(HexagonGridState *state)
static HexagonGridState * hexagon_grid_state(double size, const GBOX *gbox, int32_t srid)
static SquareGridState * square_grid_state(double size, const GBOX *gbox, int32_t srid)
static LWGEOM * hexagon(double origin_x, double origin_y, double size, int cell_i, int cell_j, int32_t srid)
static LWGEOM * square(double origin_x, double origin_y, double size, int cell_i, int cell_j, int32_t srid)
GeometryShape cell_shape

References GeometryGridState::cell_shape, HexagonGridState::cell_shape, GeometryGridState::done, gserialized_get_gbox_p(), gserialized_get_srid(), hexagon(), hexagon_grid_state(), hexagon_state_next(), GeometryGridState::i, HexagonGridState::i, GeometryGridState::j, HexagonGridState::j, LW_FAILURE, lwfree(), result, SHAPE_HEXAGON, SHAPE_SQUARE, GeometryGridState::size, HexagonGridState::size, square(), square_grid_state(), square_state_next(), GeometryGridState::srid, and HexagonGridState::srid.

Here is the call graph for this function: