Optimize away any features that don't draw at all

This commit is contained in:
Eric Fischer 2014-09-23 11:30:32 -07:00
parent 8ebeada364
commit 405889317e

201
tile.cc
View File

@ -42,6 +42,84 @@ static inline int compress(std::string const& input, std::string& output) {
return 0;
}
int draw(char **meta, mapnik::vector::tile_feature *feature, int z, unsigned tx, unsigned ty, int detail) {
int px = 0, py = 0;
int cmd_idx = -1;
int cmd = -1;
int length = 0;
int drew = 0;
while (1) {
int op;
deserialize_int(meta, &op);
if (op == VT_END) {
break;
}
if (op != cmd) {
if (cmd_idx >= 0) {
if (feature != NULL) {
feature->set_geometry(cmd_idx, (length << CMD_BITS) | (cmd & ((1 << CMD_BITS) - 1)));
}
}
cmd = op;
length = 0;
if (feature != NULL) {
cmd_idx = feature->geometry_size();
feature->add_geometry(0);
}
}
if (op == VT_MOVETO || op == VT_LINETO) {
int wx, wy;
deserialize_int(meta, &wx);
deserialize_int(meta, &wy);
long long wwx = (unsigned) wx;
long long wwy = (unsigned) wy;
if (z != 0) {
wwx -= tx << (32 - z);
wwy -= ty << (32 - z);
}
wwx >>= (32 - detail - z);
wwy >>= (32 - detail - z);
int dx = wwx - px;
int dy = wwy - py;
if (dx != 0 || dy != 0 || length == 0) {
if (feature != NULL) {
feature->add_geometry((dx << 1) ^ (dx >> 31));
feature->add_geometry((dy << 1) ^ (dy >> 31));
}
px = wwx;
py = wwy;
length++;
if (op == VT_LINETO && (dx != 0 || dy != 0)) {
drew = 1;
}
}
} else if (op == VT_CLOSEPATH) {
length++;
}
}
if (cmd_idx >= 0) {
if (feature != NULL) {
feature->set_geometry(cmd_idx, (length << CMD_BITS) | (cmd & ((1 << CMD_BITS) - 1)));
}
}
return drew;
}
void write_tile(struct index *start, struct index *end, char *metabase, unsigned *file_bbox, int z, unsigned tx, unsigned ty, int detail) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
@ -61,109 +139,44 @@ void write_tile(struct index *start, struct index *end, char *metabase, unsigned
keys.tail = NULL;
struct index *i;
//printf("tile -----------------------------------------------\n");
for (i = start; i < end; i++) {
mapnik::vector::tile_feature *feature = layer->add_features();
int px = 0, py = 0;
int cmd_idx = -1;
int cmd = -1;
int length = 0;
//printf("%llx ", i->index);
int t;
char *meta = metabase + i->fpos;
int t;
deserialize_int(&meta, &t);
//printf("(%d) ", t);
if (t == VT_POINT) {
feature->set_type(mapnik::vector::tile::Point);
} else if (t == VT_LINE) {
feature->set_type(mapnik::vector::tile::LineString);
} else if (t == VT_POLYGON) {
feature->set_type(mapnik::vector::tile::Polygon);
} else {
feature->set_type(mapnik::vector::tile::Unknown);
}
while (1) {
int op;
deserialize_int(&meta, &op);
if (op == VT_END) {
break;
}
//printf("%d: ", op);
if (op != cmd) {
if (cmd_idx >= 0) {
feature->set_geometry(cmd_idx, (length << CMD_BITS) | (cmd & ((1 << CMD_BITS) - 1)));
}
cmd = op;
length = 0;
cmd_idx = feature->geometry_size();
feature->add_geometry(0);
}
if (op == VT_MOVETO || op == VT_LINETO) {
int wx, wy;
deserialize_int(&meta, &wx);
deserialize_int(&meta, &wy);
long long wwx = (unsigned) wx;
long long wwy = (unsigned) wy;
if (z != 0) {
wwx -= tx << (32 - z);
wwy -= ty << (32 - z);
}
wwx >>= (32 - detail - z);
wwy >>= (32 - detail - z);
int dx = wwx - px;
int dy = wwy - py;
if (dx != 0 || dy != 0 || length == 0) {
feature->add_geometry((dx << 1) ^ (dx >> 31));
feature->add_geometry((dy << 1) ^ (dy >> 31));
px = wwx;
py = wwy;
length++;
}
//printf("%lld,%lld ", wwx, wwy);
} else if (op == VT_CLOSEPATH) {
length++;
}
}
if (cmd_idx >= 0) {
feature->set_geometry(cmd_idx, (length << CMD_BITS) | (cmd & ((1 << CMD_BITS) - 1)));
}
int m;
deserialize_int(&meta, &m);
int i;
for (i = 0; i < m; i++) {
int t;
if (t == VT_POINT || draw(&meta, NULL, z, tx, ty, detail)) {
meta = metabase + i->fpos;
deserialize_int(&meta, &t);
struct pool_val *key = deserialize_string(&meta, &keys, VT_STRING);
struct pool_val *value = deserialize_string(&meta, &keys, t);
feature->add_tags(key->n);
feature->add_tags(value->n);
mapnik::vector::tile_feature *feature = layer->add_features();
//printf("%s (%d) = %s (%d)\n", key->s, key->n, value->s, value->n);
if (t == VT_POINT) {
feature->set_type(mapnik::vector::tile::Point);
} else if (t == VT_LINE) {
feature->set_type(mapnik::vector::tile::LineString);
} else if (t == VT_POLYGON) {
feature->set_type(mapnik::vector::tile::Polygon);
} else {
feature->set_type(mapnik::vector::tile::Unknown);
}
draw(&meta, feature, z, tx, ty, detail);
int m;
deserialize_int(&meta, &m);
int i;
for (i = 0; i < m; i++) {
int t;
deserialize_int(&meta, &t);
struct pool_val *key = deserialize_string(&meta, &keys, VT_STRING);
struct pool_val *value = deserialize_string(&meta, &keys, t);
feature->add_tags(key->n);
feature->add_tags(value->n);
}
}
//printf("\n");
}
struct pool_val *pv;