Add --accumulate-attribute to tippecanoe-overzoom (#189)

* Starting to factor out attribute accumulation into its own file

* Continuing to factor out attribute accumulation

* Reduce duplicate code

* Plumbing the accumulate-attribute option around

* Call the attribute accumulator

* Test that accumulation works

* Add missing #includes

* Don't sort within individual multiplier clusters

Doing so throws off the spatial distribution of the low zooms

* Docs and changelog

* Add comments
This commit is contained in:
Erica Fischer
2024-01-23 15:41:36 -08:00
committed by GitHub
parent f957f30f90
commit cbf222754b
17 changed files with 493 additions and 431 deletions
+5
View File
@@ -1,3 +1,8 @@
# 2.41.2
* Add --accumulate-attribute to tippecanoe-overzoom
* Go back to ordering features within each multiplier cluster spatially, not in the order specified for tile feature order
# 2.41.1 # 2.41.1
* Make --preserve-input-order, --order-by, --order-descending-by, --order-smallest-first, and --order-largest-first cooperate with --retain-points-multiplier. The clusters will be ordered by their lead feature in the specified sequence. The other features in each cluster will continue to be physically near the lead feature, but ordered as specified within the cluster. * Make --preserve-input-order, --order-by, --order-descending-by, --order-smallest-first, and --order-largest-first cooperate with --retain-points-multiplier. The clusters will be ordered by their lead feature in the specified sequence. The other features in each cluster will continue to be physically near the lead feature, but ordered as specified within the cluster.
+8 -3
View File
@@ -58,7 +58,7 @@ C = $(wildcard *.c) $(wildcard *.cpp)
INCLUDES = -I/usr/local/include -I. INCLUDES = -I/usr/local/include -I.
LIBS = -L/usr/local/lib LIBS = -L/usr/local/lib
tippecanoe: geojson.o jsonpull/jsonpull.o tile.o pool.o mbtiles.o geometry.o projection.o memfile.o mvt.o serial.o main.o text.o dirtiles.o pmtiles_file.o plugin.o read_json.o write_json.o geobuf.o flatgeobuf.o evaluator.o geocsv.o csv.o geojson-loop.o json_logger.o visvalingam.o compression.o clip.o sort.o tippecanoe: geojson.o jsonpull/jsonpull.o tile.o pool.o mbtiles.o geometry.o projection.o memfile.o mvt.o serial.o main.o text.o dirtiles.o pmtiles_file.o plugin.o read_json.o write_json.o geobuf.o flatgeobuf.o evaluator.o geocsv.o csv.o geojson-loop.o json_logger.o visvalingam.o compression.o clip.o sort.o attribute.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
tippecanoe-enumerate: enumerate.o tippecanoe-enumerate: enumerate.o
@@ -67,7 +67,7 @@ tippecanoe-enumerate: enumerate.o
tippecanoe-decode: decode.o projection.o mvt.o write_json.o text.o jsonpull/jsonpull.o dirtiles.o pmtiles_file.o tippecanoe-decode: decode.o projection.o mvt.o write_json.o text.o jsonpull/jsonpull.o dirtiles.o pmtiles_file.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3
tile-join: tile-join.o projection.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o write_json.o pmtiles_file.o clip.o tile-join: tile-join.o projection.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o write_json.o pmtiles_file.o clip.o attribute.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
tippecanoe-json-tool: jsontool.o jsonpull/jsonpull.o csv.o text.o geojson-loop.o tippecanoe-json-tool: jsontool.o jsonpull/jsonpull.o csv.o text.o geojson-loop.o
@@ -76,7 +76,7 @@ tippecanoe-json-tool: jsontool.o jsonpull/jsonpull.o csv.o text.o geojson-loop.o
unit: unit.o text.o sort.o mvt.o unit: unit.o text.o sort.o mvt.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
tippecanoe-overzoom: overzoom.o mvt.o clip.o evaluator.o jsonpull/jsonpull.o text.o tippecanoe-overzoom: overzoom.o mvt.o clip.o evaluator.o jsonpull/jsonpull.o text.o attribute.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
-include $(wildcard *.d) -include $(wildcard *.d)
@@ -296,6 +296,11 @@ overzoom-test: tippecanoe-overzoom
./tippecanoe-decode tests/pbf/0-0-0-pop-filtered.pbf 0 0 0 > tests/pbf/0-0-0-pop-filtered.pbf.json.check ./tippecanoe-decode tests/pbf/0-0-0-pop-filtered.pbf 0 0 0 > tests/pbf/0-0-0-pop-filtered.pbf.json.check
cmp tests/pbf/0-0-0-pop-filtered.pbf.json.check tests/pbf/0-0-0-pop-filtered.pbf.json cmp tests/pbf/0-0-0-pop-filtered.pbf.json.check tests/pbf/0-0-0-pop-filtered.pbf.json
rm tests/pbf/0-0-0-pop-filtered.pbf tests/pbf/0-0-0-pop-filtered.pbf.json.check rm tests/pbf/0-0-0-pop-filtered.pbf tests/pbf/0-0-0-pop-filtered.pbf.json.check
# Thinning with accumulation
./tippecanoe-overzoom -y NAME -m --accumulate-attribute NAME:comma -o tests/pbf/0-0-0-pop-accum.pbf tests/pbf/0-0-0-pop.pbf 0/0/0 0/0/0
./tippecanoe-decode tests/pbf/0-0-0-pop-accum.pbf 0 0 0 > tests/pbf/0-0-0-pop-accum.pbf.json.check
cmp tests/pbf/0-0-0-pop-accum.pbf.json.check tests/pbf/0-0-0-pop-accum.pbf.json
rm tests/pbf/0-0-0-pop-accum.pbf tests/pbf/0-0-0-pop-accum.pbf.json.check
# Filtering # Filtering
# 243 features in the source tile tests/pbf/0-0-0-pop.pbf # 243 features in the source tile tests/pbf/0-0-0-pop.pbf
# 27 of them match the filter and are retained # 27 of them match the filter and are retained
+1
View File
@@ -997,3 +997,4 @@ reads tile `inz/inx/iny` of `in.mvt.gz` and produces tile `outz/outx/outy` of `o
* `-j` *filter*: Filter features using the same expression syntax as in tippecanoe. * `-j` *filter*: Filter features using the same expression syntax as in tippecanoe.
* `-m`: If a tile was created with the `--retain-points-multiplier` option, thin the tile back down to its normal feature count during overzooming. The first feature from each cluster will be retained, unless `-j` is used to specify a filter, in which case the first matching filter from each cluster will be retained instead. * `-m`: If a tile was created with the `--retain-points-multiplier` option, thin the tile back down to its normal feature count during overzooming. The first feature from each cluster will be retained, unless `-j` is used to specify a filter, in which case the first matching filter from each cluster will be retained instead.
* `--preserve-input-order`: Restore a set of filtered features to its original input order * `--preserve-input-order`: Restore a set of filtered features to its original input order
* `--accumulate-attribute`: Behaves as in `tippecanoe` to sum attributes from the features of a multiplier cluster that are not included in the final output. The attributes from features that are filtered away with `-j` are *not* accumulated onto the output feature.
+146
View File
@@ -0,0 +1,146 @@
#include <string>
#include <map>
#include "attribute.hpp"
#include "errors.hpp"
#include "serial.hpp"
#include "jsonpull/jsonpull.h"
#include "milo/dtoa_milo.h"
void set_attribute_accum(std::map<std::string, attribute_op> &attribute_accum, std::string name, std::string type) {
attribute_op t;
if (type == "sum") {
t = op_sum;
} else if (type == "product") {
t = op_product;
} else if (type == "mean") {
t = op_mean;
} else if (type == "max") {
t = op_max;
} else if (type == "min") {
t = op_min;
} else if (type == "concat") {
t = op_concat;
} else if (type == "comma") {
t = op_comma;
} else {
fprintf(stderr, "Attribute method (%s) must be sum, product, mean, max, min, concat, or comma\n", type.c_str());
exit(EXIT_ARGS);
}
attribute_accum.insert(std::pair<std::string, attribute_op>(name, t));
}
void set_attribute_accum(std::map<std::string, attribute_op> &attribute_accum, const char *arg, char **argv) {
if (*arg == '{') {
json_pull *jp = json_begin_string(arg);
json_object *o = json_read_tree(jp);
if (o == NULL) {
fprintf(stderr, "%s: -E%s: %s\n", *argv, arg, jp->error);
exit(EXIT_JSON);
}
if (o->type != JSON_HASH) {
fprintf(stderr, "%s: -E%s: not a JSON object\n", *argv, arg);
exit(EXIT_JSON);
}
for (size_t i = 0; i < o->value.object.length; i++) {
json_object *k = o->value.object.keys[i];
json_object *v = o->value.object.values[i];
if (k->type != JSON_STRING) {
fprintf(stderr, "%s: -E%s: key %zu not a string\n", *argv, arg, i);
exit(EXIT_JSON);
}
if (v->type != JSON_STRING) {
fprintf(stderr, "%s: -E%s: value %zu not a string\n", *argv, arg, i);
exit(EXIT_JSON);
}
set_attribute_accum(attribute_accum, k->value.string.string, v->value.string.string);
}
json_free(o);
json_end(jp);
return;
}
const char *s = strchr(arg, ':');
if (s == NULL) {
fprintf(stderr, "-E%s option must be in the form -Ename:method\n", arg);
exit(EXIT_ARGS);
}
std::string name = std::string(arg, s - arg);
std::string type = std::string(s + 1);
set_attribute_accum(attribute_accum, name, type);
}
void preserve_attribute(attribute_op op, std::string &key, serial_val &val, std::vector<std::string> &full_keys, std::vector<serial_val> &full_values, std::map<std::string, accum_state> &attribute_accum_state) {
for (size_t i = 0; i < full_keys.size(); i++) {
if (key == full_keys[i]) {
switch (op) {
case op_sum:
full_values[i].s = milo::dtoa_milo(atof(full_values[i].s.c_str()) + atof(val.s.c_str()));
full_values[i].type = mvt_double;
break;
case op_product:
full_values[i].s = milo::dtoa_milo(atof(full_values[i].s.c_str()) * atof(val.s.c_str()));
full_values[i].type = mvt_double;
break;
case op_max: {
double existing = atof(full_values[i].s.c_str());
double maybe = atof(val.s.c_str());
if (maybe > existing) {
full_values[i].s = val.s.c_str();
full_values[i].type = mvt_double;
}
break;
}
case op_min: {
double existing = atof(full_values[i].s.c_str());
double maybe = atof(val.s.c_str());
if (maybe < existing) {
full_values[i].s = val.s.c_str();
full_values[i].type = mvt_double;
}
break;
}
case op_mean: {
auto state = attribute_accum_state.find(key);
if (state == attribute_accum_state.end()) {
accum_state s;
s.sum = atof(full_values[i].s.c_str()) + atof(val.s.c_str());
s.count = 2;
attribute_accum_state.insert(std::pair<std::string, accum_state>(key, s));
full_values[i].s = milo::dtoa_milo(s.sum / s.count);
} else {
state->second.sum += atof(val.s.c_str());
state->second.count += 1;
full_values[i].s = milo::dtoa_milo(state->second.sum / state->second.count);
}
break;
}
case op_concat:
full_values[i].s += val.s;
full_values[i].type = mvt_string;
break;
case op_comma:
full_values[i].s += std::string(",") + val.s;
full_values[i].type = mvt_string;
break;
}
}
}
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef ATTRIBUTE_HPP
#define ATTRIBUTE_HPP
#include <vector>
#include <map>
enum attribute_op {
op_sum,
op_product,
op_mean,
op_concat,
op_comma,
op_max,
op_min,
};
struct accum_state {
double sum = 0;
double count = 0;
};
struct serial_val;
void set_attribute_accum(std::map<std::string, attribute_op> &attribute_accum, std::string name, std::string type);
void set_attribute_accum(std::map<std::string, attribute_op> &attribute_accum, const char *arg, char **argv);
void preserve_attribute(attribute_op op, std::string &key, serial_val &val, std::vector<std::string> &full_keys, std::vector<serial_val> &full_values, std::map<std::string, accum_state> &attribute_accum_state);
#endif
+57 -15
View File
@@ -9,6 +9,7 @@
#include "mvt.hpp" #include "mvt.hpp"
#include "evaluator.hpp" #include "evaluator.hpp"
#include "serial.hpp" #include "serial.hpp"
#include "attribute.hpp"
static std::vector<std::pair<double, double>> clip_poly1(std::vector<std::pair<double, double>> &geom, static std::vector<std::pair<double, double>> clip_poly1(std::vector<std::pair<double, double>> &geom,
long long minx, long long miny, long long maxx, long long maxy, long long minx, long long miny, long long maxx, long long maxy,
@@ -757,7 +758,7 @@ static std::vector<std::pair<double, double>> clip_poly1(std::vector<std::pair<d
std::string overzoom(std::string s, int oz, int ox, int oy, int nz, int nx, int ny, std::string overzoom(std::string s, int oz, int ox, int oy, int nz, int nx, int ny,
int detail, int buffer, std::set<std::string> const &keep, bool do_compress, int detail, int buffer, std::set<std::string> const &keep, bool do_compress,
std::vector<std::pair<unsigned, unsigned>> *next_overzoomed_tiles, std::vector<std::pair<unsigned, unsigned>> *next_overzoomed_tiles,
bool demultiply, json_object *filter, bool preserve_input_order) { bool demultiply, json_object *filter, bool preserve_input_order, std::map<std::string, attribute_op> const &attribute_accum) {
mvt_tile tile; mvt_tile tile;
try { try {
@@ -771,7 +772,7 @@ std::string overzoom(std::string s, int oz, int ox, int oy, int nz, int nx, int
exit(EXIT_PROTOBUF); exit(EXIT_PROTOBUF);
} }
return overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, do_compress, next_overzoomed_tiles, demultiply, filter, preserve_input_order); return overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, do_compress, next_overzoomed_tiles, demultiply, filter, preserve_input_order, attribute_accum);
} }
struct tile_feature { struct tile_feature {
@@ -784,28 +785,69 @@ struct tile_feature {
size_t seq = 0; size_t seq = 0;
}; };
void feature_out(tile_feature const &feature, mvt_layer &outlayer, std::set<std::string> const &keep) { static void feature_out(std::vector<tile_feature> const &features, mvt_layer &outlayer, std::set<std::string> const &keep, std::map<std::string, attribute_op> const &attribute_accum) {
// Add geometry to output feature // Add geometry to output feature
mvt_feature outfeature; mvt_feature outfeature;
outfeature.type = feature.t; outfeature.type = features[0].t;
for (auto const &g : feature.geom) { for (auto const &g : features[0].geom) {
outfeature.geometry.emplace_back(g.op, g.x, g.y); outfeature.geometry.emplace_back(g.op, g.x, g.y);
} }
// ID and attributes, if it didn't get clipped away // ID and attributes, if it didn't get clipped away
if (outfeature.geometry.size() > 0) { if (outfeature.geometry.size() > 0) {
if (feature.has_id) { if (features[0].has_id) {
outfeature.has_id = true; outfeature.has_id = true;
outfeature.id = feature.id; outfeature.id = features[0].id;
} }
outfeature.seq = feature.seq; outfeature.seq = features[0].seq;
for (size_t i = 0; i + 1 < feature.tags.size(); i += 2) { if (attribute_accum.size() > 0) {
if (keep.size() == 0 || keep.find(feature.layer->keys[feature.tags[i]]) != keep.end()) { // convert the attributes of the output feature
outlayer.tag(outfeature, feature.layer->keys[feature.tags[i]], feature.layer->values[feature.tags[i + 1]]); // from mvt_value to serial_val so they can have
// attributes from the other features of the
// multiplier cluster accumulated onto them
std::map<std::string, accum_state> attribute_accum_state;
std::vector<std::string> full_keys;
std::vector<serial_val> full_values;
for (size_t i = 0; i + 1 < features[0].tags.size(); i += 2) {
full_keys.push_back(features[0].layer->keys[features[0].tags[i]]);
full_values.push_back(mvt_value_to_serial_val(features[0].layer->values[features[0].tags[i + 1]]));
}
// accumulate whatever attributes are specified to be accumulated
// onto the feature that will survive into the output, from the
// features that will not
for (size_t i = 1; i < features.size(); i++) {
for (size_t j = 0; j + 1 < features[i].tags.size(); j += 2) {
std::string key = features[i].layer->keys[features[i].tags[j]];
auto f = attribute_accum.find(key);
if (f != attribute_accum.end()) {
serial_val val = mvt_value_to_serial_val(features[i].layer->values[features[i].tags[j + 1]]);
preserve_attribute(f->second, key, val, full_keys, full_values, attribute_accum_state);
}
}
}
// convert the final attributes back to mvt_value
// and tag them onto the output feature
for (size_t i = 0; i < full_keys.size(); i++) {
if (keep.size() == 0 || keep.find(full_keys[i]) != keep.end()) {
outlayer.tag(outfeature, full_keys[i], stringified_to_mvt_value(full_values[i].type, full_values[i].s.c_str()));
}
}
} else {
for (size_t i = 0; i + 1 < features[0].tags.size(); i += 2) {
if (keep.size() == 0 || keep.find(features[0].layer->keys[features[0].tags[i]]) != keep.end()) {
outlayer.tag(outfeature, features[0].layer->keys[features[0].tags[i]], features[0].layer->values[features[0].tags[i + 1]]);
}
} }
} }
@@ -822,7 +864,7 @@ static struct preservecmp {
std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int ny, std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int ny,
int detail, int buffer, std::set<std::string> const &keep, bool do_compress, int detail, int buffer, std::set<std::string> const &keep, bool do_compress,
std::vector<std::pair<unsigned, unsigned>> *next_overzoomed_tiles, std::vector<std::pair<unsigned, unsigned>> *next_overzoomed_tiles,
bool demultiply, json_object *filter, bool preserve_input_order) { bool demultiply, json_object *filter, bool preserve_input_order, std::map<std::string, attribute_op> const &attribute_accum) {
mvt_tile outtile; mvt_tile outtile;
for (auto const &layer : tile.layers) { for (auto const &layer : tile.layers) {
@@ -863,7 +905,7 @@ std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int
if (flush_multiplier_cluster) { if (flush_multiplier_cluster) {
if (pending_tile_features.size() > 0) { if (pending_tile_features.size() > 0) {
feature_out(pending_tile_features[0], outlayer, keep); feature_out(pending_tile_features, outlayer, keep, attribute_accum);
pending_tile_features.clear(); pending_tile_features.clear();
} }
} }
@@ -958,7 +1000,7 @@ std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int
} }
if (pending_tile_features.size() > 0) { if (pending_tile_features.size() > 0) {
feature_out(pending_tile_features[0], outlayer, keep); feature_out(pending_tile_features, outlayer, keep, attribute_accum);
pending_tile_features.clear(); pending_tile_features.clear();
} }
@@ -985,7 +1027,7 @@ std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int
std::string child = overzoom(outtile, nz, nx, ny, std::string child = overzoom(outtile, nz, nx, ny,
nz + 1, nx * 2 + x, ny * 2 + y, nz + 1, nx * 2 + x, ny * 2 + y,
detail, buffer, keep, false, NULL, detail, buffer, keep, false, NULL,
demultiply, filter, preserve_input_order); demultiply, filter, preserve_input_order, attribute_accum);
if (child.size() > 0) { if (child.size() > 0) {
next_overzoomed_tiles->emplace_back(nx * 2 + x, ny * 2 + y); next_overzoomed_tiles->emplace_back(nx * 2 + x, ny * 2 + y);
} }
+5 -2
View File
@@ -9,6 +9,7 @@
#include <stdio.h> #include <stdio.h>
#include <mvt.hpp> #include <mvt.hpp>
#include "jsonpull/jsonpull.h" #include "jsonpull/jsonpull.h"
#include "attribute.hpp"
#define VT_POINT 1 #define VT_POINT 1
#define VT_LINE 2 #define VT_LINE 2
@@ -102,11 +103,13 @@ double distance_from_line(long long point_x, long long point_y, long long segA_x
std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int ny, std::string overzoom(mvt_tile tile, int oz, int ox, int oy, int nz, int nx, int ny,
int detail, int buffer, std::set<std::string> const &keep, bool do_compress, int detail, int buffer, std::set<std::string> const &keep, bool do_compress,
std::vector<std::pair<unsigned, unsigned>> *next_overzoomed_tiles, std::vector<std::pair<unsigned, unsigned>> *next_overzoomed_tiles,
bool demultiply, json_object *filter, bool preserve_input_order); bool demultiply, json_object *filter, bool preserve_input_order,
std::map<std::string, attribute_op> const &attribute_accum);
std::string overzoom(std::string s, int oz, int ox, int oy, int nz, int nx, int ny, std::string overzoom(std::string s, int oz, int ox, int oy, int nz, int nx, int ny,
int detail, int buffer, std::set<std::string> const &keep, bool do_compress, int detail, int buffer, std::set<std::string> const &keep, bool do_compress,
std::vector<std::pair<unsigned, unsigned>> *next_overzoomed_tiles, std::vector<std::pair<unsigned, unsigned>> *next_overzoomed_tiles,
bool demultiply, json_object *filter, bool preserve_input_order); bool demultiply, json_object *filter, bool preserve_input_order,
std::map<std::string, attribute_op> const &attribute_accum);
#endif #endif
+2 -74
View File
@@ -66,6 +66,7 @@
#include "errors.hpp" #include "errors.hpp"
#include "read_json.hpp" #include "read_json.hpp"
#include "sort.hpp" #include "sort.hpp"
#include "attribute.hpp"
static int low_detail = 12; static int low_detail = 12;
static int full_detail = -1; static int full_detail = -1;
@@ -2871,79 +2872,6 @@ void set_attribute_type(std::map<std::string, int> &attribute_types, const char
attribute_types.insert(std::pair<std::string, int>(name, t)); attribute_types.insert(std::pair<std::string, int>(name, t));
} }
void set_attribute_accum(std::map<std::string, attribute_op> &attribute_accum, std::string name, std::string type) {
attribute_op t;
if (type == "sum") {
t = op_sum;
} else if (type == "product") {
t = op_product;
} else if (type == "mean") {
t = op_mean;
} else if (type == "max") {
t = op_max;
} else if (type == "min") {
t = op_min;
} else if (type == "concat") {
t = op_concat;
} else if (type == "comma") {
t = op_comma;
} else {
fprintf(stderr, "Attribute method (%s) must be sum, product, mean, max, min, concat, or comma\n", type.c_str());
exit(EXIT_ARGS);
}
attribute_accum.insert(std::pair<std::string, attribute_op>(name, t));
}
void set_attribute_accum(std::map<std::string, attribute_op> &attribute_accum, const char *arg) {
if (*arg == '{') {
json_pull *jp = json_begin_string(arg);
json_object *o = json_read_tree(jp);
if (o == NULL) {
fprintf(stderr, "%s: -E%s: %s\n", *av, arg, jp->error);
exit(EXIT_JSON);
}
if (o->type != JSON_HASH) {
fprintf(stderr, "%s: -E%s: not a JSON object\n", *av, arg);
exit(EXIT_JSON);
}
for (size_t i = 0; i < o->value.object.length; i++) {
json_object *k = o->value.object.keys[i];
json_object *v = o->value.object.values[i];
if (k->type != JSON_STRING) {
fprintf(stderr, "%s: -E%s: key %zu not a string\n", *av, arg, i);
exit(EXIT_JSON);
}
if (v->type != JSON_STRING) {
fprintf(stderr, "%s: -E%s: value %zu not a string\n", *av, arg, i);
exit(EXIT_JSON);
}
set_attribute_accum(attribute_accum, k->value.string.string, v->value.string.string);
}
json_free(o);
json_end(jp);
return;
}
const char *s = strchr(arg, ':');
if (s == NULL) {
fprintf(stderr, "-E%s option must be in the form -Ename:method\n", arg);
exit(EXIT_ARGS);
}
std::string name = std::string(arg, s - arg);
std::string type = std::string(s + 1);
set_attribute_accum(attribute_accum, name, type);
}
void set_attribute_value(const char *arg) { void set_attribute_value(const char *arg) {
if (*arg == '{') { if (*arg == '{') {
json_pull *jp = json_begin_string(arg); json_pull *jp = json_begin_string(arg);
@@ -3694,7 +3622,7 @@ int main(int argc, char **argv) {
break; break;
case 'E': case 'E':
set_attribute_accum(attribute_accum, optarg); set_attribute_accum(attribute_accum, optarg, argv);
break; break;
default: { default: {
+2
View File
@@ -1268,4 +1268,6 @@ reads tile \fB\fCinz/inx/iny\fR of \fB\fCin.mvt.gz\fR and produces tile \fB\fCou
\fB\fC\-m\fR: If a tile was created with the \fB\fC\-\-retain\-points\-multiplier\fR option, thin the tile back down to its normal feature count during overzooming. The first feature from each cluster will be retained, unless \fB\fC\-j\fR is used to specify a filter, in which case the first matching filter from each cluster will be retained instead. \fB\fC\-m\fR: If a tile was created with the \fB\fC\-\-retain\-points\-multiplier\fR option, thin the tile back down to its normal feature count during overzooming. The first feature from each cluster will be retained, unless \fB\fC\-j\fR is used to specify a filter, in which case the first matching filter from each cluster will be retained instead.
.IP \(bu 2 .IP \(bu 2
\fB\fC\-\-preserve\-input\-order\fR: Restore a set of filtered features to its original input order \fB\fC\-\-preserve\-input\-order\fR: Restore a set of filtered features to its original input order
.IP \(bu 2
\fB\fC\-\-accumulate\-attribute\fR: Behaves as in \fB\fCtippecanoe\fR to sum attributes from the features of a multiplier cluster that are not included in the final output. The attributes from features that are filtered away with \fB\fC\-j\fR are \fInot\fP accumulated onto the output feature.
.RE .RE
+8 -1
View File
@@ -7,6 +7,7 @@
#include "mvt.hpp" #include "mvt.hpp"
#include "geometry.hpp" #include "geometry.hpp"
#include "evaluator.hpp" #include "evaluator.hpp"
#include "attribute.hpp"
extern char *optarg; extern char *optarg;
extern int optind; extern int optind;
@@ -16,6 +17,7 @@ int buffer = 5; // tippecanoe-style: mvt buffer == extent * buffer / 256;
bool demultiply = false; bool demultiply = false;
std::string filter; std::string filter;
bool preserve_input_order = false; bool preserve_input_order = false;
std::map<std::string, attribute_op> attribute_accum;
std::set<std::string> keep; std::set<std::string> keep;
@@ -37,6 +39,7 @@ int main(int argc, char **argv) {
{"filter-points-multiplier", no_argument, 0, 'm'}, {"filter-points-multiplier", no_argument, 0, 'm'},
{"feature-filter", required_argument, 0, 'j'}, {"feature-filter", required_argument, 0, 'j'},
{"preserve-input-order", no_argument, 0, 'o' & 0x1F}, {"preserve-input-order", no_argument, 0, 'o' & 0x1F},
{"accumulate-attribute", required_argument, 0, 'E'},
{0, 0, 0, 0}, {0, 0, 0, 0},
}; };
@@ -83,6 +86,10 @@ int main(int argc, char **argv) {
preserve_input_order = true; preserve_input_order = true;
break; break;
case 'E':
set_attribute_accum(attribute_accum, optarg, argv);
break;
default: default:
fprintf(stderr, "Unrecognized flag -%c\n", i); fprintf(stderr, "Unrecognized flag -%c\n", i);
usage(argv); usage(argv);
@@ -137,7 +144,7 @@ int main(int argc, char **argv) {
json_filter = parse_filter(filter.c_str()); json_filter = parse_filter(filter.c_str());
} }
std::string out = overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, true, NULL, demultiply, json_filter, preserve_input_order); std::string out = overzoom(tile, oz, ox, oy, nz, nx, ny, detail, buffer, keep, true, NULL, demultiply, json_filter, preserve_input_order, attribute_accum);
fwrite(out.c_str(), sizeof(char), out.size(), f); fwrite(out.c_str(), sizeof(char), out.size(), f);
fclose(f); fclose(f);
@@ -16,41 +16,17 @@
}, "features": [ }, "features": [
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [ { "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Andorra", "tippecanoe:retain_points_multiplier_sequence": 4, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 1.494141, 42.488302 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Luxembourg", "tippecanoe:retain_points_multiplier_sequence": 0 }, "geometry": { "type": "Point", "coordinates": [ 6.152344, 49.610710 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Paris", "tippecanoe:retain_points_multiplier_sequence": 89 }, "geometry": { "type": "Point", "coordinates": [ 2.373047, 48.864715 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Astana", "tippecanoe:retain_points_multiplier_sequence": 41, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 71.455078, 51.179343 ] } } { "type": "Feature", "properties": { "NAME": "Astana", "tippecanoe:retain_points_multiplier_sequence": 41, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 71.455078, 51.179343 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Bishkek", "tippecanoe:retain_points_multiplier_sequence": 29 }, "geometry": { "type": "Point", "coordinates": [ 74.619141, 42.875964 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Tashkent", "tippecanoe:retain_points_multiplier_sequence": 67 }, "geometry": { "type": "Point", "coordinates": [ 69.257812, 41.310824 ] } } { "type": "Feature", "properties": { "NAME": "Tashkent", "tippecanoe:retain_points_multiplier_sequence": 67 }, "geometry": { "type": "Point", "coordinates": [ 69.257812, 41.310824 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Auckland", "tippecanoe:retain_points_multiplier_sequence": 71, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 174.726562, -36.879621 ], [ -185.273438, -36.879621 ] ] } } { "type": "Feature", "properties": { "NAME": "Bishkek", "tippecanoe:retain_points_multiplier_sequence": 29 }, "geometry": { "type": "Point", "coordinates": [ 74.619141, 42.875964 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Funafuti", "tippecanoe:retain_points_multiplier_sequence": 1 }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 179.208984, -8.494105 ], [ -180.791016, -8.494105 ] ] } }
,
{ "type": "Feature", "properties": { "NAME": "Suva", "tippecanoe:retain_points_multiplier_sequence": 37 }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 178.417969, -18.145852 ], [ -181.582031, -18.145852 ] ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Bangkok", "tippecanoe:retain_points_multiplier_sequence": 68, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 100.546875, 13.752725 ] } } { "type": "Feature", "properties": { "NAME": "Bangkok", "tippecanoe:retain_points_multiplier_sequence": 68, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 100.546875, 13.752725 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Hanoi", "tippecanoe:retain_points_multiplier_sequence": 51 }, "geometry": { "type": "Point", "coordinates": [ 105.820312, 21.043491 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Vientiane", "tippecanoe:retain_points_multiplier_sequence": 42 }, "geometry": { "type": "Point", "coordinates": [ 102.568359, 17.978733 ] } } { "type": "Feature", "properties": { "NAME": "Vientiane", "tippecanoe:retain_points_multiplier_sequence": 42 }, "geometry": { "type": "Point", "coordinates": [ 102.568359, 17.978733 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Beirut", "tippecanoe:retain_points_multiplier_sequence": 40, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 35.507812, 33.870416 ] } } { "type": "Feature", "properties": { "NAME": "Hanoi", "tippecanoe:retain_points_multiplier_sequence": 51 }, "geometry": { "type": "Point", "coordinates": [ 105.820312, 21.043491 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Cairo", "tippecanoe:retain_points_multiplier_sequence": 87 }, "geometry": { "type": "Point", "coordinates": [ 31.289062, 30.069094 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Tel Aviv-Yafo", "tippecanoe:retain_points_multiplier_sequence": 61 }, "geometry": { "type": "Point", "coordinates": [ 34.804688, 32.101190 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Belmopan", "tippecanoe:retain_points_multiplier_sequence": 44, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -88.769531, 17.224758 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Nassau", "tippecanoe:retain_points_multiplier_sequence": 50 }, "geometry": { "type": "Point", "coordinates": [ -77.343750, 25.085599 ] } }
,
{ "type": "Feature", "properties": { "NAME": "New York", "tippecanoe:retain_points_multiplier_sequence": 81 }, "geometry": { "type": "Point", "coordinates": [ -74.003906, 40.780541 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Berlin", "tippecanoe:retain_points_multiplier_sequence": 72, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 13.359375, 52.536273 ] } } { "type": "Feature", "properties": { "NAME": "Berlin", "tippecanoe:retain_points_multiplier_sequence": 72, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 13.359375, 52.536273 ] } }
, ,
@@ -64,53 +40,17 @@
, ,
{ "type": "Feature", "properties": { "NAME": "Nouakchott", "tippecanoe:retain_points_multiplier_sequence": 39 }, "geometry": { "type": "Point", "coordinates": [ -15.996094, 18.062312 ] } } { "type": "Feature", "properties": { "NAME": "Nouakchott", "tippecanoe:retain_points_multiplier_sequence": 39 }, "geometry": { "type": "Point", "coordinates": [ -15.996094, 18.062312 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Bratislava", "tippecanoe:retain_points_multiplier_sequence": 7, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 17.138672, 48.166085 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Budapest", "tippecanoe:retain_points_multiplier_sequence": 52 }, "geometry": { "type": "Point", "coordinates": [ 19.072266, 47.517201 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Rome", "tippecanoe:retain_points_multiplier_sequence": 84 }, "geometry": { "type": "Point", "coordinates": [ 12.480469, 41.902277 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bridgetown", "tippecanoe:retain_points_multiplier_sequence": 13, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -59.589844, 13.068777 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kingstown", "tippecanoe:retain_points_multiplier_sequence": 14 }, "geometry": { "type": "Point", "coordinates": [ -61.171875, 13.154376 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Saint George's", "tippecanoe:retain_points_multiplier_sequence": 15 }, "geometry": { "type": "Point", "coordinates": [ -61.699219, 12.039321 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bucharest", "tippecanoe:retain_points_multiplier_sequence": 53, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 26.103516, 44.465151 ] } } { "type": "Feature", "properties": { "NAME": "Bucharest", "tippecanoe:retain_points_multiplier_sequence": 53, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 26.103516, 44.465151 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Chisinau", "tippecanoe:retain_points_multiplier_sequence": 26 }, "geometry": { "type": "Point", "coordinates": [ 28.828125, 46.980252 ] } } { "type": "Feature", "properties": { "NAME": "Chisinau", "tippecanoe:retain_points_multiplier_sequence": 26 }, "geometry": { "type": "Point", "coordinates": [ 28.828125, 46.980252 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Istanbul", "tippecanoe:retain_points_multiplier_sequence": 83 }, "geometry": { "type": "Point", "coordinates": [ 29.003906, 41.112469 ] } } { "type": "Feature", "properties": { "NAME": "Istanbul", "tippecanoe:retain_points_multiplier_sequence": 83 }, "geometry": { "type": "Point", "coordinates": [ 29.003906, 41.112469 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Chicago", "tippecanoe:retain_points_multiplier_sequence": 65, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -87.714844, 41.836828 ] } } { "type": "Feature", "properties": { "NAME": "Cairo", "tippecanoe:retain_points_multiplier_sequence": 87, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 31.289062, 30.069094 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Guatemala", "tippecanoe:retain_points_multiplier_sequence": 35 }, "geometry": { "type": "Point", "coordinates": [ -90.527344, 14.604847 ] } } { "type": "Feature", "properties": { "NAME": "Tel Aviv-Yafo", "tippecanoe:retain_points_multiplier_sequence": 61 }, "geometry": { "type": "Point", "coordinates": [ 34.804688, 32.101190 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Toronto", "tippecanoe:retain_points_multiplier_sequence": 77 }, "geometry": { "type": "Point", "coordinates": [ -79.453125, 43.707594 ] } } { "type": "Feature", "properties": { "NAME": "Beirut", "tippecanoe:retain_points_multiplier_sequence": 40 }, "geometry": { "type": "Point", "coordinates": [ 35.507812, 33.870416 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Colombo", "tippecanoe:retain_points_multiplier_sequence": 27, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 79.892578, 6.926427 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Male", "tippecanoe:retain_points_multiplier_sequence": 48 }, "geometry": { "type": "Point", "coordinates": [ 73.476562, 4.127285 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Sri Jawewardenepura Kotte", "tippecanoe:retain_points_multiplier_sequence": 9 }, "geometry": { "type": "Point", "coordinates": [ 79.980469, 6.926427 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dar es Salaam", "tippecanoe:retain_points_multiplier_sequence": 56, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 39.287109, -6.839170 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dodoma", "tippecanoe:retain_points_multiplier_sequence": 10 }, "geometry": { "type": "Point", "coordinates": [ 35.771484, -6.140555 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Nairobi", "tippecanoe:retain_points_multiplier_sequence": 85 }, "geometry": { "type": "Point", "coordinates": [ 36.826172, -1.318243 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dili", "tippecanoe:retain_points_multiplier_sequence": 19, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 125.595703, -8.581021 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Jakarta", "tippecanoe:retain_points_multiplier_sequence": 86 }, "geometry": { "type": "Point", "coordinates": [ 106.787109, -6.140555 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Port Moresby", "tippecanoe:retain_points_multiplier_sequence": 25 }, "geometry": { "type": "Point", "coordinates": [ 147.216797, -9.449062 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Doha", "tippecanoe:retain_points_multiplier_sequence": 8, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 51.503906, 25.324167 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dubai", "tippecanoe:retain_points_multiplier_sequence": 66 }, "geometry": { "type": "Point", "coordinates": [ 55.283203, 25.244696 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Manama", "tippecanoe:retain_points_multiplier_sequence": 16 }, "geometry": { "type": "Point", "coordinates": [ 50.625000, 26.273714 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Dublin", "tippecanoe:retain_points_multiplier_sequence": 57, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -6.240234, 53.330873 ] } } { "type": "Feature", "properties": { "NAME": "Dublin", "tippecanoe:retain_points_multiplier_sequence": 57, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -6.240234, 53.330873 ] } }
, ,
@@ -118,11 +58,17 @@
, ,
{ "type": "Feature", "properties": { "NAME": "Praia", "tippecanoe:retain_points_multiplier_sequence": 49 }, "geometry": { "type": "Point", "coordinates": [ -23.554688, 14.944785 ] } } { "type": "Feature", "properties": { "NAME": "Praia", "tippecanoe:retain_points_multiplier_sequence": 49 }, "geometry": { "type": "Point", "coordinates": [ -23.554688, 14.944785 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Helsinki", "tippecanoe:retain_points_multiplier_sequence": 62, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 24.960938, 60.196156 ] } } { "type": "Feature", "properties": { "NAME": "Funafuti", "tippecanoe:retain_points_multiplier_sequence": 1, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 179.208984, -8.494105 ], [ -180.791016, -8.494105 ] ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Skopje", "tippecanoe:retain_points_multiplier_sequence": 12 }, "geometry": { "type": "Point", "coordinates": [ 21.445312, 41.967659 ] } } { "type": "Feature", "properties": { "NAME": "Suva", "tippecanoe:retain_points_multiplier_sequence": 37 }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 178.417969, -18.145852 ], [ -181.582031, -18.145852 ] ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Tallinn", "tippecanoe:retain_points_multiplier_sequence": 34 }, "geometry": { "type": "Point", "coordinates": [ 24.697266, 59.445075 ] } } { "type": "Feature", "properties": { "NAME": "Auckland", "tippecanoe:retain_points_multiplier_sequence": 71 }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 174.726562, -36.879621 ], [ -185.273438, -36.879621 ] ] } }
,
{ "type": "Feature", "properties": { "NAME": "Guatemala", "tippecanoe:retain_points_multiplier_sequence": 35, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -90.527344, 14.604847 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Chicago", "tippecanoe:retain_points_multiplier_sequence": 65 }, "geometry": { "type": "Point", "coordinates": [ -87.714844, 41.836828 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Toronto", "tippecanoe:retain_points_multiplier_sequence": 77 }, "geometry": { "type": "Point", "coordinates": [ -79.453125, 43.707594 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Hong Kong", "tippecanoe:retain_points_multiplier_sequence": 92, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 114.169922, 22.268764 ] } } { "type": "Feature", "properties": { "NAME": "Hong Kong", "tippecanoe:retain_points_multiplier_sequence": 92, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 114.169922, 22.268764 ] } }
, ,
@@ -130,77 +76,131 @@
, ,
{ "type": "Feature", "properties": { "NAME": "Taipei", "tippecanoe:retain_points_multiplier_sequence": 79 }, "geometry": { "type": "Point", "coordinates": [ 121.552734, 25.005973 ] } } { "type": "Feature", "properties": { "NAME": "Taipei", "tippecanoe:retain_points_multiplier_sequence": 79 }, "geometry": { "type": "Point", "coordinates": [ 121.552734, 25.005973 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Islamabad", "tippecanoe:retain_points_multiplier_sequence": 23, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 73.125000, 33.724340 ] } } { "type": "Feature", "properties": { "NAME": "Jakarta", "tippecanoe:retain_points_multiplier_sequence": 86, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 106.787109, -6.140555 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Kabul", "tippecanoe:retain_points_multiplier_sequence": 78 }, "geometry": { "type": "Point", "coordinates": [ 69.169922, 34.524661 ] } } { "type": "Feature", "properties": { "NAME": "Dili", "tippecanoe:retain_points_multiplier_sequence": 19 }, "geometry": { "type": "Point", "coordinates": [ 125.595703, -8.581021 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Port Moresby", "tippecanoe:retain_points_multiplier_sequence": 25 }, "geometry": { "type": "Point", "coordinates": [ 147.216797, -9.449062 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kabul", "tippecanoe:retain_points_multiplier_sequence": 78, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 69.169922, 34.524661 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Islamabad", "tippecanoe:retain_points_multiplier_sequence": 23 }, "geometry": { "type": "Point", "coordinates": [ 73.125000, 33.724340 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "New Delhi", "tippecanoe:retain_points_multiplier_sequence": 75 }, "geometry": { "type": "Point", "coordinates": [ 77.167969, 28.613459 ] } } { "type": "Feature", "properties": { "NAME": "New Delhi", "tippecanoe:retain_points_multiplier_sequence": 75 }, "geometry": { "type": "Point", "coordinates": [ 77.167969, 28.613459 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Juba", "tippecanoe:retain_points_multiplier_sequence": 6, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 31.552734, 4.828260 ] } } { "type": "Feature", "properties": { "NAME": "Khartoum", "tippecanoe:retain_points_multiplier_sequence": 54, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 32.519531, 15.623037 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Juba", "tippecanoe:retain_points_multiplier_sequence": 6 }, "geometry": { "type": "Point", "coordinates": [ 31.552734, 4.828260 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Kampala", "tippecanoe:retain_points_multiplier_sequence": 21 }, "geometry": { "type": "Point", "coordinates": [ 32.607422, 0.351560 ] } } { "type": "Feature", "properties": { "NAME": "Kampala", "tippecanoe:retain_points_multiplier_sequence": 21 }, "geometry": { "type": "Point", "coordinates": [ 32.607422, 0.351560 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Khartoum", "tippecanoe:retain_points_multiplier_sequence": 54 }, "geometry": { "type": "Point", "coordinates": [ 32.519531, 15.623037 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kingston", "tippecanoe:retain_points_multiplier_sequence": 31, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -76.728516, 17.978733 ] } } { "type": "Feature", "properties": { "NAME": "Kingston", "tippecanoe:retain_points_multiplier_sequence": 31, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -76.728516, 17.978733 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Port-au-Prince", "tippecanoe:retain_points_multiplier_sequence": 20 }, "geometry": { "type": "Point", "coordinates": [ -72.333984, 18.562947 ] } } { "type": "Feature", "properties": { "NAME": "Port-au-Prince", "tippecanoe:retain_points_multiplier_sequence": 20 }, "geometry": { "type": "Point", "coordinates": [ -72.333984, 18.562947 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Santo Domingo", "tippecanoe:retain_points_multiplier_sequence": 60 }, "geometry": { "type": "Point", "coordinates": [ -69.873047, 18.479609 ] } } { "type": "Feature", "properties": { "NAME": "Santo Domingo", "tippecanoe:retain_points_multiplier_sequence": 60 }, "geometry": { "type": "Point", "coordinates": [ -69.873047, 18.479609 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Kingstown", "tippecanoe:retain_points_multiplier_sequence": 14, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -61.171875, 13.154376 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Saint George's", "tippecanoe:retain_points_multiplier_sequence": 15 }, "geometry": { "type": "Point", "coordinates": [ -61.699219, 12.039321 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bridgetown", "tippecanoe:retain_points_multiplier_sequence": 13 }, "geometry": { "type": "Point", "coordinates": [ -59.589844, 13.068777 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kinshasa", "tippecanoe:retain_points_multiplier_sequence": 74, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 15.292969, -4.302591 ] } } { "type": "Feature", "properties": { "NAME": "Kinshasa", "tippecanoe:retain_points_multiplier_sequence": 74, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 15.292969, -4.302591 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Luanda", "tippecanoe:retain_points_multiplier_sequence": 63 }, "geometry": { "type": "Point", "coordinates": [ 13.271484, -8.841651 ] } } { "type": "Feature", "properties": { "NAME": "Luanda", "tippecanoe:retain_points_multiplier_sequence": 63 }, "geometry": { "type": "Point", "coordinates": [ 13.271484, -8.841651 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Windhoek", "tippecanoe:retain_points_multiplier_sequence": 28 }, "geometry": { "type": "Point", "coordinates": [ 17.050781, -22.593726 ] } } { "type": "Feature", "properties": { "NAME": "Windhoek", "tippecanoe:retain_points_multiplier_sequence": 28 }, "geometry": { "type": "Point", "coordinates": [ 17.050781, -22.593726 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Kyoto", "tippecanoe:retain_points_multiplier_sequence": 11, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 135.791016, 35.029996 ] } } { "type": "Feature", "properties": { "NAME": "Lima", "tippecanoe:retain_points_multiplier_sequence": 69, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -77.080078, -12.039321 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Melekeok", "tippecanoe:retain_points_multiplier_sequence": 2 }, "geometry": { "type": "Point", "coordinates": [ 134.648438, 7.449624 ] } } { "type": "Feature", "properties": { "NAME": "La Paz", "tippecanoe:retain_points_multiplier_sequence": 45 }, "geometry": { "type": "Point", "coordinates": [ -68.115234, -16.467695 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Osaka", "tippecanoe:retain_points_multiplier_sequence": 73 }, "geometry": { "type": "Point", "coordinates": [ 135.439453, 34.741612 ] } }
,
{ "type": "Feature", "properties": { "NAME": "La Paz", "tippecanoe:retain_points_multiplier_sequence": 45, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -68.115234, -16.467695 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Lima", "tippecanoe:retain_points_multiplier_sequence": 69 }, "geometry": { "type": "Point", "coordinates": [ -77.080078, -12.039321 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Valparaiso", "tippecanoe:retain_points_multiplier_sequence": 38 }, "geometry": { "type": "Point", "coordinates": [ -71.630859, -33.063924 ] } } { "type": "Feature", "properties": { "NAME": "Valparaiso", "tippecanoe:retain_points_multiplier_sequence": 38 }, "geometry": { "type": "Point", "coordinates": [ -71.630859, -33.063924 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Libreville", "tippecanoe:retain_points_multiplier_sequence": 36, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 9.492188, 0.351560 ] } } { "type": "Feature", "properties": { "NAME": "Luxembourg", "tippecanoe:retain_points_multiplier_sequence": 0, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 6.152344, 49.610710 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Malabo", "tippecanoe:retain_points_multiplier_sequence": 33 }, "geometry": { "type": "Point", "coordinates": [ 8.789062, 3.776559 ] } } { "type": "Feature", "properties": { "NAME": "Paris", "tippecanoe:retain_points_multiplier_sequence": 89 }, "geometry": { "type": "Point", "coordinates": [ 2.373047, 48.864715 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Andorra", "tippecanoe:retain_points_multiplier_sequence": 4 }, "geometry": { "type": "Point", "coordinates": [ 1.494141, 42.488302 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Malabo", "tippecanoe:retain_points_multiplier_sequence": 33, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 8.789062, 3.776559 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Libreville", "tippecanoe:retain_points_multiplier_sequence": 36 }, "geometry": { "type": "Point", "coordinates": [ 9.492188, 0.351560 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Ndjamena", "tippecanoe:retain_points_multiplier_sequence": 32 }, "geometry": { "type": "Point", "coordinates": [ 15.029297, 12.125264 ] } } { "type": "Feature", "properties": { "NAME": "Ndjamena", "tippecanoe:retain_points_multiplier_sequence": 32 }, "geometry": { "type": "Point", "coordinates": [ 15.029297, 12.125264 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Lome", "tippecanoe:retain_points_multiplier_sequence": 18, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 1.230469, 6.140555 ] } } { "type": "Feature", "properties": { "NAME": "Male", "tippecanoe:retain_points_multiplier_sequence": 48, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 73.476562, 4.127285 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Niamey", "tippecanoe:retain_points_multiplier_sequence": 22 }, "geometry": { "type": "Point", "coordinates": [ 2.109375, 13.496473 ] } } { "type": "Feature", "properties": { "NAME": "Colombo", "tippecanoe:retain_points_multiplier_sequence": 27 }, "geometry": { "type": "Point", "coordinates": [ 79.892578, 6.926427 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Valletta", "tippecanoe:retain_points_multiplier_sequence": 47 }, "geometry": { "type": "Point", "coordinates": [ 14.501953, 35.889050 ] } } { "type": "Feature", "properties": { "NAME": "Sri Jawewardenepura Kotte", "tippecanoe:retain_points_multiplier_sequence": 9 }, "geometry": { "type": "Point", "coordinates": [ 79.980469, 6.926427 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Los Angeles", "tippecanoe:retain_points_multiplier_sequence": 80, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -118.212891, 34.016242 ] } } { "type": "Feature", "properties": { "NAME": "Manama", "tippecanoe:retain_points_multiplier_sequence": 16, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 50.625000, 26.273714 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "San Francisco", "tippecanoe:retain_points_multiplier_sequence": 64 }, "geometry": { "type": "Point", "coordinates": [ -122.431641, 37.788081 ] } } { "type": "Feature", "properties": { "NAME": "Doha", "tippecanoe:retain_points_multiplier_sequence": 8 }, "geometry": { "type": "Point", "coordinates": [ 51.503906, 25.324167 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Vancouver", "tippecanoe:retain_points_multiplier_sequence": 76 }, "geometry": { "type": "Point", "coordinates": [ -123.134766, 49.267805 ] } } { "type": "Feature", "properties": { "NAME": "Dubai", "tippecanoe:retain_points_multiplier_sequence": 66 }, "geometry": { "type": "Point", "coordinates": [ 55.283203, 25.244696 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Maseru", "tippecanoe:retain_points_multiplier_sequence": 30, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 27.509766, -29.305561 ] } } { "type": "Feature", "properties": { "NAME": "Maseru", "tippecanoe:retain_points_multiplier_sequence": 30, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 27.509766, -29.305561 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Mbabane", "tippecanoe:retain_points_multiplier_sequence": 5 }, "geometry": { "type": "Point", "coordinates": [ 31.113281, -26.352498 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Pretoria", "tippecanoe:retain_points_multiplier_sequence": 24 }, "geometry": { "type": "Point", "coordinates": [ 28.212891, -25.720735 ] } } { "type": "Feature", "properties": { "NAME": "Pretoria", "tippecanoe:retain_points_multiplier_sequence": 24 }, "geometry": { "type": "Point", "coordinates": [ 28.212891, -25.720735 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Monrovia", "tippecanoe:retain_points_multiplier_sequence": 58, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -10.810547, 6.315299 ] } } { "type": "Feature", "properties": { "NAME": "Mbabane", "tippecanoe:retain_points_multiplier_sequence": 5 }, "geometry": { "type": "Point", "coordinates": [ 31.113281, -26.352498 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Ouagadougou", "tippecanoe:retain_points_multiplier_sequence": 46 }, "geometry": { "type": "Point", "coordinates": [ -1.494141, 12.382928 ] } } { "type": "Feature", "properties": { "NAME": "Melekeok", "tippecanoe:retain_points_multiplier_sequence": 2, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 134.648438, 7.449624 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Osaka", "tippecanoe:retain_points_multiplier_sequence": 73 }, "geometry": { "type": "Point", "coordinates": [ 135.439453, 34.741612 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kyoto", "tippecanoe:retain_points_multiplier_sequence": 11 }, "geometry": { "type": "Point", "coordinates": [ 135.791016, 35.029996 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Nairobi", "tippecanoe:retain_points_multiplier_sequence": 85, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 36.826172, -1.318243 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dodoma", "tippecanoe:retain_points_multiplier_sequence": 10 }, "geometry": { "type": "Point", "coordinates": [ 35.771484, -6.140555 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dar es Salaam", "tippecanoe:retain_points_multiplier_sequence": 56 }, "geometry": { "type": "Point", "coordinates": [ 39.287109, -6.839170 ] } }
,
{ "type": "Feature", "properties": { "NAME": "New York", "tippecanoe:retain_points_multiplier_sequence": 81, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -74.003906, 40.780541 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Nassau", "tippecanoe:retain_points_multiplier_sequence": 50 }, "geometry": { "type": "Point", "coordinates": [ -77.343750, 25.085599 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Belmopan", "tippecanoe:retain_points_multiplier_sequence": 44 }, "geometry": { "type": "Point", "coordinates": [ -88.769531, 17.224758 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Ouagadougou", "tippecanoe:retain_points_multiplier_sequence": 46, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -1.494141, 12.382928 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Monrovia", "tippecanoe:retain_points_multiplier_sequence": 58 }, "geometry": { "type": "Point", "coordinates": [ -10.810547, 6.315299 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Yamoussoukro", "tippecanoe:retain_points_multiplier_sequence": 43 }, "geometry": { "type": "Point", "coordinates": [ -5.273438, 6.839170 ] } } { "type": "Feature", "properties": { "NAME": "Yamoussoukro", "tippecanoe:retain_points_multiplier_sequence": 43 }, "geometry": { "type": "Point", "coordinates": [ -5.273438, 6.839170 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Montevideo", "tippecanoe:retain_points_multiplier_sequence": 17, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -56.162109, -34.885931 ] } } { "type": "Feature", "properties": { "NAME": "Rome", "tippecanoe:retain_points_multiplier_sequence": 84, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 12.480469, 41.902277 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bratislava", "tippecanoe:retain_points_multiplier_sequence": 7 }, "geometry": { "type": "Point", "coordinates": [ 17.138672, 48.166085 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Budapest", "tippecanoe:retain_points_multiplier_sequence": 52 }, "geometry": { "type": "Point", "coordinates": [ 19.072266, 47.517201 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Sao Paulo", "tippecanoe:retain_points_multiplier_sequence": 91, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -46.669922, -23.563987 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Montevideo", "tippecanoe:retain_points_multiplier_sequence": 17 }, "geometry": { "type": "Point", "coordinates": [ -56.162109, -34.885931 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Rio de Janeiro", "tippecanoe:retain_points_multiplier_sequence": 90 }, "geometry": { "type": "Point", "coordinates": [ -43.242188, -22.917923 ] } } { "type": "Feature", "properties": { "NAME": "Rio de Janeiro", "tippecanoe:retain_points_multiplier_sequence": 90 }, "geometry": { "type": "Point", "coordinates": [ -43.242188, -22.917923 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Sao Paulo", "tippecanoe:retain_points_multiplier_sequence": 91 }, "geometry": { "type": "Point", "coordinates": [ -46.669922, -23.563987 ] } } { "type": "Feature", "properties": { "NAME": "Skopje", "tippecanoe:retain_points_multiplier_sequence": 12, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 21.445312, 41.967659 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Helsinki", "tippecanoe:retain_points_multiplier_sequence": 62 }, "geometry": { "type": "Point", "coordinates": [ 24.960938, 60.196156 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Tallinn", "tippecanoe:retain_points_multiplier_sequence": 34 }, "geometry": { "type": "Point", "coordinates": [ 24.697266, 59.445075 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Valletta", "tippecanoe:retain_points_multiplier_sequence": 47, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 14.501953, 35.889050 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Niamey", "tippecanoe:retain_points_multiplier_sequence": 22 }, "geometry": { "type": "Point", "coordinates": [ 2.109375, 13.496473 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Lome", "tippecanoe:retain_points_multiplier_sequence": 18 }, "geometry": { "type": "Point", "coordinates": [ 1.230469, 6.140555 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Vancouver", "tippecanoe:retain_points_multiplier_sequence": 76, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -123.134766, 49.267805 ] } }
,
{ "type": "Feature", "properties": { "NAME": "San Francisco", "tippecanoe:retain_points_multiplier_sequence": 64 }, "geometry": { "type": "Point", "coordinates": [ -122.431641, 37.788081 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Los Angeles", "tippecanoe:retain_points_multiplier_sequence": 80 }, "geometry": { "type": "Point", "coordinates": [ -118.212891, 34.016242 ] } }
] } ] }
] } ] }
] } ] }
@@ -16,119 +16,95 @@
}, "features": [ }, "features": [
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [ { "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [ { "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Luxembourg", "tippecanoe:retain_points_multiplier_sequence": 0, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 6.152344, 49.610710 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Paris", "tippecanoe:retain_points_multiplier_sequence": 89 }, "geometry": { "type": "Point", "coordinates": [ 2.373047, 48.864715 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Andorra", "tippecanoe:retain_points_multiplier_sequence": 4 }, "geometry": { "type": "Point", "coordinates": [ 1.494141, 42.488302 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Funafuti", "tippecanoe:retain_points_multiplier_sequence": 1, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 179.208984, -8.494105 ], [ -180.791016, -8.494105 ] ] } }
,
{ "type": "Feature", "properties": { "NAME": "Suva", "tippecanoe:retain_points_multiplier_sequence": 37 }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 178.417969, -18.145852 ], [ -181.582031, -18.145852 ] ] } }
,
{ "type": "Feature", "properties": { "NAME": "Auckland", "tippecanoe:retain_points_multiplier_sequence": 71 }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 174.726562, -36.879621 ], [ -185.273438, -36.879621 ] ] } }
,
{ "type": "Feature", "properties": { "NAME": "Melekeok", "tippecanoe:retain_points_multiplier_sequence": 2, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 134.648438, 7.449624 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Osaka", "tippecanoe:retain_points_multiplier_sequence": 73 }, "geometry": { "type": "Point", "coordinates": [ 135.439453, 34.741612 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kyoto", "tippecanoe:retain_points_multiplier_sequence": 11 }, "geometry": { "type": "Point", "coordinates": [ 135.791016, 35.029996 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bir Lehlou", "tippecanoe:retain_points_multiplier_sequence": 3, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -9.667969, 26.115986 ] } } { "type": "Feature", "properties": { "NAME": "Bir Lehlou", "tippecanoe:retain_points_multiplier_sequence": 3, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -9.667969, 26.115986 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Dakar", "tippecanoe:retain_points_multiplier_sequence": 70 }, "geometry": { "type": "Point", "coordinates": [ -17.490234, 14.689881 ] } } { "type": "Feature", "properties": { "NAME": "Dakar", "tippecanoe:retain_points_multiplier_sequence": 70 }, "geometry": { "type": "Point", "coordinates": [ -17.490234, 14.689881 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Nouakchott", "tippecanoe:retain_points_multiplier_sequence": 39 }, "geometry": { "type": "Point", "coordinates": [ -15.996094, 18.062312 ] } } { "type": "Feature", "properties": { "NAME": "Nouakchott", "tippecanoe:retain_points_multiplier_sequence": 39 }, "geometry": { "type": "Point", "coordinates": [ -15.996094, 18.062312 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Andorra", "tippecanoe:retain_points_multiplier_sequence": 4, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 1.494141, 42.488302 ] } } { "type": "Feature", "properties": { "NAME": "Skopje", "tippecanoe:retain_points_multiplier_sequence": 12, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 21.445312, 41.967659 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Luxembourg", "tippecanoe:retain_points_multiplier_sequence": 0 }, "geometry": { "type": "Point", "coordinates": [ 6.152344, 49.610710 ] } } { "type": "Feature", "properties": { "NAME": "Helsinki", "tippecanoe:retain_points_multiplier_sequence": 62 }, "geometry": { "type": "Point", "coordinates": [ 24.960938, 60.196156 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Paris", "tippecanoe:retain_points_multiplier_sequence": 89 }, "geometry": { "type": "Point", "coordinates": [ 2.373047, 48.864715 ] } } { "type": "Feature", "properties": { "NAME": "Tallinn", "tippecanoe:retain_points_multiplier_sequence": 34 }, "geometry": { "type": "Point", "coordinates": [ 24.697266, 59.445075 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Juba", "tippecanoe:retain_points_multiplier_sequence": 6, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 31.552734, 4.828260 ] } } { "type": "Feature", "properties": { "NAME": "Kingstown", "tippecanoe:retain_points_multiplier_sequence": 14, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -61.171875, 13.154376 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kampala", "tippecanoe:retain_points_multiplier_sequence": 21 }, "geometry": { "type": "Point", "coordinates": [ 32.607422, 0.351560 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Khartoum", "tippecanoe:retain_points_multiplier_sequence": 54 }, "geometry": { "type": "Point", "coordinates": [ 32.519531, 15.623037 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bratislava", "tippecanoe:retain_points_multiplier_sequence": 7, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 17.138672, 48.166085 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Budapest", "tippecanoe:retain_points_multiplier_sequence": 52 }, "geometry": { "type": "Point", "coordinates": [ 19.072266, 47.517201 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Rome", "tippecanoe:retain_points_multiplier_sequence": 84 }, "geometry": { "type": "Point", "coordinates": [ 12.480469, 41.902277 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Doha", "tippecanoe:retain_points_multiplier_sequence": 8, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 51.503906, 25.324167 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dubai", "tippecanoe:retain_points_multiplier_sequence": 66 }, "geometry": { "type": "Point", "coordinates": [ 55.283203, 25.244696 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Manama", "tippecanoe:retain_points_multiplier_sequence": 16 }, "geometry": { "type": "Point", "coordinates": [ 50.625000, 26.273714 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kyoto", "tippecanoe:retain_points_multiplier_sequence": 11, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 135.791016, 35.029996 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Melekeok", "tippecanoe:retain_points_multiplier_sequence": 2 }, "geometry": { "type": "Point", "coordinates": [ 134.648438, 7.449624 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Osaka", "tippecanoe:retain_points_multiplier_sequence": 73 }, "geometry": { "type": "Point", "coordinates": [ 135.439453, 34.741612 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bridgetown", "tippecanoe:retain_points_multiplier_sequence": 13, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -59.589844, 13.068777 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kingstown", "tippecanoe:retain_points_multiplier_sequence": 14 }, "geometry": { "type": "Point", "coordinates": [ -61.171875, 13.154376 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Saint George's", "tippecanoe:retain_points_multiplier_sequence": 15 }, "geometry": { "type": "Point", "coordinates": [ -61.699219, 12.039321 ] } } { "type": "Feature", "properties": { "NAME": "Saint George's", "tippecanoe:retain_points_multiplier_sequence": 15 }, "geometry": { "type": "Point", "coordinates": [ -61.699219, 12.039321 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Montevideo", "tippecanoe:retain_points_multiplier_sequence": 17, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -56.162109, -34.885931 ] } } { "type": "Feature", "properties": { "NAME": "Bridgetown", "tippecanoe:retain_points_multiplier_sequence": 13 }, "geometry": { "type": "Point", "coordinates": [ -59.589844, 13.068777 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Rio de Janeiro", "tippecanoe:retain_points_multiplier_sequence": 90 }, "geometry": { "type": "Point", "coordinates": [ -43.242188, -22.917923 ] } } { "type": "Feature", "properties": { "NAME": "Manama", "tippecanoe:retain_points_multiplier_sequence": 16, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 50.625000, 26.273714 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Sao Paulo", "tippecanoe:retain_points_multiplier_sequence": 91 }, "geometry": { "type": "Point", "coordinates": [ -46.669922, -23.563987 ] } } { "type": "Feature", "properties": { "NAME": "Doha", "tippecanoe:retain_points_multiplier_sequence": 8 }, "geometry": { "type": "Point", "coordinates": [ 51.503906, 25.324167 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Lome", "tippecanoe:retain_points_multiplier_sequence": 18, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 1.230469, 6.140555 ] } } { "type": "Feature", "properties": { "NAME": "Dubai", "tippecanoe:retain_points_multiplier_sequence": 66 }, "geometry": { "type": "Point", "coordinates": [ 55.283203, 25.244696 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Niamey", "tippecanoe:retain_points_multiplier_sequence": 22 }, "geometry": { "type": "Point", "coordinates": [ 2.109375, 13.496473 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Valletta", "tippecanoe:retain_points_multiplier_sequence": 47 }, "geometry": { "type": "Point", "coordinates": [ 14.501953, 35.889050 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dili", "tippecanoe:retain_points_multiplier_sequence": 19, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 125.595703, -8.581021 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Jakarta", "tippecanoe:retain_points_multiplier_sequence": 86 }, "geometry": { "type": "Point", "coordinates": [ 106.787109, -6.140555 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Port Moresby", "tippecanoe:retain_points_multiplier_sequence": 25 }, "geometry": { "type": "Point", "coordinates": [ 147.216797, -9.449062 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Islamabad", "tippecanoe:retain_points_multiplier_sequence": 23, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 73.125000, 33.724340 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kabul", "tippecanoe:retain_points_multiplier_sequence": 78 }, "geometry": { "type": "Point", "coordinates": [ 69.169922, 34.524661 ] } }
,
{ "type": "Feature", "properties": { "NAME": "New Delhi", "tippecanoe:retain_points_multiplier_sequence": 75 }, "geometry": { "type": "Point", "coordinates": [ 77.167969, 28.613459 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Colombo", "tippecanoe:retain_points_multiplier_sequence": 27, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 79.892578, 6.926427 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Male", "tippecanoe:retain_points_multiplier_sequence": 48 }, "geometry": { "type": "Point", "coordinates": [ 73.476562, 4.127285 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Sri Jawewardenepura Kotte", "tippecanoe:retain_points_multiplier_sequence": 9 }, "geometry": { "type": "Point", "coordinates": [ 79.980469, 6.926427 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Maseru", "tippecanoe:retain_points_multiplier_sequence": 30, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 27.509766, -29.305561 ] } } { "type": "Feature", "properties": { "NAME": "Maseru", "tippecanoe:retain_points_multiplier_sequence": 30, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 27.509766, -29.305561 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Mbabane", "tippecanoe:retain_points_multiplier_sequence": 5 }, "geometry": { "type": "Point", "coordinates": [ 31.113281, -26.352498 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Pretoria", "tippecanoe:retain_points_multiplier_sequence": 24 }, "geometry": { "type": "Point", "coordinates": [ 28.212891, -25.720735 ] } } { "type": "Feature", "properties": { "NAME": "Pretoria", "tippecanoe:retain_points_multiplier_sequence": 24 }, "geometry": { "type": "Point", "coordinates": [ 28.212891, -25.720735 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Mbabane", "tippecanoe:retain_points_multiplier_sequence": 5 }, "geometry": { "type": "Point", "coordinates": [ 31.113281, -26.352498 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kingston", "tippecanoe:retain_points_multiplier_sequence": 31, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -76.728516, 17.978733 ] } } { "type": "Feature", "properties": { "NAME": "Kingston", "tippecanoe:retain_points_multiplier_sequence": 31, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -76.728516, 17.978733 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Port-au-Prince", "tippecanoe:retain_points_multiplier_sequence": 20 }, "geometry": { "type": "Point", "coordinates": [ -72.333984, 18.562947 ] } } { "type": "Feature", "properties": { "NAME": "Port-au-Prince", "tippecanoe:retain_points_multiplier_sequence": 20 }, "geometry": { "type": "Point", "coordinates": [ -72.333984, 18.562947 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Santo Domingo", "tippecanoe:retain_points_multiplier_sequence": 60 }, "geometry": { "type": "Point", "coordinates": [ -69.873047, 18.479609 ] } } { "type": "Feature", "properties": { "NAME": "Santo Domingo", "tippecanoe:retain_points_multiplier_sequence": 60 }, "geometry": { "type": "Point", "coordinates": [ -69.873047, 18.479609 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Libreville", "tippecanoe:retain_points_multiplier_sequence": 36, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 9.492188, 0.351560 ] } } { "type": "Feature", "properties": { "NAME": "Malabo", "tippecanoe:retain_points_multiplier_sequence": 33, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 8.789062, 3.776559 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Malabo", "tippecanoe:retain_points_multiplier_sequence": 33 }, "geometry": { "type": "Point", "coordinates": [ 8.789062, 3.776559 ] } } { "type": "Feature", "properties": { "NAME": "Libreville", "tippecanoe:retain_points_multiplier_sequence": 36 }, "geometry": { "type": "Point", "coordinates": [ 9.492188, 0.351560 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Ndjamena", "tippecanoe:retain_points_multiplier_sequence": 32 }, "geometry": { "type": "Point", "coordinates": [ 15.029297, 12.125264 ] } } { "type": "Feature", "properties": { "NAME": "Ndjamena", "tippecanoe:retain_points_multiplier_sequence": 32 }, "geometry": { "type": "Point", "coordinates": [ 15.029297, 12.125264 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Beirut", "tippecanoe:retain_points_multiplier_sequence": 40, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 35.507812, 33.870416 ] } } { "type": "Feature", "properties": { "NAME": "Guatemala", "tippecanoe:retain_points_multiplier_sequence": 35, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -90.527344, 14.604847 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Cairo", "tippecanoe:retain_points_multiplier_sequence": 87 }, "geometry": { "type": "Point", "coordinates": [ 31.289062, 30.069094 ] } } { "type": "Feature", "properties": { "NAME": "Chicago", "tippecanoe:retain_points_multiplier_sequence": 65 }, "geometry": { "type": "Point", "coordinates": [ -87.714844, 41.836828 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Tel Aviv-Yafo", "tippecanoe:retain_points_multiplier_sequence": 61 }, "geometry": { "type": "Point", "coordinates": [ 34.804688, 32.101190 ] } } { "type": "Feature", "properties": { "NAME": "Toronto", "tippecanoe:retain_points_multiplier_sequence": 77 }, "geometry": { "type": "Point", "coordinates": [ -79.453125, 43.707594 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Astana", "tippecanoe:retain_points_multiplier_sequence": 41, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 71.455078, 51.179343 ] } } { "type": "Feature", "properties": { "NAME": "Astana", "tippecanoe:retain_points_multiplier_sequence": 41, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 71.455078, 51.179343 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Bishkek", "tippecanoe:retain_points_multiplier_sequence": 29 }, "geometry": { "type": "Point", "coordinates": [ 74.619141, 42.875964 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Tashkent", "tippecanoe:retain_points_multiplier_sequence": 67 }, "geometry": { "type": "Point", "coordinates": [ 69.257812, 41.310824 ] } } { "type": "Feature", "properties": { "NAME": "Tashkent", "tippecanoe:retain_points_multiplier_sequence": 67 }, "geometry": { "type": "Point", "coordinates": [ 69.257812, 41.310824 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Belmopan", "tippecanoe:retain_points_multiplier_sequence": 44, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -88.769531, 17.224758 ] } } { "type": "Feature", "properties": { "NAME": "Bishkek", "tippecanoe:retain_points_multiplier_sequence": 29 }, "geometry": { "type": "Point", "coordinates": [ 74.619141, 42.875964 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Nassau", "tippecanoe:retain_points_multiplier_sequence": 50 }, "geometry": { "type": "Point", "coordinates": [ -77.343750, 25.085599 ] } } { "type": "Feature", "properties": { "NAME": "Ouagadougou", "tippecanoe:retain_points_multiplier_sequence": 46, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -1.494141, 12.382928 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "New York", "tippecanoe:retain_points_multiplier_sequence": 81 }, "geometry": { "type": "Point", "coordinates": [ -74.003906, 40.780541 ] } } { "type": "Feature", "properties": { "NAME": "Monrovia", "tippecanoe:retain_points_multiplier_sequence": 58 }, "geometry": { "type": "Point", "coordinates": [ -10.810547, 6.315299 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "La Paz", "tippecanoe:retain_points_multiplier_sequence": 45, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -68.115234, -16.467695 ] } } { "type": "Feature", "properties": { "NAME": "Yamoussoukro", "tippecanoe:retain_points_multiplier_sequence": 43 }, "geometry": { "type": "Point", "coordinates": [ -5.273438, 6.839170 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Lima", "tippecanoe:retain_points_multiplier_sequence": 69 }, "geometry": { "type": "Point", "coordinates": [ -77.080078, -12.039321 ] } } { "type": "Feature", "properties": { "NAME": "Valletta", "tippecanoe:retain_points_multiplier_sequence": 47, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 14.501953, 35.889050 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Valparaiso", "tippecanoe:retain_points_multiplier_sequence": 38 }, "geometry": { "type": "Point", "coordinates": [ -71.630859, -33.063924 ] } } { "type": "Feature", "properties": { "NAME": "Niamey", "tippecanoe:retain_points_multiplier_sequence": 22 }, "geometry": { "type": "Point", "coordinates": [ 2.109375, 13.496473 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Lome", "tippecanoe:retain_points_multiplier_sequence": 18 }, "geometry": { "type": "Point", "coordinates": [ 1.230469, 6.140555 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Male", "tippecanoe:retain_points_multiplier_sequence": 48, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 73.476562, 4.127285 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Colombo", "tippecanoe:retain_points_multiplier_sequence": 27 }, "geometry": { "type": "Point", "coordinates": [ 79.892578, 6.926427 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Sri Jawewardenepura Kotte", "tippecanoe:retain_points_multiplier_sequence": 9 }, "geometry": { "type": "Point", "coordinates": [ 79.980469, 6.926427 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Bucharest", "tippecanoe:retain_points_multiplier_sequence": 53, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 26.103516, 44.465151 ] } } { "type": "Feature", "properties": { "NAME": "Bucharest", "tippecanoe:retain_points_multiplier_sequence": 53, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 26.103516, 44.465151 ] } }
, ,
@@ -136,11 +112,11 @@
, ,
{ "type": "Feature", "properties": { "NAME": "Istanbul", "tippecanoe:retain_points_multiplier_sequence": 83 }, "geometry": { "type": "Point", "coordinates": [ 29.003906, 41.112469 ] } } { "type": "Feature", "properties": { "NAME": "Istanbul", "tippecanoe:retain_points_multiplier_sequence": 83 }, "geometry": { "type": "Point", "coordinates": [ 29.003906, 41.112469 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Dar es Salaam", "tippecanoe:retain_points_multiplier_sequence": 56, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 39.287109, -6.839170 ] } } { "type": "Feature", "properties": { "NAME": "Khartoum", "tippecanoe:retain_points_multiplier_sequence": 54, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 32.519531, 15.623037 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Dodoma", "tippecanoe:retain_points_multiplier_sequence": 10 }, "geometry": { "type": "Point", "coordinates": [ 35.771484, -6.140555 ] } } { "type": "Feature", "properties": { "NAME": "Juba", "tippecanoe:retain_points_multiplier_sequence": 6 }, "geometry": { "type": "Point", "coordinates": [ 31.552734, 4.828260 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Nairobi", "tippecanoe:retain_points_multiplier_sequence": 85 }, "geometry": { "type": "Point", "coordinates": [ 36.826172, -1.318243 ] } } { "type": "Feature", "properties": { "NAME": "Kampala", "tippecanoe:retain_points_multiplier_sequence": 21 }, "geometry": { "type": "Point", "coordinates": [ 32.607422, 0.351560 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Dublin", "tippecanoe:retain_points_multiplier_sequence": 57, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -6.240234, 53.330873 ] } } { "type": "Feature", "properties": { "NAME": "Dublin", "tippecanoe:retain_points_multiplier_sequence": 57, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -6.240234, 53.330873 ] } }
, ,
@@ -148,35 +124,17 @@
, ,
{ "type": "Feature", "properties": { "NAME": "Praia", "tippecanoe:retain_points_multiplier_sequence": 49 }, "geometry": { "type": "Point", "coordinates": [ -23.554688, 14.944785 ] } } { "type": "Feature", "properties": { "NAME": "Praia", "tippecanoe:retain_points_multiplier_sequence": 49 }, "geometry": { "type": "Point", "coordinates": [ -23.554688, 14.944785 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Monrovia", "tippecanoe:retain_points_multiplier_sequence": 58, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -10.810547, 6.315299 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Ouagadougou", "tippecanoe:retain_points_multiplier_sequence": 46 }, "geometry": { "type": "Point", "coordinates": [ -1.494141, 12.382928 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Yamoussoukro", "tippecanoe:retain_points_multiplier_sequence": 43 }, "geometry": { "type": "Point", "coordinates": [ -5.273438, 6.839170 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Helsinki", "tippecanoe:retain_points_multiplier_sequence": 62, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 24.960938, 60.196156 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Skopje", "tippecanoe:retain_points_multiplier_sequence": 12 }, "geometry": { "type": "Point", "coordinates": [ 21.445312, 41.967659 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Tallinn", "tippecanoe:retain_points_multiplier_sequence": 34 }, "geometry": { "type": "Point", "coordinates": [ 24.697266, 59.445075 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Chicago", "tippecanoe:retain_points_multiplier_sequence": 65, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -87.714844, 41.836828 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Guatemala", "tippecanoe:retain_points_multiplier_sequence": 35 }, "geometry": { "type": "Point", "coordinates": [ -90.527344, 14.604847 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Toronto", "tippecanoe:retain_points_multiplier_sequence": 77 }, "geometry": { "type": "Point", "coordinates": [ -79.453125, 43.707594 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bangkok", "tippecanoe:retain_points_multiplier_sequence": 68, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 100.546875, 13.752725 ] } } { "type": "Feature", "properties": { "NAME": "Bangkok", "tippecanoe:retain_points_multiplier_sequence": 68, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 100.546875, 13.752725 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Hanoi", "tippecanoe:retain_points_multiplier_sequence": 51 }, "geometry": { "type": "Point", "coordinates": [ 105.820312, 21.043491 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Vientiane", "tippecanoe:retain_points_multiplier_sequence": 42 }, "geometry": { "type": "Point", "coordinates": [ 102.568359, 17.978733 ] } } { "type": "Feature", "properties": { "NAME": "Vientiane", "tippecanoe:retain_points_multiplier_sequence": 42 }, "geometry": { "type": "Point", "coordinates": [ 102.568359, 17.978733 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Auckland", "tippecanoe:retain_points_multiplier_sequence": 71, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 174.726562, -36.879621 ], [ -185.273438, -36.879621 ] ] } } { "type": "Feature", "properties": { "NAME": "Hanoi", "tippecanoe:retain_points_multiplier_sequence": 51 }, "geometry": { "type": "Point", "coordinates": [ 105.820312, 21.043491 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Funafuti", "tippecanoe:retain_points_multiplier_sequence": 1 }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 179.208984, -8.494105 ], [ -180.791016, -8.494105 ] ] } } { "type": "Feature", "properties": { "NAME": "Lima", "tippecanoe:retain_points_multiplier_sequence": 69, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -77.080078, -12.039321 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Suva", "tippecanoe:retain_points_multiplier_sequence": 37 }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 178.417969, -18.145852 ], [ -181.582031, -18.145852 ] ] } } { "type": "Feature", "properties": { "NAME": "La Paz", "tippecanoe:retain_points_multiplier_sequence": 45 }, "geometry": { "type": "Point", "coordinates": [ -68.115234, -16.467695 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Valparaiso", "tippecanoe:retain_points_multiplier_sequence": 38 }, "geometry": { "type": "Point", "coordinates": [ -71.630859, -33.063924 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Berlin", "tippecanoe:retain_points_multiplier_sequence": 72, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 13.359375, 52.536273 ] } } { "type": "Feature", "properties": { "NAME": "Berlin", "tippecanoe:retain_points_multiplier_sequence": 72, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 13.359375, 52.536273 ] } }
, ,
@@ -190,11 +148,53 @@
, ,
{ "type": "Feature", "properties": { "NAME": "Windhoek", "tippecanoe:retain_points_multiplier_sequence": 28 }, "geometry": { "type": "Point", "coordinates": [ 17.050781, -22.593726 ] } } { "type": "Feature", "properties": { "NAME": "Windhoek", "tippecanoe:retain_points_multiplier_sequence": 28 }, "geometry": { "type": "Point", "coordinates": [ 17.050781, -22.593726 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Los Angeles", "tippecanoe:retain_points_multiplier_sequence": 80, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -118.212891, 34.016242 ] } } { "type": "Feature", "properties": { "NAME": "Vancouver", "tippecanoe:retain_points_multiplier_sequence": 76, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -123.134766, 49.267805 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "San Francisco", "tippecanoe:retain_points_multiplier_sequence": 64 }, "geometry": { "type": "Point", "coordinates": [ -122.431641, 37.788081 ] } } { "type": "Feature", "properties": { "NAME": "San Francisco", "tippecanoe:retain_points_multiplier_sequence": 64 }, "geometry": { "type": "Point", "coordinates": [ -122.431641, 37.788081 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Vancouver", "tippecanoe:retain_points_multiplier_sequence": 76 }, "geometry": { "type": "Point", "coordinates": [ -123.134766, 49.267805 ] } } { "type": "Feature", "properties": { "NAME": "Los Angeles", "tippecanoe:retain_points_multiplier_sequence": 80 }, "geometry": { "type": "Point", "coordinates": [ -118.212891, 34.016242 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kabul", "tippecanoe:retain_points_multiplier_sequence": 78, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 69.169922, 34.524661 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Islamabad", "tippecanoe:retain_points_multiplier_sequence": 23 }, "geometry": { "type": "Point", "coordinates": [ 73.125000, 33.724340 ] } }
,
{ "type": "Feature", "properties": { "NAME": "New Delhi", "tippecanoe:retain_points_multiplier_sequence": 75 }, "geometry": { "type": "Point", "coordinates": [ 77.167969, 28.613459 ] } }
,
{ "type": "Feature", "properties": { "NAME": "New York", "tippecanoe:retain_points_multiplier_sequence": 81, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -74.003906, 40.780541 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Nassau", "tippecanoe:retain_points_multiplier_sequence": 50 }, "geometry": { "type": "Point", "coordinates": [ -77.343750, 25.085599 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Belmopan", "tippecanoe:retain_points_multiplier_sequence": 44 }, "geometry": { "type": "Point", "coordinates": [ -88.769531, 17.224758 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Rome", "tippecanoe:retain_points_multiplier_sequence": 84, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 12.480469, 41.902277 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bratislava", "tippecanoe:retain_points_multiplier_sequence": 7 }, "geometry": { "type": "Point", "coordinates": [ 17.138672, 48.166085 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Budapest", "tippecanoe:retain_points_multiplier_sequence": 52 }, "geometry": { "type": "Point", "coordinates": [ 19.072266, 47.517201 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Nairobi", "tippecanoe:retain_points_multiplier_sequence": 85, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 36.826172, -1.318243 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dodoma", "tippecanoe:retain_points_multiplier_sequence": 10 }, "geometry": { "type": "Point", "coordinates": [ 35.771484, -6.140555 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dar es Salaam", "tippecanoe:retain_points_multiplier_sequence": 56 }, "geometry": { "type": "Point", "coordinates": [ 39.287109, -6.839170 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Jakarta", "tippecanoe:retain_points_multiplier_sequence": 86, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 106.787109, -6.140555 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dili", "tippecanoe:retain_points_multiplier_sequence": 19 }, "geometry": { "type": "Point", "coordinates": [ 125.595703, -8.581021 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Port Moresby", "tippecanoe:retain_points_multiplier_sequence": 25 }, "geometry": { "type": "Point", "coordinates": [ 147.216797, -9.449062 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Cairo", "tippecanoe:retain_points_multiplier_sequence": 87, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 31.289062, 30.069094 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Tel Aviv-Yafo", "tippecanoe:retain_points_multiplier_sequence": 61 }, "geometry": { "type": "Point", "coordinates": [ 34.804688, 32.101190 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Beirut", "tippecanoe:retain_points_multiplier_sequence": 40 }, "geometry": { "type": "Point", "coordinates": [ 35.507812, 33.870416 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Sao Paulo", "tippecanoe:retain_points_multiplier_sequence": 91, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ -46.669922, -23.563987 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Montevideo", "tippecanoe:retain_points_multiplier_sequence": 17 }, "geometry": { "type": "Point", "coordinates": [ -56.162109, -34.885931 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Rio de Janeiro", "tippecanoe:retain_points_multiplier_sequence": 90 }, "geometry": { "type": "Point", "coordinates": [ -43.242188, -22.917923 ] } }
, ,
{ "type": "Feature", "properties": { "NAME": "Hong Kong", "tippecanoe:retain_points_multiplier_sequence": 92, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 114.169922, 22.268764 ] } } { "type": "Feature", "properties": { "NAME": "Hong Kong", "tippecanoe:retain_points_multiplier_sequence": 92, "tippecanoe:retain_points_multiplier_first": true }, "geometry": { "type": "Point", "coordinates": [ 114.169922, 22.268764 ] } }
, ,
+21
View File
@@ -0,0 +1,21 @@
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Vancouver,San Francisco,Los Angeles,Denver,Monterrey,Houston,Mexico City,Guatemala,Chicago,Toronto,Ottawa,Atlanta,Havana,Miami,Washington, D.C.,New York,Nassau,Belmopan,Tegucigalpa,San Salvador,Managua,San Jose,Panama City,Kingston,Port-au-Prince,Santo Domingo,Bogota,Basseterre,Saint John's,Roseau" }, "geometry": { "type": "Point", "coordinates": [ -123.134766, 49.267805 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Castries,Kingstown,Saint George's,Bridgetown,Caracas,Port-of-Spain,Georgetown,Paramaribo,Reykjavík,Dublin,London,Praia,Laayoune,Lisbon,Casablanca,Rabat,Madrid,Bir Lehlou,Dakar,Nouakchott,Banjul,Bissau,Conakry,Freetown,Bamako,Ouagadougou,Monrovia,Yamoussoukro,Abidjan,Accra" }, "geometry": { "type": "Point", "coordinates": [ -60.996094, 14.008696 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Nukualofa,Apia,Quito,Lima,La Paz,Valparaiso,Santiago,Sucre,Brasilia,Asuncion,Buenos Aires,Sao Paulo,Montevideo,Rio de Janeiro,Oslo,Stockholm,The Hague,Amsterdam,Brussels,Luxembourg,Paris,Andorra,Geneva,Bern,Vaduz,Monaco,København,Berlin,Prague,Warsaw" }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -175.166016, -21.125498 ], [ 184.833984, -21.125498 ] ] } }
,
{ "type": "Feature", "properties": { "NAME": "Vienna,Ljubljana,Zagreb,San Marino,Vatican City,Rome,Bratislava,Budapest,Sarajevo,Podgorica,Belgrade,Tirana,Pristina,Skopje,Helsinki,Tallinn,Riga,Vilnius,Minsk,Kiev,Sofia,Bucharest,Chisinau,Istanbul,Moscow,Tbilisi,Algiers,Tunis,Tripoli,Valletta" }, "geometry": { "type": "Point", "coordinates": [ 16.347656, 48.166085 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Niamey,Lome,Cotonou,Porto-Novo,Lagos,Abuja,Sao Tome,Malabo,Libreville,Ndjamena,Yaounde,Bangui,Athens,Ankara,Nicosia,Cairo,Tel Aviv-Yafo,Beirut,Damascus,Yerevan,Baghdad,Jerusalem,Amman,Khartoum,Juba,Kampala,Asmara,Sanaa,Djibouti,Addis Ababa" }, "geometry": { "type": "Point", "coordinates": [ 2.109375, 13.496473 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Hargeysa,Astana,Tashkent,Bishkek,Urumqi,Baku,Tehran,Kuwait,Riyadh,Manama,Doha,Dubai,Abu Dhabi,Ashgabat,Muscat,Mogadishu,Dushanbe,Kabul,Islamabad,New Delhi,Kathmandu,Thimphu,Kolkata,Mumbai,Bangalore,Male,Colombo,Sri Jawewardenepura Kotte,Ulaanbaatar,Dhaka" }, "geometry": { "type": "Point", "coordinates": [ 44.121094, 9.535749 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Chengdu,Naypyidaw,Rangoon,Bangkok,Vientiane,Hanoi,Phnom Penh,Kuala Lumpur,Putrajaya,Singapore,Beijing,Hong Kong,Shanghai,Taipei,Pyongyang,Seoul,Baguio City,Manila,Bandar Seri Begawan,Melekeok,Osaka,Kyoto,Tokyo,Palikir,Majuro,Tarawa,Brazzaville,Kinshasa,Luanda,Windhoek" }, "geometry": { "type": "Point", "coordinates": [ 104.062500, 30.675715 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Cape Town,Kigali,Bujumbura,Lusaka,Harare,Nairobi,Dodoma,Dar es Salaam,Lilongwe,Moroni,Gaborone,Johannesburg,Bloemfontein,Maseru,Pretoria,Mbabane,Lobamba,Maputo,Victoria,Antananarivo,Port Louis,Jakarta,Dili,Port Moresby,Melbourne,Sydney,Canberra,Honiara,Port Vila,Funafuti" }, "geometry": { "type": "Point", "coordinates": [ 18.457031, -33.943360 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Suva,Auckland,Wellington" }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 178.505859, -18.145852 ], [ -181.582031, -18.145852 ] ] } }
] }
] }
+8 -53
View File
@@ -70,21 +70,6 @@ struct stats {
std::vector<struct strategy> strategies; std::vector<struct strategy> strategies;
}; };
void aprintf(std::string *buf, const char *format, ...) {
va_list ap;
char *tmp;
va_start(ap, format);
if (vasprintf(&tmp, format, ap) < 0) {
fprintf(stderr, "memory allocation failure\n");
exit(EXIT_MEMORY);
}
va_end(ap);
buf->append(tmp, strlen(tmp));
free(tmp);
}
void append_tile(std::string message, int z, unsigned x, unsigned y, std::map<std::string, layermap_entry> &layermap, std::vector<std::string> &header, std::map<std::string, std::vector<std::string>> &mapping, std::set<std::string> &exclude, std::set<std::string> &include, std::set<std::string> &keep_layers, std::set<std::string> &remove_layers, int ifmatched, mvt_tile &outtile, json_object *filter) { void append_tile(std::string message, int z, unsigned x, unsigned y, std::map<std::string, layermap_entry> &layermap, std::vector<std::string> &header, std::map<std::string, std::vector<std::string>> &mapping, std::set<std::string> &exclude, std::set<std::string> &include, std::set<std::string> &keep_layers, std::set<std::string> &remove_layers, int ifmatched, mvt_tile &outtile, json_object *filter) {
mvt_tile tile; mvt_tile tile;
int features_added = 0; int features_added = 0;
@@ -173,49 +158,19 @@ void append_tile(std::string message, int z, unsigned x, unsigned y, std::map<st
for (size_t t = 0; t + 1 < feat.tags.size(); t += 2) { for (size_t t = 0; t + 1 < feat.tags.size(); t += 2) {
const char *key = layer.keys[feat.tags[t]].c_str(); const char *key = layer.keys[feat.tags[t]].c_str();
mvt_value &val = layer.values[feat.tags[t + 1]]; mvt_value &val = layer.values[feat.tags[t + 1]];
std::string value; serial_val sv = mvt_value_to_serial_val(val);
int type = -1;
if (val.type == mvt_string) { if (sv.type == mvt_null) {
value = val.string_value;
type = mvt_string;
} else if (val.type == mvt_int) {
aprintf(&value, "%lld", (long long) val.numeric_value.int_value);
type = mvt_double;
} else if (val.type == mvt_double) {
aprintf(&value, "%s", milo::dtoa_milo(val.numeric_value.double_value).c_str());
type = mvt_double;
} else if (val.type == mvt_float) {
aprintf(&value, "%s", milo::dtoa_milo(val.numeric_value.float_value).c_str());
type = mvt_double;
} else if (val.type == mvt_bool) {
aprintf(&value, "%s", val.numeric_value.bool_value ? "true" : "false");
type = mvt_bool;
} else if (val.type == mvt_sint) {
aprintf(&value, "%lld", (long long) val.numeric_value.sint_value);
type = mvt_double;
} else if (val.type == mvt_uint) {
aprintf(&value, "%llu", (long long) val.numeric_value.uint_value);
type = mvt_double;
} else {
continue;
}
if (type < 0) {
continue; continue;
} }
if (include.count(std::string(key)) || (!exclude_all && exclude.count(std::string(key)) == 0 && exclude_attributes.count(std::string(key)) == 0)) { if (include.count(std::string(key)) || (!exclude_all && exclude.count(std::string(key)) == 0 && exclude_attributes.count(std::string(key)) == 0)) {
serial_val sv;
sv.type = type;
sv.s = value;
attributes.insert(std::pair<std::string, std::pair<mvt_value, serial_val>>(key, std::pair<mvt_value, serial_val>(val, sv))); attributes.insert(std::pair<std::string, std::pair<mvt_value, serial_val>>(key, std::pair<mvt_value, serial_val>(val, sv)));
key_order.push_back(key); key_order.push_back(key);
} }
if (header.size() > 0 && strcmp(key, header[0].c_str()) == 0) { if (header.size() > 0 && strcmp(key, header[0].c_str()) == 0) {
std::map<std::string, std::vector<std::string>>::iterator ii = mapping.find(value); std::map<std::string, std::vector<std::string>>::iterator ii = mapping.find(sv.s);
if (ii != mapping.end()) { if (ii != mapping.end()) {
std::vector<std::string> fields = ii->second; std::vector<std::string> fields = ii->second;
@@ -253,14 +208,14 @@ void append_tile(std::string message, int z, unsigned x, unsigned y, std::map<st
attributes.erase(fa); attributes.erase(fa);
} }
serial_val sv; serial_val outsv;
sv.type = outval.type; outsv.type = outval.type;
sv.s = joinval; outsv.s = joinval;
// Convert from double to int if the joined attribute is an integer // Convert from double to int if the joined attribute is an integer
outval = stringified_to_mvt_value(outval.type, joinval.c_str()); outval = stringified_to_mvt_value(outval.type, joinval.c_str());
attributes.insert(std::pair<std::string, std::pair<mvt_value, serial_val>>(joinkey, std::pair<mvt_value, serial_val>(outval, sv))); attributes.insert(std::pair<std::string, std::pair<mvt_value, serial_val>>(joinkey, std::pair<mvt_value, serial_val>(outval, outsv)));
key_order.push_back(joinkey); key_order.push_back(joinkey);
} }
} }
@@ -744,7 +699,7 @@ struct tileset_reader {
} }
if (source.layers.size() != 0) { if (source.layers.size() != 0) {
std::string ret = overzoom(source, parent_tile.z, parent_tile.x, parent_tile.y, tile.z, tile.x, tile.y, -1, buffer, std::set<std::string>(), false, &next_overzoomed_tiles, false, NULL, false); std::string ret = overzoom(source, parent_tile.z, parent_tile.x, parent_tile.y, tile.z, tile.x, tile.y, -1, buffer, std::set<std::string>(), false, &next_overzoomed_tiles, false, NULL, false, std::map<std::string, attribute_op>());
return ret; return ret;
} }
+6 -78
View File
@@ -43,6 +43,7 @@
#include "errors.hpp" #include "errors.hpp"
#include "compression.hpp" #include "compression.hpp"
#include "protozero/varint.hpp" #include "protozero/varint.hpp"
#include "attribute.hpp"
extern "C" { extern "C" {
#include "jsonpull/jsonpull.h" #include "jsonpull/jsonpull.h"
@@ -507,11 +508,6 @@ void rewrite(drawvec &geom, int z, int nextzoom, int maxzoom, long long *bbox, u
} }
} }
struct accum_state {
double sum = 0;
double count = 0;
};
struct partial { struct partial {
std::vector<drawvec> geoms = std::vector<drawvec>(); std::vector<drawvec> geoms = std::vector<drawvec>();
std::vector<long long> keys = std::vector<long long>(); std::vector<long long> keys = std::vector<long long>();
@@ -1825,7 +1821,7 @@ void add_tilestats(std::string const &layername, int z, std::vector<std::map<std
add_to_tilestats(ts->second.tilestats, key, val); add_to_tilestats(ts->second.tilestats, key, val);
} }
void preserve_attribute(attribute_op op, serial_feature &, char *stringpool, long long *pool_off, std::string &key, serial_val &val, partial &p) { void promote_attribute(std::string const &key, partial &p, char *stringpool, long long *pool_off) {
if (p.need_tilestats.count(key) == 0) { if (p.need_tilestats.count(key) == 0) {
p.need_tilestats.insert(key); p.need_tilestats.insert(key);
} }
@@ -1848,70 +1844,6 @@ void preserve_attribute(attribute_op op, serial_feature &, char *stringpool, lon
break; break;
} }
} }
for (size_t i = 0; i < p.full_keys.size(); i++) {
if (key == p.full_keys[i]) {
switch (op) {
case op_sum:
p.full_values[i].s = milo::dtoa_milo(atof(p.full_values[i].s.c_str()) + atof(val.s.c_str()));
p.full_values[i].type = mvt_double;
break;
case op_product:
p.full_values[i].s = milo::dtoa_milo(atof(p.full_values[i].s.c_str()) * atof(val.s.c_str()));
p.full_values[i].type = mvt_double;
break;
case op_max: {
double existing = atof(p.full_values[i].s.c_str());
double maybe = atof(val.s.c_str());
if (maybe > existing) {
p.full_values[i].s = val.s.c_str();
p.full_values[i].type = mvt_double;
}
break;
}
case op_min: {
double existing = atof(p.full_values[i].s.c_str());
double maybe = atof(val.s.c_str());
if (maybe < existing) {
p.full_values[i].s = val.s.c_str();
p.full_values[i].type = mvt_double;
}
break;
}
case op_mean: {
auto state = p.attribute_accum_state.find(key);
if (state == p.attribute_accum_state.end()) {
accum_state s;
s.sum = atof(p.full_values[i].s.c_str()) + atof(val.s.c_str());
s.count = 2;
p.attribute_accum_state.insert(std::pair<std::string, accum_state>(key, s));
p.full_values[i].s = milo::dtoa_milo(s.sum / s.count);
} else {
state->second.sum += atof(val.s.c_str());
state->second.count += 1;
p.full_values[i].s = milo::dtoa_milo(state->second.sum / state->second.count);
}
break;
}
case op_concat:
p.full_values[i].s += val.s;
p.full_values[i].type = mvt_string;
break;
case op_comma:
p.full_values[i].s += std::string(",") + val.s;
p.full_values[i].type = mvt_string;
break;
}
}
}
} }
void preserve_attributes(std::map<std::string, attribute_op> const *attribute_accum, serial_feature &sf, char *stringpool, long long *pool_off, partial &p) { void preserve_attributes(std::map<std::string, attribute_op> const *attribute_accum, serial_feature &sf, char *stringpool, long long *pool_off, partial &p) {
@@ -1924,7 +1856,8 @@ void preserve_attributes(std::map<std::string, attribute_op> const *attribute_ac
auto f = attribute_accum->find(key); auto f = attribute_accum->find(key);
if (f != attribute_accum->end()) { if (f != attribute_accum->end()) {
preserve_attribute(f->second, sf, stringpool, pool_off, key, sv, p); promote_attribute(key, p, stringpool, pool_off);
preserve_attribute(f->second, key, sv, p.full_keys, p.full_values, p.attribute_accum_state);
} }
} }
for (size_t i = 0; i < sf.full_keys.size(); i++) { for (size_t i = 0; i < sf.full_keys.size(); i++) {
@@ -1933,7 +1866,8 @@ void preserve_attributes(std::map<std::string, attribute_op> const *attribute_ac
auto f = attribute_accum->find(key); auto f = attribute_accum->find(key);
if (f != attribute_accum->end()) { if (f != attribute_accum->end()) {
preserve_attribute(f->second, sf, stringpool, pool_off, key, sv, p); promote_attribute(key, p, stringpool, pool_off);
preserve_attribute(f->second, key, sv, p.full_keys, p.full_values, p.attribute_accum_state);
} }
} }
} }
@@ -2721,18 +2655,12 @@ long long write_tile(decompressor *geoms, std::atomic<long long> *geompos_in, ch
if (prevent[P_INPUT_ORDER]) { if (prevent[P_INPUT_ORDER]) {
auto clustered = assemble_multiplier_clusters(layer_features); auto clustered = assemble_multiplier_clusters(layer_features);
for (auto &c : clustered) {
std::sort(c.begin(), c.end());
}
std::sort(clustered.begin(), clustered.end(), preservecmp); std::sort(clustered.begin(), clustered.end(), preservecmp);
layer_features = disassemble_multiplier_clusters(clustered); layer_features = disassemble_multiplier_clusters(clustered);
} }
if (order_by.size() != 0) { if (order_by.size() != 0) {
auto clustered = assemble_multiplier_clusters(layer_features); auto clustered = assemble_multiplier_clusters(layer_features);
for (auto &c : clustered) {
std::sort(c.begin(), c.end());
}
std::sort(clustered.begin(), clustered.end(), ordercmp); std::sort(clustered.begin(), clustered.end(), ordercmp);
layer_features = disassemble_multiplier_clusters(clustered); layer_features = disassemble_multiplier_clusters(clustered);
} }
+1 -10
View File
@@ -8,18 +8,9 @@
#include <map> #include <map>
#include "mbtiles.hpp" #include "mbtiles.hpp"
#include "serial.hpp" #include "serial.hpp"
#include "attribute.hpp"
#include "jsonpull/jsonpull.h" #include "jsonpull/jsonpull.h"
enum attribute_op {
op_sum,
op_product,
op_mean,
op_concat,
op_comma,
op_max,
op_min,
};
struct atomic_strategy { struct atomic_strategy {
std::atomic<size_t> dropped_by_rate; std::atomic<size_t> dropped_by_rate;
std::atomic<size_t> dropped_by_gamma; std::atomic<size_t> dropped_by_gamma;
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef VERSION_HPP #ifndef VERSION_HPP
#define VERSION_HPP #define VERSION_HPP
#define VERSION "v2.41.1" #define VERSION "v2.41.2"
#endif #endif