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