More work on plumbing attribute accumulation through (#263)

* Plumb bounding boxes through potential intersections

* Quick bbox reject for bins that can't possibly intersect

* Inching toward attribute accumulation in megatile handling

* Some sort of test for how all these things interact with each other.

Automatic numeric attribute accumulation does *not* apply to attributes
that have an explicit attribute accumulator set, because the order of
operations is too messy and weird

* More sketching

* More sketching

* Actually do some accumulation

* Put all that behind an --accumulate-numeric flag

* Use the same attribute accumulation logic in binning as in megatiles

* Fix backwards conditional

* Add means, but somehow I have some counts of 0

* Handle aggregated attributes with no base attribute in the feature

* Checkpoint before I break everything

* Found a flaw, now to debug

* Fix a typo that broke accumulation

* Add binning tests

* Make sure IDs make it through on the bins

* Fix count/mean accumulation

* Make the numeric accumulation prefix configurable

* Make sure the accumulate test still works with a different prefix

* Forgot to update this test

* More testing to make sure cluster sizes make it all the way through

* Fix neglected --accumulate-attribute when binning

* Mark unexercised attribute accumulation cases as "can't happen"

* Factor out numeric preservation

* Attrs with the accumulation prefix are just preserved, not accumulated

* Test behavior of prefixed attributes

* Plumbing for exclude and exclude-prefix

* Implement and test attribute prefix stripping in overzoom

* Update version and changelog

* For debugging, make an attribute list of source feature IDs

* Revert "For debugging, make an attribute list of source feature IDs"

This reverts commit 65fc99c9d1.
This commit is contained in:
Erica Fischer
2024-09-20 15:30:29 -07:00
committed by GitHub
parent 534242887d
commit c5f2f0da34
23 changed files with 2386 additions and 3919 deletions
+52 -8
View File
@@ -6,6 +6,13 @@
#include "jsonpull/jsonpull.h"
#include "milo/dtoa_milo.h"
std::map<std::string, attribute_op> numeric_operations = {
{"sum", op_sum},
{"min", op_min},
{"max", op_max},
{"count", op_count},
};
void set_attribute_accum(std::unordered_map<std::string, attribute_op> &attribute_accum, std::string name, std::string type) {
attribute_op t;
@@ -88,12 +95,12 @@ void preserve_attribute(attribute_op const &op, std::string const &key, serial_v
case op_sum:
full_values[i].s = milo::dtoa_milo(atof(full_values[i].s.c_str()) + atof(val.s.c_str()));
full_values[i].type = mvt_double;
break;
return;
case op_product:
full_values[i].s = milo::dtoa_milo(atof(full_values[i].s.c_str()) * atof(val.s.c_str()));
full_values[i].type = mvt_double;
break;
return;
case op_max: {
double existing = atof(full_values[i].s.c_str());
@@ -102,7 +109,7 @@ void preserve_attribute(attribute_op const &op, std::string const &key, serial_v
full_values[i].s = val.s.c_str();
full_values[i].type = mvt_double;
}
break;
return;
}
case op_min: {
@@ -112,7 +119,7 @@ void preserve_attribute(attribute_op const &op, std::string const &key, serial_v
full_values[i].s = val.s.c_str();
full_values[i].type = mvt_double;
}
break;
return;
}
case op_mean: {
@@ -124,24 +131,26 @@ void preserve_attribute(attribute_op const &op, std::string const &key, serial_v
attribute_accum_state.insert(std::pair<std::string, accum_state>(key, s));
full_values[i].s = milo::dtoa_milo(s.sum / s.count);
full_values[i].type = mvt_double;
} else {
state->second.sum += atof(val.s.c_str());
state->second.count += 1;
full_values[i].s = milo::dtoa_milo(state->second.sum / state->second.count);
full_values[i].type = mvt_double;
}
break;
return;
}
case op_concat:
full_values[i].s += val.s;
full_values[i].type = mvt_string;
break;
return;
case op_comma:
full_values[i].s += std::string(",") + val.s;
full_values[i].type = mvt_string;
break;
return;
case op_count: {
auto state = attribute_accum_state.find(key);
@@ -155,9 +164,44 @@ void preserve_attribute(attribute_op const &op, std::string const &key, serial_v
state->second.count += 1;
full_values[i].s = std::to_string(state->second.count);
}
break;
return;
}
}
}
}
// not found, so we are making a new value
serial_val sv;
switch (op) {
case op_sum:
case op_max:
case op_min:
sv.s = val.s;
sv.type = mvt_double;
break;
case op_count: {
auto state = attribute_accum_state.find(key);
if (state == attribute_accum_state.end()) { // not already present
accum_state s;
s.count = 1;
attribute_accum_state.insert(std::pair<std::string, accum_state>(key, s));
sv.s = std::to_string(s.count);
} else { // already present, incrementing
fprintf(stderr, "preserve_attribute: can't happen (count)\n");
exit(EXIT_IMPOSSIBLE);
}
sv.type = mvt_double;
break;
}
default:
fprintf(stderr, "can't happen: operation that isn't used by --accumulate-numeric-attributes\n");
exit(EXIT_IMPOSSIBLE);
}
full_keys.push_back(key);
full_values.push_back(sv);
}