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