PostGIS  3.0.0dev-r@@SVN_REVISION@@
lwgeom_out_mvt.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright (C) 2016-2017 Bj√∂rn Harrtell <bjorn@wololo.org>
22  *
23  **********************************************************************/
24 
25 #include "postgres.h"
26 #include "utils/builtins.h"
27 #include "executor/spi.h"
28 #include "../postgis_config.h"
29 #include "lwgeom_pg.h"
30 #include "lwgeom_log.h"
31 #include "liblwgeom.h"
32 #include "mvt.h"
33 
34 #ifdef HAVE_LIBPROTOBUF
35 #include "vector_tile.pb-c.h"
36 #endif /* HAVE_LIBPROTOBUF */
37 
42 Datum ST_AsMVTGeom(PG_FUNCTION_ARGS)
43 {
44 #ifndef HAVE_LIBPROTOBUF
45  elog(ERROR, "Missing libprotobuf-c");
46  PG_RETURN_NULL();
47 #else
48  LWGEOM *lwgeom_in, *lwgeom_out;
49  GSERIALIZED *geom_in, *geom_out;
50  GBOX *bounds;
51  int extent, buffer;
52  bool clip_geom;
53  if (PG_ARGISNULL(0))
54  PG_RETURN_NULL();
55  geom_in = PG_GETARG_GSERIALIZED_P_COPY(0);
56  lwgeom_in = lwgeom_from_gserialized(geom_in);
57  if (PG_ARGISNULL(1))
58  elog(ERROR, "%s: parameter bounds cannot be null", __func__);
59  bounds = (GBOX *) PG_GETARG_POINTER(1);
60  extent = PG_ARGISNULL(2) ? 4096 : PG_GETARG_INT32(2);
61  buffer = PG_ARGISNULL(3) ? 256 : PG_GETARG_INT32(3);
62  clip_geom = PG_ARGISNULL(4) ? true : PG_GETARG_BOOL(4);
63  // NOTE: can both return in clone and in place modification so
64  // not known if lwgeom_in can be freed
65  lwgeom_out = mvt_geom(lwgeom_in, bounds, extent, buffer, clip_geom);
66  if (lwgeom_out == NULL)
67  PG_RETURN_NULL();
68  geom_out = geometry_serialize(lwgeom_out);
69  lwgeom_free(lwgeom_out);
70  PG_FREE_IF_COPY(geom_in, 0);
71  PG_RETURN_POINTER(geom_out);
72 #endif
73 }
74 
79 Datum pgis_asmvt_transfn(PG_FUNCTION_ARGS)
80 {
81 #ifndef HAVE_LIBPROTOBUF
82  elog(ERROR, "Missing libprotobuf-c");
83  PG_RETURN_NULL();
84 #else
85  MemoryContext aggcontext;
86  mvt_agg_context *ctx;
87 
88  if (!AggCheckCallContext(fcinfo, &aggcontext))
89  elog(ERROR, "%s called in non-aggregate context", __func__);
90  MemoryContextSwitchTo(aggcontext);
91 
92  if (PG_ARGISNULL(0)) {
93  ctx = palloc(sizeof(*ctx));
94  ctx->name = "default";
95  if (PG_NARGS() > 2 && !PG_ARGISNULL(2))
96  ctx->name = text_to_cstring(PG_GETARG_TEXT_P(2));
97  ctx->extent = 4096;
98  if (PG_NARGS() > 3 && !PG_ARGISNULL(3))
99  ctx->extent = PG_GETARG_INT32(3);
100  ctx->geom_name = NULL;
101  if (PG_NARGS() > 4 && !PG_ARGISNULL(4))
102  ctx->geom_name = text_to_cstring(PG_GETARG_TEXT_P(4));
103  if (PG_NARGS() > 5 && !PG_ARGISNULL(5))
104  ctx->id_name = text_to_cstring(PG_GETARG_TEXT_P(5));
105  else
106  ctx->id_name = NULL;
108  } else {
109  ctx = (mvt_agg_context *) PG_GETARG_POINTER(0);
110  }
111 
112  if (!type_is_rowtype(get_fn_expr_argtype(fcinfo->flinfo, 1)))
113  elog(ERROR, "%s: parameter row cannot be other than a rowtype", __func__);
114  ctx->row = PG_GETARG_HEAPTUPLEHEADER(1);
115 
116  mvt_agg_transfn(ctx);
117  PG_FREE_IF_COPY(ctx->row, 1);
118  PG_RETURN_POINTER(ctx);
119 #endif
120 }
121 
126 Datum pgis_asmvt_finalfn(PG_FUNCTION_ARGS)
127 {
128 #ifndef HAVE_LIBPROTOBUF
129  elog(ERROR, "Missing libprotobuf-c");
130  PG_RETURN_NULL();
131 #else
132  mvt_agg_context *ctx;
133  bytea *buf;
134  elog(DEBUG2, "%s called", __func__);
135  if (!AggCheckCallContext(fcinfo, NULL))
136  elog(ERROR, "%s called in non-aggregate context", __func__);
137 
138  if (PG_ARGISNULL(0))
139  {
140  bytea *emptybuf = palloc(VARHDRSZ);
141  SET_VARSIZE(emptybuf, VARHDRSZ);
142  PG_RETURN_BYTEA_P(emptybuf);
143  }
144 
145  ctx = (mvt_agg_context *) PG_GETARG_POINTER(0);
146  buf = mvt_agg_finalfn(ctx);
147  PG_RETURN_BYTEA_P(buf);
148 #endif
149 }
150 
152 Datum pgis_asmvt_serialfn(PG_FUNCTION_ARGS)
153 {
154 #ifndef HAVE_LIBPROTOBUF
155  elog(ERROR, "Missing libprotobuf-c");
156  PG_RETURN_NULL();
157 #else
158  mvt_agg_context *ctx;
159  elog(DEBUG2, "%s called", __func__);
160  if (!AggCheckCallContext(fcinfo, NULL))
161  elog(ERROR, "%s called in non-aggregate context", __func__);
162 
163  if (PG_ARGISNULL(0))
164  {
165  bytea *emptybuf = palloc(VARHDRSZ);
166  SET_VARSIZE(emptybuf, VARHDRSZ);
167  PG_RETURN_BYTEA_P(emptybuf);
168  }
169 
170  ctx = (mvt_agg_context *) PG_GETARG_POINTER(0);
171  PG_RETURN_BYTEA_P(mvt_ctx_serialize(ctx));
172 #endif
173 }
174 
175 
177 Datum pgis_asmvt_deserialfn(PG_FUNCTION_ARGS)
178 {
179 #ifndef HAVE_LIBPROTOBUF
180  elog(ERROR, "Missing libprotobuf-c");
181  PG_RETURN_NULL();
182 #else
183  MemoryContext aggcontext, oldcontext;
184  mvt_agg_context *ctx;
185  elog(DEBUG2, "%s called", __func__);
186  if (!AggCheckCallContext(fcinfo, &aggcontext))
187  elog(ERROR, "%s called in non-aggregate context", __func__);
188 
189  oldcontext = MemoryContextSwitchTo(aggcontext);
190  ctx = mvt_ctx_deserialize(PG_GETARG_BYTEA_P(0));
191  MemoryContextSwitchTo(oldcontext);
192 
193  PG_RETURN_POINTER(ctx);
194 #endif
195 }
196 
198 Datum pgis_asmvt_combinefn(PG_FUNCTION_ARGS)
199 {
200 #ifndef HAVE_LIBPROTOBUF
201  elog(ERROR, "Missing libprotobuf-c");
202  PG_RETURN_NULL();
203 #else
204  MemoryContext aggcontext, oldcontext;
205  mvt_agg_context *ctx, *ctx1, *ctx2;
206  elog(DEBUG2, "%s called", __func__);
207  if (!AggCheckCallContext(fcinfo, &aggcontext))
208  elog(ERROR, "%s called in non-aggregate context", __func__);
209 
210  ctx1 = (mvt_agg_context*)PG_GETARG_POINTER(0);
211  ctx2 = (mvt_agg_context*)PG_GETARG_POINTER(1);
212  oldcontext = MemoryContextSwitchTo(aggcontext);
213  ctx = mvt_ctx_combine(ctx1, ctx2);
214  MemoryContextSwitchTo(oldcontext);
215  PG_RETURN_POINTER(ctx);
216 #endif
217 }
218 
HeapTupleHeader row
Definition: mvt.h:66
char * text_to_cstring(const text *textptr)
Datum pgis_asmvt_combinefn(PG_FUNCTION_ARGS)
char * name
Definition: mvt.h:60
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1128
char * id_name
Definition: mvt.h:62
char * geom_name
Definition: mvt.h:64
Datum ST_AsMVTGeom(PG_FUNCTION_ARGS)
mvt_agg_context * mvt_ctx_combine(mvt_agg_context *ctx1, mvt_agg_context *ctx2)
Definition: mvt.c:1264
Datum buffer(PG_FUNCTION_ARGS)
Datum pgis_asmvt_deserialfn(PG_FUNCTION_ARGS)
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.
Definition: mvt.c:831
PG_FUNCTION_INFO_V1(ST_AsMVTGeom)
Process input parameters to mvt_geom and returned serialized geometry.
Datum pgis_asmvt_finalfn(PG_FUNCTION_ARGS)
uint32_t extent
Definition: mvt.h:61
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
bytea * mvt_ctx_serialize(mvt_agg_context *ctx)
Definition: mvt.c:1089
void mvt_agg_init_context(mvt_agg_context *ctx)
Initialize aggregation context.
Definition: mvt.c:949
mvt_agg_context * mvt_ctx_deserialize(const bytea *ba)
Definition: mvt.c:1104
bytea * mvt_agg_finalfn(mvt_agg_context *ctx)
Finalize aggregation.
Definition: mvt.c:1297
This library is the generic geometry handling section of PostGIS.
Datum pgis_asmvt_transfn(PG_FUNCTION_ARGS)
Datum pgis_asmvt_serialfn(PG_FUNCTION_ARGS)
void mvt_agg_transfn(mvt_agg_context *ctx)
Aggregation step.
Definition: mvt.c:993