tippecanoe-decode reads pmtiles input. [#10]

This commit is contained in:
Brandon Liu
2022-12-21 14:57:54 +08:00
parent fedebec55a
commit 64a5a684b0
2 changed files with 62 additions and 27 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ tippecanoe: geojson.o jsonpull/jsonpull.o tile.o pool.o mbtiles.o geometry.o pro
tippecanoe-enumerate: enumerate.o tippecanoe-enumerate: enumerate.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lsqlite3 $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lsqlite3
tippecanoe-decode: decode.o projection.o mvt.o write_json.o text.o jsonpull/jsonpull.o dirtiles.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 pool.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o write_json.o tile-join: tile-join.o projection.o pool.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o write_json.o
+38 -3
View File
@@ -15,7 +15,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <protozero/pbf_reader.hpp> #include <protozero/pbf_reader.hpp>
#include <sys/stat.h>
#include "mvt.hpp" #include "mvt.hpp"
#include "projection.hpp" #include "projection.hpp"
#include "geometry.hpp" #include "geometry.hpp"
@@ -23,6 +22,7 @@
#include "jsonpull/jsonpull.h" #include "jsonpull/jsonpull.h"
#include "mbtiles.hpp" #include "mbtiles.hpp"
#include "dirtiles.hpp" #include "dirtiles.hpp"
#include "pmtiles_file.hpp"
#include "errors.hpp" #include "errors.hpp"
int minzoom = 0; int minzoom = 0;
@@ -245,7 +245,7 @@ void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> co
if (st.st_size < 50 * 1024 * 1024) { if (st.st_size < 50 * 1024 * 1024) {
char *map = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); char *map = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map != NULL && map != MAP_FAILED) { if (map != NULL && map != MAP_FAILED) {
if (strcmp(map, "SQLite format 3") != 0) { if (strcmp(map, "SQLite format 3") != 0 && strncmp(map, "PMTiles", 7) != 0) {
if (z >= 0) { if (z >= 0) {
std::string s = std::string(map, st.st_size); std::string s = std::string(map, st.st_size);
handle(s, z, x, y, to_decode, pipeline, stats, state, coordinate_mode); handle(s, z, x, y, to_decode, pipeline, stats, state, coordinate_mode);
@@ -272,11 +272,28 @@ void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> co
struct stat st; struct stat st;
std::vector<zxy> tiles; std::vector<zxy> tiles;
char *pmtiles_map;
std::vector<pmtiles::entry_zxy> entries;
if (stat(fname, &st) == 0 && (st.st_mode & S_IFDIR) != 0) { if (stat(fname, &st) == 0 && (st.st_mode & S_IFDIR) != 0) {
isdir = true; isdir = true;
db = dirmeta2tmp(fname); db = dirmeta2tmp(fname);
tiles = enumerate_dirtiles(fname, minzoom, maxzoom); tiles = enumerate_dirtiles(fname, minzoom, maxzoom);
} else if (pmtiles_has_suffix(fname)) {
int pmtiles_fd = open(fname, O_RDONLY | O_CLOEXEC);
pmtiles_map = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, pmtiles_fd, 0);
if (pmtiles_map == MAP_FAILED) {
perror("mmap in decode");
exit(EXIT_MEMORY);
}
if (close(pmtiles_fd) != 0) {
perror("close");
exit(EXIT_CLOSE);
}
db = pmtilesmeta2tmp(fname, pmtiles_map);
entries = pmtiles_entries_tms(pmtiles_map, minzoom, maxzoom);
} else { } else {
if (sqlite3_open(fname, &db) != SQLITE_OK) { if (sqlite3_open(fname, &db) != SQLITE_OK) {
fprintf(stderr, "%s: %s\n", fname, sqlite3_errmsg(db)); fprintf(stderr, "%s: %s\n", fname, sqlite3_errmsg(db));
@@ -382,6 +399,11 @@ void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> co
handle(s, tiles[i].z, tiles[i].x, tiles[i].y, to_decode, pipeline, stats, state, coordinate_mode); handle(s, tiles[i].z, tiles[i].x, tiles[i].y, to_decode, pipeline, stats, state, coordinate_mode);
} }
} else if (entries.size() > 0) {
for (auto const &entry : entries) {
std::string s{pmtiles_map + entry.offset, entry.length};
handle(s, entry.z, entry.x, entry.y, to_decode, pipeline, stats, state, coordinate_mode);
}
} else { } else {
const char *sql = "SELECT tile_data, zoom_level, tile_column, tile_row from tiles where zoom_level between ? and ? order by zoom_level, tile_column, tile_row;"; const char *sql = "SELECT tile_data, zoom_level, tile_column, tile_row from tiles where zoom_level between ? and ? order by zoom_level, tile_column, tile_row;";
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
@@ -447,6 +469,19 @@ void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> co
} else { } else {
int handled = 0; int handled = 0;
while (z >= 0 && !handled) { while (z >= 0 && !handled) {
if (entries.size() > 0) {
uint64_t tile_offset;
uint32_t tile_length;
std::tie(tile_offset, tile_length) = pmtiles_get_tile(pmtiles_map, z, x, y);
if (tile_length > 0) {
if (z != oz) {
fprintf(stderr, "%s: Warning: using tile %d/%u/%u instead of %d/%u/%u\n", fname, z, x, y, oz, ox, oy);
}
std::string s{pmtiles_map + tile_offset, tile_length};
handle(s, z, x, y, to_decode, pipeline, stats, state, coordinate_mode);
handled = 1;
}
} else {
const char *sql = "SELECT tile_data from tiles where zoom_level = ? and tile_column = ? and tile_row = ?;"; const char *sql = "SELECT tile_data from tiles where zoom_level = ? and tile_column = ? and tile_row = ?;";
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) { if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
@@ -474,8 +509,8 @@ void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> co
handle(std::string(s, len), z, x, y, to_decode, pipeline, stats, state, coordinate_mode); handle(std::string(s, len), z, x, y, to_decode, pipeline, stats, state, coordinate_mode);
handled = 1; handled = 1;
} }
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
}
z--; z--;
x /= 2; x /= 2;