mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Stabilize feature order in overzoom (#210)
* Stabilize feature order in overzoom
* I want my sorts to be stable, please
* Revert "[ci] test in debug mode (#202)"
This reverts commit 853ada87b5.
* No need to reinitialize here
This commit is contained in:
@@ -5,10 +5,7 @@ on: [push]
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
version: ['Release', 'Debug']
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: uname -a; BUILDTYPE=${{ matrix.version }} make
|
- run: uname -a; make
|
||||||
- run: make test
|
- run: make test
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
# 2.47.0
|
||||||
|
|
||||||
|
* Stabilize feature order in tippecanoe-overzoom when --preserve-feature-order is specified but the sequence attribute is not present
|
||||||
|
|
||||||
# 2.46.0
|
# 2.46.0
|
||||||
|
|
||||||
* Polygon dust returns to having the attributes of the contributing feature nearest the placeholder instead of the contributing feature with the largest area.
|
* Polygon dust returns to having the attributes of the contributing feature nearest the placeholder instead of the contributing feature with the largest area.
|
||||||
|
|||||||
@@ -278,6 +278,12 @@ overzoom-test: tippecanoe-overzoom
|
|||||||
./tippecanoe-decode tests/pbf/13-1310-3166.pbf 13 1310 3166 > tests/pbf/13-1310-3166.pbf.json.check
|
./tippecanoe-decode tests/pbf/13-1310-3166.pbf 13 1310 3166 > tests/pbf/13-1310-3166.pbf.json.check
|
||||||
cmp tests/pbf/13-1310-3166.pbf.json.check tests/pbf/13-1310-3166.pbf.json
|
cmp tests/pbf/13-1310-3166.pbf.json.check tests/pbf/13-1310-3166.pbf.json
|
||||||
rm tests/pbf/13-1310-3166.pbf tests/pbf/13-1310-3166.pbf.json.check
|
rm tests/pbf/13-1310-3166.pbf tests/pbf/13-1310-3166.pbf.json.check
|
||||||
|
# Make sure feature order is stable
|
||||||
|
./tippecanoe-overzoom --preserve-input-order -o tests/pbf/11-327-791-out.pbf tests/pbf/11-327-791.pbf 11/327/791 11/327/791
|
||||||
|
./tippecanoe-decode tests/pbf/11-327-791.pbf 11 327 791 > tests/pbf/11-327-791.json
|
||||||
|
./tippecanoe-decode tests/pbf/11-327-791-out.pbf 11 327 791 > tests/pbf/11-327-791-out.json
|
||||||
|
cmp tests/pbf/11-327-791.json tests/pbf/11-327-791-out.json
|
||||||
|
rm tests/pbf/11-327-791.json tests/pbf/11-327-791-out.json tests/pbf/11-327-791-out.pbf
|
||||||
# Different detail and buffer, and attribute stripping
|
# Different detail and buffer, and attribute stripping
|
||||||
./tippecanoe-overzoom -d8 -b30 -y NAME -y name -y scalerank -o tests/pbf/13-1310-3166-8-30.pbf tests/pbf/11-327-791.pbf 11/327/791 13/1310/3166
|
./tippecanoe-overzoom -d8 -b30 -y NAME -y name -y scalerank -o tests/pbf/13-1310-3166-8-30.pbf tests/pbf/11-327-791.pbf 11/327/791 13/1310/3166
|
||||||
./tippecanoe-decode tests/pbf/13-1310-3166-8-30.pbf 13 1310 3166 > tests/pbf/13-1310-3166-8-30.pbf.json.check
|
./tippecanoe-decode tests/pbf/13-1310-3166-8-30.pbf 13 1310 3166 > tests/pbf/13-1310-3166-8-30.pbf.json.check
|
||||||
|
|||||||
@@ -1026,7 +1026,7 @@ std::string overzoom(const mvt_tile &tile, int oz, int ox, int oy, int nz, int n
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (preserve_input_order) {
|
if (preserve_input_order) {
|
||||||
std::sort(outlayer.features.begin(), outlayer.features.end(), preservecmp);
|
std::stable_sort(outlayer.features.begin(), outlayer.features.end(), preservecmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outlayer.features.size() > 0) {
|
if (outlayer.features.size() > 0) {
|
||||||
|
|||||||
+1
-1
@@ -176,7 +176,7 @@ std::vector<zxy> enumerate_dirtiles(const char *fname, int minzoom, int maxzoom)
|
|||||||
closedir(d1);
|
closedir(d1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(tiles.begin(), tiles.end());
|
std::stable_sort(tiles.begin(), tiles.end());
|
||||||
return tiles;
|
return tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1189,7 +1189,7 @@ drawvec polygon_to_anchor(const drawvec &geom) {
|
|||||||
std::vector<candidate> candidates;
|
std::vector<candidate> candidates;
|
||||||
|
|
||||||
for (size_t pass = 0; pass < 4; pass++) {
|
for (size_t pass = 0; pass < 4; pass++) {
|
||||||
std::sort(points.begin(), points.end(), sorty_sorter(pass));
|
std::stable_sort(points.begin(), points.end(), sorty_sorter(pass));
|
||||||
|
|
||||||
for (size_t i = 1; i < points.size(); i++) {
|
for (size_t i = 1; i < points.size(); i++) {
|
||||||
double dx = points[i].x - points[i - 1].x;
|
double dx = points[i].x - points[i - 1].x;
|
||||||
@@ -1213,7 +1213,7 @@ drawvec polygon_to_anchor(const drawvec &geom) {
|
|||||||
// segment, if we find one whose midpoint is inside the polygon and
|
// segment, if we find one whose midpoint is inside the polygon and
|
||||||
// far enough from any edge to be good enough, stop looking.
|
// far enough from any edge to be good enough, stop looking.
|
||||||
|
|
||||||
std::sort(candidates.begin(), candidates.end());
|
std::stable_sort(candidates.begin(), candidates.end());
|
||||||
// only check the top 50 stride midpoints, since this list can be quite large
|
// only check the top 50 stride midpoints, since this list can be quite large
|
||||||
for (size_t i = 0; i < candidates.size() && i < 50; i++) {
|
for (size_t i = 0; i < candidates.size() && i < 50; i++) {
|
||||||
double maybe_goodness = label_goodness(geom, candidates[i].x, candidates[i].y);
|
double maybe_goodness = label_goodness(geom, candidates[i].x, candidates[i].y);
|
||||||
|
|||||||
@@ -2704,7 +2704,7 @@ std::pair<int, metadata> read_input(std::vector<source> &sources, char *fname, i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(ddv.begin(), ddv.end());
|
std::stable_sort(ddv.begin(), ddv.end());
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (int z = 0; z <= basezoom; z++) {
|
for (int z = 0; z <= basezoom; z++) {
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ std::string mvt_tile::encode() {
|
|||||||
sorted_values.push_back(std::move(sv));
|
sorted_values.push_back(std::move(sv));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(sorted_values.begin(), sorted_values.end());
|
std::stable_sort(sorted_values.begin(), sorted_values.end());
|
||||||
std::vector<size_t> mapping;
|
std::vector<size_t> mapping;
|
||||||
mapping.resize(sorted_values.size());
|
mapping.resize(sorted_values.size());
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -174,7 +174,7 @@ void mbtiles_map_image_to_pmtiles(char *fname, metadata m, bool tile_compression
|
|||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(tile_ids.begin(), tile_ids.end());
|
std::stable_sort(tile_ids.begin(), tile_ids.end());
|
||||||
|
|
||||||
std::unordered_map<std::string, std::pair<unsigned long long, unsigned long>> hash_to_offset_len;
|
std::unordered_map<std::string, std::pair<unsigned long long, unsigned long>> hash_to_offset_len;
|
||||||
std::vector<pmtiles::entryv3> entries;
|
std::vector<pmtiles::entryv3> entries;
|
||||||
@@ -263,7 +263,7 @@ void mbtiles_map_image_to_pmtiles(char *fname, metadata m, bool tile_compression
|
|||||||
|
|
||||||
// finalize PMTiles archive.
|
// finalize PMTiles archive.
|
||||||
{
|
{
|
||||||
std::sort(entries.begin(), entries.end(), pmtiles::entryv3_cmp());
|
std::stable_sort(entries.begin(), entries.end(), pmtiles::entryv3_cmp());
|
||||||
|
|
||||||
std::string root_bytes;
|
std::string root_bytes;
|
||||||
std::string leaves_bytes;
|
std::string leaves_bytes;
|
||||||
|
|||||||
+1
-1
@@ -604,7 +604,7 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::
|
|||||||
locs.push_back(encode_index(SHIFT_LEFT(scaled_geometry[i].x), SHIFT_LEFT(scaled_geometry[i].y)));
|
locs.push_back(encode_index(SHIFT_LEFT(scaled_geometry[i].x), SHIFT_LEFT(scaled_geometry[i].y)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(locs.begin(), locs.end());
|
std::stable_sort(locs.begin(), locs.end());
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
double sum = 0;
|
double sum = 0;
|
||||||
for (size_t i = 1; i < locs.size(); i++) {
|
for (size_t i = 1; i < locs.size(); i++) {
|
||||||
|
|||||||
+2
-2
@@ -136,7 +136,7 @@ bool find_common_edges(std::vector<serial_feature> &features, int z, int line_de
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(edges.begin(), edges.end(), edgecmp_ring);
|
std::stable_sort(edges.begin(), edges.end(), edgecmp_ring);
|
||||||
std::set<draw> necessaries;
|
std::set<draw> necessaries;
|
||||||
|
|
||||||
// Now mark all the points where the set of rings using the edge on one side
|
// Now mark all the points where the set of rings using the edge on one side
|
||||||
@@ -397,7 +397,7 @@ bool find_common_edges(std::vector<serial_feature> &features, int z, int line_de
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(order.begin(), order.end());
|
std::stable_sort(order.begin(), order.end());
|
||||||
|
|
||||||
size_t merged = 0;
|
size_t merged = 0;
|
||||||
for (size_t o = 0; o < order.size(); o++) {
|
for (size_t o = 0; o < order.size(); o++) {
|
||||||
|
|||||||
+1
-1
@@ -584,7 +584,7 @@ struct tileset_reader {
|
|||||||
next_overzoomed_tiles.clear();
|
next_overzoomed_tiles.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(overzoomed_tiles.begin(), overzoomed_tiles.end(), tilecmp);
|
std::stable_sort(overzoomed_tiles.begin(), overzoomed_tiles.end(), tilecmp);
|
||||||
overzoom_consumed_at_this_zoom = false;
|
overzoom_consumed_at_this_zoom = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ static std::vector<serial_feature> disassemble_multiplier_clusters(std::vector<s
|
|||||||
|
|
||||||
// sort the other features by their drop sequence, for consistency across zoom levels
|
// sort the other features by their drop sequence, for consistency across zoom levels
|
||||||
if (cluster.size() > 1) {
|
if (cluster.size() > 1) {
|
||||||
std::sort(cluster.begin() + 1, cluster.end(), drop_sequence_cmp());
|
std::stable_sort(cluster.begin() + 1, cluster.end(), drop_sequence_cmp());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const &feature : cluster) {
|
for (auto const &feature : cluster) {
|
||||||
@@ -814,7 +814,7 @@ static unsigned long long choose_mingap(std::vector<unsigned long long> const &i
|
|||||||
// If there are no higher extents available, the tile has already been reduced as much as possible
|
// If there are no higher extents available, the tile has already been reduced as much as possible
|
||||||
// and tippecanoe will exit with an error.
|
// and tippecanoe will exit with an error.
|
||||||
static long long choose_minextent(std::vector<long long> &extents, double f, long long existing_extent) {
|
static long long choose_minextent(std::vector<long long> &extents, double f, long long existing_extent) {
|
||||||
std::sort(extents.begin(), extents.end());
|
std::stable_sort(extents.begin(), extents.end());
|
||||||
|
|
||||||
size_t ix = (extents.size() - 1) * (1 - f);
|
size_t ix = (extents.size() - 1) * (1 - f);
|
||||||
while (ix + 1 < extents.size() && extents[ix] == existing_extent) {
|
while (ix + 1 < extents.size() && extents[ix] == existing_extent) {
|
||||||
@@ -829,7 +829,7 @@ static unsigned long long choose_mindrop_sequence(std::vector<unsigned long long
|
|||||||
return ULLONG_MAX;
|
return ULLONG_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(drop_sequences.begin(), drop_sequences.end());
|
std::stable_sort(drop_sequences.begin(), drop_sequences.end());
|
||||||
|
|
||||||
size_t ix = (drop_sequences.size() - 1) * (1 - f);
|
size_t ix = (drop_sequences.size() - 1) * (1 - f);
|
||||||
while (ix + 1 < drop_sequences.size() && drop_sequences[ix] == existing_drop_sequence) {
|
while (ix + 1 < drop_sequences.size() && drop_sequences[ix] == existing_drop_sequence) {
|
||||||
@@ -2009,7 +2009,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
|||||||
// Reorder and coalesce.
|
// Reorder and coalesce.
|
||||||
// Sort back into input order or by attribute value
|
// Sort back into input order or by attribute value
|
||||||
|
|
||||||
std::sort(shared_nodes.begin(), shared_nodes.end());
|
std::stable_sort(shared_nodes.begin(), shared_nodes.end());
|
||||||
|
|
||||||
for (auto &kv : layers) {
|
for (auto &kv : layers) {
|
||||||
std::string const &layername = kv.first;
|
std::string const &layername = kv.first;
|
||||||
@@ -2031,7 +2031,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
|||||||
// these will be smaller numbers, and avoid the problem of the
|
// these will be smaller numbers, and avoid the problem of the
|
||||||
// original sequence number varying based on how many reader threads
|
// original sequence number varying based on how many reader threads
|
||||||
// there were reading the input
|
// there were reading the input
|
||||||
std::sort(feature_sequences.begin(), feature_sequences.end());
|
std::stable_sort(feature_sequences.begin(), feature_sequences.end());
|
||||||
for (size_t i = 0; i < feature_sequences.size(); i++) {
|
for (size_t i = 0; i < feature_sequences.size(); i++) {
|
||||||
size_t j = feature_sequences[i].second;
|
size_t j = feature_sequences[i].second;
|
||||||
serial_val sv(mvt_double, std::to_string(i));
|
serial_val sv(mvt_double, std::to_string(i));
|
||||||
@@ -2151,7 +2151,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
|||||||
std::vector<serial_feature> &layer_features = features;
|
std::vector<serial_feature> &layer_features = features;
|
||||||
|
|
||||||
if (additional[A_REORDER]) {
|
if (additional[A_REORDER]) {
|
||||||
std::sort(layer_features.begin(), layer_features.end(), coalindexcmp_comparator());
|
std::stable_sort(layer_features.begin(), layer_features.end(), coalindexcmp_comparator());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (additional[A_COALESCE]) {
|
if (additional[A_COALESCE]) {
|
||||||
@@ -2215,13 +2215,13 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
|||||||
|
|
||||||
if (prevent[P_INPUT_ORDER]) {
|
if (prevent[P_INPUT_ORDER]) {
|
||||||
auto clustered = assemble_multiplier_clusters(layer_features);
|
auto clustered = assemble_multiplier_clusters(layer_features);
|
||||||
std::sort(clustered.begin(), clustered.end(), preservecmp);
|
std::stable_sort(clustered.begin(), clustered.end(), preservecmp);
|
||||||
layer_features = disassemble_multiplier_clusters(clustered);
|
layer_features = disassemble_multiplier_clusters(clustered);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order_by.size() != 0) {
|
if (order_by.size() != 0) {
|
||||||
auto clustered = assemble_multiplier_clusters(layer_features);
|
auto clustered = assemble_multiplier_clusters(layer_features);
|
||||||
std::sort(clustered.begin(), clustered.end(), ordercmp());
|
std::stable_sort(clustered.begin(), clustered.end(), ordercmp());
|
||||||
layer_features = disassemble_multiplier_clusters(clustered);
|
layer_features = disassemble_multiplier_clusters(clustered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#ifndef VERSION_HPP
|
#ifndef VERSION_HPP
|
||||||
#define VERSION_HPP
|
#define VERSION_HPP
|
||||||
|
|
||||||
#define VERSION "v2.46.0"
|
#define VERSION "v2.47.0"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user