diff --git a/plugin.cpp b/plugin.cpp index db06357..579a4d1 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -34,10 +34,11 @@ extern "C" { struct writer_arg { int write_to; - mvt_layer *layer; + std::vector *layers; unsigned z; unsigned x; unsigned y; + int extent; }; void *run_writer(void *a) { @@ -49,7 +50,9 @@ void *run_writer(void *a) { exit(EXIT_FAILURE); } - layer_to_geojson(fp, *(wa->layer), wa->z, wa->x, wa->y, false, false); + for (size_t i = 0; i < wa->layers->size(); i++) { + layer_to_geojson(fp, (*(wa->layers))[i], wa->z, wa->x, wa->y, false, true); + } if (fclose(fp) != 0) { if (errno == EPIPE) { @@ -78,13 +81,8 @@ static std::vector to_feature(drawvec &geom) { return out; } -mvt_layer parse_layer(int fd, int z, unsigned x, unsigned y, mvt_layer const &olayer, std::vector> *layermaps, size_t tiling_seg, std::vector> *layer_unmaps) { - mvt_layer ret; - ret.name = olayer.name; - ret.version = olayer.version; - ret.extent = olayer.extent; - - std::string layername = olayer.name; +std::vector parse_layers(int fd, int z, unsigned x, unsigned y, std::vector> *layermaps, size_t tiling_seg, std::vector> *layer_unmaps, int extent) { + std::map ret; FILE *f = fdopen(fd, "r"); if (f == NULL) { @@ -164,6 +162,26 @@ mvt_layer parse_layer(int fd, int z, unsigned x, unsigned y, mvt_layer const &ol exit(EXIT_FAILURE); } + std::string layername = "unknown"; + json_object *tippecanoe = json_hash_get(j, "tippecanoe"); + json_object *layer = NULL; + if (tippecanoe != NULL) { + layer = json_hash_get(tippecanoe, "layer"); + if (layer != NULL && layer->type == JSON_STRING) { + layername = std::string(layer->string); + } + } + + if (ret.count(layername) == 0) { + mvt_layer l; + l.name = layername; + l.version = 2; + l.extent = extent; + + ret.insert(std::pair(layername, l)); + } + auto l = ret.find(layername); + drawvec dv; parse_geometry(t, coordinates, dv, VT_MOVETO, "Filter output", jp->line, j); if (mb_geometry[t] == VT_POLYGON) { @@ -173,8 +191,8 @@ mvt_layer parse_layer(int fd, int z, unsigned x, unsigned y, mvt_layer const &ol // Scale and offset geometry from global to tile for (size_t i = 0; i < dv.size(); i++) { long long scale = 1LL << (32 - z); - dv[i].x = std::round((dv[i].x - scale * x) * olayer.extent / (double) scale); - dv[i].y = std::round((dv[i].y - scale * y) * olayer.extent / (double) scale); + dv[i].x = std::round((dv[i].x - scale * x) * extent / (double) scale); + dv[i].y = std::round((dv[i].y - scale * y) * extent / (double) scale); } if (mb_geometry[t] == VT_POLYGON) { @@ -208,7 +226,7 @@ mvt_layer parse_layer(int fd, int z, unsigned x, unsigned y, mvt_layer const &ol stringify_value(properties->values[i], tp, s, "Filter output", jp->line, j); if (tp >= 0) { mvt_value v = stringified_to_mvt_value(tp, s.c_str()); - ret.tag(feature, std::string(properties->keys[i]->string), v); + l->second.tag(feature, std::string(properties->keys[i]->string), v); if (layermap.count(layername) == 0) { layermap_entry lme = layermap_entry(layermap.size()); @@ -238,7 +256,7 @@ mvt_layer parse_layer(int fd, int z, unsigned x, unsigned y, mvt_layer const &ol } } - ret.features.push_back(feature); + l->second.features.push_back(feature); } json_free(j); @@ -249,7 +267,12 @@ mvt_layer parse_layer(int fd, int z, unsigned x, unsigned y, mvt_layer const &ol perror("fclose postfilter output"); exit(EXIT_FAILURE); } - return ret; + + std::vector final; + for (auto a : ret) { + final.push_back(a.second); + } + return final; } serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::vector> *layermaps, size_t tiling_seg, std::vector> *layer_unmaps) { @@ -520,17 +543,18 @@ void setup_filter(const char *filter, int *write_to, int *read_from, pid_t *pid, } } -mvt_layer filter_layer(const char *filter, mvt_layer &layer, unsigned z, unsigned x, unsigned y, std::vector> *layermaps, size_t tiling_seg, std::vector> *layer_unmaps) { +std::vector filter_layers(const char *filter, std::vector &layers, unsigned z, unsigned x, unsigned y, std::vector> *layermaps, size_t tiling_seg, std::vector> *layer_unmaps, int extent) { int write_to, read_from; pid_t pid; setup_filter(filter, &write_to, &read_from, &pid, z, x, y); writer_arg wa; wa.write_to = write_to; - wa.layer = &layer; + wa.layers = &layers; wa.z = z; wa.x = x; wa.y = y; + wa.extent = extent; pthread_t writer; if (pthread_create(&writer, NULL, run_writer, &wa) != 0) { @@ -538,7 +562,7 @@ mvt_layer filter_layer(const char *filter, mvt_layer &layer, unsigned z, unsigne exit(EXIT_FAILURE); } - layer = parse_layer(read_from, z, x, y, layer, layermaps, tiling_seg, layer_unmaps); + layers = parse_layers(read_from, z, x, y, layermaps, tiling_seg, layer_unmaps, extent); while (1) { int stat_loc; @@ -557,5 +581,5 @@ mvt_layer filter_layer(const char *filter, mvt_layer &layer, unsigned z, unsigne exit(EXIT_FAILURE); } - return layer; + return layers; } diff --git a/plugin.hpp b/plugin.hpp index 07f848f..ec87a31 100644 --- a/plugin.hpp +++ b/plugin.hpp @@ -1,3 +1,3 @@ -mvt_layer filter_layer(const char *filter, mvt_layer &layer, unsigned z, unsigned x, unsigned y, std::vector> *layermaps, size_t tiling_seg, std::vector> *layer_unmaps); +std::vector filter_layers(const char *filter, std::vector &layer, unsigned z, unsigned x, unsigned y, std::vector> *layermaps, size_t tiling_seg, std::vector> *layer_unmaps, int extent); void setup_filter(const char *filter, int *write_to, int *read_from, pid_t *pid, unsigned z, unsigned x, unsigned y); serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::vector> *layermaps, size_t tiling_seg, std::vector> *layer_unmaps); diff --git a/tile.cpp b/tile.cpp index e92d23b..e003f60 100644 --- a/tile.cpp +++ b/tile.cpp @@ -1833,15 +1833,15 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s layer.features.push_back(feature); } - if (postfilter != NULL) { - layer = filter_layer(postfilter, layer, z, tx, ty, layermaps, tiling_seg, layer_unmaps); - } - if (layer.features.size() > 0) { tile.layers.push_back(layer); } } + if (postfilter != NULL) { + tile.layers = filter_layers(postfilter, tile.layers, z, tx, ty, layermaps, tiling_seg, layer_unmaps, 1 << line_detail); + } + if (z == 0 && unclipped_features < original_features / 2) { fprintf(stderr, "\n\nMore than half the features were clipped away at zoom level 0.\n"); fprintf(stderr, "Is your data in the wrong projection? It should be in WGS84/EPSG:4326.\n");