#include #include #include #include #include #include #include #include #include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wshadow" #include #pragma GCC diagnostic pop namespace po = boost::program_options; using namespace std::literals::chrono_literals; int main(int argc, char *argv[]) { std::string style = mbgl::util::default_styles::streets.url; double north = 37.2, west = -122.8, south = 38.1, east = -121.7; // Bay area double minZoom = 0.0, maxZoom = 15.0, pixelRatio = 1.0; std::string output = "offline.db"; const char* tokenEnv = getenv("MAPBOX_ACCESS_TOKEN"); std::string token = tokenEnv ? tokenEnv : std::string(); po::options_description desc("Allowed options"); desc.add_options() ("style,s", po::value(&style)->value_name("URL"), "Map stylesheet") ("north", po::value(&north)->value_name("degrees")->default_value(north), "North latitude") ("west", po::value(&west)->value_name("degrees")->default_value(west), "West longitude") ("south", po::value(&south)->value_name("degrees")->default_value(south), "South latitude") ("east", po::value(&east)->value_name("degrees")->default_value(east), "East longitude") ("minZoom", po::value(&minZoom)->value_name("number")->default_value(minZoom), "Min zoom level") ("maxZoom", po::value(&maxZoom)->value_name("number")->default_value(maxZoom), "Max zoom level") ("pixelRatio", po::value(&pixelRatio)->value_name("number")->default_value(pixelRatio), "Pixel ratio") ("token,t", po::value(&token)->value_name("key")->default_value(token), "Mapbox access token") ("output,o", po::value(&output)->value_name("file")->default_value(output), "Output database file name") ; try { po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); } catch(std::exception& e) { std::cout << "Error: " << e.what() << std::endl << desc; exit(1); } using namespace mbgl; util::RunLoop loop; static DefaultFileSource fileSource(output, "."); static std::unique_ptr region; std::signal(SIGINT, [] (int) { if (region) { std::cout << "Stopping download... "; fileSource.setOfflineRegionDownloadState(*region, OfflineRegionDownloadState::Inactive); } }); fileSource.setAccessToken(token); LatLngBounds boundingBox = LatLngBounds::hull(LatLng(north, west), LatLng(south, east)); OfflineTilePyramidRegionDefinition definition(style, boundingBox, minZoom, maxZoom, pixelRatio); OfflineRegionMetadata metadata; class Observer : public OfflineRegionObserver { public: Observer(OfflineRegion& region_, DefaultFileSource& fileSource_, util::RunLoop& loop_) : region(region_), fileSource(fileSource_), loop(loop_), start(SystemClock::now()) { } void statusChanged(OfflineRegionStatus status) override { if (status.downloadState == OfflineRegionDownloadState::Inactive) { std::cout << "stopped" << std::endl; loop.stop(); return; } std::string bytesPerSecond = "-"; auto elapsedSeconds = (SystemClock::now() - start) / 1s; if (elapsedSeconds != 0) { bytesPerSecond = util::toString(status.completedResourceSize / elapsedSeconds); } std::cout << status.completedResourceCount << " / " << status.requiredResourceCount << " resources" << (status.requiredResourceCountIsPrecise ? "; " : " (indeterminate); ") << status.completedResourceSize << " bytes downloaded" << " (" << bytesPerSecond << " bytes/sec)" << std::endl; if (status.complete()) { std::cout << "Finished" << std::endl; loop.stop(); } } void responseError(Response::Error error) override { std::cerr << error.reason << " downloading resource: " << error.message << std::endl; } void mapboxTileCountLimitExceeded(uint64_t limit) override { std::cerr << "Error: reached limit of " << limit << " offline tiles" << std::endl; } OfflineRegion& region; DefaultFileSource& fileSource; util::RunLoop& loop; SystemTimePoint start; }; fileSource.createOfflineRegion(definition, metadata, [&] (std::exception_ptr error, optional region_) { if (error) { std::cerr << "Error creating region: " << util::toString(error) << std::endl; loop.stop(); exit(1); } else { assert(region_); region = std::make_unique(std::move(*region_)); fileSource.setOfflineRegionObserver(*region, std::make_unique(*region, fileSource, loop)); fileSource.setOfflineRegionDownloadState(*region, OfflineRegionDownloadState::Active); } }); loop.run(); return 0; }