Warning, file /education/marble/tools/vectorosm-tilecreator/vectorosm-cachetiles.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2016 Dennis Nienhüser <nienhueser@kde.org> 0004 // 0005 0006 #include "GeoDataDocumentWriter.h" 0007 #include "GeoDataGeometry.h" 0008 #include "GeoDataLatLonAltBox.h" 0009 #include "GeoDataPlacemark.h" 0010 #include "GeoDataPolygon.h" 0011 #include "MarbleDirs.h" 0012 #include "MarbleModel.h" 0013 #include "MbTileWriter.h" 0014 #include "NodeReducer.h" 0015 #include "ParsingRunnerManager.h" 0016 #include "TileDirectory.h" 0017 #include "TileId.h" 0018 #include "VectorClipper.h" 0019 #include "WayConcatenator.h" 0020 #include "TileQueue.h" 0021 0022 #include <QApplication> 0023 #include <QBuffer> 0024 #include <QCommandLineParser> 0025 #include <QDebug> 0026 #include <QFileInfo> 0027 #include <QRect> 0028 0029 #include <iostream> 0030 0031 using namespace Marble; 0032 0033 GeoDataDocument* mergeDocuments(GeoDataDocument* map1, GeoDataDocument* map2) 0034 { 0035 GeoDataDocument* mergedMap = new GeoDataDocument(*map1); 0036 0037 OsmPlacemarkData marbleLand; 0038 marbleLand.addTag("marble_land","landmass"); 0039 for (auto placemark: map2->placemarkList()) { 0040 GeoDataPlacemark* land = new GeoDataPlacemark(*placemark); 0041 if (geodata_cast<GeoDataPolygon>(land->geometry())) { 0042 land->setOsmData(marbleLand); 0043 } 0044 mergedMap->append(land); 0045 } 0046 0047 return mergedMap; 0048 } 0049 0050 int main(int argc, char *argv[]) 0051 { 0052 QTime timer; 0053 timer.start(); 0054 0055 QCoreApplication app(argc, argv); 0056 0057 QCoreApplication::setApplicationName("marble-vectorosm-cachetiles"); 0058 QCoreApplication::setApplicationVersion("0.1"); 0059 0060 QCommandLineParser parser; 0061 parser.setApplicationDescription("Create a vectorosm tile and its neighborhood"); 0062 parser.addHelpOption(); 0063 parser.addVersionOption(); 0064 parser.addPositionalArgument("tile", "The tile to create (in z/x/y.extension format)"); 0065 0066 parser.addOptions({ 0067 {{"c", "cache-directory"}, "Directory for temporary data.", "cache", "cache"}, 0068 {{"m", "mbtile"}, "Store tiles in a mbtile database.", "mbtile"}, 0069 {"verbose", "Write progress information to standard output."} 0070 }); 0071 parser.process(app); 0072 0073 const QStringList args = parser.positionalArguments(); 0074 if (args.size() != 1) { 0075 parser.showHelp(); 0076 return 0; 0077 } 0078 0079 auto const input = args.first().split('/'); 0080 if (input.size() != 3) { 0081 qWarning() << "Tile" << input << "does not match the z/x/y.format convention"; 0082 parser.showHelp(); 0083 return 1; 0084 } 0085 0086 bool canParse[] = {false, false, false}; 0087 TileId centerTile(0, input[0].toInt(&canParse[0]), input[1].toInt(&canParse[1]), QFileInfo(input[2]).baseName().toInt(&canParse[2])); 0088 if (!canParse[0] || !canParse[1] || !canParse[2]) { 0089 qWarning() << "Tile" << input << "does not consist of digits in the format z/x/y.format"; 0090 parser.showHelp(); 0091 return 1; 0092 } 0093 0094 TileQueue tileQueue; 0095 QSet<TileId> dynamicTiles; 0096 tileQueue.read(dynamicTiles); 0097 if (dynamicTiles.contains(centerTile)) { 0098 return 0; 0099 } 0100 0101 QString const extension = QFileInfo(input[2]).completeSuffix(); 0102 QString const mbtile = parser.value("mbtile"); 0103 QSharedPointer<MbTileWriter> mbtileWriter = QSharedPointer<MbTileWriter>(new MbTileWriter(mbtile, extension)); 0104 mbtileWriter->setReportProgress(false); 0105 mbtileWriter->setCommitInterval(500); 0106 0107 MarbleModel model; 0108 ParsingRunnerManager manager(model.pluginManager()); 0109 QString const cacheDirectory = parser.value("cache-directory"); 0110 QDir().mkpath(cacheDirectory); 0111 if (!QFileInfo(cacheDirectory).isWritable()) { 0112 qWarning() << "Cannot write to cache directory" << cacheDirectory; 0113 parser.showHelp(1); 0114 } 0115 0116 TileDirectory mapTiles(TileDirectory::OpenStreetMap, cacheDirectory, manager, centerTile.zoomLevel()); 0117 TileDirectory landTiles(TileDirectory::Landmass, cacheDirectory, manager, centerTile.zoomLevel()); 0118 0119 int const offset = 3; 0120 int const N = pow(2,centerTile.zoomLevel()); 0121 QRect boundaries = QRect(0, 0, N-1, N-1) & QRect(QPoint(centerTile.x()-offset, centerTile.y()-offset), 0122 QPoint(centerTile.x()+offset, centerTile.y()+offset)); 0123 int count = 0; 0124 int const total = boundaries.width() * boundaries.height(); 0125 bool const printProgress = parser.isSet("verbose"); 0126 for (int x=boundaries.left(); x<=boundaries.right(); ++x) { 0127 for (int y=boundaries.top(); y<=boundaries.bottom(); ++y) { 0128 auto const tileId = TileId (0, centerTile.zoomLevel(), x, y); 0129 ++count; 0130 if (mbtileWriter->hasTile(x, y, tileId.zoomLevel())) { 0131 continue; 0132 } 0133 0134 using GeoDocPtr = QSharedPointer<GeoDataDocument>; 0135 GeoDocPtr tile1 = GeoDocPtr(mapTiles.clip(tileId.zoomLevel(), tileId.x(), tileId.y())); 0136 TagsFilter::removeAnnotationTags(tile1.data()); 0137 if (tileId.zoomLevel() < 17) { 0138 WayConcatenator concatenator(tile1.data()); 0139 } 0140 NodeReducer nodeReducer(tile1.data(), tileId); 0141 GeoDocPtr tile2 = GeoDocPtr(landTiles.clip(tileId.zoomLevel(), tileId.x(), tileId.y())); 0142 GeoDocPtr combined = GeoDocPtr(mergeDocuments(tile1.data(), tile2.data())); 0143 0144 QBuffer buffer; 0145 buffer.open(QBuffer::ReadWrite); 0146 if (GeoDataDocumentWriter::write(&buffer, *combined, extension)) { 0147 buffer.seek(0); 0148 mbtileWriter->addTile(&buffer, tileId.x(), tileId.y(), tileId.zoomLevel()); 0149 } else { 0150 qWarning() << "Could not write the tile " << combined->name(); 0151 } 0152 0153 dynamicTiles << tileId; 0154 0155 if (printProgress) { 0156 TileDirectory::printProgress(qreal(count) / total); 0157 std::cout << " Tile " << count << "/" << total << " ("; 0158 std::cout << combined->name().toStdString() << ")."; 0159 std::cout << std::string(20, ' ') << '\r'; 0160 std::cout.flush(); 0161 } 0162 } 0163 } 0164 0165 tileQueue.write(dynamicTiles); 0166 0167 if (printProgress) { 0168 TileDirectory::printProgress(1.0); 0169 std::cout << "Vector OSM tiles complete after " << timer.elapsed() << " ms." << std::string(30, ' ') << std::endl; 0170 } 0171 0172 return 0; 0173 }