mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-05 09:55:41 +02:00
Don't carry a bounding box around with the feature
This commit is contained in:
-19
@@ -398,8 +398,6 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::
|
|||||||
sf.geometry = dv;
|
sf.geometry = dv;
|
||||||
sf.seq = 0;
|
sf.seq = 0;
|
||||||
sf.index = 0;
|
sf.index = 0;
|
||||||
sf.bbox[0] = sf.bbox[1] = LLONG_MAX;
|
|
||||||
sf.bbox[2] = sf.bbox[3] = LLONG_MIN;
|
|
||||||
sf.extent = 0;
|
sf.extent = 0;
|
||||||
sf.has_id = false;
|
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");
|
json_object *id = json_hash_get(j, "id");
|
||||||
if (id != NULL && id->type == JSON_NUMBER) {
|
if (id != NULL && id->type == JSON_NUMBER) {
|
||||||
sf.id = id->value.number.number;
|
sf.id = id->value.number.number;
|
||||||
|
|||||||
+26
-25
@@ -230,7 +230,7 @@ std::string serialize_feature(serial_feature *sf, long long wx, long long wy) {
|
|||||||
return s;
|
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;
|
serial_feature sf;
|
||||||
const char *cp = geoms.c_str();
|
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.label_point = 0;
|
||||||
sf.extent = 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)) {
|
if (sf.layer & (1 << FLAG_INDEX)) {
|
||||||
deserialize_ulong_long(&cp, &sf.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) {
|
int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::string const &layername) {
|
||||||
struct reader *r = &(*sst->readers)[sst->segment];
|
struct reader *r = &(*sst->readers)[sst->segment];
|
||||||
|
|
||||||
sf.bbox[0] = LLONG_MAX;
|
long long sf_bbox[4];
|
||||||
sf.bbox[1] = LLONG_MAX;
|
sf_bbox[0] = LLONG_MAX;
|
||||||
sf.bbox[2] = LLONG_MIN;
|
sf_bbox[1] = LLONG_MAX;
|
||||||
sf.bbox[3] = LLONG_MIN;
|
sf_bbox[2] = LLONG_MIN;
|
||||||
|
sf_bbox[3] = LLONG_MIN;
|
||||||
|
|
||||||
for (size_t i = 0; i < sf.geometry.size(); i++) {
|
for (size_t i = 0; i < sf.geometry.size(); i++) {
|
||||||
if (sf.geometry[i].op == VT_MOVETO || sf.geometry[i].op == VT_LINETO) {
|
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
|
// try to remind myself that the geometry in this function is in SCALED COORDINATES
|
||||||
drawvec scaled_geometry = sf.geometry;
|
drawvec scaled_geometry = sf.geometry;
|
||||||
sf.geometry.clear();
|
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.
|
// 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.
|
// 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);
|
scaled_geometry = remove_noop(scaled_geometry, sf.t, 0);
|
||||||
|
|
||||||
sf.bbox[0] = LLONG_MAX;
|
sf_bbox[0] = LLONG_MAX;
|
||||||
sf.bbox[1] = LLONG_MAX;
|
sf_bbox[1] = LLONG_MAX;
|
||||||
sf.bbox[2] = LLONG_MIN;
|
sf_bbox[2] = LLONG_MIN;
|
||||||
sf.bbox[3] = LLONG_MIN;
|
sf_bbox[3] = LLONG_MIN;
|
||||||
|
|
||||||
for (auto &g : scaled_geometry) {
|
for (auto &g : scaled_geometry) {
|
||||||
long long x = SHIFT_LEFT(g.x);
|
long long x = SHIFT_LEFT(g.x);
|
||||||
long long y = SHIFT_LEFT(g.y);
|
long long y = SHIFT_LEFT(g.y);
|
||||||
|
|
||||||
if (x < sf.bbox[0]) {
|
if (x < sf_bbox[0]) {
|
||||||
sf.bbox[0] = x;
|
sf_bbox[0] = x;
|
||||||
}
|
}
|
||||||
if (y < sf.bbox[1]) {
|
if (y < sf_bbox[1]) {
|
||||||
sf.bbox[1] = y;
|
sf_bbox[1] = y;
|
||||||
}
|
}
|
||||||
if (x > sf.bbox[2]) {
|
if (x > sf_bbox[2]) {
|
||||||
sf.bbox[2] = x;
|
sf_bbox[2] = x;
|
||||||
}
|
}
|
||||||
if (y > sf.bbox[3]) {
|
if (y > sf_bbox[3]) {
|
||||||
sf.bbox[3] = y;
|
sf_bbox[3] = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -672,8 +673,8 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf, std::
|
|||||||
|
|
||||||
if (sf.t == VT_POINT) {
|
if (sf.t == VT_POINT) {
|
||||||
// keep old behavior, which loses one bit of precision at the bottom
|
// keep old behavior, which loses one bit of precision at the bottom
|
||||||
midx = (sf.bbox[0] / 2 + sf.bbox[2] / 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);
|
midy = (sf_bbox[1] / 2 + sf_bbox[3] / 2) & ((1LL << 32) - 1);
|
||||||
} else {
|
} else {
|
||||||
// To reduce the chances of giving multiple polygons or linestrings
|
// To reduce the chances of giving multiple polygons or linestrings
|
||||||
// the same index, use an arbitrary but predictable point from the
|
// 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);
|
fwrite_check(&index, sizeof(struct index), 1, r->indexfile, &r->indexpos, sst->fname);
|
||||||
|
|
||||||
for (size_t i = 0; i < 2; i++) {
|
for (size_t i = 0; i < 2; i++) {
|
||||||
if (sf.bbox[i] < r->file_bbox[i]) {
|
if (sf_bbox[i] < r->file_bbox[i]) {
|
||||||
r->file_bbox[i] = sf.bbox[i];
|
r->file_bbox[i] = sf_bbox[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t i = 2; i < 4; i++) {
|
for (size_t i = 2; i < 4; i++) {
|
||||||
if (sf.bbox[i] > r->file_bbox[i]) {
|
if (sf_bbox[i] > r->file_bbox[i]) {
|
||||||
r->file_bbox[i] = sf.bbox[i];
|
r->file_bbox[i] = sf_bbox[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -65,30 +65,30 @@ struct serial_feature {
|
|||||||
int tippecanoe_minzoom = -1;
|
int tippecanoe_minzoom = -1;
|
||||||
int tippecanoe_maxzoom = -1;
|
int tippecanoe_maxzoom = -1;
|
||||||
|
|
||||||
drawvec geometry = drawvec();
|
drawvec geometry;
|
||||||
unsigned long long index = 0;
|
unsigned long long index = 0;
|
||||||
unsigned long long label_point = 0;
|
unsigned long long label_point = 0;
|
||||||
long long extent = 0;
|
long long extent = 0;
|
||||||
|
|
||||||
// These fields are not directly serialized, but are used
|
// These fields are not directly serialized, but are used
|
||||||
// to create the keys and values references into the string pool
|
// 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<std::string> full_keys;
|
||||||
std::vector<serial_val> full_values{};
|
std::vector<serial_val> full_values;
|
||||||
|
|
||||||
// These fields are generated from full_keys and full_values
|
// These fields are generated from full_keys and full_values
|
||||||
// during initial serialization and then replace the string
|
// during initial serialization and then replace the string
|
||||||
// representations:
|
// representations:
|
||||||
|
|
||||||
std::vector<long long> keys{};
|
std::vector<long long> keys;
|
||||||
std::vector<long long> values{};
|
std::vector<long long> values;
|
||||||
|
|
||||||
// These fields are used during tiling,
|
// These fields are used during tiling,
|
||||||
// but are not serialized and are not expected
|
// but are not serialized and are not expected
|
||||||
// to be provided by frontends:
|
// 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?
|
drawvec edge_nodes; // what nodes at the tile edge were added during clipping?
|
||||||
|
|
||||||
#define FEATURE_DROPPED -1
|
#define FEATURE_DROPPED -1
|
||||||
@@ -112,7 +112,7 @@ struct serial_feature {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::string serialize_feature(serial_feature *sf, long long wx, long long wy);
|
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 {
|
struct reader {
|
||||||
int poolfd = -1;
|
int poolfd = -1;
|
||||||
|
|||||||
@@ -438,7 +438,7 @@ static std::vector<serial_feature> disassemble_multiplier_clusters(std::vector<s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write out copies of a feature into the temporary files for the next zoom level
|
// Write out copies of a feature into the temporary files for the next zoom level
|
||||||
static void rewrite(serial_feature const &osf, int z, int nextzoom, int maxzoom, unsigned tx, unsigned ty, int buffer, int within[], std::atomic<long long> *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<long long> *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)) {
|
if (osf.geometry.size() > 0 && (nextzoom <= maxzoom || additional[A_EXTEND_ZOOMS] || extend_zooms_max > 0)) {
|
||||||
int xo, yo;
|
int xo, yo;
|
||||||
int span = 1 << (nextzoom - z);
|
int span = 1 << (nextzoom - z);
|
||||||
@@ -449,7 +449,7 @@ static void rewrite(serial_feature const &osf, int z, int nextzoom, int maxzoom,
|
|||||||
int k;
|
int k;
|
||||||
for (k = 0; k < 4; k++) {
|
for (k = 0; k < 4; k++) {
|
||||||
// Division instead of right-shift because coordinates can be negative
|
// 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
|
// Decrement the top and left edges so that any features that are
|
||||||
// touching the edge can potentially be included in the adjacent tiles too.
|
// 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
|
// 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
|
// with the specified buffer. Returns true if the feature was entirely clipped away
|
||||||
// by bounding box alone; otherwise returns false.
|
// by bounding box alone; otherwise returns false.
|
||||||
static bool clip_to_tile(serial_feature &sf, int z, long long 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);
|
int quick = quick_check(sf_bbox, z, buffer);
|
||||||
|
|
||||||
if (z == 0) {
|
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
|
// 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.
|
// shifted by 360 degrees, and then make sure both copies get clipped down to size.
|
||||||
|
|
||||||
size_t n = sf.geometry.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++) {
|
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.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++) {
|
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.geometry.push_back(draw(sf.geometry[i].op, sf.geometry[i].x - (1LL << 32), sf.geometry[i].y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sf.bbox[0] = 0;
|
sf_bbox[0] = 0;
|
||||||
sf.bbox[2] = 1LL << 32;
|
sf_bbox[2] = 1LL << 32;
|
||||||
|
|
||||||
quick = -1;
|
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
|
// that are duplicated across the date line
|
||||||
|
|
||||||
if (prevent[P_DUPLICATION] && z != 0) {
|
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
|
// sf.geometry is unchanged
|
||||||
} else {
|
} else {
|
||||||
sf.geometry.clear();
|
sf.geometry.clear();
|
||||||
@@ -1060,7 +1060,8 @@ static serial_feature next_feature(decompressor *geoms, std::atomic<long long> *
|
|||||||
exit(EXIT_READ);
|
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];
|
sf.stringpool = global_stringpool + pool_off[sf.segment];
|
||||||
|
|
||||||
size_t passes = pass + 1;
|
size_t passes = pass + 1;
|
||||||
@@ -1078,7 +1079,7 @@ static serial_feature next_feature(decompressor *geoms, std::atomic<long long> *
|
|||||||
|
|
||||||
(*original_features)++;
|
(*original_features)++;
|
||||||
|
|
||||||
if (clip_to_tile(sf, z, buffer)) {
|
if (clip_to_tile(sf, z, buffer, sf_bbox)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1090,7 +1091,7 @@ static serial_feature next_feature(decompressor *geoms, std::atomic<long long> *
|
|||||||
|
|
||||||
if (first_time && pass == 0) { /* only write out the next zoom once, even if we retry */
|
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) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user