26 #include "utils/builtins.h"
27 #include "executor/spi.h"
28 #include "../postgis_config.h"
29 #include "lwgeom_pg.h"
34 #ifdef HAVE_LIBPROTOBUF
35 #include "vector_tile.pb-c.h"
44 #ifndef HAVE_LIBPROTOBUF
45 elog(ERROR,
"ST_AsMVTGeom: Compiled without protobuf-c support");
51 bool clip_geom =
true;
53 LWGEOM *lwgeom_in, *lwgeom_out;
63 elog(ERROR,
"%s: Geometric bounds cannot be null", __func__);
66 bounds = (
GBOX *)PG_GETARG_POINTER(1);
69 elog(ERROR,
"%s: Geometric bounds are too small", __func__);
73 extent = PG_ARGISNULL(2) ? 4096 : PG_GETARG_INT32(2);
76 elog(ERROR,
"%s: Extent must be greater than 0", __func__);
80 buffer = PG_ARGISNULL(3) ? 256 : PG_GETARG_INT32(3);
81 clip_geom = PG_ARGISNULL(4) ? true : PG_GETARG_BOOL(4);
83 geom_in = PG_GETARG_GSERIALIZED_P_COPY(0);
95 double geom_width = gserialized_box.
xmax - gserialized_box.
xmin;
96 double geom_height = gserialized_box.
ymax - gserialized_box.
ymin;
100 double bounds_width = ((bounds->
xmax - bounds->
xmin) / extent) / 2.0;
101 double bounds_height = ((bounds->
ymax - bounds->
ymin) / extent) / 2.0;
102 if (geom_width < bounds_width && geom_height < bounds_height)
111 lwgeom_out =
mvt_geom(lwgeom_in, bounds, extent,
buffer, clip_geom);
112 if (lwgeom_out == NULL)
115 geom_out = geometry_serialize(lwgeom_out);
117 PG_FREE_IF_COPY(geom_in, 0);
118 PG_RETURN_POINTER(geom_out);
128 #ifndef HAVE_LIBPROTOBUF
129 elog(ERROR,
"ST_AsMVT: Compiled without protobuf-c support");
132 MemoryContext aggcontext, old_context;
136 postgis_initialize_cache();
138 if (!AggCheckCallContext(fcinfo, &aggcontext))
139 elog(ERROR,
"%s called in non-aggregate context", __func__);
141 if (PG_ARGISNULL(0)) {
142 old_context = MemoryContextSwitchTo(aggcontext);
143 ctx = palloc(
sizeof(*ctx));
144 ctx->
name =
"default";
145 if (PG_NARGS() > 2 && !PG_ARGISNULL(2))
146 ctx->
name = text_to_cstring(PG_GETARG_TEXT_P(2));
148 if (PG_NARGS() > 3 && !PG_ARGISNULL(3))
149 ctx->
extent = PG_GETARG_INT32(3);
151 if (PG_NARGS() > 4 && !PG_ARGISNULL(4))
152 ctx->
geom_name = text_to_cstring(PG_GETARG_TEXT_P(4));
153 if (PG_NARGS() > 5 && !PG_ARGISNULL(5))
154 ctx->
id_name = text_to_cstring(PG_GETARG_TEXT_P(5));
158 ctx->
trans_context = AllocSetContextCreate(aggcontext,
"MVT transfn", ALLOCSET_DEFAULT_SIZES);
162 MemoryContextSwitchTo(old_context);
167 if (!type_is_rowtype(get_fn_expr_argtype(fcinfo->flinfo, 1)))
168 elog(ERROR,
"%s: parameter row cannot be other than a rowtype", __func__);
169 ctx->
row = PG_GETARG_HEAPTUPLEHEADER(1);
173 MemoryContextSwitchTo(old_context);
175 PG_FREE_IF_COPY(ctx->
row, 1);
176 PG_RETURN_POINTER(ctx);
186 #ifndef HAVE_LIBPROTOBUF
187 elog(ERROR,
"ST_AsMVT: Compiled without protobuf-c support");
192 elog(DEBUG2,
"%s called", __func__);
193 if (!AggCheckCallContext(fcinfo, NULL))
194 elog(ERROR,
"%s called in non-aggregate context", __func__);
198 bytea *emptybuf = palloc(VARHDRSZ);
199 SET_VARSIZE(emptybuf, VARHDRSZ);
200 PG_RETURN_BYTEA_P(emptybuf);
205 PG_RETURN_BYTEA_P(buf);
212 #ifndef HAVE_LIBPROTOBUF
213 elog(ERROR,
"ST_AsMVT: Compiled without protobuf-c support");
218 elog(DEBUG2,
"%s called", __func__);
219 if (!AggCheckCallContext(fcinfo, NULL))
220 elog(ERROR,
"%s called in non-aggregate context", __func__);
224 bytea *emptybuf = palloc(VARHDRSZ);
225 SET_VARSIZE(emptybuf, VARHDRSZ);
226 PG_RETURN_BYTEA_P(emptybuf);
234 PG_RETURN_BYTEA_P(
result);
242 #ifndef HAVE_LIBPROTOBUF
243 elog(ERROR,
"ST_AsMVT: Compiled without protobuf-c support");
246 MemoryContext aggcontext, oldcontext;
248 elog(DEBUG2,
"%s called", __func__);
249 if (!AggCheckCallContext(fcinfo, &aggcontext))
250 elog(ERROR,
"%s called in non-aggregate context", __func__);
252 oldcontext = MemoryContextSwitchTo(aggcontext);
254 MemoryContextSwitchTo(oldcontext);
256 PG_RETURN_POINTER(ctx);
263 #ifndef HAVE_LIBPROTOBUF
264 elog(ERROR,
"ST_AsMVT: Compiled without protobuf-c support");
267 MemoryContext aggcontext, oldcontext;
269 elog(DEBUG2,
"%s called", __func__);
270 if (!AggCheckCallContext(fcinfo, &aggcontext))
271 elog(ERROR,
"%s called in non-aggregate context", __func__);
275 oldcontext = MemoryContextSwitchTo(aggcontext);
277 MemoryContextSwitchTo(oldcontext);
278 PG_RETURN_POINTER(ctx);
char result[OUT_DOUBLE_BUFFER_SIZE]
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
int gserialized_fast_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or return #LWFAILURE if box is unavailable.
void lwgeom_free(LWGEOM *geom)
This library is the generic geometry handling section of PostGIS.
Datum ST_AsMVTGeom(PG_FUNCTION_ARGS)
Datum pgis_asmvt_serialfn(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(ST_AsMVTGeom)
Process input parameters to mvt_geom and returned serialized geometry.
Datum pgis_asmvt_finalfn(PG_FUNCTION_ARGS)
Datum pgis_asmvt_transfn(PG_FUNCTION_ARGS)
Datum pgis_asmvt_deserialfn(PG_FUNCTION_ARGS)
Datum pgis_asmvt_combinefn(PG_FUNCTION_ARGS)
mvt_agg_context * mvt_ctx_combine(mvt_agg_context *ctx1, mvt_agg_context *ctx2)
mvt_agg_context * mvt_ctx_deserialize(const bytea *ba)
LWGEOM * mvt_geom(LWGEOM *lwgeom, const GBOX *gbox, uint32_t extent, uint32_t buffer, bool clip_geom)
Transform a geometry into vector tile coordinate space.
bytea * mvt_agg_finalfn(mvt_agg_context *ctx)
Finalize aggregation.
bytea * mvt_ctx_serialize(mvt_agg_context *ctx)
void mvt_agg_init_context(mvt_agg_context *ctx)
Initialize aggregation context.
void mvt_agg_transfn(mvt_agg_context *ctx)
Aggregation step.
Datum buffer(PG_FUNCTION_ARGS)
MemoryContext trans_context