Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bail out sooner as the tile feature limit approaches #206

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,6 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::
sf.geometry = dv;
sf.seq = 0;
sf.index = 0;
sf.bbox[0] = sf.bbox[1] = LLONG_MAX;
sf.bbox[2] = sf.bbox[3] = LLONG_MIN;
sf.extent = 0;
sf.has_id = false;

Expand Down Expand Up @@ -434,23 +432,6 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::
}
}

for (size_t i = 0; i < dv.size(); i++) {
if (dv[i].op == VT_MOVETO || dv[i].op == VT_LINETO) {
if (dv[i].x < sf.bbox[0]) {
sf.bbox[0] = dv[i].x;
}
if (dv[i].y < sf.bbox[1]) {
sf.bbox[1] = dv[i].y;
}
if (dv[i].x > sf.bbox[2]) {
sf.bbox[2] = dv[i].x;
}
if (dv[i].y > sf.bbox[3]) {
sf.bbox[3] = dv[i].y;
}
}
}

json_object *id = json_hash_get(j, "id");
if (id != NULL && id->type == JSON_NUMBER) {
sf.id = id->value.number.number;
Expand Down
51 changes: 26 additions & 25 deletions serial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ std::string serialize_feature(serial_feature *sf, long long wx, long long wy) {
return s;
}

serial_feature deserialize_feature(std::string const &geoms, unsigned z, unsigned tx, unsigned ty, unsigned *initial_x, unsigned *initial_y) {
serial_feature deserialize_feature(std::string const &geoms, unsigned z, unsigned tx, unsigned ty, unsigned *initial_x, unsigned *initial_y, long long bbox[]) {
serial_feature sf;
const char *cp = geoms.c_str();

Expand Down Expand Up @@ -261,7 +261,7 @@ serial_feature deserialize_feature(std::string const &geoms, unsigned z, unsigne
sf.label_point = 0;
sf.extent = 0;

sf.geometry = decode_geometry(&cp, z, tx, ty, sf.bbox, initial_x[sf.segment], initial_y[sf.segment]);
sf.geometry = decode_geometry(&cp, z, tx, ty, bbox, initial_x[sf.segment], initial_y[sf.segment]);

if (sf.layer & (1 << FLAG_INDEX)) {
deserialize_ulong_long(&cp, &sf.index);
Expand Down Expand Up @@ -412,10 +412,11 @@ static void add_scaled_node(struct reader *r, serialization_state *sst, draw g)
int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::string const &layername) {
struct reader *r = &(*sst->readers)[sst->segment];

sf.bbox[0] = LLONG_MAX;
sf.bbox[1] = LLONG_MAX;
sf.bbox[2] = LLONG_MIN;
sf.bbox[3] = LLONG_MIN;
long long sf_bbox[4];
sf_bbox[0] = LLONG_MAX;
sf_bbox[1] = LLONG_MAX;
sf_bbox[2] = LLONG_MIN;
sf_bbox[3] = LLONG_MIN;

for (size_t i = 0; i < sf.geometry.size(); i++) {
if (sf.geometry[i].op == VT_MOVETO || sf.geometry[i].op == VT_LINETO) {
Expand Down Expand Up @@ -448,7 +449,7 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::
// try to remind myself that the geometry in this function is in SCALED COORDINATES
drawvec scaled_geometry = sf.geometry;
sf.geometry.clear();
scale_geometry(sst, sf.bbox, scaled_geometry);
scale_geometry(sst, sf_bbox, scaled_geometry);

// This has to happen after scaling so that the wraparound detection has happened first.
// Otherwise the inner/outer calculation will be confused by bad geometries.
Expand All @@ -467,26 +468,26 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::

scaled_geometry = remove_noop(scaled_geometry, sf.t, 0);

sf.bbox[0] = LLONG_MAX;
sf.bbox[1] = LLONG_MAX;
sf.bbox[2] = LLONG_MIN;
sf.bbox[3] = LLONG_MIN;
sf_bbox[0] = LLONG_MAX;
sf_bbox[1] = LLONG_MAX;
sf_bbox[2] = LLONG_MIN;
sf_bbox[3] = LLONG_MIN;

for (auto &g : scaled_geometry) {
long long x = SHIFT_LEFT(g.x);
long long y = SHIFT_LEFT(g.y);

if (x < sf.bbox[0]) {
sf.bbox[0] = x;
if (x < sf_bbox[0]) {
sf_bbox[0] = x;
}
if (y < sf.bbox[1]) {
sf.bbox[1] = y;
if (y < sf_bbox[1]) {
sf_bbox[1] = y;
}
if (x > sf.bbox[2]) {
sf.bbox[2] = x;
if (x > sf_bbox[2]) {
sf_bbox[2] = x;
}
if (y > sf.bbox[3]) {
sf.bbox[3] = y;
if (y > sf_bbox[3]) {
sf_bbox[3] = y;
}
}
}
Expand Down Expand Up @@ -672,8 +673,8 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::

if (sf.t == VT_POINT) {
// keep old behavior, which loses one bit of precision at the bottom
midx = (sf.bbox[0] / 2 + sf.bbox[2] / 2) & ((1LL << 32) - 1);
midy = (sf.bbox[1] / 2 + sf.bbox[3] / 2) & ((1LL << 32) - 1);
midx = (sf_bbox[0] / 2 + sf_bbox[2] / 2) & ((1LL << 32) - 1);
midy = (sf_bbox[1] / 2 + sf_bbox[3] / 2) & ((1LL << 32) - 1);
} else {
// To reduce the chances of giving multiple polygons or linestrings
// the same index, use an arbitrary but predictable point from the
Expand Down Expand Up @@ -858,13 +859,13 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::
fwrite_check(&index, sizeof(struct index), 1, r->indexfile, &r->indexpos, sst->fname);

for (size_t i = 0; i < 2; i++) {
if (sf.bbox[i] < r->file_bbox[i]) {
r->file_bbox[i] = sf.bbox[i];
if (sf_bbox[i] < r->file_bbox[i]) {
r->file_bbox[i] = sf_bbox[i];
}
}
for (size_t i = 2; i < 4; i++) {
if (sf.bbox[i] > r->file_bbox[i]) {
r->file_bbox[i] = sf.bbox[i];
if (sf_bbox[i] > r->file_bbox[i]) {
r->file_bbox[i] = sf_bbox[i];
}
}

Expand Down
28 changes: 10 additions & 18 deletions serial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,30 +65,30 @@ struct serial_feature {
int tippecanoe_minzoom = -1;
int tippecanoe_maxzoom = -1;

drawvec geometry = drawvec();
drawvec geometry;
unsigned long long index = 0;
unsigned long long label_point = 0;
long long extent = 0;

// These fields are not directly serialized, but are used
// to create the keys and values references into the string pool
// during initial serialization
// during initial serialization,
// and are used to store attributes that are altered during tiling

std::vector<std::string> full_keys{};
std::vector<serial_val> full_values{};
std::vector<std::string> full_keys;
std::vector<serial_val> full_values;

// These fields are generated from full_keys and full_values
// during initial serialization and then replace the string
// representations:

std::vector<long long> keys{};
std::vector<long long> values{};
std::vector<long long> keys;
std::vector<long long> values;

// These fields are used during tiling,
// but are not serialized and are not expected
// to be provided by frontends:

long long bbox[4] = {0, 0, 0, 0};
drawvec edge_nodes; // what nodes at the tile edge were added during clipping?

#define FEATURE_DROPPED -1
Expand All @@ -99,28 +99,20 @@ struct serial_feature {
int dropped = FEATURE_DROPPED; // was this feature dropped by rate?

// unsigned long long drop_by; // dot-dropping priority
bool reduced; // is polygon dust
bool coalesced; // was coalesced from multiple features
int line_detail; // current tile resolution being used for simplification
int extra_detail; // extra tile resolution to retain in output
int maxzoom;
bool reduced; // is polygon dust
bool coalesced; // was coalesced from multiple features
double spacing; // feature spacing for --calculate-feature-density
double simplification; // simplification level at this zoom level
std::vector<ssize_t> arc_polygon; // used in --detect-shared-borders
ssize_t renamed; // used in --detect-shared-borders logic
long long clustered; // does this feature need the clustered/point_count attributes?
const char *stringpool; // string pool for keys/values lookup
std::shared_ptr<std::string> tile_stringpool; // string pool for mvt_value construction
std::set<std::string> need_tilestats;
std::unordered_map<std::string, accum_state> attribute_accum_state;

int z; // tile being produced
int tx;
int ty;
};

std::string serialize_feature(serial_feature *sf, long long wx, long long wy);
serial_feature deserialize_feature(std::string const &geoms, unsigned z, unsigned tx, unsigned ty, unsigned *initial_x, unsigned *initial_y);
serial_feature deserialize_feature(std::string const &geoms, unsigned z, unsigned tx, unsigned ty, unsigned *initial_x, unsigned *initial_y, long long bbox[]);

struct reader {
int poolfd = -1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"maxzoom": "0",
"minzoom": "0",
"name": "tests/loop/out/-z0_-O200_--cluster-densest-as-needed.json.check.mbtiles",
"strategies": "[{\"coalesced_as_needed\":999,\"feature_count_desired\":1000}]",
"strategies": "[{\"coalesced_as_needed\":999,\"feature_count_desired\":401}]",
"type": "overlay",
"version": "2"
}, "features": [
Expand Down
2 changes: 1 addition & 1 deletion tests/loop/out/-z0_-O200_--drop-densest-as-needed.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"maxzoom": "0",
"minzoom": "0",
"name": "tests/loop/out/-z0_-O200_--drop-densest-as-needed.json.check.mbtiles",
"strategies": "[{\"dropped_as_needed\":999,\"feature_count_desired\":1000}]",
"strategies": "[{\"dropped_as_needed\":999,\"feature_count_desired\":401}]",
"type": "overlay",
"version": "2"
}, "features": [
Expand Down
2 changes: 1 addition & 1 deletion tests/loop/out/-z0_-O200_--drop-fraction-as-needed.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"maxzoom": "0",
"minzoom": "0",
"name": "tests/loop/out/-z0_-O200_--drop-fraction-as-needed.json.check.mbtiles",
"strategies": "[{\"dropped_as_needed\":999,\"feature_count_desired\":1000}]",
"strategies": "[{\"dropped_as_needed\":999,\"feature_count_desired\":401}]",
"type": "overlay",
"version": "2"
}, "features": [
Expand Down
Loading
Loading