PostGIS 3.7.0dev-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
28#if defined HAVE_LIBPROTOBUF
29
30#define FEATURES_CAPACITY_INITIAL 50
31#define MAX_PRECISION 1e6
32
33static Data__Geometry *encode_geometry(struct geobuf_agg_context *ctx,
34 LWGEOM *lwgeom);
35
36static 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
44static 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
52static 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
86static 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
96static 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
161static 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
187static 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
208static 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
236static 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
255static 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
272static 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
309static 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
347static 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
398static 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
424static 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
454static 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
461static 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
476static 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
526static 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;
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
static int64_t * encode_coords(struct geobuf_agg_context *ctx, POINTARRAY *pa, int64_t *coords, int len, int offset)
Definition geobuf.c:161
static Data__Geometry * encode_mline(struct geobuf_agg_context *ctx, LWMLINE *lwmline)
Definition geobuf.c:272
static Data__Geometry * encode_collection(struct geobuf_agg_context *ctx, LWCOLLECTION *lwcollection)
Definition geobuf.c:398
static void analyze_geometry_flags(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
Definition geobuf.c:511
static Data__Geometry * galloc(Data__Geometry__Type type)
Definition geobuf.c:36
static void analyze_pa(struct geobuf_agg_context *ctx, POINTARRAY *pa)
Definition geobuf.c:461
void geobuf_agg_init_context(struct geobuf_agg_context *ctx)
Initialize aggregation context.
Definition geobuf.c:540
static Data__Geometry * encode_poly(struct geobuf_agg_context *ctx, LWPOLY *lwpoly)
Definition geobuf.c:309
void geobuf_agg_transfn(struct geobuf_agg_context *ctx)
Aggregation step.
Definition geobuf.c:577
static Data__Geometry * encode_mpoly(struct geobuf_agg_context *ctx, LWMPOLY *lwmpoly)
Definition geobuf.c:347
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 Data__Geometry * encode_point(struct geobuf_agg_context *ctx, LWPOINT *lwpoint)
Definition geobuf.c:187
static TupleDesc get_tuple_desc(struct geobuf_agg_context *ctx)
Definition geobuf.c:44
static Data__Geometry * encode_line(struct geobuf_agg_context *ctx, LWLINE *lwline)
Definition geobuf.c:236
static void encode_properties(struct geobuf_agg_context *ctx, Data__Feature *feature)
Definition geobuf.c:96
uint8_t * geobuf_agg_finalfn(struct geobuf_agg_context *ctx)
Finalize aggregation.
Definition geobuf.c:623
static void set_int_value(Data__Value *value, int64 intval)
Definition geobuf.c:86
static void encode_keys(struct geobuf_agg_context *ctx)
Definition geobuf.c:52
static Data__Geometry * encode_triangle(struct geobuf_agg_context *ctx, LWTRIANGLE *lwtri)
Definition geobuf.c:256
static Data__Feature * encode_feature(struct geobuf_agg_context *ctx)
Definition geobuf.c:526
static Data__Geometry * encode_mpoint(struct geobuf_agg_context *ctx, LWMPOINT *lwmpoint)
Definition geobuf.c:208
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.
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:108
#define MULTILINETYPE
Definition liblwgeom.h:106
#define LINETYPE
Definition liblwgeom.h:103
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
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:962
#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
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:969
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
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