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