Remove undocumented command-line options (#361)

* Remove --accumulate-numeric-attributes

* Remove join-sqlite, etc.

* Remove --accumulate-numeric-attributes from overzoom

* Remove --assign-to-bins and --bin-by-id-list

* Remove --clip-polygon and --clip-bounding-box

* Remove FSL expressions

* Update version and changelog
This commit is contained in:
Erica Fischer
2025-07-31 17:03:01 -07:00
committed by GitHub
parent 68ab8dcc22
commit 533e000faa
14 changed files with 35 additions and 2920 deletions
+16 -603
View File
@@ -1214,47 +1214,6 @@ bool pnpoly_mp(drawvec const &geom, long long x, long long y) {
return found;
}
clipbbox parse_clip_poly(std::string arg) {
json_pull *jp = json_begin_string(arg.c_str());
json_object *j = json_read_tree(jp);
if (j == NULL) {
fprintf(stderr, "Expected JSON object, not %s\n", arg.c_str());
exit(EXIT_ARGS);
}
if (j->type != JSON_HASH) {
fprintf(stderr, "Expected JSON geometry object, not %s\n", arg.c_str());
exit(EXIT_ARGS);
}
std::pair<int, drawvec> parsed_geometry = parse_geometry(j, jp, j, 0, 0, 0, 1LL << 32, false, false);
json_end(jp);
clipbbox out;
out.minx = LLONG_MAX;
out.miny = LLONG_MAX;
out.maxx = LLONG_MIN;
out.maxy = LLONG_MIN;
for (auto const &d : parsed_geometry.second) {
if (d.op == VT_MOVETO || d.op == VT_LINETO) {
if (d.x < out.minx) {
out.minx = d.x;
}
if (d.y < out.miny) {
out.miny = d.y;
}
if (d.x > out.maxx) {
out.maxx = d.x;
}
if (d.y > out.maxy) {
out.maxy = d.y;
}
}
}
out.dv = std::move(parsed_geometry.second);
return out;
}
std::string overzoom(std::vector<input_tile> const &tiles, int nz, int nx, int ny,
int detail_or_unspecified, int buffer,
std::set<std::string> const &keep,
@@ -1266,9 +1225,9 @@ std::string overzoom(std::vector<input_tile> const &tiles, int nz, int nx, int n
std::unordered_map<std::string, attribute_op> const &attribute_accum,
std::vector<std::string> const &unidecode_data, double simplification,
double tiny_polygon_size,
std::vector<mvt_layer> const &bins, std::string const &bin_by_id_list,
std::string const &accumulate_numeric, size_t feature_limit,
std::vector<clipbbox> const &clipbboxes,
std::vector<mvt_layer> const &unused2, std::string const &unused3,
std::string const &unused, size_t feature_limit,
std::vector<clipbbox> const &unused4,
bool deduplicate_by_id) {
std::vector<source_tile> decoded;
@@ -1295,7 +1254,7 @@ std::string overzoom(std::vector<input_tile> const &tiles, int nz, int nx, int n
decoded.push_back(out);
}
return overzoom(decoded, nz, nx, ny, detail_or_unspecified, buffer, keep, exclude, exclude_prefix, do_compress, next_overzoomed_tiles, demultiply, filter, preserve_input_order, attribute_accum, unidecode_data, simplification, tiny_polygon_size, bins, bin_by_id_list, accumulate_numeric, feature_limit, clipbboxes, deduplicate_by_id);
return overzoom(decoded, nz, nx, ny, detail_or_unspecified, buffer, keep, exclude, exclude_prefix, do_compress, next_overzoomed_tiles, demultiply, filter, preserve_input_order, attribute_accum, unidecode_data, simplification, tiny_polygon_size, unused2, unused3, unused, feature_limit, unused4, deduplicate_by_id);
}
// like a minimal serial_feature, but with mvt_feature-style attributes
@@ -1330,152 +1289,6 @@ static bool should_keep(std::string const &key,
return false;
}
static void add_mean(mvt_feature &feature, mvt_layer &layer, std::string const &accumulate_numeric,
std::set<std::string> const &keep, std::set<std::string> const &exclude,
std::vector<std::string> const &exclude_prefix) {
std::string accumulate_numeric_colon = accumulate_numeric + ":";
std::unordered_map<std::string, size_t> attributes;
for (size_t i = 0; i + 1 < feature.tags.size(); i += 2) {
std::string const &key = layer.keys[feature.tags[i]];
if (starts_with(key, accumulate_numeric_colon)) {
attributes.emplace(key, i);
}
}
for (size_t i = 0; i + 1 < feature.tags.size(); i += 2) {
std::string accumulate_numeric_sum_colon = accumulate_numeric + ":sum:";
std::string const &key = layer.keys[feature.tags[i]];
if (starts_with(key, accumulate_numeric_sum_colon)) {
std::string trunc = key.substr(accumulate_numeric_sum_colon.size());
auto const f = attributes.find(accumulate_numeric + ":count:" + trunc);
if (f != attributes.end()) {
mvt_value const &sum = layer.values[feature.tags[i + 1]];
mvt_value const &count = layer.values[feature.tags[f->second + 1]];
double count_val = mvt_value_to_double(count);
if (count_val <= 0) {
fprintf(stderr, "can't happen: count is %s (type %d)\n", count.toString().c_str(), count.type);
exit(EXIT_IMPOSSIBLE);
}
mvt_value mean;
mean.type = mvt_double;
mean.numeric_value.double_value = mvt_value_to_double(sum) / count_val;
if (should_keep(key, keep, exclude, exclude_prefix)) {
layer.tag(feature, accumulate_numeric + ":mean:" + trunc, mean);
}
}
}
}
};
// accumulate :sum:, :min:, :max:, and :count: versions of the specified attribute
static void preserve_numeric(const std::string &key, const mvt_value &val, // numeric attribute being accumulated
std::vector<std::shared_ptr<std::string>> &full_keys, // keys of feature being accumulated onto
std::vector<mvt_value> &full_values, // values of features being accumulated onto
const std::string &accumulate_numeric, // prefix of accumulations
std::set<std::string> &keys, // key presence in the source feature
std::map<std::string, size_t> &numeric_out_field, // key index in the output feature
key_pool &key_pool,
std::set<std::string> const &keep, std::set<std::string> const &exclude,
std::vector<std::string> const &exclude_prefix) {
// If this is a numeric attribute, but there is also a prefix:sum (etc.) for the
// same attribute, we want to use that one instead of this one.
for (auto const &op : numeric_operations) {
std::string compound_key = accumulate_numeric + ":" + op.first + ":" + key;
auto compound_found = keys.find(compound_key);
if (compound_found != keys.end()) {
// found, so skip this one
} else {
// not found, so accumulate this one
// if this is already prefixed, strip off the prefix
// if it is the right one, and skip the attribute if
// it is the wrong one.
std::string outkey = key;
bool starting_from_accumulation;
if (starts_with(outkey, accumulate_numeric + ":")) {
std::string prefix = accumulate_numeric + ":" + op.first + ":";
if (starts_with(outkey, prefix)) {
outkey = outkey.substr(prefix.size());
starting_from_accumulation = true; // from a subaccumulation
} else {
continue; // to next operation
}
} else {
starting_from_accumulation = false; // from a plain value
}
// and then put it back on for the output field
std::string prefixed = accumulate_numeric + ":" + op.first + ":" + outkey;
if (!should_keep(prefixed, keep, exclude, exclude_prefix)) {
continue;
}
// Does it exist in the output feature already?
auto prefixed_attr = numeric_out_field.find(prefixed);
if (prefixed_attr == numeric_out_field.end()) {
// No? Does it exist unprefixed in the output feature already?
auto out_attr = numeric_out_field.find(outkey);
if (out_attr == numeric_out_field.end()) {
// not present at all, so copy our value to the prefixed output
numeric_out_field.emplace(prefixed, full_keys.size());
full_keys.push_back(key_pool.pool(prefixed));
if (op.second == op_count) {
if (starting_from_accumulation) {
// copy our count
full_values.push_back(val);
} else {
// new count of 1
full_values.push_back(mvt_value(1));
}
} else {
full_values.push_back(val);
}
} else {
// exists unprefixed, so copy it, and then accumulate on our value
numeric_out_field.emplace(prefixed, full_keys.size());
full_keys.push_back(key_pool.pool(prefixed));
if (op.second == op_count) {
mvt_value v;
if (starting_from_accumulation) {
// sum our count onto the existing 1
v = mvt_value(1 + mvt_value_to_long_long(val));
} else {
// sum our 1 onto the existing 1
v = mvt_value(2);
}
full_values.push_back(v);
} else {
full_values.push_back(full_values[out_attr->second]);
preserve_attribute(op.second, prefixed, val, full_keys, full_values, key_pool);
}
}
} else {
// exists, so accumulate on our value
if (op.second == op_count) {
if (starting_from_accumulation) {
// sum our count onto the existing count
full_values[prefixed_attr->second] = mvt_value(mvt_value_to_long_long(full_values[prefixed_attr->second]) + mvt_value_to_long_long(val));
} else {
full_values[prefixed_attr->second] = mvt_value(mvt_value_to_long_long(full_values[prefixed_attr->second]) + 1);
}
} else {
preserve_attribute(op.second, prefixed, val, full_keys, full_values, key_pool);
}
}
}
}
}
static void handle_closepath_from_mvt(drawvec &geom) {
// mvt geometries close polygons with a mvt_closepath operation
// tippecanoe-internal geometries close polygons with a lineto to the initial point
@@ -1497,9 +1310,9 @@ static bool feature_out(std::vector<tile_feature> const &features, mvt_layer &ou
std::set<std::string> const &exclude,
std::vector<std::string> const &exclude_prefix,
std::unordered_map<std::string, attribute_op> const &attribute_accum,
std::string const &accumulate_numeric,
std::string const &,
key_pool &key_pool, int buffer, bool include_nonaggregate,
std::vector<clipbbox> const &clipbboxes, int nz, int nx, int ny,
std::vector<clipbbox> const &, int, int, int,
std::set<unsigned long long> *deduplicate_ids) {
// Add geometry to output feature
@@ -1507,7 +1320,7 @@ static bool feature_out(std::vector<tile_feature> const &features, mvt_layer &ou
int t = features[0].t;
bool fix_polygons = false;
if ((buffer >= 0 || clipbboxes.size() > 0) && t == VT_POLYGON) {
if ((buffer >= 0) && t == VT_POLYGON) {
fix_polygons = true;
}
@@ -1528,48 +1341,6 @@ static bool feature_out(std::vector<tile_feature> const &features, mvt_layer &ou
geom = remove_noop(geom, t, 0);
}
if (clipbboxes.size() != 0) {
// bounding box is in world coordinates at world scale
// feature is in local coordinates at tile scale
long long dx = (long long) nx << (32 - nz);
long long dy = (long long) ny << (32 - nz);
double scale = (double) outlayer.extent / (1LL << (32 - nz));
for (auto const &c_world : clipbboxes) {
clipbbox c = c_world;
c.minx = std::llround((c_world.minx - dx) * scale);
c.miny = std::llround((c_world.miny - dy) * scale);
c.maxx = std::llround((c_world.maxx - dx) * scale);
c.maxy = std::llround((c_world.maxy - dy) * scale);
for (auto &p : c.dv) {
p.x = std::llround((p.x - dx) * scale);
p.y = std::llround((p.y - dy) * scale);
}
if (t == VT_POLYGON) {
geom = simple_clip_poly(geom, c.minx, c.miny, c.maxx, c.maxy, false);
if (c.dv.size() > 0 && geom.size() > 0) {
geom = clip_poly_poly(geom, c.dv);
}
} else if (t == VT_LINE) {
geom = clip_lines(geom, c.minx, c.miny, c.maxx, c.maxy);
if (c.dv.size() > 0 && geom.size() > 0) {
geom = clip_lines_poly(geom, c.dv);
}
} else if (t == VT_POINT) {
geom = clip_point(geom, c.minx, c.miny, c.maxx, c.maxy);
if (c.dv.size() > 0 && geom.size() > 0) {
geom = clip_point_poly(geom, c.dv);
}
}
}
geom = remove_noop(geom, t, 0);
}
if (fix_polygons) {
geom = clean_or_clip_poly(geom, 0, 0, false, false);
geom = close_poly(geom);
@@ -1599,7 +1370,7 @@ static bool feature_out(std::vector<tile_feature> const &features, mvt_layer &ou
outfeature.seq = features[0].seq;
if (attribute_accum.size() > 0 || accumulate_numeric.size() > 0) {
if (attribute_accum.size() > 0) {
// convert the attributes of the output feature
// from layer references to a vector so they can have
// attributes from the other features of the
@@ -1617,11 +1388,6 @@ static bool feature_out(std::vector<tile_feature> const &features, mvt_layer &ou
// this attribute has an accumulator, so convert it
full_keys.push_back(key_pool.pool(f.layer->keys[f.tags[i]]));
full_values.push_back(f.layer->values[f.tags[i + 1]]);
} else if (accumulate_numeric.size() > 0 && f.layer->values[f.tags[i + 1]].is_numeric()) {
// convert numeric for accumulation
numeric_out_field.emplace(key, full_keys.size());
full_keys.push_back(key_pool.pool(key));
full_values.push_back(f.layer->values[f.tags[i + 1]]);
} else if (include_nonaggregate) {
// otherwise just tag it directly onto the output feature
outlayer.tag(outfeature, f.layer->keys[f.tags[i]], f.layer->values[f.tags[i + 1]]);
@@ -1650,14 +1416,6 @@ static bool feature_out(std::vector<tile_feature> const &features, mvt_layer &ou
if (found != attribute_accum.end()) {
mvt_value val = features[i].layer->values[features[i].tags[j + 1]];
preserve_attribute(found->second, key, val, full_keys, full_values, key_pool);
} else if (accumulate_numeric.size() > 0) {
const mvt_value &val = features[i].layer->values[features[i].tags[j + 1]];
if (val.is_numeric()) {
preserve_numeric(key, val, full_keys, full_values,
accumulate_numeric,
keys, numeric_out_field, key_pool,
keep, exclude, exclude_prefix);
}
}
}
}
@@ -1671,10 +1429,6 @@ static bool feature_out(std::vector<tile_feature> const &features, mvt_layer &ou
outlayer.tag(outfeature, *full_keys[i], full_values[i]);
}
}
if (accumulate_numeric.size() > 0) {
add_mean(outfeature, outlayer, accumulate_numeric, keep, exclude, exclude_prefix);
}
} else if (include_nonaggregate) {
for (size_t i = 0; i + 1 < features[0].tags.size(); i += 2) {
if (should_keep(features[0].layer->keys[features[0].tags[i]], keep, exclude, exclude_prefix)) {
@@ -1696,316 +1450,6 @@ static struct preservecmp {
}
} preservecmp;
struct index_event {
unsigned long long where;
enum index_event_kind {
ENTER = 0, // new bin in is now active
CHECK, // point needs to be checked against active bins
EXIT // bin has ceased to be active
} kind;
size_t layer;
size_t feature;
long long xmin, ymin, xmax, ymax;
index_event(unsigned long long where_, index_event_kind kind_, size_t layer_, size_t feature_,
long long xmin_, long long ymin_, long long xmax_, long long ymax_)
: where(where_), kind(kind_), layer(layer_), feature(feature_), xmin(xmin_), ymin(ymin_), xmax(xmax_), ymax(ymax_) {
}
bool operator<(const index_event &ie) const {
if (where < ie.where) {
return true;
} else if (where == ie.where) {
if (kind < ie.kind) {
return true;
} else if (kind == ie.kind) {
if (layer < ie.layer) {
return true;
} else if (layer == ie.layer) {
if (feature < ie.feature) {
return true;
}
}
}
}
return false;
}
};
struct active_bin {
size_t layer;
size_t feature;
active_bin(size_t layer_, size_t feature_)
: layer(layer_), feature(feature_) {
}
bool operator<(const active_bin &o) const {
if (layer < o.layer) {
return true;
} else if (layer == o.layer) {
if (feature < o.feature) {
return true;
}
}
return false;
}
size_t outfeature;
long long xmin, ymin, xmax, ymax;
size_t counter = 0;
};
void get_quadkey_bounds(long long xmin, long long ymin, long long xmax, long long ymax,
unsigned long long *start, unsigned long long *end) {
if (xmin < 0 || ymin < 0 || xmax >= 1LL << 32 || ymax >= 1LL << 32) {
*start = 0;
*end = ULLONG_MAX;
return;
}
*start = encode_quadkey(xmin, ymin);
*end = encode_quadkey(xmax, ymax);
for (ssize_t i = 62; i >= 0; i -= 2) {
if ((*start & (3LL << i)) != (*end & (3LL << i))) {
for (; i >= 0; i -= 2) {
*start &= ~(3LL << i);
*end |= 3LL << i;
}
break;
}
}
}
static bool bbox_intersects(long long x1min, long long y1min, long long x1max, long long y1max,
long long x2min, long long y2min, long long x2max, long long y2max) {
if (x1max < x2min) {
return false;
}
if (x2max < x1min) {
return false;
}
if (y1max < y2min) {
return false;
}
if (y2max < y1min) {
return false;
}
return true;
}
static std::vector<size_t> parse_ids_string(mvt_value const &v) {
std::vector<size_t> out;
std::string s = v.toString();
for (size_t i = 0; i < s.size(); i++) {
if (i == 0 || s[i - 1] == ',') {
out.push_back(atoll(s.c_str() + i));
}
}
return out;
}
mvt_tile assign_to_bins(mvt_tile &features,
std::vector<mvt_layer> const &bins, std::string const &bin_by_id_list,
int z, int x, int y,
std::unordered_map<std::string, attribute_op> const &attribute_accum,
std::string const &accumulate_numeric,
std::set<std::string> keep,
std::set<std::string> exclude,
std::vector<std::string> exclude_prefix,
int buffer, std::vector<clipbbox> const &clipbboxes) {
std::vector<index_event> events;
key_pool key_pool;
if (bins.size() == 0) {
return mvt_tile();
}
// Index bins
for (size_t i = 0; i < bins.size(); i++) {
for (size_t j = 0; j < bins[i].features.size(); j++) {
long long xmin, ymin, xmax, ymax;
unsigned long long start, end;
get_bbox(bins[i].features[j].geometry, &xmin, &ymin, &xmax, &ymax, z, x, y, bins[i].detail());
get_quadkey_bounds(xmin, ymin, xmax, ymax, &start, &end);
events.emplace_back(start, index_event::ENTER, i, j, xmin, ymin, xmax, ymax);
events.emplace_back(end, index_event::EXIT, i, j, xmin, ymin, xmax, ymax);
}
}
std::map<unsigned long long, std::pair<size_t, size_t>> fid_to_feature;
// Index points
for (size_t i = 0; i < features.layers.size(); i++) {
for (size_t j = 0; j < features.layers[i].features.size(); j++) {
long long xmin, ymin, xmax, ymax;
unsigned long long start, end;
if (features.layers[i].features[j].geometry.size() > 0) {
if (features.layers[i].features[j].has_id) {
fid_to_feature.emplace(features.layers[i].features[j].id, std::make_pair(i, j));
}
get_bbox(features.layers[i].features[j].geometry, &xmin, &ymin, &xmax, &ymax, z, x, y, features.layers[i].detail());
get_quadkey_bounds(xmin, ymin, xmax, ymax, &start, &end);
events.emplace_back(start, index_event::CHECK, i, j, xmin, ymin, xmax, ymax);
}
}
}
std::sort(events.begin(), events.end());
std::set<active_bin> active;
mvt_layer outlayer;
outlayer.extent = bins[0].extent;
outlayer.version = 2;
outlayer.name = features.layers[0].name;
std::vector<std::vector<tile_feature>> outfeatures;
for (auto &e : events) {
if (e.kind == index_event::ENTER) {
active_bin a(e.layer, e.feature);
a.xmin = e.xmin;
a.ymin = e.ymin;
a.xmax = e.xmax;
a.ymax = e.ymax;
const mvt_feature &bin = bins[e.layer].features[e.feature];
{
tile_feature outfeature;
for (auto const &g : bin.geometry) {
outfeature.geom.emplace_back(g.op, g.x, g.y);
}
outfeature.t = bin.type;
outfeature.has_id = bin.has_id;
outfeature.id = bin.id;
outfeature.tags = bin.tags;
outfeature.layer = &bins[e.layer];
outfeature.seq = e.feature;
a.outfeature = outfeatures.size();
outfeatures.push_back({std::move(outfeature)});
}
if (bin_by_id_list.size() > 0) {
for (size_t k = 0; k < bin.tags.size(); k += 2) {
if (bins[e.layer].keys[bin.tags[k]] == bin_by_id_list) {
std::vector<size_t> ids = parse_ids_string(bins[e.layer].values[bin.tags[k + 1]]);
for (auto &id : ids) {
auto f = fid_to_feature.find(id);
if (f != fid_to_feature.end()) {
mvt_feature &feature = features.layers[f->second.first].features[f->second.second];
if (feature.geometry.size() > 0) {
tile_feature outfeature;
for (auto const &g : feature.geometry) {
outfeature.geom.emplace_back(g.op, g.x, g.y);
}
feature.geometry.clear();
outfeature.t = feature.type;
outfeature.has_id = feature.has_id;
outfeature.id = feature.id;
outfeature.tags = feature.tags;
outfeature.layer = &features.layers[e.layer];
outfeature.seq = e.feature;
outfeatures.back().push_back(std::move(outfeature));
}
}
}
break;
}
}
}
active.insert(std::move(a));
} else if (e.kind == index_event::CHECK) {
if (bin_by_id_list.size() > 0) {
continue; // only bin by id, not geometrically
}
auto const &feature = features.layers[e.layer].features[e.feature];
if (feature.geometry.size() == 0) {
// already assigned by ID
continue;
}
// if we can't find a real match,
// assign points to the most nearby bin
ssize_t which_outfeature = outfeatures.size() - 1;
for (auto const &a : active) {
auto const &bin = bins[a.layer].features[a.feature];
if (bbox_intersects(e.xmin, e.ymin, e.xmax, e.ymax,
a.xmin, a.ymin, a.xmax, a.ymax)) {
if (pnpoly_mp(bin.geometry, feature.geometry[0].x, feature.geometry[0].y)) {
which_outfeature = a.outfeature;
break;
}
}
}
if (which_outfeature >= 0) {
tile_feature outfeature;
for (auto const &g : feature.geometry) {
outfeature.geom.emplace_back(g.op, g.x, g.y);
}
outfeature.t = feature.type;
outfeature.has_id = feature.has_id;
outfeature.id = feature.id;
outfeature.tags = feature.tags;
outfeature.layer = &features.layers[e.layer];
outfeature.seq = e.feature;
outfeatures[which_outfeature].push_back(std::move(outfeature));
}
} else /* EXIT */ {
auto const &found = active.find({e.layer, e.feature});
if (found != active.end()) {
active.erase(found);
} else {
fprintf(stderr, "event mismatch: can't happen\n");
exit(EXIT_IMPOSSIBLE);
}
}
}
for (size_t i = 0; i < outfeatures.size(); i++) {
if (outfeatures[i].size() > 1) {
if (feature_out(outfeatures[i], outlayer,
keep, exclude, exclude_prefix, attribute_accum,
accumulate_numeric, key_pool, buffer, true,
clipbboxes, z, x, y, NULL)) {
mvt_feature &nfeature = outlayer.features.back();
mvt_value val;
val.type = mvt_uint;
val.numeric_value.uint_value = outfeatures[i].size() - 1;
std::string attrname;
if (accumulate_numeric.size() == 0) {
attrname = "tippecanoe:count";
} else {
attrname = accumulate_numeric + ":count";
}
if (should_keep(attrname, keep, exclude, exclude_prefix)) {
outlayer.tag(nfeature, attrname, val);
}
}
}
}
mvt_tile ret;
ret.layers.push_back(outlayer);
return ret;
}
std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int ny,
int detail_or_unspecified, int buffer,
std::set<std::string> const &keep,
@@ -2017,9 +1461,9 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
std::unordered_map<std::string, attribute_op> const &attribute_accum,
std::vector<std::string> const &unidecode_data, double simplification,
double tiny_polygon_size,
std::vector<mvt_layer> const &bins, std::string const &bin_by_id_list,
std::string const &accumulate_numeric, size_t feature_limit,
std::vector<clipbbox> const &clipbboxes,
std::vector<mvt_layer> const &unused2, std::string const &unused3,
std::string const &unused, size_t feature_limit,
std::vector<clipbbox> const &unused4,
bool deduplicate_by_id) {
mvt_tile outtile;
key_pool key_pool;
@@ -2093,30 +1537,6 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
}
}
// Clip to user-specified bounding boxes.
// Bounding box clip first, to reduce complexity of the full clip.
// But don't clip here if we are binning, because we need to bin points in the buffer
if (bins.size() == 0) {
for (auto &c : clipbboxes) {
if (t == VT_POLYGON) {
geom = simple_clip_poly(geom, c.minx, c.miny, c.maxx, c.maxy, false);
if (c.dv.size() > 0 && geom.size() > 0) {
geom = clip_poly_poly(geom, c.dv);
}
} else if (t == VT_LINE) {
geom = clip_lines(geom, c.minx, c.miny, c.maxx, c.maxy);
if (c.dv.size() > 0 && geom.size() > 0) {
geom = clip_lines_poly(geom, c.dv);
}
} else if (t == VT_POINT) {
geom = clip_point(geom, c.minx, c.miny, c.maxx, c.maxy);
if (c.dv.size() > 0 && geom.size() > 0) {
geom = clip_point_poly(geom, c.dv);
}
}
}
}
// Now offset from world coordinates to output tile coordinates,
// but retain world scale, because that is what tippecanoe zoom-oriented clipping expects
@@ -2126,8 +1546,7 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
g.y -= ny * outtilesize;
}
// Don't clip here if we are binning, because we need to bin points in the buffer
if (bins.size() == 0) {
{
// Clip to output tile
long long xmin = LLONG_MAX;
@@ -2190,7 +1609,7 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
if (flush_multiplier_cluster) {
if (pending_tile_features.size() > 0) {
feature_out(pending_tile_features, *outlayer, keep, exclude, exclude_prefix, attribute_accum, accumulate_numeric, key_pool, -1, bins.size() == 0, std::vector<clipbbox>(), nz, nx, ny, deduplicate_by_id_set);
feature_out(pending_tile_features, *outlayer, keep, exclude, exclude_prefix, attribute_accum, unused, key_pool, -1, true, std::vector<clipbbox>(), nz, nx, ny, deduplicate_by_id_set);
if (outlayer->features.size() >= feature_limit) {
break;
}
@@ -2262,7 +1681,7 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
}
if (pending_tile_features.size() > 0) {
feature_out(pending_tile_features, *outlayer, keep, exclude, exclude_prefix, attribute_accum, accumulate_numeric, key_pool, -1, bins.size() == 0, std::vector<clipbbox>(), nz, nx, ny, deduplicate_by_id_set);
feature_out(pending_tile_features, *outlayer, keep, exclude, exclude_prefix, attribute_accum, unused, key_pool, -1, true, std::vector<clipbbox>(), nz, nx, ny, deduplicate_by_id_set);
pending_tile_features.clear();
if (outlayer->features.size() >= feature_limit) {
break;
@@ -2301,8 +1720,8 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
nz + 1, nx * 2 + x, ny * 2 + y,
detail_or_unspecified, buffer, keep, exclude, exclude_prefix, false, NULL,
demultiply, filter, preserve_input_order, attribute_accum, unidecode_data,
simplification, tiny_polygon_size, bins, bin_by_id_list, accumulate_numeric,
1, clipbboxes, deduplicate_by_id);
simplification, tiny_polygon_size, unused2, unused3, unused,
1, unused4, deduplicate_by_id);
if (child.size() > 0) {
next_overzoomed_tiles->emplace_back(nx * 2 + x, ny * 2 + y);
}
@@ -2311,12 +1730,6 @@ std::string overzoom(std::vector<source_tile> const &tiles, int nz, int nx, int
}
}
if (bins.size() > 0) {
outtile = assign_to_bins(outtile, bins, bin_by_id_list, nz, nx, ny,
attribute_accum, accumulate_numeric,
keep, exclude, exclude_prefix, buffer, clipbboxes);
}
for (ssize_t i = outtile.layers.size() - 1; i >= 0; i--) {
if (outtile.layers[i].features.size() == 0) {
outtile.layers.erase(outtile.layers.begin() + i);