diff --git a/tile.cc b/tile.cc index 56fbd6de..83d31999 100644 --- a/tile.cc +++ b/tile.cc @@ -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;