From 5ab2673b8c9f1bfef02e1cd1b7b606fb2d4c0479 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Mon, 14 Sep 2015 15:42:06 -0700 Subject: [PATCH] Add a flag to preserve the original order of the features from the input --- README.md | 1 + geojson.c | 1 + man/tippecanoe.1 | 2 ++ tile.cc | 20 ++++++++++++++++++-- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 128dc90..b232611 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ Options * -pf: Don't limit tiles to 200,000 features * -pk: Don't limit tiles to 500K bytes * -pd: Dynamically drop some fraction of features from large tiles to keep them under the 500K size limit. It will probably look ugly at the tile boundaries. + * -pi: Preserve the original inport order of features as the drawing order instead of ordering geographically. (This is implemented as a restoration of the original order at the end, so that dot-dropping is still geographic, which means it also undoes -ao). * -q: Work quietly instead of reporting progress Example diff --git a/geojson.c b/geojson.c index 8b24d42..c02233c 100644 --- a/geojson.c +++ b/geojson.c @@ -499,6 +499,7 @@ int serialize_geometry(json_object *geometry, json_object *properties, const cha long long geomstart = *geompos; serialize_byte(geomfile, mb_geometry[t], geompos, fname); + serialize_long_long(geomfile, *seq, geompos, fname); serialize_long_long(geomfile, n, geompos, fname); serialize_long_long(geomfile, metastart, geompos, fname); long long wx = initial_x, wy = initial_y; diff --git a/man/tippecanoe.1 b/man/tippecanoe.1 index 44a69c0..19631e7 100644 --- a/man/tippecanoe.1 +++ b/man/tippecanoe.1 @@ -120,6 +120,8 @@ it encounters. .IP \(bu 2 \-pd: Dynamically drop some fraction of features from large tiles to keep them under the 500K size limit. It will probably look ugly at the tile boundaries. .IP \(bu 2 +\-pi: Preserve the original inport order of features as the drawing order instead of ordering geographically. (This is implemented as a restoration of the original order at the end, so that dot\-dropping is still geographic, which means it also undoes \-ao). +.IP \(bu 2 \-q: Work quietly instead of reporting progress .RE .SH Example diff --git a/tile.cc b/tile.cc index 88dbff3..d4f6003 100644 --- a/tile.cc +++ b/tile.cc @@ -133,6 +133,7 @@ struct coalesce { unsigned long long index2; char *metasrc; bool coalesced; + long long original_seq; bool operator<(const coalesce &o) const { int cmp = coalindexcmp(this, &o); @@ -144,6 +145,12 @@ struct coalesce { } }; +struct preservecmp { + bool operator()(struct coalesce &a, struct coalesce &b) { + return a.original_seq < b.original_seq; + } +} preservecmp; + int coalcmp(const void *v1, const void *v2) { const struct coalesce *c1 = (const struct coalesce *) v1; const struct coalesce *c2 = (const struct coalesce *) v2; @@ -362,7 +369,7 @@ void evaluate(std::vector &features, char *metabase, struct pool *file } #endif -void rewrite(drawvec &geom, int z, int nextzoom, int file_maxzoom, long long *bbox, unsigned tx, unsigned ty, int buffer, int line_detail, int *within, long long *geompos, FILE **geomfile, const char *fname, signed char t, int layer, long long metastart, signed char feature_minzoom) { +void rewrite(drawvec &geom, int z, int nextzoom, int file_maxzoom, long long *bbox, unsigned tx, unsigned ty, int buffer, int line_detail, int *within, long long *geompos, FILE **geomfile, const char *fname, signed char t, int layer, long long metastart, signed char feature_minzoom, long long seq) { if (geom.size() > 0 && nextzoom <= file_maxzoom) { int xo, yo; int span = 1 << (nextzoom - z); @@ -428,6 +435,7 @@ void rewrite(drawvec &geom, int z, int nextzoom, int file_maxzoom, long long *bb // printf("type %d, meta %lld\n", t, metastart); serialize_byte(geomfile[j], t, &geompos[j], fname); + serialize_long_long(geomfile[j], seq, &geompos[j], fname); serialize_long_long(geomfile[j], layer, &geompos[j], fname); serialize_long_long(geomfile[j], metastart, &geompos[j], fname); long long wx = initial_x, wy = initial_y; @@ -518,6 +526,9 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, unsigned *f break; } + long long original_seq; + deserialize_long_long(geoms, &original_seq); + long long layer; deserialize_long_long(geoms, &layer); @@ -565,7 +576,7 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, unsigned *f } if (line_detail == detail && fraction == 1) { /* only write out the next zoom once, even if we retry */ - rewrite(geom, z, nextzoom, file_maxzoom, bbox, tx, ty, buffer, line_detail, within, geompos, geomfile, fname, t, layer, metastart, feature_minzoom); + rewrite(geom, z, nextzoom, file_maxzoom, bbox, tx, ty, buffer, line_detail, within, geompos, geomfile, fname, t, layer, metastart, feature_minzoom, original_seq); } if (z < file_minzoom) { @@ -672,6 +683,7 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, unsigned *f c.geom = geom; c.metasrc = meta; c.coalesced = false; + c.original_seq = original_seq; decode_meta(&meta, stringpool, keys[layer], values[layer], file_keys[layer], &c.meta, NULL); features[layer].push_back(c); @@ -720,6 +732,10 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, unsigned *f features[j][x].geom = simplify_lines(features[j][x].geom, 32, 0); } } + + if (prevent['i' & 0xFF]) { + std::sort(features[j].begin(), features[j].end(), preservecmp); + } } if (z == 0 && unclipped_features < original_features / 2) {