mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Improve tiling speed (#195)
* Add a way to run tippecanoe single-threaded for profiling * Do less work when the tilestats sample values list is already full * Save a copy when retrieving the attribute key * Fewer atomic operations * Move string hashing from mbtiles to text * Only do approximate attribute deduplication when writing tiles * Feature dropping tests are sensitive to exact tile size * All tile creators now create a string pool for the tile * Features clipped away to nothing should not participate in that tile * Revert "Only do approximate attribute deduplication when writing tiles" This reverts commitc42b34b498. * Also revert the related test changes * Revert "Revert "Only do approximate attribute deduplication when writing tiles"" This reverts commit18509876c3. * Be more specific about the string hash function * Use fnv1a instead of std::hash for everything * Reduce the chance of hash collisions * Stick a hash search on the front of the tree search in addpool * Eliminate repeated hashing of the same string * Switch instead of ifs in json parsing * A few more cases to populate the hash in addpool * Store the hash in the tree instead of recalculating * Add explanatory comment for mysterious argument * Fewer copies in attribute stringification * Clean up ancient weirdness in JSON attribute stringification * More serial_val cleanup * Pass a serial_feature to rewrite instead of many broken-down arguments * Get rid of the multiple geometries within `partial` * Revert "Pass a serial_feature to rewrite instead of many broken-down arguments" This reverts commit6f4ab9b725. * Goodbye, struct coalesce * Revert "Features clipped away to nothing should not participate in that tile" This reverts commit124462fbdc. * Migrating fields from partial to serial_feature * Name reconciliation between serial_feature and partial * Replace struct partial with an augmented serial_feature * Fix some overzealous search-and-replace renaming * Don't say struct so often * Remove more of the former partial construction * Commenting and cleaning up * Trying again to avoid all these arguments to rewrite * I swear I did this same thing before and it didn't work. * More rewrite cleanup * Exile --detect-shared-borders to its own file * Add missing headers * More commenting and cleanup * More comments * Sprinkle consts around * Emplacing and std::moving * More cleanup * That shouldn't have worked after a std::move * Don't need to allocate memory to compare keys * Reduce use of the global string pool in tiling * Another avoidable mvt_value construction * Further reduction to explicit string pool passing * These reverses are no longer optimizations * These layernames can all be references * Don't drag an unused layername string around with every feature * Heed a compiler warning about potential buffer overflow * Fix my confusion about which feature's string pool is relevant * Avoid some unnecessary allocations in attribute accumulation * Maybe faster serialization? * Eliminate a comparison * Do the same here * Save a couple of allocations when parsing numbers in JSON * Immediately assign features to layers instead of subdividing later * Maintain tilestats for tippecanoe:retain_points_multiplier_sequence * Crunch out more duplicate attribute values when writing out the tile * Do tilestats for tippecanoe:retain_points_multiplier_first too * Shell filters need to be real threads, even if nothing else does * Simplify tippecanoe_minzoom/maxzoom representation * Update version and changelog
This commit is contained in:
+24
-32
@@ -21,7 +21,7 @@
|
||||
#include "errors.hpp"
|
||||
#include "projection.hpp"
|
||||
|
||||
drawvec decode_geometry(char **meta, int z, unsigned tx, unsigned ty, long long *bbox, unsigned initial_x, unsigned initial_y) {
|
||||
drawvec decode_geometry(const char **meta, int z, unsigned tx, unsigned ty, long long *bbox, unsigned initial_x, unsigned initial_y) {
|
||||
drawvec out;
|
||||
|
||||
bbox[0] = LLONG_MAX;
|
||||
@@ -56,18 +56,10 @@ drawvec decode_geometry(char **meta, int z, unsigned tx, unsigned ty, long long
|
||||
wwy -= ty << (32 - z);
|
||||
}
|
||||
|
||||
if (wwx < bbox[0]) {
|
||||
bbox[0] = wwx;
|
||||
}
|
||||
if (wwy < bbox[1]) {
|
||||
bbox[1] = wwy;
|
||||
}
|
||||
if (wwx > bbox[2]) {
|
||||
bbox[2] = wwx;
|
||||
}
|
||||
if (wwy > bbox[3]) {
|
||||
bbox[3] = wwy;
|
||||
}
|
||||
bbox[0] = std::min(wwx, bbox[0]);
|
||||
bbox[1] = std::min(wwy, bbox[1]);
|
||||
bbox[2] = std::max(wwx, bbox[2]);
|
||||
bbox[3] = std::max(wwy, bbox[3]);
|
||||
|
||||
d.x = wwx;
|
||||
d.y = wwy;
|
||||
@@ -118,13 +110,13 @@ void check_polygon(drawvec &geom) {
|
||||
mapbox::geometry::linear_ring<long long> lr;
|
||||
|
||||
for (size_t k = i; k < j; k++) {
|
||||
lr.push_back(mapbox::geometry::point<long long>(geom[k].x, geom[k].y));
|
||||
lr.push_back({geom[k].x, geom[k].y});
|
||||
}
|
||||
|
||||
if (lr.size() >= 3) {
|
||||
mapbox::geometry::polygon<long long> p;
|
||||
p.push_back(lr);
|
||||
mp.push_back(p);
|
||||
p.push_back(std::move(lr));
|
||||
mp.push_back(std::move(p));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +168,7 @@ void check_polygon(drawvec &geom) {
|
||||
}
|
||||
}
|
||||
|
||||
drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *still_needs_simplification, bool *reduced_away, double *accum_area, serial_feature *this_feature, serial_feature *tiny_feature) {
|
||||
drawvec reduce_tiny_poly(drawvec const &geom, int z, int detail, bool *still_needs_simplification, bool *reduced_away, double *accum_area, serial_feature *this_feature, serial_feature *tiny_feature) {
|
||||
drawvec out;
|
||||
const double pixel = (1LL << (32 - detail - z)) * (double) tiny_polygon_size;
|
||||
bool includes_real = false;
|
||||
@@ -220,11 +212,11 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *still_needs_sim
|
||||
if (area > 0 && *accum_area > pixel * pixel) {
|
||||
// XXX use centroid;
|
||||
|
||||
out.push_back(draw(VT_MOVETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2));
|
||||
out.push_back(draw(VT_LINETO, geom[i].x - pixel / 2 + pixel, geom[i].y - pixel / 2));
|
||||
out.push_back(draw(VT_LINETO, geom[i].x - pixel / 2 + pixel, geom[i].y - pixel / 2 + pixel));
|
||||
out.push_back(draw(VT_LINETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2 + pixel));
|
||||
out.push_back(draw(VT_LINETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2));
|
||||
out.emplace_back(VT_MOVETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2 + pixel, geom[i].y - pixel / 2);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2 + pixel, geom[i].y - pixel / 2 + pixel);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2 + pixel);
|
||||
out.emplace_back(VT_LINETO, geom[i].x - pixel / 2, geom[i].y - pixel / 2);
|
||||
includes_dust = true;
|
||||
|
||||
*accum_area -= pixel * pixel;
|
||||
@@ -296,7 +288,7 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *still_needs_sim
|
||||
return out;
|
||||
}
|
||||
|
||||
int quick_check(long long *bbox, int z, long long buffer) {
|
||||
int quick_check(const long long *bbox, int z, long long buffer) {
|
||||
long long min = 0;
|
||||
long long area = 1LL << (32 - z);
|
||||
|
||||
@@ -454,7 +446,7 @@ static void douglas_peucker(drawvec &geom, int start, int n, double e, size_t ke
|
||||
// If any line segment crosses a tile boundary, add a node there
|
||||
// that cannot be simplified away, to prevent the edge of any
|
||||
// feature from jumping abruptly at the tile boundary.
|
||||
drawvec impose_tile_boundaries(drawvec &geom, long long extent) {
|
||||
drawvec impose_tile_boundaries(const drawvec &geom, long long extent) {
|
||||
drawvec out;
|
||||
|
||||
for (size_t i = 0; i < geom.size(); i++) {
|
||||
@@ -469,11 +461,11 @@ drawvec impose_tile_boundaries(drawvec &geom, long long extent) {
|
||||
|
||||
if (c > 1) { // clipped
|
||||
if (x1 != geom[i - 1].x || y1 != geom[i - 1].y) {
|
||||
out.push_back(draw(VT_LINETO, x1, y1));
|
||||
out.emplace_back(VT_LINETO, x1, y1);
|
||||
out[out.size() - 1].necessary = 1;
|
||||
}
|
||||
if (x2 != geom[i - 0].x || y2 != geom[i - 0].y) {
|
||||
out.push_back(draw(VT_LINETO, x2, y2));
|
||||
out.emplace_back(VT_LINETO, x2, y2);
|
||||
out[out.size() - 1].necessary = 1;
|
||||
}
|
||||
}
|
||||
@@ -567,17 +559,17 @@ drawvec simplify_lines(drawvec &geom, int z, int tx, int ty, int detail, bool ma
|
||||
}
|
||||
}
|
||||
|
||||
drawvec out;
|
||||
size_t out = 0;
|
||||
for (size_t i = 0; i < geom.size(); i++) {
|
||||
if (geom[i].necessary) {
|
||||
out.push_back(geom[i]);
|
||||
geom[out++] = geom[i];
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
geom.resize(out);
|
||||
return geom;
|
||||
}
|
||||
|
||||
drawvec reorder_lines(drawvec &geom) {
|
||||
drawvec reorder_lines(const drawvec &geom) {
|
||||
// Only reorder simple linestrings with a single moveto
|
||||
|
||||
if (geom.size() == 0) {
|
||||
@@ -623,7 +615,7 @@ drawvec reorder_lines(drawvec &geom) {
|
||||
return geom;
|
||||
}
|
||||
|
||||
drawvec fix_polygon(drawvec &geom) {
|
||||
drawvec fix_polygon(const drawvec &geom) {
|
||||
int outer = 1;
|
||||
drawvec out;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user