28 #if defined HAVE_LIBPROTOBUF
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);
55 uint32_t natts = (uint32_t) tupdesc->natts;
56 char **keys = palloc(natts *
sizeof(*keys));
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);
64 if (!geom_found && typoid == postgis_oid(GEOMETRYOID)) {
70 if (!geom_found && strcmp(key, ctx->
geom_name) == 0) {
79 elog(ERROR,
"encode_keys: no geometry column found");
80 ctx->
data->n_keys = k;
81 ctx->
data->keys = keys;
82 ReleaseTupleDesc(tupdesc);
88 value->value_type_case = DATA__VALUE__VALUE_TYPE_POS_INT_VALUE;
89 value->pos_int_value = (uint64_t) intval;
91 value->value_type_case = DATA__VALUE__VALUE_TYPE_NEG_INT_VALUE;
92 value->neg_int_value = (uint64_t)llabs(intval);
97 Data__Feature *feature)
100 Data__Value **values;
101 uint32_t i, k = 0, c = 0;
103 uint32_t natts = (uint32_t) tupdesc->natts;
104 properties = palloc(
sizeof (*properties) * (natts - 1) * 2);
105 values = palloc (
sizeof (*values) * (natts - 1));
107 for (i = 0; i < natts; i++) {
109 char *
type, *string_value;
119 data__value__init(
value);
121 type = SPI_gettype(tupdesc, i + 1);
122 datum = GetAttributeByNum(ctx->
row, i + 1, &isnull);
126 typoid = getBaseType(TupleDescAttr(tupdesc, i)->atttypid);
128 if (strcmp(
type,
"int2") == 0) {
130 }
else if (strcmp(
type,
"int4") == 0) {
132 }
else if (strcmp(
type,
"int8") == 0) {
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);
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;
148 properties[c * 2] = k - 1;
149 properties[c * 2 + 1] = c;
153 ReleaseTupleDesc(tupdesc);
155 feature->n_values = c;
156 feature->values = values;
157 feature->n_properties = c * 2;
158 feature->properties = properties;
162 int64_t *coords,
int len,
int offset)
166 int64_t sum[] = { 0, 0, 0, 0 };
169 coords = palloc(
sizeof (int64_t) * len * ctx->
dimensions);
171 coords = repalloc(coords,
sizeof (int64_t) *
175 for (i = 0; i < len; i++) {
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]);
180 sum[2] += coords[c++] = (int64_t) (ceil(pt.
z * ctx->
e) - sum[2]);
182 sum[3] += coords[c++] = (int64_t) (ceil(pt.
m * ctx->
e) - sum[3]);
191 Data__Geometry *geometry;
194 geometry =
galloc(DATA__GEOMETRY__TYPE__POINT);
202 geometry->n_coords = (size_t)npoints * ctx->
dimensions;
213 Data__Geometry *geometry;
215 geometry =
galloc(DATA__GEOMETRY__TYPE__MULTIPOINT);
217 ngeoms = lwmpoint->
ngeoms;
224 for (i = 0; i < ngeoms; i++) {
230 geometry->n_coords = (size_t)ngeoms * ctx->
dimensions;
240 Data__Geometry *geometry;
242 geometry =
galloc(DATA__GEOMETRY__TYPE__LINESTRING);
255 static Data__Geometry *
258 Data__Geometry *geometry =
galloc(DATA__GEOMETRY__TYPE__POLYGON);
266 geometry->n_coords = (size_t)len * ctx->
dimensions;
275 int i, offset, ngeoms;
277 Data__Geometry *geometry;
279 int64_t *coords = NULL;
281 geometry =
galloc(DATA__GEOMETRY__TYPE__MULTILINESTRING);
288 lengths = palloc (
sizeof (uint32_t) * ngeoms);
291 for (i = 0; i < ngeoms; i++) {
299 geometry->n_lengths = ngeoms;
300 geometry->lengths = lengths;
303 geometry->n_coords = offset;
304 geometry->coords = coords;
312 int i, len, nrings, offset;
314 Data__Geometry *geometry;
316 int64_t *coords = NULL;
318 geometry =
galloc(DATA__GEOMETRY__TYPE__POLYGON);
325 lengths = palloc (
sizeof (uint32_t) * nrings);
328 for (i = 0; i < nrings; i++) {
329 pa = lwpoly->
rings[i];
337 geometry->n_lengths = nrings;
338 geometry->lengths = lengths;
341 geometry->n_coords = offset;
342 geometry->coords = coords;
350 int i, j, c, len, offset, n_lengths, ngeoms, nrings;
352 Data__Geometry *geometry;
354 int64_t *coords = NULL;
356 geometry =
galloc(DATA__GEOMETRY__TYPE__MULTIPOLYGON);
360 if (ngeoms == 0)
return geometry;
363 for (i = 0; i < ngeoms; i++) {
366 for (j = 0; j < nrings; j++)
370 lengths = palloc (
sizeof (uint32_t) * n_lengths);
374 lengths[c++] = ngeoms;
375 for (i = 0; i < ngeoms; i++) {
377 lengths[c++] = nrings;
378 for (j = 0; j < nrings; j++) {
388 geometry->n_lengths = n_lengths;
389 geometry->lengths = lengths;
392 geometry->n_coords = offset;
393 geometry->coords = coords;
402 Data__Geometry *geometry, **geometries;
404 geometry =
galloc(DATA__GEOMETRY__TYPE__GEOMETRYCOLLECTION);
406 ngeoms = lwcollection->
ngeoms;
411 geometries = palloc (
sizeof (Data__Geometry *) * ngeoms);
412 for (i = 0; i < ngeoms; i++) {
415 geometries[i] = geom;
418 geometry->n_geometries = ngeoms;
419 geometry->geometries = geometries;
448 elog(ERROR,
"encode_geometry: '%s' geometry type not supported",
456 if (fabs((round(val * ctx->
e) / ctx->
e) - val) >= EPSILON &&
465 for (i = 0; i < pa->
npoints; i++) {
488 lwline = (
LWLINE*) lwgeom;
492 lwpoly = (
LWPOLY*) lwgeom;
493 for (i = 0; i < lwpoly->
nrings; i++)
502 for (i = 0; i < lwcollection->
ngeoms; i++)
506 elog(ERROR,
"analyze_geometry: '%s' geometry type not supported",
528 Data__Feature *feature;
530 feature = palloc (
sizeof (Data__Feature));
531 data__feature__init(feature);
543 Data__FeatureCollection *fc;
555 fc = palloc(
sizeof(*fc));
556 data__feature_collection__init(fc);
559 sizeof(*fc->features));
564 data->data_type_case = DATA__DATA_TYPE_FEATURE_COLLECTION;
565 data->feature_collection = fc;
582 Data__FeatureCollection *fc = ctx->
data->feature_collection;
584 Data__Feature *feature;
588 fc->features = repalloc(fc->features, new_capacity *
589 sizeof(*fc->features));
596 if (fc->n_features == 0)
599 datum = GetAttributeByNum(ctx->
row, ctx->
geom_index + 1, &isnull);
609 if (fc->n_features == 0)
614 ctx->
lwgeoms[fc->n_features] = lwgeom;
615 fc->features[fc->n_features++] = feature;
627 Data__FeatureCollection *fc;
631 fc =
data->feature_collection;
644 data->has_precision = 1;
648 for (i = 0; i < fc->n_features; i++)
651 len = data__get_packed_size(
data);
652 buf = palloc(
sizeof(*buf) * (len + VARHDRSZ));
653 data__pack(
data, buf + VARHDRSZ);
655 SET_VARSIZE(buf, VARHDRSZ + len);
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)
static Data__Geometry * encode_triangle(struct geobuf_agg_context *ctx, LWTRIANGLE *lwtri)
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)
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
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.
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
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,...
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
protobuf_c_boolean has_precision
protobuf_c_boolean has_dimensions