File indexing completed on 2024-09-15 11:53:27
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2016 Dennis Nienhüser <nienhueser@kde.org> 0004 // 0005 0006 #include "MbTileWriter.h" 0007 0008 #include <QCoreApplication> 0009 #include <QApplication> 0010 #include <QCommandLineParser> 0011 #include <QFileInfo> 0012 #include <QFile> 0013 #include <QDir> 0014 #include <QDirIterator> 0015 #include <QSqlDatabase> 0016 #include <QSqlQuery> 0017 #include <QSqlError> 0018 #include <QDebug> 0019 0020 using namespace std; 0021 using namespace Marble; 0022 0023 void importTiles(const QString &tileDirectory, MbTileWriter &tileWriter, const QPair<int, int> &tileLevels) 0024 { 0025 QString const extension = "o5m"; 0026 QDir tileDir(tileDirectory); 0027 auto const strip = 1+tileDir.absolutePath().size(); 0028 for(const auto &entryInfo: tileDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { 0029 bool isNumber; 0030 int const z = entryInfo.baseName().toInt(&isNumber); 0031 if (isNumber && tileLevels.first <= z && z <= tileLevels.second) { 0032 QDirIterator tileIter(entryInfo.absoluteFilePath(), QDirIterator::Subdirectories); 0033 for (; tileIter.hasNext(); tileIter.next()) { 0034 auto tileInfo = tileIter.fileInfo(); 0035 if (!tileInfo.isFile() || tileInfo.completeSuffix() != extension) { 0036 continue; 0037 } 0038 0039 QString const tileId = tileInfo.absoluteFilePath().mid(strip); 0040 QStringList const tileEntries = tileId.split(QLatin1Char('/')); 0041 if (tileEntries.size() == 3) { 0042 int const x = tileEntries[1].toInt(&isNumber); 0043 if (isNumber && x >= 0) { 0044 int const y = tileInfo.baseName().toInt(&isNumber); 0045 if (isNumber && y >= 0) { 0046 tileWriter.addTile(tileInfo, x, y, z); 0047 } 0048 } 0049 } 0050 } 0051 } 0052 } 0053 } 0054 0055 int main(int argc, char** argv) 0056 { 0057 QCoreApplication app(argc, argv); 0058 QCoreApplication::setApplicationName("mbtile-import"); 0059 QCoreApplication::setApplicationVersion("0.1"); 0060 0061 QCommandLineParser parser; 0062 parser.setApplicationDescription("Import tiles from a z/x/y.ext directory structure to a .mbtiles SQLite database."); 0063 auto const helpOption = parser.addHelpOption(); 0064 auto const versionOption = parser.addVersionOption(); 0065 parser.addPositionalArgument("directory", "Directory with tiles in z/x/y.ext structure"); 0066 parser.addPositionalArgument("output", "Destination MBTile database"); 0067 0068 parser.addOptions({ 0069 {{"o", "overwrite"}, "Overwrite existing tiles in the database"}, 0070 {{"q", "quiet"}, "No progress report to stdout"}, 0071 {{"t", "tilelevels"}, "Restrict tile levels to <tilelevels>", "tilelevels", "0-20"}, 0072 {{"i", "interval"}, "Commit each <interval> tiles (0: single transaction)", "interval", "10000"}, 0073 }); 0074 0075 if (!parser.parse(QCoreApplication::arguments())) { 0076 qDebug() << parser.errorText(); 0077 parser.showHelp(2); 0078 } else if (parser.isSet(helpOption)) { 0079 parser.showHelp(0); 0080 } else if (parser.isSet(versionOption)) { 0081 parser.showVersion(); 0082 return 0; 0083 } 0084 0085 const QStringList positionalArguments = parser.positionalArguments(); 0086 if (positionalArguments.size() != 2) { 0087 parser.showHelp(positionalArguments.size() == 0 ? 0 : 1); 0088 } 0089 0090 QString const tileDirectory = parser.positionalArguments()[0]; 0091 if (!QFileInfo(tileDirectory).isDir()) { 0092 qDebug() << tileDirectory << "is not a directory"; 0093 parser.showHelp(3); 0094 } 0095 0096 QStringList const tileLevels = parser.value("tilelevels").split(QLatin1Char('-')); 0097 QPair<int, int> tileLevelRange = QPair<int, int>(0, 20); 0098 bool haveValidRange = false; 0099 if (tileLevels.size() == 2) { 0100 bool ok; 0101 tileLevelRange.first = tileLevels[0].toInt(&ok); 0102 if (ok) { 0103 tileLevelRange.second = tileLevels[1].toInt(&ok); 0104 if (ok) { 0105 haveValidRange = tileLevelRange.first >= 0 && tileLevelRange.first <= tileLevelRange.second && tileLevelRange.second <= 30; 0106 } 0107 } 0108 } 0109 0110 if (!haveValidRange) { 0111 qDebug() << "Cannot parse tile level range. Expecting format 'minLevel-maxLevel', e.g. '3-7'."; 0112 return 4; 0113 } 0114 0115 QString const mbTilesFile = parser.positionalArguments()[1]; 0116 MbTileWriter tileWriter(mbTilesFile); 0117 tileWriter.setOverwriteTiles(parser.isSet("overwrite")); 0118 tileWriter.setReportProgress(!parser.isSet("quiet")); 0119 tileWriter.setCommitInterval(parser.value("interval").toInt()); 0120 0121 importTiles(tileDirectory, tileWriter, tileLevelRange); 0122 return 0; 0123 }