28 #include "access/htup_details.h"
30 #include "../postgis_config.h"
31 #include "lwgeom_pg.h"
67 #define H 0.8660254037844387
70 static const double hex_x[] = {-1.0, -0.5, 0.5, 1.0, 0.5, -0.5, -1.0};
71 static const double hex_y[] = {0.0, -0.5, -0.5, 0.0, 0.5, 0.5, 0.0};
74 hexagon(
double origin_x,
double origin_y,
double size,
int cell_i,
int cell_j, int32_t srid)
79 for (uint32_t i = 0; i < 7; ++i)
81 double height = size * 2 *
H;
83 pt.
x = origin_x + size * (1.5 * cell_i +
hex_x[i]);
84 pt.
y = origin_y + height * (cell_j + 0.5 * (abs(cell_i) % 2) +
hex_y[i]);
111 double col_width = 1.5 * size;
112 double row_height = size * 2 *
H;
147 if (!state || state->
done)
return;
166 square(
double origin_x,
double origin_y,
double size,
int cell_i,
int cell_j, int32_t srid)
168 double ll_x = origin_x + (size * cell_i);
169 double ll_y = origin_y + (size * cell_j);
170 double ur_x = origin_x + (size * (cell_i + 1));
171 double ur_y = origin_y + (size * (cell_j + 1));
212 if (!state || state->
done)
return;
235 FuncCallContext *funcctx;
241 bool isnull[3] = {0,0,0};
246 if (SRF_IS_FIRSTCALL())
248 MemoryContext oldcontext;
249 const char *func_name;
250 char gbounds_is_empty;
253 funcctx = SRF_FIRSTCALL_INIT();
256 gbounds = PG_GETARG_GSERIALIZED_P(1);
257 size = PG_GETARG_FLOAT8(0);
262 if (size <= 0.0 || gbounds_is_empty)
264 funcctx = SRF_PERCALL_SETUP();
265 SRF_RETURN_DONE(funcctx);
268 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
274 func_name = get_func_name(fcinfo->flinfo->fn_oid);
275 if (strcmp(func_name,
"st_hexagongrid") == 0)
279 else if (strcmp(func_name,
"st_squaregrid") == 0)
285 ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
286 errmsg(
"%s called from unsupported functional context '%s'", __func__, func_name)));
289 funcctx->user_fctx = state;
292 if (get_call_result_type(fcinfo, 0, &funcctx->tuple_desc) != TYPEFUNC_COMPOSITE)
294 ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
295 errmsg(
"set-valued function called in context that cannot accept a set")));
298 BlessTupleDesc(funcctx->tuple_desc);
299 MemoryContextSwitchTo(oldcontext);
303 funcctx = SRF_PERCALL_SETUP();
306 state = funcctx->user_fctx;
311 SRF_RETURN_DONE(funcctx);
315 tuple_arr[1] = Int32GetDatum(state->
i);
316 tuple_arr[2] = Int32GetDatum(state->
j);
332 ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
333 errmsg(
"%s called from with unsupported shape '%d'", __func__, state->
cell_shape)));
336 tuple_arr[0] = PointerGetDatum(geometry_serialize(lwgeom));
340 tuple = heap_form_tuple(funcctx->tuple_desc, tuple_arr, isnull);
341 result = HeapTupleGetDatum(tuple);
342 SRF_RETURN_NEXT(funcctx,
result);
352 double size = PG_GETARG_FLOAT8(0);
354 int cell_i = PG_GETARG_INT32(1);
355 int cell_j = PG_GETARG_INT32(2);
362 elog(ERROR,
"%s: origin point is empty", __func__);
369 elog(ERROR,
"%s: origin argument is not a point", __func__);
374 size, cell_i, cell_j,
377 ghex = geometry_serialize(lwhex);
378 PG_FREE_IF_COPY(gorigin, 3);
379 PG_RETURN_POINTER(ghex);
390 double size = PG_GETARG_FLOAT8(0);
392 int cell_i = PG_GETARG_INT32(1);
393 int cell_j = PG_GETARG_INT32(2);
400 elog(ERROR,
"%s: origin point is empty", __func__);
407 elog(ERROR,
"%s: origin argument is not a point", __func__);
412 size, cell_i, cell_j,
415 gsqr = geometry_serialize(lwsqr);
416 PG_FREE_IF_COPY(gorigin, 3);
417 PG_RETURN_POINTER(gsqr);
char result[OUT_DOUBLE_BUFFER_SIZE]
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)...
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
double lwpoint_get_x(const LWPOINT *point)
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...
LWPOLY * lwpoly_construct_envelope(int32_t srid, double x1, double y1, double x2, double y2)
void * lwalloc(size_t size)
LWPOLY * lwpoly_construct(int32_t srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
double lwpoint_get_y(const LWPOINT *point)
This library is the generic geometry handling section of PostGIS.
static void square_state_next(SquareGridState *state)
static void hexagon_state_next(HexagonGridState *state)
PG_FUNCTION_INFO_V1(ST_ShapeGrid)
ST_HexagonGrid(size float8, bounds geometry) ST_SquareGrid(size float8, bounds geometry)
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 const double hex_x[]
struct HexagonGridState HexagonGridState
static const double hex_y[]
static LWGEOM * hexagon(double origin_x, double origin_y, double size, int cell_i, int cell_j, int32_t srid)
Datum ST_Square(PG_FUNCTION_ARGS)
static LWGEOM * square(double origin_x, double origin_y, double size, int cell_i, int cell_j, int32_t srid)
Datum ST_ShapeGrid(PG_FUNCTION_ARGS)
struct SquareGridState SquareGridState
struct GeometryGridState GeometryGridState
Datum ST_Hexagon(PG_FUNCTION_ARGS)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)