diff --git a/plugin.cpp b/plugin.cpp index 73b68282..1c67b2ba 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -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; @@ -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; diff --git a/serial.cpp b/serial.cpp index 83f11449..ea22fb91 100644 --- a/serial.cpp +++ b/serial.cpp @@ -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(); @@ -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); @@ -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) { @@ -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. @@ -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; } } } @@ -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 @@ -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]; } } diff --git a/serial.hpp b/serial.hpp index 122f33e2..776fbd72 100644 --- a/serial.hpp +++ b/serial.hpp @@ -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 full_keys{}; - std::vector full_values{}; + std::vector full_keys; + std::vector full_values; // These fields are generated from full_keys and full_values // during initial serialization and then replace the string // representations: - std::vector keys{}; - std::vector values{}; + std::vector keys; + std::vector 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 @@ -112,7 +112,7 @@ struct serial_feature { }; 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; diff --git a/tile.cpp b/tile.cpp index 72eaddc7..3fa55250 100644 --- a/tile.cpp +++ b/tile.cpp @@ -438,7 +438,7 @@ static std::vector disassemble_multiplier_clusters(std::vector *geompos, compressor *geomfile[], const char *fname, int child_shards, int max_zoom_increment, int segment, unsigned *initial_x, unsigned *initial_y) { +static void rewrite(serial_feature const &osf, int z, int nextzoom, int maxzoom, unsigned tx, unsigned ty, int buffer, int within[], std::atomic *geompos, compressor *geomfile[], const char *fname, int child_shards, int max_zoom_increment, int segment, unsigned *initial_x, unsigned *initial_y, long long osf_bbox[]) { if (osf.geometry.size() > 0 && (nextzoom <= maxzoom || additional[A_EXTEND_ZOOMS] || extend_zooms_max > 0)) { int xo, yo; int span = 1 << (nextzoom - z); @@ -449,7 +449,7 @@ static void rewrite(serial_feature const &osf, int z, int nextzoom, int maxzoom, int k; for (k = 0; k < 4; k++) { // Division instead of right-shift because coordinates can be negative - bbox2[k] = osf.bbox[k] / (1 << (32 - nextzoom - 8)); + bbox2[k] = osf_bbox[k] / (1 << (32 - nextzoom - 8)); } // Decrement the top and left edges so that any features that are // touching the edge can potentially be included in the adjacent tiles too. @@ -920,30 +920,30 @@ struct write_tile_args { // Clips a feature's geometry to the tile bounds at the specified zoom level // with the specified buffer. Returns true if the feature was entirely clipped away // by bounding box alone; otherwise returns false. -static bool clip_to_tile(serial_feature &sf, int z, long long buffer) { - int quick = quick_check(sf.bbox, z, buffer); +static bool clip_to_tile(serial_feature &sf, int z, long long buffer, long long sf_bbox[]) { + int quick = quick_check(sf_bbox, z, buffer); if (z == 0) { - if (sf.bbox[0] <= (1LL << 32) * buffer / 256 || sf.bbox[2] >= (1LL << 32) - ((1LL << 32) * buffer / 256)) { + if (sf_bbox[0] <= (1LL << 32) * buffer / 256 || sf_bbox[2] >= (1LL << 32) - ((1LL << 32) * buffer / 256)) { // If the geometry extends off the edge of the world, concatenate on another copy // shifted by 360 degrees, and then make sure both copies get clipped down to size. size_t n = sf.geometry.size(); - if (sf.bbox[0] <= (1LL << 32) * buffer / 256) { + if (sf_bbox[0] <= (1LL << 32) * buffer / 256) { for (size_t i = 0; i < n; i++) { sf.geometry.push_back(draw(sf.geometry[i].op, sf.geometry[i].x + (1LL << 32), sf.geometry[i].y)); } } - if (sf.bbox[2] >= (1LL << 32) - ((1LL << 32) * buffer / 256)) { + if (sf_bbox[2] >= (1LL << 32) - ((1LL << 32) * buffer / 256)) { for (size_t i = 0; i < n; i++) { sf.geometry.push_back(draw(sf.geometry[i].op, sf.geometry[i].x - (1LL << 32), sf.geometry[i].y)); } } - sf.bbox[0] = 0; - sf.bbox[2] = 1LL << 32; + sf_bbox[0] = 0; + sf_bbox[2] = 1LL << 32; quick = -1; } @@ -986,7 +986,7 @@ static bool clip_to_tile(serial_feature &sf, int z, long long buffer) { // that are duplicated across the date line if (prevent[P_DUPLICATION] && z != 0) { - if (point_within_tile((sf.bbox[0] + sf.bbox[2]) / 2, (sf.bbox[1] + sf.bbox[3]) / 2, z)) { + if (point_within_tile((sf_bbox[0] + sf_bbox[2]) / 2, (sf_bbox[1] + sf_bbox[3]) / 2, z)) { // sf.geometry is unchanged } else { sf.geometry.clear(); @@ -1060,7 +1060,8 @@ static serial_feature next_feature(decompressor *geoms, std::atomic * exit(EXIT_READ); } - sf = deserialize_feature(s, z, tx, ty, initial_x, initial_y); + long long sf_bbox[4]; + sf = deserialize_feature(s, z, tx, ty, initial_x, initial_y, sf_bbox); sf.stringpool = global_stringpool + pool_off[sf.segment]; size_t passes = pass + 1; @@ -1078,7 +1079,7 @@ static serial_feature next_feature(decompressor *geoms, std::atomic * (*original_features)++; - if (clip_to_tile(sf, z, buffer)) { + if (clip_to_tile(sf, z, buffer, sf_bbox)) { continue; } @@ -1090,7 +1091,7 @@ static serial_feature next_feature(decompressor *geoms, std::atomic * if (first_time && pass == 0) { /* only write out the next zoom once, even if we retry */ if (sf.tippecanoe_maxzoom == -1 || sf.tippecanoe_maxzoom >= nextzoom) { - rewrite(sf, z, nextzoom, maxzoom, tx, ty, buffer, within, geompos, geomfile, fname, child_shards, max_zoom_increment, sf.segment, initial_x, initial_y); + rewrite(sf, z, nextzoom, maxzoom, tx, ty, buffer, within, geompos, geomfile, fname, child_shards, max_zoom_increment, sf.segment, initial_x, initial_y, sf_bbox); } }