PostGIS  2.5.0dev-r@@SVN_REVISION@@
geobuf.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 <math.h>
26 #include "geobuf.h"
27 
28 #ifdef HAVE_LIBPROTOBUF
29 
30 #define FEATURES_CAPACITY_INITIAL 50
31 #define MAX_PRECISION 1e6
32 
33 static Data__Geometry *encode_geometry(struct geobuf_agg_context *ctx,
34  LWGEOM *lwgeom);
35 
36 static Data__Geometry *galloc(Data__Geometry__Type type) {
37  Data__Geometry *geometry;
38  geometry = palloc (sizeof (Data__Geometry));
39  data__geometry__init(geometry);
40  geometry->type = type;
41  return geometry;
42 }
43 
44 static TupleDesc get_tuple_desc(struct geobuf_agg_context *ctx)
45 {
46  Oid tupType = HeapTupleHeaderGetTypeId(ctx->row);
47  int32 tupTypmod = HeapTupleHeaderGetTypMod(ctx->row);
48  TupleDesc tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
49  return tupdesc;
50 }
51 
52 static void encode_keys(struct geobuf_agg_context *ctx)
53 {
54  TupleDesc tupdesc = get_tuple_desc(ctx);
55  uint32_t natts = (uint32_t) tupdesc->natts;
56  char **keys = palloc(natts * sizeof(*keys));
57  uint32_t i, k = 0;
58  bool geom_found = false;
59  for (i = 0; i < natts; i++) {
60 #if POSTGIS_PGSQL_VERSION < 110
61  Oid typoid = getBaseType(tupdesc->attrs[i]->atttypid);
62  char *tkey = tupdesc->attrs[i]->attname.data;
63 #else
64  Oid typoid = getBaseType(tupdesc->attrs[i].atttypid);
65  char *tkey = tupdesc->attrs[i].attname.data;
66 #endif
67  char *key = pstrdup(tkey);
68  if (ctx->geom_name == NULL) {
69  if (!geom_found && typoid == TypenameGetTypid("geometry")) {
70  ctx->geom_index = i;
71  geom_found = 1;
72  continue;
73  }
74  } else {
75  if (!geom_found && strcmp(key, ctx->geom_name) == 0) {
76  ctx->geom_index = i;
77  geom_found = 1;
78  continue;
79  }
80  }
81  keys[k++] = key;
82  }
83  if (!geom_found)
84  elog(ERROR, "encode_keys: no geometry column found");
85  ctx->data->n_keys = k;
86  ctx->data->keys = keys;
87  ReleaseTupleDesc(tupdesc);
88 }
89 
90 
91 static void set_int_value(Data__Value *value, int64 intval) {
92  if (intval >= 0) {
93  value->value_type_case = DATA__VALUE__VALUE_TYPE_POS_INT_VALUE;
94  value->pos_int_value = (uint64_t) intval;
95  } else {
96  value->value_type_case = DATA__VALUE__VALUE_TYPE_NEG_INT_VALUE;
97  value->neg_int_value = (uint64_t) labs(intval);
98  }
99 }
100 
101 static void encode_properties(struct geobuf_agg_context *ctx,
102  Data__Feature *feature)
103 {
104  uint32_t *properties;
105  Data__Value **values;
106  uint32_t i, k = 0, c = 0;
107  TupleDesc tupdesc = get_tuple_desc(ctx);
108  uint32_t natts = (uint32_t) tupdesc->natts;
109  properties = palloc(sizeof (*properties) * (natts - 1) * 2);
110  values = palloc (sizeof (*values) * (natts - 1));
111 
112  for (i = 0; i < natts; i++) {
113  Data__Value *value;
114  char *type, *string_value;
115  Datum datum;
116  bool isnull;
117 
118  if (i == ctx->geom_index)
119  continue;
120  k++;
121 
122  value = palloc (sizeof (*value));
123  data__value__init(value);
124 
125  type = SPI_gettype(tupdesc, i + 1);
126  datum = GetAttributeByNum(ctx->row, i + 1, &isnull);
127  if (isnull)
128  continue;
129 #if POSTGIS_PGSQL_VERSION < 110
130  Oid typoid = getBaseType(tupdesc->attrs[i]->atttypid);
131 #else
132  Oid typoid = getBaseType(tupdesc->attrs[i].atttypid);
133 #endif
134  if (strcmp(type, "int2") == 0) {
135  set_int_value(value, DatumGetInt16(datum));
136  } else if (strcmp(type, "int4") == 0) {
137  set_int_value(value, DatumGetInt32(datum));
138  } else if (strcmp(type, "int8") == 0) {
139  set_int_value(value, DatumGetInt64(datum));
140  } else if (strcmp(type, "float4") == 0) {
141  value->value_type_case = DATA__VALUE__VALUE_TYPE_DOUBLE_VALUE;
142  value->double_value = DatumGetFloat4(datum);
143  } else if (strcmp(type, "float8") == 0) {
144  value->value_type_case = DATA__VALUE__VALUE_TYPE_DOUBLE_VALUE;
145  value->double_value = DatumGetFloat8(datum);
146  } else {
147  Oid foutoid;
148  bool typisvarlena;
149  getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
150  string_value = OidOutputFunctionCall(foutoid, datum);
151  value->value_type_case = DATA__VALUE__VALUE_TYPE_STRING_VALUE;
152  value->string_value = string_value;
153  }
154  properties[c * 2] = k - 1;
155  properties[c * 2 + 1] = c;
156  values[c++] = value;
157  }
158 
159  ReleaseTupleDesc(tupdesc);
160 
161  feature->n_values = c;
162  feature->values = values;
163  feature->n_properties = c * 2;
164  feature->properties = properties;
165 }
166 
167 static int64_t *encode_coords(struct geobuf_agg_context *ctx, POINTARRAY *pa,
168  int64_t *coords, int len, int offset)
169 {
170  int i, c;
171  POINT4D pt;
172  int64_t sum[] = { 0, 0, 0, 0 };
173 
174  if (offset == 0)
175  coords = palloc(sizeof (int64_t) * len * ctx->dimensions);
176  else
177  coords = repalloc(coords, sizeof (int64_t) *
178  ((len * ctx->dimensions) + offset));
179 
180  c = offset;
181  for (i = 0; i < len; i++) {
182  getPoint4d_p(pa, i, &pt);
183  sum[0] += coords[c++] = (int64_t) (ceil(pt.x * ctx->e) - sum[0]);
184  sum[1] += coords[c++] = (int64_t) (ceil(pt.y * ctx->e) - sum[1]);
185  if (ctx->dimensions == 3)
186  sum[2] += coords[c++] = (int64_t) (ceil(pt.z * ctx->e) - sum[2]);
187  else if (ctx->dimensions == 4)
188  sum[3] += coords[c++] = (int64_t) (ceil(pt.m * ctx->e) - sum[3]);
189  }
190  return coords;
191 }
192 
193 static Data__Geometry *encode_point(struct geobuf_agg_context *ctx,
194  LWPOINT *lwpoint)
195 {
196  int npoints;
197  Data__Geometry *geometry;
198  POINTARRAY *pa;
199 
200  geometry = galloc(DATA__GEOMETRY__TYPE__POINT);
201 
202  pa = lwpoint->point;
203  npoints = pa->npoints;
204 
205  if (npoints == 0)
206  return geometry;
207 
208  geometry->n_coords = npoints * ctx->dimensions;
209  geometry->coords = encode_coords(ctx, pa, NULL, 1, 0);
210 
211  return geometry;
212 }
213 
214 static Data__Geometry *encode_mpoint(struct geobuf_agg_context *ctx,
215  LWMPOINT *lwmpoint)
216 {
217  int i, ngeoms;
218  POINTARRAY *pa;
219  Data__Geometry *geometry;
220 
221  geometry = galloc(DATA__GEOMETRY__TYPE__MULTIPOINT);
222 
223  ngeoms = lwmpoint->ngeoms;
224 
225  if (ngeoms == 0)
226  return geometry;
227 
228  pa = ptarray_construct_empty(0, 0, ngeoms);
229 
230  for (i = 0; i < ngeoms; i++) {
231  POINT4D pt;
232  getPoint4d_p(lwmpoint->geoms[i]->point, 0, &pt);
233  ptarray_append_point(pa, &pt, 0);
234  }
235 
236  geometry->n_coords = ngeoms * ctx->dimensions;
237  geometry->coords = encode_coords(ctx, pa, NULL, ngeoms, 0);
238 
239  return geometry;
240 }
241 
242 static Data__Geometry *encode_line(struct geobuf_agg_context *ctx,
243  LWLINE *lwline)
244 {
245  POINTARRAY *pa;
246  Data__Geometry *geometry;
247 
248  geometry = galloc(DATA__GEOMETRY__TYPE__LINESTRING);
249 
250  pa = lwline->points;
251 
252  if (pa->npoints == 0)
253  return geometry;
254 
255  geometry->n_coords = pa->npoints * ctx->dimensions;
256  geometry->coords = encode_coords(ctx, pa, NULL, pa->npoints, 0);
257 
258  return geometry;
259 }
260 
261 static Data__Geometry *encode_mline(struct geobuf_agg_context *ctx,
262  LWMLINE *lwmline)
263 {
264  int i, offset, ngeoms;
265  POINTARRAY *pa;
266  Data__Geometry *geometry;
267  uint32_t *lengths;
268  int64_t *coords = NULL;
269 
270  geometry = galloc(DATA__GEOMETRY__TYPE__MULTILINESTRING);
271 
272  ngeoms = lwmline->ngeoms;
273 
274  if (ngeoms == 0)
275  return geometry;
276 
277  lengths = palloc (sizeof (uint32_t) * ngeoms);
278 
279  offset = 0;
280  for (i = 0; i < ngeoms; i++) {
281  pa = lwmline->geoms[i]->points;
282  coords = encode_coords(ctx, pa, coords, pa->npoints, offset);
283  offset += pa->npoints * ctx->dimensions;
284  lengths[i] = pa->npoints;
285  }
286 
287  if (ngeoms > 1) {
288  geometry->n_lengths = ngeoms;
289  geometry->lengths = lengths;
290  }
291 
292  geometry->n_coords = offset;
293  geometry->coords = coords;
294 
295  return geometry;
296 }
297 
298 static Data__Geometry *encode_poly(struct geobuf_agg_context *ctx,
299  LWPOLY *lwpoly)
300 {
301  int i, len, nrings, offset;
302  POINTARRAY *pa;
303  Data__Geometry *geometry;
304  uint32_t *lengths;
305  int64_t *coords = NULL;
306 
307  geometry = galloc(DATA__GEOMETRY__TYPE__POLYGON);
308 
309  nrings = lwpoly->nrings;
310 
311  if (nrings == 0)
312  return geometry;
313 
314  lengths = palloc (sizeof (uint32_t) * nrings);
315 
316  offset = 0;
317  for (i = 0; i < nrings; i++) {
318  pa = lwpoly->rings[i];
319  len = pa->npoints - 1;
320  coords = encode_coords(ctx, pa, coords, len, offset);
321  offset += len * ctx->dimensions;
322  lengths[i] = len;
323  }
324 
325  if (nrings > 1) {
326  geometry->n_lengths = nrings;
327  geometry->lengths = lengths;
328  }
329 
330  geometry->n_coords = offset;
331  geometry->coords = coords;
332 
333  return geometry;
334 }
335 
336 static Data__Geometry *encode_mpoly(struct geobuf_agg_context *ctx,
337  LWMPOLY* lwmpoly)
338 {
339  int i, j, c, len, offset, n_lengths, ngeoms, nrings;
340  POINTARRAY *pa;
341  Data__Geometry *geometry;
342  uint32_t *lengths;
343  int64_t *coords = NULL;
344 
345  geometry = galloc(DATA__GEOMETRY__TYPE__MULTIPOLYGON);
346 
347  ngeoms = lwmpoly->ngeoms;
348 
349  if (ngeoms == 0) return geometry;
350 
351  n_lengths = 1;
352  for (i = 0; i < ngeoms; i++) {
353  nrings = lwmpoly->geoms[i]->nrings;
354  n_lengths++;
355  for (j = 0; j < nrings; j++)
356  n_lengths++;
357  }
358 
359  lengths = palloc (sizeof (uint32_t) * n_lengths);
360 
361  c = 0;
362  offset = 0;
363  lengths[c++] = ngeoms;
364  for (i = 0; i < ngeoms; i++) {
365  nrings = lwmpoly->geoms[i]->nrings;
366  lengths[c++] = nrings;
367  for (j = 0; j < nrings; j++) {
368  pa = lwmpoly->geoms[i]->rings[j];
369  len = pa->npoints - 1;
370  coords = encode_coords(ctx, pa, coords, len, offset);
371  offset += len * ctx->dimensions;
372  lengths[c++] = len;
373  }
374  }
375 
376  if (c > 1) {
377  geometry->n_lengths = n_lengths;
378  geometry->lengths = lengths;
379  }
380 
381  geometry->n_coords = offset;
382  geometry->coords = coords;
383 
384  return geometry;
385 }
386 
387 static Data__Geometry *encode_collection(struct geobuf_agg_context *ctx,
388  LWCOLLECTION* lwcollection)
389 {
390  int i, ngeoms;
391  Data__Geometry *geometry, **geometries;
392 
393  geometry = galloc(DATA__GEOMETRY__TYPE__GEOMETRYCOLLECTION);
394 
395  ngeoms = lwcollection->ngeoms;
396 
397  if (ngeoms == 0)
398  return geometry;
399 
400  geometries = palloc (sizeof (Data__Geometry *) * ngeoms);
401  for (i = 0; i < ngeoms; i++) {
402  LWGEOM *lwgeom = lwcollection->geoms[i];
403  Data__Geometry *geom = encode_geometry(ctx, lwgeom);
404  geometries[i] = geom;
405  }
406 
407  geometry->n_geometries = ngeoms;
408  geometry->geometries = geometries;
409 
410  return geometry;
411 }
412 
413 static Data__Geometry *encode_geometry(struct geobuf_agg_context *ctx,
414  LWGEOM *lwgeom)
415 {
416  int type = lwgeom->type;
417  switch (type)
418  {
419  case POINTTYPE:
420  return encode_point(ctx, (LWPOINT*)lwgeom);
421  case LINETYPE:
422  return encode_line(ctx, (LWLINE*)lwgeom);
423  case POLYGONTYPE:
424  return encode_poly(ctx, (LWPOLY*)lwgeom);
425  case MULTIPOINTTYPE:
426  return encode_mpoint(ctx, (LWMPOINT*)lwgeom);
427  case MULTILINETYPE:
428  return encode_mline(ctx, (LWMLINE*)lwgeom);
429  case MULTIPOLYGONTYPE:
430  return encode_mpoly(ctx, (LWMPOLY*)lwgeom);
431  case COLLECTIONTYPE:
432  return encode_collection(ctx, (LWCOLLECTION*)lwgeom);
433  default:
434  elog(ERROR, "encode_geometry: '%s' geometry type not supported",
435  lwtype_name(type));
436  }
437  return NULL;
438 }
439 
440 static void analyze_val(struct geobuf_agg_context *ctx, double val)
441 {
442  if (fabs((round(val * ctx->e) / ctx->e) - val) >= EPSILON &&
443  ctx->e < MAX_PRECISION)
444  ctx->e *= 10;
445 }
446 
447 static void analyze_pa(struct geobuf_agg_context *ctx, POINTARRAY *pa)
448 {
449  uint32_t i;
450  POINT4D pt;
451  for (i = 0; i < pa->npoints; i++) {
452  getPoint4d_p(pa, i, &pt);
453  analyze_val(ctx, pt.x);
454  analyze_val(ctx, pt.y);
455  if (ctx->dimensions == 3)
456  analyze_val(ctx, pt.z);
457  if (ctx->dimensions == 4)
458  analyze_val(ctx, pt.m);
459  }
460 }
461 
462 static void analyze_geometry(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
463 {
464  uint32_t i, type;
465  LWLINE *lwline;
466  LWPOLY *lwpoly;
467  LWCOLLECTION *lwcollection;
468  type = lwgeom->type;
469  switch (type)
470  {
471  case POINTTYPE:
472  case LINETYPE:
473  lwline = (LWLINE*) lwgeom;
474  analyze_pa(ctx, lwline->points);
475  break;
476  case POLYGONTYPE:
477  lwpoly = (LWPOLY*) lwgeom;
478  for (i = 0; i < lwpoly->nrings; i++)
479  analyze_pa(ctx, lwpoly->rings[i]);
480  break;
481  case MULTIPOINTTYPE:
482  case MULTILINETYPE:
483  case MULTIPOLYGONTYPE:
484  case COLLECTIONTYPE:
485  lwcollection = (LWCOLLECTION*) lwgeom;
486  for (i = 0; i < lwcollection->ngeoms; i++)
487  analyze_geometry(ctx, lwcollection->geoms[i]);
488  break;
489  default:
490  elog(ERROR, "analyze_geometry: '%s' geometry type not supported",
491  lwtype_name(type));
492  }
493 }
494 
496  LWGEOM *lwgeom)
497 {
498  if (!ctx->has_dimensions) {
499  if (FLAGS_GET_Z(lwgeom->flags) || FLAGS_GET_M(lwgeom->flags))
500  ctx->dimensions = 3;
501  else if (FLAGS_GET_ZM(lwgeom->flags))
502  ctx->dimensions = 4;
503  else
504  ctx->dimensions = 2;
505  ctx->has_dimensions = 1;
506  }
507 }
508 
509 static Data__Feature *encode_feature(struct geobuf_agg_context *ctx)
510 {
511  Data__Feature *feature;
512 
513  feature = palloc (sizeof (Data__Feature));
514  data__feature__init(feature);
515 
516  encode_properties(ctx, feature);
517  return feature;
518 }
519 
524 {
525  Data *data;
526  Data__FeatureCollection *fc;
527 
528  ctx->has_dimensions = 0;
529  ctx->dimensions = 2;
530  ctx->has_precision = 0;
531  ctx->precision = MAX_PRECISION;
532  ctx->e = 1;
534 
535  data = palloc(sizeof(*data));
536  data__init(data);
537 
538  fc = palloc(sizeof(*fc));
539  data__feature_collection__init(fc);
540 
541  fc->features = palloc (ctx->features_capacity *
542  sizeof(*fc->features));
543 
544  ctx->lwgeoms = palloc (ctx->features_capacity *
545  sizeof(*ctx->lwgeoms));
546 
547  data->data_type_case = DATA__DATA_TYPE_FEATURE_COLLECTION;
548  data->feature_collection = fc;
549 
550  ctx->data = data;
551 }
552 
561 {
562  LWGEOM *lwgeom;
563  bool isnull = false;
564  Datum datum;
565  Data__FeatureCollection *fc = ctx->data->feature_collection;
566 /* Data__Feature **features = fc->features; */
567  Data__Feature *feature;
568  GSERIALIZED *gs;
569  if (fc->n_features >= ctx->features_capacity) {
570  size_t new_capacity = ctx->features_capacity * 2;
571  fc->features = repalloc(fc->features, new_capacity *
572  sizeof(*fc->features));
573  ctx->lwgeoms = repalloc(ctx->lwgeoms, new_capacity *
574  sizeof(*ctx->lwgeoms));
575  ctx->features_capacity = new_capacity;
576  }
577 
578  /* inspect row and encode keys assuming static schema */
579  if (fc->n_features == 0)
580  encode_keys(ctx);
581 
582  datum = GetAttributeByNum(ctx->row, ctx->geom_index + 1, &isnull);
583  if (isnull)
584  return;
585 
586  gs = (GSERIALIZED *) PG_DETOAST_DATUM_COPY(datum);
587  lwgeom = lwgeom_from_gserialized(gs);
588 
589  feature = encode_feature(ctx);
590 
591  /* inspect geometry flags assuming static schema */
592  if (fc->n_features == 0)
593  analyze_geometry_flags(ctx, lwgeom);
594 
595  analyze_geometry(ctx, lwgeom);
596 
597  ctx->lwgeoms[fc->n_features] = lwgeom;
598  fc->features[fc->n_features++] = feature;
599 }
600 
607 {
608  size_t i;
609  Data *data;
610  Data__FeatureCollection *fc;
611 
612  data = ctx->data;
613  fc = data->feature_collection;
614 
615  /* check and set dimensions if not default */
616  if (ctx->dimensions != 2) {
617  data->has_dimensions = ctx->has_dimensions;
618  data->dimensions = ctx->dimensions;
619  }
620 
621  /* check and set precision if not default */
622  if (ctx->e > MAX_PRECISION)
623  ctx->e = MAX_PRECISION;
624  ctx->precision = ceil(log(ctx->e) / log(10));
625  if (ctx->precision != 6) {
626  data->has_precision = 1;
627  data->precision = ctx->precision;
628  }
629 
630  for (i = 0; i < fc->n_features; i++)
631  fc->features[i]->geometry = encode_geometry(ctx, ctx->lwgeoms[i]);
632 
633  size_t len = data__get_packed_size(data);
634  uint8_t *buf = palloc(sizeof(*buf) * (len + VARHDRSZ));
635  data__pack(data, buf + VARHDRSZ);
636 
637  SET_VARSIZE(buf, VARHDRSZ + len);
638 
639  return buf;
640 }
641 
642 #endif
double x
Definition: liblwgeom.h:351
#define LINETYPE
Definition: liblwgeom.h:85
HeapTupleHeader row
Definition: geobuf.h:52
unsigned int int32
Definition: shpopen.c:273
static Data__Geometry * encode_mline(struct geobuf_agg_context *ctx, LWMLINE *lwmline)
Definition: geobuf.c:261
static void analyze_geometry_flags(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
Definition: geobuf.c:495
double m
Definition: liblwgeom.h:351
static Data__Geometry * encode_geometry(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
Definition: geobuf.c:413
uint32_t ngeoms
Definition: liblwgeom.h:467
protobuf_c_boolean has_precision
Definition: geobuf.h:58
protobuf_c_boolean has_dimensions
Definition: geobuf.h:60
tuple data
Definition: ovdump.py:103
static Data__Geometry * encode_collection(struct geobuf_agg_context *ctx, LWCOLLECTION *lwcollection)
Definition: geobuf.c:387
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint32_t ngeoms
Definition: liblwgeom.h:493
#define POLYGONTYPE
Definition: liblwgeom.h:86
uint8_t flags
Definition: liblwgeom.h:396
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
#define MULTIPOINTTYPE
Definition: liblwgeom.h:87
static Data__Geometry * encode_poly(struct geobuf_agg_context *ctx, LWPOLY *lwpoly)
Definition: geobuf.c:298
void geobuf_agg_transfn(struct geobuf_agg_context *ctx)
Aggregation step.
Definition: geobuf.c:560
#define FLAGS_GET_ZM(flags)
Definition: liblwgeom.h:152
static Data__Geometry * galloc(Data__Geometry__Type type)
Definition: geobuf.c:36
#define FEATURES_CAPACITY_INITIAL
Definition: geobuf.c:30
uint32_t ngeoms
Definition: liblwgeom.h:506
POINTARRAY * point
Definition: liblwgeom.h:410
#define MAX_PRECISION
Definition: geobuf.c:31
static Data__Geometry * encode_mpoly(struct geobuf_agg_context *ctx, LWMPOLY *lwmpoly)
Definition: geobuf.c:336
static TupleDesc get_tuple_desc(struct geobuf_agg_context *ctx)
Definition: geobuf.c:44
uint32_t nrings
Definition: liblwgeom.h:454
static Data__Geometry * encode_point(struct geobuf_agg_context *ctx, LWPOINT *lwpoint)
Definition: geobuf.c:193
uint32_t dimensions
Definition: geobuf.h:61
unsigned int uint32_t
Definition: uthash.h:78
uint32_t precision
Definition: geobuf.h:59
void geobuf_agg_init_context(struct geobuf_agg_context *ctx)
Initialize aggregation context.
Definition: geobuf.c:523
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
size_t features_capacity
Definition: geobuf.h:56
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE, then a duplicate point will not be added.
Definition: ptarray.c:156
static void analyze_val(struct geobuf_agg_context *ctx, double val)
Definition: geobuf.c:440
LWPOLY ** geoms
Definition: liblwgeom.h:495
static void analyze_pa(struct geobuf_agg_context *ctx, POINTARRAY *pa)
Definition: geobuf.c:447
LWGEOM ** geoms
Definition: liblwgeom.h:508
uint8_t * geobuf_agg_finalfn(struct geobuf_agg_context *ctx)
Finalize aggregation.
Definition: geobuf.c:606
static int64_t * encode_coords(struct geobuf_agg_context *ctx, POINTARRAY *pa, int64_t *coords, int len, int offset)
Definition: geobuf.c:167
LWGEOM ** lwgeoms
Definition: geobuf.h:53
POINTARRAY ** rings
Definition: liblwgeom.h:456
uint32_t geom_index
Definition: geobuf.h:51
LWPOINT ** geoms
Definition: liblwgeom.h:469
static void encode_keys(struct geobuf_agg_context *ctx)
Definition: geobuf.c:52
static Data__Feature * encode_feature(struct geobuf_agg_context *ctx)
Definition: geobuf.c:509
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:139
double z
Definition: liblwgeom.h:351
static Data__Geometry * encode_mpoint(struct geobuf_agg_context *ctx, LWMPOINT *lwmpoint)
Definition: geobuf.c:214
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:113
static void encode_properties(struct geobuf_agg_context *ctx, Data__Feature *feature)
Definition: geobuf.c:101
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:89
uint32_t ngeoms
Definition: liblwgeom.h:480
LWLINE ** geoms
Definition: liblwgeom.h:482
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:84
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:140
static void analyze_geometry(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
Definition: geobuf.c:462
uint8_t type
Definition: liblwgeom.h:395
static void set_int_value(Data__Value *value, int64 intval)
Definition: geobuf.c:91
double y
Definition: liblwgeom.h:351
#define MULTILINETYPE
Definition: liblwgeom.h:88
static Data__Geometry * encode_line(struct geobuf_agg_context *ctx, LWLINE *lwline)
Definition: geobuf.c:242
unsigned char uint8_t
Definition: uthash.h:79
uint32_t e
Definition: geobuf.h:57
char * geom_name
Definition: geobuf.h:50
#define COLLECTIONTYPE
Definition: liblwgeom.h:90
POINTARRAY * points
Definition: liblwgeom.h:421
uint32_t npoints
Definition: liblwgeom.h:370