mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 16:35:40 +02:00
Merge branch 'h3-index' into faster-bin-assign
This commit is contained in:
+2
-4
@@ -944,12 +944,10 @@ drawvec polygon_to_anchor(const drawvec &geom) {
|
||||
return drawvec();
|
||||
}
|
||||
|
||||
drawvec checkerboard_anchors(drawvec const &geom, int tx, int ty, int z, unsigned long long label_point) {
|
||||
drawvec checkerboard_anchors(drawvec const &geom, int tx, int ty, int z, unsigned wx, unsigned wy) {
|
||||
drawvec out;
|
||||
|
||||
// anchor point in world coordinates
|
||||
unsigned wx, wy;
|
||||
decode_index(label_point, &wx, &wy);
|
||||
// wx,wy is anchor point in world coordinates
|
||||
|
||||
// upper left of tile in world coordinates
|
||||
long long tx1 = 0, ty1 = 0;
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ void check_polygon(drawvec &geom);
|
||||
double get_area(const drawvec &geom, size_t i, size_t j);
|
||||
double get_mp_area(drawvec &geom);
|
||||
drawvec polygon_to_anchor(const drawvec &geom);
|
||||
drawvec checkerboard_anchors(drawvec const &geom, int tx, int ty, int z, unsigned long long label_point);
|
||||
drawvec checkerboard_anchors(drawvec const &geom, int tx, int ty, int z, unsigned label_x, unsigned label_y);
|
||||
|
||||
drawvec simple_clip_poly(drawvec &geom, int z, int buffer, drawvec &shared_nodes, bool prevent_simplify_shared_nodes);
|
||||
drawvec simple_clip_poly(drawvec &geom, long long x1, long long y1, long long x2, long long y2, bool prevent_simplify_shared_nodes);
|
||||
|
||||
@@ -94,11 +94,13 @@ unsigned int drop_denser = 0;
|
||||
std::map<std::string, serial_val> set_attributes;
|
||||
unsigned long long preserve_point_density_threshold = 0;
|
||||
unsigned long long preserve_multiplier_density_threshold = 0;
|
||||
std::vector<int> preserve_multiplier_density_bits_by_zoom;
|
||||
long long extend_zooms_max = 0;
|
||||
int retain_points_multiplier = 1;
|
||||
std::vector<std::string> unidecode_data;
|
||||
size_t maximum_string_attribute_length = 0;
|
||||
std::string accumulate_numeric;
|
||||
std::string use_h3_index;
|
||||
|
||||
std::vector<order_field> order_by;
|
||||
bool order_reverse;
|
||||
@@ -2498,6 +2500,7 @@ std::pair<int, metadata> read_input(std::vector<source> &sources, char *fname, i
|
||||
long long ip;
|
||||
for (ip = 0; ip < indices; ip++) {
|
||||
unsigned xx, yy;
|
||||
// XXX this will behave oddly if the index is actually H3
|
||||
decode_index(map[ip].ix, &xx, &yy);
|
||||
|
||||
long long nprogress = 100 * ip / indices;
|
||||
@@ -3087,6 +3090,7 @@ int main(int argc, char **argv) {
|
||||
{"cluster-maxzoom", required_argument, 0, 'k'},
|
||||
{"preserve-point-density-threshold", required_argument, 0, '~'},
|
||||
{"preserve-multiplier-density-threshold", required_argument, 0, '~'},
|
||||
{"preserve-multiplier-density-bits-by-zoom", required_argument, 0, '~'},
|
||||
|
||||
{"Dropping or merging a fraction of features to keep under tile size limits", 0, 0, 0},
|
||||
{"drop-densest-as-needed", no_argument, &additional[A_DROP_DENSEST_AS_NEEDED], 1},
|
||||
@@ -3129,6 +3133,7 @@ int main(int argc, char **argv) {
|
||||
{"coalesce", no_argument, &additional[A_COALESCE], 1},
|
||||
{"reverse", no_argument, &additional[A_REVERSE], 1},
|
||||
{"hilbert", no_argument, &additional[A_HILBERT], 1},
|
||||
{"use-h3-index", required_argument, 0, '~'},
|
||||
{"order-by", required_argument, 0, '~'},
|
||||
{"order-descending-by", required_argument, 0, '~'},
|
||||
{"order-smallest-first", no_argument, 0, '~'},
|
||||
@@ -3270,6 +3275,8 @@ int main(int argc, char **argv) {
|
||||
fprintf(stderr, "%s: --extra-detail can be at most 30\n", argv[0]);
|
||||
exit(EXIT_ARGS);
|
||||
}
|
||||
} else if (strcmp(opt, "use-h3-index") == 0) {
|
||||
use_h3_index = optarg;
|
||||
} else if (strcmp(opt, "order-by") == 0) {
|
||||
order_by.push_back(order_field(optarg, false));
|
||||
} else if (strcmp(opt, "order-descending-by") == 0) {
|
||||
@@ -3301,6 +3308,21 @@ int main(int argc, char **argv) {
|
||||
preserve_point_density_threshold = atoll_require(optarg, "Preserve point density threshold");
|
||||
} else if (strcmp(opt, "preserve-multiplier-density-threshold") == 0) {
|
||||
preserve_multiplier_density_threshold = atoll_require(optarg, "Preserve multiplier density threshold");
|
||||
} else if (strcmp(opt, "preserve-multiplier-density-bits-by-zoom") == 0) {
|
||||
const char *cp = optarg;
|
||||
while (*cp != '\0') {
|
||||
if (!isdigit(*cp)) {
|
||||
fprintf(stderr, "%s: unexpected multiplier density bits by zoom %s\n", argv[0], cp);
|
||||
exit(EXIT_ARGS);
|
||||
}
|
||||
preserve_multiplier_density_bits_by_zoom.push_back(atoi(cp));
|
||||
while (isdigit(*cp)) {
|
||||
cp++;
|
||||
}
|
||||
if (*cp == ',') {
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(opt, "extend-zooms-if-still-dropping-maximum") == 0) {
|
||||
extend_zooms_max = atoll_require(optarg, "Maximum number by which to extend zooms");
|
||||
} else if (strcmp(opt, "retain-points-multiplier") == 0) {
|
||||
|
||||
@@ -53,7 +53,9 @@ extern long long extend_zooms_max;
|
||||
extern int retain_points_multiplier;
|
||||
extern size_t maximum_string_attribute_length;
|
||||
extern std::string accumulate_numeric;
|
||||
extern std::string use_h3_index;
|
||||
extern unsigned long long preserve_multiplier_density_threshold;
|
||||
extern std::vector<int> preserve_multiplier_density_bits_by_zoom;
|
||||
|
||||
struct order_field {
|
||||
std::string name;
|
||||
|
||||
+31
-6
@@ -186,7 +186,7 @@ std::string serialize_feature(serial_feature *sf, long long wx, long long wy) {
|
||||
|
||||
long long layer = 0;
|
||||
layer |= sf->layer << FLAG_LAYER;
|
||||
layer |= (sf->label_point != 0) << FLAG_LABEL_POINT;
|
||||
layer |= ((sf->label_x | sf->label_y) != 0) << FLAG_LABEL_POINT;
|
||||
layer |= (sf->index != 0) << FLAG_INDEX;
|
||||
layer |= (sf->extent != 0) << FLAG_EXTENT;
|
||||
layer |= sf->has_id << FLAG_ID;
|
||||
@@ -211,10 +211,13 @@ std::string serialize_feature(serial_feature *sf, long long wx, long long wy) {
|
||||
|
||||
if (sf->index != 0) {
|
||||
serialize_ulong_long(s, sf->index);
|
||||
serialize_uint(s, sf->wx);
|
||||
serialize_uint(s, sf->wy);
|
||||
serialize_ulong_long(s, sf->gap);
|
||||
}
|
||||
if (sf->label_point != 0) {
|
||||
serialize_ulong_long(s, sf->label_point);
|
||||
if ((sf->label_x | sf->label_y) != 0) {
|
||||
serialize_uint(s, sf->label_x);
|
||||
serialize_uint(s, sf->label_y);
|
||||
}
|
||||
if (sf->extent != 0) {
|
||||
serialize_long_long(s, sf->extent);
|
||||
@@ -261,17 +264,21 @@ serial_feature deserialize_feature(std::string const &geoms, unsigned z, unsigne
|
||||
|
||||
sf.index = 0;
|
||||
sf.gap = 0;
|
||||
sf.label_point = 0;
|
||||
sf.label_x = 0;
|
||||
sf.label_y = 0;
|
||||
sf.extent = 0;
|
||||
|
||||
sf.geometry = decode_geometry(&cp, z, tx, ty, sf.bbox, initial_x[sf.segment], initial_y[sf.segment]);
|
||||
|
||||
if (sf.layer & (1 << FLAG_INDEX)) {
|
||||
deserialize_ulong_long(&cp, &sf.index);
|
||||
deserialize_uint(&cp, &sf.wx);
|
||||
deserialize_uint(&cp, &sf.wy);
|
||||
deserialize_ulong_long(&cp, &sf.gap);
|
||||
}
|
||||
if (sf.layer & (1 << FLAG_LABEL_POINT)) {
|
||||
deserialize_ulong_long(&cp, &sf.label_point);
|
||||
deserialize_uint(&cp, &sf.label_x);
|
||||
deserialize_uint(&cp, &sf.label_y);
|
||||
}
|
||||
if (sf.layer & (1 << FLAG_EXTENT)) {
|
||||
deserialize_long_long(&cp, &sf.extent);
|
||||
@@ -714,6 +721,19 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::
|
||||
}
|
||||
|
||||
bbox_index = encode_index(midx, midy);
|
||||
|
||||
if (use_h3_index.size() > 0) {
|
||||
for (size_t i = 0; i < sf.full_keys.size(); i++) {
|
||||
if (*(sf.full_keys[i]) == use_h3_index) {
|
||||
unsigned long long h3_index = atoll(sf.full_values[i].s.c_str());
|
||||
// the top 52 bits of the feature index are the H3 index;
|
||||
// the bottom 12 bits are retained from what otherwise would have been the index.
|
||||
bbox_index = ((h3_index & ((1LL << 52) - 1)) << 12) | (bbox_index & ((1 << 12) - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (additional[A_CALCULATE_INDEX]) {
|
||||
sf.full_keys.push_back(key_pool.pool("tippecanoe:index"));
|
||||
|
||||
@@ -728,7 +748,8 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::
|
||||
if (dv.size() > 0) {
|
||||
dv[0].x = SHIFT_LEFT(dv[0].x) & ((1LL << 32) - 1);
|
||||
dv[0].y = SHIFT_LEFT(dv[0].y) & ((1LL << 32) - 1);
|
||||
sf.label_point = encode_index(dv[0].x, dv[0].y);
|
||||
sf.label_x = dv[0].x;
|
||||
sf.label_y = dv[0].y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -748,8 +769,12 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::
|
||||
preserve_multiplier_density_threshold > 0 ||
|
||||
cluster_distance != 0) {
|
||||
sf.index = bbox_index;
|
||||
sf.wx = midx;
|
||||
sf.wy = midy;
|
||||
} else {
|
||||
sf.index = 0;
|
||||
sf.wx = 0;
|
||||
sf.wy = 0;
|
||||
}
|
||||
|
||||
if (sst->layermap->count(layername) == 0) {
|
||||
|
||||
+6
-1
@@ -58,6 +58,10 @@ struct serial_val {
|
||||
s = milo::dtoa_milo(val);
|
||||
}
|
||||
|
||||
std::string toString() const {
|
||||
return s;
|
||||
}
|
||||
|
||||
double to_double() const {
|
||||
return atof(s.c_str());
|
||||
}
|
||||
@@ -118,8 +122,9 @@ struct serial_feature {
|
||||
|
||||
drawvec geometry = drawvec();
|
||||
unsigned long long index = 0;
|
||||
unsigned wx = 0, wy = 0;
|
||||
unsigned long long gap = 0; // filled in during z0. square of planar distance
|
||||
unsigned long long label_point = 0;
|
||||
unsigned label_x = 0, label_y = 0;
|
||||
long long extent = 0;
|
||||
|
||||
// These fields are not directly serialized, but are used
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+8320
File diff suppressed because one or more lines are too long
@@ -377,7 +377,7 @@ struct ordercmp {
|
||||
static std::vector<std::vector<std::shared_ptr<serial_feature>>> assemble_multiplier_clusters(std::vector<std::shared_ptr<serial_feature>> const &features) {
|
||||
std::vector<std::vector<std::shared_ptr<serial_feature>>> clusters;
|
||||
|
||||
if (retain_points_multiplier == 1) {
|
||||
if (!(retain_points_multiplier > 1 || preserve_multiplier_density_threshold != 0 || preserve_multiplier_density_bits_by_zoom.size() > 0)) {
|
||||
for (auto const &feature : features) {
|
||||
std::vector<std::shared_ptr<serial_feature>> cluster;
|
||||
cluster.push_back(std::move(feature));
|
||||
@@ -714,7 +714,7 @@ static void *simplification_worker(void *v) {
|
||||
|
||||
if (t == VT_POLYGON && additional[A_GENERATE_POLYGON_LABEL_POINTS]) {
|
||||
t = (*features)[i]->t = VT_POINT;
|
||||
geom = checkerboard_anchors(from_tile_scale(geom, z, out_detail), (*features)[i]->tx, (*features)[i]->ty, z, (*features)[i]->label_point);
|
||||
geom = checkerboard_anchors(from_tile_scale(geom, z, out_detail), (*features)[i]->tx, (*features)[i]->ty, z, (*features)[i]->label_x, (*features)[i]->label_y);
|
||||
to_tile_scale(geom, z, out_detail);
|
||||
}
|
||||
|
||||
@@ -1059,6 +1059,7 @@ static bool skip_next_feature(decompressor *geoms, std::atomic<long long> *geomp
|
||||
|
||||
struct next_feature_state {
|
||||
unsigned long long previndex = 0;
|
||||
unsigned prevx = 0, prevy = 0;
|
||||
unsigned long long prev_not_dropped_index = 0;
|
||||
};
|
||||
|
||||
@@ -1128,9 +1129,11 @@ static serial_feature next_feature(decompressor *geoms, std::atomic<long long> *
|
||||
long long ox = (1LL << (32 - z)) * tx;
|
||||
long long oy = (1LL << (32 - z)) * ty;
|
||||
|
||||
unsigned wx1, wy1;
|
||||
decode_index(next_feature_state.previndex, &wx1, &wy1);
|
||||
unsigned wx1 = next_feature_state.prevx;
|
||||
unsigned wy1 = next_feature_state.prevy;
|
||||
|
||||
// find the furthest distance of a vertex in this feature
|
||||
// from the representative point of the previous feature
|
||||
for (auto const &g : sf.geometry) {
|
||||
long long dx = (long long) wx1 - (g.x + ox);
|
||||
long long dy = (long long) wy1 - (g.y + oy);
|
||||
@@ -1143,6 +1146,8 @@ static serial_feature next_feature(decompressor *geoms, std::atomic<long long> *
|
||||
}
|
||||
}
|
||||
next_feature_state.previndex = sf.index;
|
||||
next_feature_state.prevx = sf.wx;
|
||||
next_feature_state.prevy = sf.wy;
|
||||
|
||||
if (clip_to_tile(sf, z, buffer)) {
|
||||
continue;
|
||||
@@ -1250,6 +1255,11 @@ static serial_feature next_feature(decompressor *geoms, std::atomic<long long> *
|
||||
} else if (preserve_multiplier_density_threshold > 0 &&
|
||||
sf.index - next_feature_state.prev_not_dropped_index > ((1LL << (32 - z)) / preserve_multiplier_density_threshold) * ((1LL << (32 - z)) / preserve_multiplier_density_threshold)) {
|
||||
sf.dropped = FEATURE_ADDED_FOR_MULTIPLIER_DENSITY;
|
||||
} else if (preserve_multiplier_density_bits_by_zoom.size() > 0 &&
|
||||
(size_t) z < preserve_multiplier_density_bits_by_zoom.size() &&
|
||||
(sf.index >> (64 - preserve_multiplier_density_bits_by_zoom[z])) !=
|
||||
(next_feature_state.prev_not_dropped_index >> (64 - preserve_multiplier_density_bits_by_zoom[z]))) {
|
||||
sf.dropped = FEATURE_ADDED_FOR_MULTIPLIER_DENSITY;
|
||||
} else {
|
||||
sf.dropped = FEATURE_DROPPED;
|
||||
}
|
||||
@@ -2143,7 +2153,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
||||
sf.dropped = FEATURE_KEPT;
|
||||
}
|
||||
|
||||
if (sf.dropped == FEATURE_KEPT && retain_points_multiplier > 1) {
|
||||
if (sf.dropped == FEATURE_KEPT && (retain_points_multiplier > 1 || preserve_multiplier_density_threshold != 0 || preserve_multiplier_density_bits_by_zoom.size() > 0)) {
|
||||
sf.full_keys.push_back(key_pool.pool("tippecanoe:retain_points_multiplier_first"));
|
||||
sf.full_values.emplace_back(mvt_bool, "true");
|
||||
}
|
||||
@@ -2293,7 +2303,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
||||
std::string const &layername = kv.first;
|
||||
std::vector<std::shared_ptr<serial_feature>> &features = kv.second.features;
|
||||
|
||||
if (retain_points_multiplier > 1) {
|
||||
if ((retain_points_multiplier > 1 || preserve_multiplier_density_threshold != 0 || preserve_multiplier_density_bits_by_zoom.size() > 0)) {
|
||||
// mapping from input sequence to current sequence within this tile
|
||||
std::vector<std::pair<size_t, size_t>> feature_sequences;
|
||||
|
||||
@@ -2820,7 +2830,7 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
|
||||
}
|
||||
|
||||
if (skipped > 0 || too_many_bytes || too_many_features) {
|
||||
fprintf(stderr, "Can't happen: writing tile even though we skipped\n");
|
||||
fprintf(stderr, "Can't happen: writing tile even though we skipped (%zu %d %d)\n", skipped, too_many_bytes, too_many_features);
|
||||
exit(EXIT_IMPOSSIBLE);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user