From a08e57357a8c322d6b36cb41fe747ae3c4c94cd0 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Mon, 29 Sep 2014 15:33:14 -0700 Subject: [PATCH] Coalesce geometries of features with the same attributes --- README.md | 4 ++-- tile.cc | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e9561fd..4516101 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,8 @@ in some places), so I need to figure out an equitable way to throw features away It also throws away any polygons that are too small to draw. I'm not sure yet if it is appropriate to do more than that. -It should consolidate features in the same tile that share the same type and attributes, -to make the tile data smaller, but doesn't do that yet. +Features in the same tile that share the same type and attributes are coalesced +together into a single geometry. Development ----------- diff --git a/tile.cc b/tile.cc index bb68446..7aad026 100644 --- a/tile.cc +++ b/tile.cc @@ -446,6 +446,27 @@ struct coalesce { int *meta; }; +int coalcmp(const void *v1, const void *v2) { + const struct coalesce *c1 = (const struct coalesce *) v1; + const struct coalesce *c2 = (const struct coalesce *) v2; + + int cmp = c1->type - c2->type; + if (cmp != 0) { + return cmp; + } + + int i; + for (i = 0; i < c1->nmeta && i < c2->nmeta; i++) { + cmp = c1->meta[i] - c2->meta[i]; + + if (cmp != 0) { + return cmp; + } + } + + return c1->nmeta - c2->nmeta; +} + long long write_tile(struct index *start, struct index *end, char *metabase, unsigned *file_bbox, int z, unsigned tx, unsigned ty, int detail, int basezoom, struct pool *file_keys, char *layername, sqlite3 *outdb) { GOOGLE_PROTOBUF_VERIFY_VERSION; @@ -554,7 +575,28 @@ long long write_tile(struct index *start, struct index *end, char *metabase, uns } } + qsort(features, nfeatures, sizeof(struct coalesce), coalcmp); int x; + + int out = 0; + for (x = 0; x < nfeatures; x++) { + if (out > 0 && features[out - 1].ngeom + features[x].ngeom < 20000 && coalcmp(&features[x], &features[out - 1]) == 0) { + struct draw *tmp = (struct draw *) malloc((features[x].ngeom + features[out - 1].ngeom) * sizeof(struct draw)); + memcpy(tmp, features[out - 1].geom, features[out - 1].ngeom * sizeof(struct draw)); + memcpy(tmp + features[out - 1].ngeom, features[x].geom, features[x].ngeom * sizeof(struct draw)); + + free(features[x].geom); + free(features[out - 1].geom); + free(features[x].meta); + + features[out - 1].ngeom += features[x].ngeom; + features[out - 1].geom = tmp; + } else { + features[out++] = features[x]; + } + } + nfeatures = out; + for (x = 0; x < nfeatures; x++) { mapnik::vector::tile_feature *feature = layer->add_features();