Skip to content

Commit

Permalink
support multiple input files
Browse files Browse the repository at this point in the history
Fixes #696, a regression introduced in the v3.0 work:

- use the old NodeStore/WayStore when multiple input files
- don't use lazy geometries when multiple input files
- compute the bbox from the union of all the pbfs

I suspect we could probably restore lazy geometries for multiple input
files, but I haven't dug in to see what would be required.

For testing, I built a pmtiles with monaco + liechtenstein and verified
they both showed up.
  • Loading branch information
cldellow committed Mar 29, 2024
1 parent 07e878f commit 9486b63
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 12 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ test: \
test_attribute_store \
test_deque_map \
test_helpers \
test_options_parser \
test_pbf_reader \
test_pooled_string \
test_relation_roles \
Expand Down
5 changes: 5 additions & 0 deletions src/options_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,10 @@ OptionsParser::Options OptionsParser::parse(const int argc, const char* argv[])
throw OptionException{"Couldn't open .lua script: " + options.luaFile };
}

// The lazy geometry code has assumptions that break when more than one
// input file is used.
if (options.inputFiles.size() > 1)
options.osm.materializeGeometries = true;

return options;
}
39 changes: 30 additions & 9 deletions src/tilemaker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ int main(const int argc, const char* argv[]) {

bool hasClippingBox = false;
Box clippingBox;
double minLon=0.0, maxLon=0.0, minLat=0.0, maxLat=0.0;
double minLon=std::numeric_limits<double>::max(),
maxLon=std::numeric_limits<double>::min(),
minLat=std::numeric_limits<double>::max(),
maxLat=std::numeric_limits<double>::min();
if (!bboxElements.empty()) {
hasClippingBox = true;
minLon = bboxElementFromStr(bboxElements.at(0));
Expand All @@ -131,8 +134,20 @@ int main(const int argc, const char* argv[]) {
maxLat = bboxElementFromStr(bboxElements.at(3));

} else if (options.inputFiles.size()>0) {
int ret = ReadPbfBoundingBox(options.inputFiles[0], minLon, maxLon, minLat, maxLat, hasClippingBox);
if(ret != 0) return ret;
for (const auto inputFile : options.inputFiles) {
bool localHasClippingBox;
double localMinLon, localMaxLon, localMinLat, localMaxLat;
int ret = ReadPbfBoundingBox(inputFile, localMinLon, localMaxLon, localMinLat, localMaxLat, localHasClippingBox);
if(ret != 0) return ret;
hasClippingBox = hasClippingBox || localHasClippingBox;

if (localHasClippingBox) {
minLon = std::min(minLon, localMinLon);
maxLon = std::max(maxLon, localMaxLon);
minLat = std::min(minLat, localMinLat);
maxLat = std::max(maxLat, localMaxLat);
}
}
}

if (hasClippingBox) {
Expand Down Expand Up @@ -179,7 +194,7 @@ int main(const int argc, const char* argv[]) {
return rv;
}

if (allPbfsHaveSortTypeThenID) {
if (options.inputFiles.size() == 1 && allPbfsHaveSortTypeThenID) {
std::shared_ptr<NodeStore> rv = make_shared<SortedNodeStore>(!options.osm.uncompressedNodes);
return rv;
}
Expand All @@ -198,7 +213,7 @@ int main(const int argc, const char* argv[]) {
}

auto createWayStore = [anyPbfHasLocationsOnWays, allPbfsHaveSortTypeThenID, options, &nodeStore]() {
if (!anyPbfHasLocationsOnWays && allPbfsHaveSortTypeThenID) {
if (options.inputFiles.size() == 1 && !anyPbfHasLocationsOnWays && allPbfsHaveSortTypeThenID) {
std::shared_ptr<WayStore> rv = make_shared<SortedWayStore>(!options.osm.uncompressedWays, *nodeStore.get());
return rv;
}
Expand Down Expand Up @@ -280,12 +295,18 @@ int main(const int argc, const char* argv[]) {
significantWayTags,
options.threadNum,
[&]() {
thread_local std::shared_ptr<ifstream> pbfStream(new ifstream(inputFile, ios::in | ios::binary));
return pbfStream;
thread_local std::pair<std::string, std::shared_ptr<ifstream>> pbfStream;
if (pbfStream.first != inputFile) {
pbfStream = std::make_pair(inputFile, std::make_shared<ifstream>(inputFile, ios::in | ios::binary));
}
return pbfStream.second;
},
[&]() {
thread_local std::shared_ptr<OsmLuaProcessing> osmLuaProcessing(new OsmLuaProcessing(osmStore, config, layers, options.luaFile, shpMemTiles, osmMemTiles, attributeStore, options.osm.materializeGeometries));
return osmLuaProcessing;
thread_local std::pair<std::string, std::shared_ptr<OsmLuaProcessing>> osmLuaProcessing;
if (osmLuaProcessing.first != inputFile) {
osmLuaProcessing = std::make_pair(inputFile, std::make_shared<OsmLuaProcessing>(osmStore, config, layers, options.luaFile, shpMemTiles, osmMemTiles, attributeStore, options.osm.materializeGeometries));
}
return osmLuaProcessing.second;
},
*nodeStore,
*wayStore
Expand Down
23 changes: 20 additions & 3 deletions test/options_parser.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ MU_TEST(test_options_parser) {
// No args is invalid.
ASSERT_THROWS("You must specify an output file");

// Output without input is invalid
ASSERT_THROWS("No source .osm.pbf", "--output", "foo.mbtiles");
// Output without input is valid
{
std::vector<std::string> args = {"--output", "foo.mbtiles"};
auto opts = parse(args);
mu_check(opts.inputFiles.size() == 0);
}

// You can ask for --help.
{
Expand All @@ -41,7 +45,7 @@ MU_TEST(test_options_parser) {
mu_check(opts.showHelp);
}

// Minimal valid is output and input
// Common happy path is output and input
{
std::vector<std::string> args = {"--output", "foo.mbtiles", "--input", "ontario.pbf"};
auto opts = parse(args);
Expand Down Expand Up @@ -91,6 +95,19 @@ MU_TEST(test_options_parser) {
mu_check(!opts.osm.shardStores);
}

// Two input files implies --materialize
{
std::vector<std::string> args = {"--output", "foo.mbtiles", "--input", "ontario.pbf", "--input", "alberta.pbf"};
auto opts = parse(args);
mu_check(opts.inputFiles.size() == 2);
mu_check(opts.inputFiles[0] == "ontario.pbf");
mu_check(opts.inputFiles[1] == "alberta.pbf");
mu_check(opts.outputFile == "foo.mbtiles");
mu_check(opts.outputMode == OutputMode::MBTiles);
mu_check(opts.osm.materializeGeometries);
mu_check(!opts.osm.shardStores);
}

ASSERT_THROWS("Couldn't open .json config", "--input", "foo", "--output", "bar", "--config", "nonexistent-config.json");
ASSERT_THROWS("Couldn't open .lua script", "--input", "foo", "--output", "bar", "--process", "nonexistent-script.lua");
}
Expand Down

0 comments on commit 9486b63

Please sign in to comment.