PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
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
34static Data__Geometry *encode_geometry(struct geobuf_agg_context *ctx,
35 LWGEOM *lwgeom);
36
37static 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
45static 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
53static 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
87static 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
97static 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
162static 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
188static 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
209static 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
237static 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
256static 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
273static 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
310static 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
348static 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
399static 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
425static 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
455static 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
462static 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
477static 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
527static 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;
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
static int64_t * encode_coords(struct geobuf_agg_context *ctx, POINTARRAY *pa, int64_t *coords, int len, int offset)
Definition geobuf.c:162
static Data__Geometry * encode_mline(struct geobuf_agg_context *ctx, LWMLINE *lwmline)
Definition geobuf.c:273
static Data__Geometry * encode_collection(struct geobuf_agg_context *ctx, LWCOLLECTION *lwcollection)
Definition geobuf.c:399
static void analyze_geometry_flags(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
Definition geobuf.c:512
static Data__Geometry * galloc(Data__Geometry__Type type)
Definition geobuf.c:37
static void analyze_pa(struct geobuf_agg_context *ctx, POINTARRAY *pa)
Definition geobuf.c:462
void geobuf_agg_init_context(struct geobuf_agg_context *ctx)
Initialize aggregation context.
Definition geobuf.c:541
static Data__Geometry * encode_poly(struct geobuf_agg_context *ctx, LWPOLY *lwpoly)
Definition geobuf.c:310
void geobuf_agg_transfn(struct geobuf_agg_context *ctx)
Aggregation step.
Definition geobuf.c:578
static Data__Geometry * encode_mpoly(struct geobuf_agg_context *ctx, LWMPOLY *lwmpoly)
Definition geobuf.c:348
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 Data__Geometry * encode_point(struct geobuf_agg_context *ctx, LWPOINT *lwpoint)
Definition geobuf.c:188
static TupleDesc get_tuple_desc(struct geobuf_agg_context *ctx)
Definition geobuf.c:45
static Data__Geometry * encode_line(struct geobuf_agg_context *ctx, LWLINE *lwline)
Definition geobuf.c:237
static void encode_properties(struct geobuf_agg_context *ctx, Data__Feature *feature)
Definition geobuf.c:97
uint8_t * geobuf_agg_finalfn(struct geobuf_agg_context *ctx)
Finalize aggregation.
Definition geobuf.c:624
static void set_int_value(Data__Value *value, int64 intval)
Definition geobuf.c:87
static void encode_keys(struct geobuf_agg_context *ctx)
Definition geobuf.c:53
static Data__Geometry * encode_triangle(struct geobuf_agg_context *ctx, LWTRIANGLE *lwtri)
Definition geobuf.c:257
static Data__Feature * encode_feature(struct geobuf_agg_context *ctx)
Definition geobuf.c:527
static Data__Geometry * encode_mpoint(struct geobuf_agg_context *ctx, LWMPOINT *lwmpoint)
Definition geobuf.c:209
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.
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define COLLECTIONTYPE
Definition liblwgeom.h:122
#define MULTILINETYPE
Definition liblwgeom.h:120
#define LINETYPE
Definition liblwgeom.h:117
#define MULTIPOINTTYPE
Definition liblwgeom.h:119
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition ptarray.c:59
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
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
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
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