28 #if defined HAVE_LIBPROTOBUF && defined HAVE_GEOBUF
30 #define FEATURES_CAPACITY_INITIAL 50
31 #define MAX_PRECISION 1e6
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;
46 Oid tupType = HeapTupleHeaderGetTypeId(ctx->
row);
47 int32 tupTypmod = HeapTupleHeaderGetTypMod(ctx->
row);
48 TupleDesc tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
56 char **keys = palloc(natts *
sizeof(*keys));
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;
64 Oid typoid = getBaseType(tupdesc->attrs[i].atttypid);
65 char *tkey = tupdesc->attrs[i].attname.data;
67 char *key = pstrdup(tkey);
69 if (!geom_found && typoid == postgis_oid(GEOMETRYOID)) {
75 if (!geom_found && strcmp(key, ctx->
geom_name) == 0) {
84 elog(ERROR,
"encode_keys: no geometry column found");
85 ctx->
data->n_keys = k;
86 ctx->
data->keys = keys;
87 ReleaseTupleDesc(tupdesc);
93 value->value_type_case = DATA__VALUE__VALUE_TYPE_POS_INT_VALUE;
94 value->pos_int_value = (uint64_t) intval;
96 value->value_type_case = DATA__VALUE__VALUE_TYPE_NEG_INT_VALUE;
97 value->neg_int_value = (uint64_t) labs(intval);
102 Data__Feature *feature)
105 Data__Value **values;
109 properties = palloc(
sizeof (*properties) * (natts - 1) * 2);
110 values = palloc (
sizeof (*values) * (natts - 1));
112 for (i = 0; i < natts; i++) {
114 char *
type, *string_value;
124 data__value__init(
value);
126 type = SPI_gettype(tupdesc, i + 1);
127 datum = GetAttributeByNum(ctx->
row, i + 1, &isnull);
130 #if POSTGIS_PGSQL_VERSION < 110
131 typoid = getBaseType(tupdesc->attrs[i]->atttypid);
133 typoid = getBaseType(tupdesc->attrs[i].atttypid);
135 if (strcmp(
type,
"int2") == 0) {
137 }
else if (strcmp(
type,
"int4") == 0) {
139 }
else if (strcmp(
type,
"int8") == 0) {
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);
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;
155 properties[c * 2] = k - 1;
156 properties[c * 2 + 1] = c;
160 ReleaseTupleDesc(tupdesc);
162 feature->n_values = c;
163 feature->values = values;
164 feature->n_properties = c * 2;
165 feature->properties = properties;
169 int64_t *coords,
int len,
int offset)
173 int64_t sum[] = { 0, 0, 0, 0 };
176 coords = palloc(
sizeof (int64_t) * len * ctx->
dimensions);
178 coords = repalloc(coords,
sizeof (int64_t) *
182 for (i = 0; i < len; i++) {
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]);
187 sum[2] += coords[c++] = (int64_t) (ceil(pt.
z * ctx->
e) - sum[2]);
189 sum[3] += coords[c++] = (int64_t) (ceil(pt.
m * ctx->
e) - sum[3]);
198 Data__Geometry *geometry;
201 geometry =
galloc(DATA__GEOMETRY__TYPE__POINT);
209 geometry->n_coords = npoints * ctx->
dimensions;
220 Data__Geometry *geometry;
222 geometry =
galloc(DATA__GEOMETRY__TYPE__MULTIPOINT);
224 ngeoms = lwmpoint->
ngeoms;
231 for (i = 0; i < ngeoms; i++) {
237 geometry->n_coords = ngeoms * ctx->
dimensions;
247 Data__Geometry *geometry;
249 geometry =
galloc(DATA__GEOMETRY__TYPE__LINESTRING);
265 int i, offset, ngeoms;
267 Data__Geometry *geometry;
269 int64_t *coords = NULL;
271 geometry =
galloc(DATA__GEOMETRY__TYPE__MULTILINESTRING);
278 lengths = palloc (
sizeof (
uint32_t) * ngeoms);
281 for (i = 0; i < ngeoms; i++) {
289 geometry->n_lengths = ngeoms;
290 geometry->lengths = lengths;
293 geometry->n_coords = offset;
294 geometry->coords = coords;
302 int i, len, nrings, offset;
304 Data__Geometry *geometry;
306 int64_t *coords = NULL;
308 geometry =
galloc(DATA__GEOMETRY__TYPE__POLYGON);
315 lengths = palloc (
sizeof (
uint32_t) * nrings);
318 for (i = 0; i < nrings; i++) {
319 pa = lwpoly->
rings[i];
327 geometry->n_lengths = nrings;
328 geometry->lengths = lengths;
331 geometry->n_coords = offset;
332 geometry->coords = coords;
340 int i, j, c, len, offset, n_lengths, ngeoms, nrings;
342 Data__Geometry *geometry;
344 int64_t *coords = NULL;
346 geometry =
galloc(DATA__GEOMETRY__TYPE__MULTIPOLYGON);
350 if (ngeoms == 0)
return geometry;
353 for (i = 0; i < ngeoms; i++) {
356 for (j = 0; j < nrings; j++)
360 lengths = palloc (
sizeof (
uint32_t) * n_lengths);
364 lengths[c++] = ngeoms;
365 for (i = 0; i < ngeoms; i++) {
367 lengths[c++] = nrings;
368 for (j = 0; j < nrings; j++) {
378 geometry->n_lengths = n_lengths;
379 geometry->lengths = lengths;
382 geometry->n_coords = offset;
383 geometry->coords = coords;
392 Data__Geometry *geometry, **geometries;
394 geometry =
galloc(DATA__GEOMETRY__TYPE__GEOMETRYCOLLECTION);
396 ngeoms = lwcollection->
ngeoms;
401 geometries = palloc (
sizeof (Data__Geometry *) * ngeoms);
402 for (i = 0; i < ngeoms; i++) {
405 geometries[i] = geom;
408 geometry->n_geometries = ngeoms;
409 geometry->geometries = geometries;
435 elog(ERROR,
"encode_geometry: '%s' geometry type not supported",
443 if (fabs((round(val * ctx->
e) / ctx->
e) - val) >= EPSILON &&
452 for (i = 0; i < pa->
npoints; i++) {
474 lwline = (
LWLINE*) lwgeom;
478 lwpoly = (
LWPOLY*) lwgeom;
479 for (i = 0; i < lwpoly->
nrings; i++)
487 for (i = 0; i < lwcollection->
ngeoms; i++)
491 elog(ERROR,
"analyze_geometry: '%s' geometry type not supported",
512 Data__Feature *feature;
514 feature = palloc (
sizeof (Data__Feature));
515 data__feature__init(feature);
527 Data__FeatureCollection *fc;
539 fc = palloc(
sizeof(*fc));
540 data__feature_collection__init(fc);
543 sizeof(*fc->features));
548 data->data_type_case = DATA__DATA_TYPE_FEATURE_COLLECTION;
549 data->feature_collection = fc;
566 Data__FeatureCollection *fc = ctx->
data->feature_collection;
568 Data__Feature *feature;
572 fc->features = repalloc(fc->features, new_capacity *
573 sizeof(*fc->features));
580 if (fc->n_features == 0)
583 datum = GetAttributeByNum(ctx->
row, ctx->
geom_index + 1, &isnull);
593 if (fc->n_features == 0)
598 ctx->
lwgeoms[fc->n_features] = lwgeom;
599 fc->features[fc->n_features++] = feature;
611 Data__FeatureCollection *fc;
615 fc =
data->feature_collection;
628 data->has_precision = 1;
632 for (i = 0; i < fc->n_features; i++)
635 len = data__get_packed_size(
data);
636 buf = palloc(
sizeof(*buf) * (len + VARHDRSZ));
637 data__pack(
data, buf + VARHDRSZ);
639 SET_VARSIZE(buf, VARHDRSZ + len);
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint8_t * geobuf_agg_finalfn(struct geobuf_agg_context *ctx)
Finalize aggregation.
static void analyze_geometry_flags(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
static void analyze_pa(struct geobuf_agg_context *ctx, POINTARRAY *pa)
static Data__Feature * encode_feature(struct geobuf_agg_context *ctx)
void geobuf_agg_init_context(struct geobuf_agg_context *ctx)
Initialize aggregation context.
static Data__Geometry * encode_line(struct geobuf_agg_context *ctx, LWLINE *lwline)
void geobuf_agg_transfn(struct geobuf_agg_context *ctx)
Aggregation step.
static Data__Geometry * encode_mline(struct geobuf_agg_context *ctx, LWMLINE *lwmline)
static Data__Geometry * galloc(Data__Geometry__Type type)
static void analyze_geometry(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
#define FEATURES_CAPACITY_INITIAL
static void analyze_val(struct geobuf_agg_context *ctx, double val)
static TupleDesc get_tuple_desc(struct geobuf_agg_context *ctx)
static Data__Geometry * encode_mpoly(struct geobuf_agg_context *ctx, LWMPOLY *lwmpoly)
static Data__Geometry * encode_poly(struct geobuf_agg_context *ctx, LWPOLY *lwpoly)
static void encode_properties(struct geobuf_agg_context *ctx, Data__Feature *feature)
static Data__Geometry * encode_collection(struct geobuf_agg_context *ctx, LWCOLLECTION *lwcollection)
static Data__Geometry * encode_mpoint(struct geobuf_agg_context *ctx, LWMPOINT *lwmpoint)
static void set_int_value(Data__Value *value, int64 intval)
static Data__Geometry * encode_point(struct geobuf_agg_context *ctx, LWPOINT *lwpoint)
static int64_t * encode_coords(struct geobuf_agg_context *ctx, POINTARRAY *pa, int64_t *coords, int len, int offset)
static void encode_keys(struct geobuf_agg_context *ctx)
static Data__Geometry * encode_geometry(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
#define FLAGS_GET_M(flags)
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
#define FLAGS_GET_ZM(flags)
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,...
protobuf_c_boolean has_precision
protobuf_c_boolean has_dimensions