summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Nienhüser <nienhueser@kde.org>2016-10-01 16:02:20 (GMT)
committerDennis Nienhüser <nienhueser@kde.org>2016-10-02 09:48:31 (GMT)
commita429adaf09016ae3bb6e294e465fda557338d1fd (patch)
tree3ef6927e6a2daa3684ea29c33039fa7a71c97cf2
parent464996fbb3e190c1deef176b0787ca8ff01053c4 (diff)
Introduce a cache directory, pre-tiling is done internally now.
-rw-r--r--tools/vectorosm-tilecreator/TileDirectory.cpp101
-rw-r--r--tools/vectorosm-tilecreator/TileDirectory.h18
-rw-r--r--tools/vectorosm-tilecreator/main.cpp98
3 files changed, 139 insertions, 78 deletions
diff --git a/tools/vectorosm-tilecreator/TileDirectory.cpp b/tools/vectorosm-tilecreator/TileDirectory.cpp
index 36fb9d0..8385fa8 100644
--- a/tools/vectorosm-tilecreator/TileDirectory.cpp
+++ b/tools/vectorosm-tilecreator/TileDirectory.cpp
@@ -9,13 +9,19 @@
//
#include "TileDirectory.h"
+#include "TileIterator.h"
+#include <GeoDataDocumentWriter.h>
#include <QFileInfo>
#include <QDebug>
+#include <QProcess>
+#include <QDir>
+
+#include <iostream>
namespace Marble {
-TileDirectory::TileDirectory(const QString &baseDir, ParsingRunnerManager &manager, QString const &extension) :
+TileDirectory::TileDirectory(TileType tileType, const QString &baseDir, ParsingRunnerManager &manager, QString const &extension) :
m_baseDir(baseDir),
m_manager(manager),
m_zoomLevel(QFileInfo(baseDir).baseName().toInt()),
@@ -23,7 +29,7 @@ TileDirectory::TileDirectory(const QString &baseDir, ParsingRunnerManager &manag
m_tileY(-1),
m_tagZoomLevel(-1),
m_extension(extension),
- m_filterTags(false)
+ m_tileType(tileType)
{
// nothing to do
}
@@ -50,6 +56,11 @@ QSharedPointer<GeoDataDocument> TileDirectory::load(int zoomLevel, int tileX, in
return m_landmass;
}
+void TileDirectory::setInputFile(const QString &filename)
+{
+ m_inputFile = filename;
+}
+
GeoDataDocument* TileDirectory::clip(int zoomLevel, int tileX, int tileY)
{
QSharedPointer<GeoDataDocument> oldMap = m_landmass;
@@ -175,7 +186,7 @@ QStringList TileDirectory::tagsFilteredIn(int zoomLevel) const
void TileDirectory::setTagZoomLevel(int zoomLevel)
{
m_tagZoomLevel = zoomLevel;
- if (m_filterTags) {
+ if (m_tileType == OpenStreetMap) {
QStringList const tags = tagsFilteredIn(m_tagZoomLevel);
if (m_tagZoomLevel < 17) {
m_tagsFilter = QSharedPointer<TagsFilter>(new TagsFilter(m_landmass.data(), tags));
@@ -185,9 +196,89 @@ void TileDirectory::setTagZoomLevel(int zoomLevel)
}
}
-void TileDirectory::setFilterTags(bool filter)
+GeoDataLatLonBox TileDirectory::boundingBox() const
+{
+ return m_boundingBox;
+}
+
+void TileDirectory::setBoundingBox(const GeoDataLatLonBox &boundingBox)
+{
+ m_boundingBox = boundingBox;
+}
+
+void TileDirectory::createTiles() const
+{
+ int const zoomLevel = m_tileType == OpenStreetMap ? 10 : 7;
+ QSharedPointer<GeoDataDocument> map;
+ QSharedPointer<VectorClipper> clipper;
+ TileIterator iter(m_boundingBox, zoomLevel);
+ qint64 count = 0;
+ foreach(auto const &tileId, iter) {
+ ++count;
+ QString const outputDir = QString("%1/%2").arg(m_baseDir).arg(tileId.x());
+ QString const outputFile = QString("%1/%2.%3").arg(outputDir).arg(tileId.y()).arg(m_extension);
+ if (QFileInfo(outputFile).exists()) {
+ continue;
+ }
+
+ std::cout << "Creating " << (m_tileType == OpenStreetMap ? "osm" : "landmass");
+ std::cout << " cache tile " << count << "/" << iter.total() << " (";
+ std::cout << zoomLevel << "/" << tileId.x() << "/" << tileId.y() << ") \r";
+ std::cout.flush();
+
+ QDir().mkpath(outputDir);
+ if (m_tileType == OpenStreetMap) {
+ QString const output = QString("-o=%1").arg(outputFile);
+ int const N = pow(2, zoomLevel);
+ double const minLon = TileId::tileX2lon(tileId.x(), N) * RAD2DEG;
+ double const maxLon = TileId::tileX2lon(tileId.x()+1, N) * RAD2DEG;
+ double const maxLat = TileId::tileY2lat(tileId.y(), N) * RAD2DEG;
+ double const minLat = TileId::tileY2lat(tileId.y()+1, N) * RAD2DEG;
+ QString const bbox = QString("-b=%1,%2,%3,%4").arg(minLon).arg(minLat).arg(maxLon).arg(maxLat);
+ QProcess osmconvert;
+ osmconvert.start("osmconvert", QStringList() << "--drop-author" << "--drop-version"
+ << "--complete-ways" << "--complex-ways" << bbox << output << m_inputFile);
+ osmconvert.waitForFinished();
+ if (osmconvert.exitCode() != 0) {
+ qWarning() << bbox;
+ qWarning() << osmconvert.readAllStandardError();
+ qWarning() << "osmconvert failed: " << osmconvert.errorString();
+ }
+ } else {
+ if (!map) {
+ map = open(m_inputFile, m_manager);
+ clipper = QSharedPointer<VectorClipper>(new VectorClipper(map.data()));
+ }
+ auto tile = clipper->clipTo(zoomLevel, tileId.x(), tileId.y());
+ if (tile->size() > 0) {
+ if (!GeoDataDocumentWriter::write(outputFile, *tile)) {
+ qWarning() << "Failed to write tile" << outputFile;
+ }
+ }
+ }
+ }
+
+}
+
+GeoDataLatLonBox TileDirectory::boundingBox(const QString &filename) const
{
- m_filterTags = filter;
+ QProcess osmconvert;
+ osmconvert.start("osmconvert", QStringList() << "--out-statistics" << filename);
+ osmconvert.waitForFinished();
+ QStringList const output = QString(osmconvert.readAllStandardOutput()).split('\n');
+ GeoDataLatLonBox boundingBox;
+ foreach(QString const &line, output) {
+ if (line.startsWith("lon min:")) {
+ boundingBox.setWest(line.mid(8).toDouble(), GeoDataCoordinates::Degree);
+ } else if (line.startsWith("lon max")) {
+ boundingBox.setEast(line.mid(8).toDouble(), GeoDataCoordinates::Degree);
+ } else if (line.startsWith("lat min:")) {
+ boundingBox.setSouth(line.mid(8).toDouble(), GeoDataCoordinates::Degree);
+ } else if (line.startsWith("lat max:")) {
+ boundingBox.setNorth(line.mid(8).toDouble(), GeoDataCoordinates::Degree);
+ }
+ }
+ return boundingBox;
}
}
diff --git a/tools/vectorosm-tilecreator/TileDirectory.h b/tools/vectorosm-tilecreator/TileDirectory.h
index 79cb6e4..8a43892 100644
--- a/tools/vectorosm-tilecreator/TileDirectory.h
+++ b/tools/vectorosm-tilecreator/TileDirectory.h
@@ -21,15 +21,25 @@ namespace Marble {
class TileDirectory
{
public:
- TileDirectory(const QString &baseDir, ParsingRunnerManager &manager, const QString &extension);
+ enum TileType
+ {
+ Landmass,
+ OpenStreetMap
+ };
+
+ TileDirectory(TileType tileType, const QString &baseDir, ParsingRunnerManager &manager, const QString &extension);
QSharedPointer<GeoDataDocument> load(int zoomLevel, int tileX, int tileY);
- void setFilterTags(bool filter);
+ void setInputFile(const QString &filename);
TileId tileFor(int zoomLevel, int tileX, int tileY) const;
GeoDataDocument *clip(int zoomLevel, int tileX, int tileY);
QString name() const;
static QSharedPointer<GeoDataDocument> open(const QString &filename, ParsingRunnerManager &manager);
+ GeoDataLatLonBox boundingBox(const QString &filename) const;
+ GeoDataLatLonBox boundingBox() const;
+ void setBoundingBox(const GeoDataLatLonBox &boundingBox);
+ void createTiles() const;
private:
QStringList tagsFilteredIn(int zoomLevel) const;
@@ -45,7 +55,9 @@ private:
QString m_extension;
QSharedPointer<VectorClipper> m_clipper;
QSharedPointer<TagsFilter> m_tagsFilter;
- bool m_filterTags;
+ TileType m_tileType;
+ QString m_inputFile;
+ GeoDataLatLonBox m_boundingBox;
};
}
diff --git a/tools/vectorosm-tilecreator/main.cpp b/tools/vectorosm-tilecreator/main.cpp
index 9ff134d..ee334b3 100644
--- a/tools/vectorosm-tilecreator/main.cpp
+++ b/tools/vectorosm-tilecreator/main.cpp
@@ -79,27 +79,6 @@ bool writeTile(GeoDataDocument* tile, const QString &outputFile)
return true;
}
-GeoDataLatLonBox boundingBox(const QString &inputFileName)
-{
- QProcess osmconvert;
- osmconvert.start("osmconvert", QStringList() << "--out-statistics" << inputFileName);
- osmconvert.waitForFinished();
- QStringList const output = QString(osmconvert.readAllStandardOutput()).split('\n');
- GeoDataLatLonBox boundingBox;
- foreach(QString const &line, output) {
- if (line.startsWith("lon min:")) {
- boundingBox.setWest(line.mid(8).toDouble(), GeoDataCoordinates::Degree);
- } else if (line.startsWith("lon max")) {
- boundingBox.setEast(line.mid(8).toDouble(), GeoDataCoordinates::Degree);
- } else if (line.startsWith("lat min:")) {
- boundingBox.setSouth(line.mid(8).toDouble(), GeoDataCoordinates::Degree);
- } else if (line.startsWith("lat max:")) {
- boundingBox.setNorth(line.mid(8).toDouble(), GeoDataCoordinates::Degree);
- }
- }
- return boundingBox;
-}
-
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
@@ -116,9 +95,9 @@ int main(int argc, char *argv[])
parser.addOptions({
{{"t", "osmconvert"}, "Tile data using osmconvert."},
{"conflict-resolution", "How to deal with existing tiles: overwrite, skip or merge", "mode", "overwrite"},
- {{"k", "keep-all-nodes"}, "Do not reduce nodes in line strings and rings."},
- {{"m", "merge"}, "Merge the main document with the file <file_to_merge_with>.", "file_to_merge_with"},
- {{"z", "zoom-level"}, "Zoom level according to which OSM information has to be processed.", "number"},
+ {{"c", "cache-directory"}, "Directory for temporary data.", "cache", "cache"},
+ {{"l", "landmass"}, "File with landmass polygons (world-wide).", "filename", "landmass.shp"},
+ {{"z", "zoom-level"}, "Zoom level according to which OSM information has to be processed.", "levels", "11,13,15,17"},
{{"o", "output"}, "Output file or directory", "output", QString("%1/maps/earth/vectorosm").arg(MarbleDirs::localPath())},
{{"e", "extension"}, "Output file type: o5m (default), osm or kml", "file extension", "o5m"}
});
@@ -154,39 +133,15 @@ int main(int argc, char *argv[])
MarbleModel model;
ParsingRunnerManager manager(model.pluginManager());
- bool const keepAllNodes = parser.isSet("keep-all-nodes");
+ QString const cacheDirectory = parser.value("cache-directory");
+ QDir().mkpath(cacheDirectory);
+ if (!QFileInfo(cacheDirectory).isWritable()) {
+ qWarning() << "Cannot write to cache directory" << cacheDirectory;
+ parser.showHelp(1);
+ }
+
bool const overwriteTiles = parser.value("conflict-resolution") == "overwrite";
- if (parser.isSet("osmconvert")) {
- QString const extension = parser.value("extension");
- auto mapArea = boundingBox(inputFileName);
- QString const outputName = parser.value("output");
- foreach(auto zoomLevel, zoomLevels) {
- int const N = pow(2, zoomLevel);
- TileIterator iter(mapArea, zoomLevel);
- qint64 count = 0;
- qint64 const total = iter.total();
- foreach(auto const &tileId, iter) {
- ++count;
- QString directory = QString("%1/%2/%3").arg(outputName).arg(zoomLevel).arg(tileId.x());
- QString const output = QString("-o=%1/%2.%3").arg(directory).arg(tileId.y()).arg(extension);
- if (!overwriteTiles && QFileInfo(output).exists()) {
- continue;
- }
- QDir().mkpath(directory);
- double const minLon = TileId::tileX2lon(tileId.x(), N) * RAD2DEG;
- double const maxLon = TileId::tileX2lon(tileId.x()+1, N) * RAD2DEG;
- double const maxLat = TileId::tileY2lat(tileId.y(), N) * RAD2DEG;
- double const minLat = TileId::tileY2lat(tileId.y()+1, N) * RAD2DEG;
- QString const bbox = QString("-b=%1,%2,%3,%4").arg(minLon).arg(minLat).arg(maxLon).arg(maxLat);
- QProcess osmconvert;
- osmconvert.start("osmconvert", QStringList() << "--drop-author" << "--drop-version"
- << "--complete-ways" << "--complex-ways" << bbox << output << inputFileName);
- osmconvert.waitForFinished();
- std::cout << "Tile " << count << "/" << total << " done. \r";
- std::cout.flush();
- }
- }
- } else if (*zoomLevels.cbegin() <= 9) {
+ if (*zoomLevels.cbegin() <= 9) {
auto map = TileDirectory::open(inputFileName, manager);
VectorClipper processor(map.data());
GeoDataLatLonBox world(85.0, -85.0, 180.0, -180.0, GeoDataCoordinates::Degree);
@@ -201,24 +156,29 @@ int main(int argc, char *argv[])
continue;
}
GeoDataDocument* tile = processor.clipTo(zoomLevel, tileId.x(), tileId.y());
- QSharedPointer<NodeReducer> reducer = QSharedPointer<NodeReducer>(keepAllNodes ? nullptr : new NodeReducer(tile, zoomLevel+1));
+ NodeReducer nodeReducer(tile, zoomLevel+1);
if (!writeTile(tile, filename)) {
return 4;
}
std::cout << "Tile " << count << "/" << total << " (" << tile->name().toStdString() << ") done.";
- if (reducer) {
- double const reduction = reducer->removedNodes() / qMax(1.0, double(reducer->remainingNodes() + reducer->removedNodes()));
- std::cout << " Node reduction: " << qRound(reduction * 100.0) << "%";
- }
+ double const reduction = nodeReducer.removedNodes() / qMax(1.0, double(nodeReducer.remainingNodes() + nodeReducer.removedNodes()));
+ std::cout << " Node reduction: " << qRound(reduction * 100.0) << "%";
std::cout << " \r";
std::cout.flush();
delete tile;
}
}
} else {
- TileDirectory loader(parser.value("merge"), manager, parser.value("extension"));
- TileDirectory mapTiles("tiles/10", manager, parser.value("extension"));
- mapTiles.setFilterTags(true);
+ TileDirectory loader(TileDirectory::Landmass, QString("%1/landmass/7").arg(cacheDirectory), manager, parser.value("extension"));
+ loader.setInputFile(parser.value("landmass"));
+ auto const boundingBox = loader.boundingBox(inputFileName);
+ loader.setBoundingBox(boundingBox);
+ loader.createTiles();
+
+ TileDirectory mapTiles(TileDirectory::OpenStreetMap, QString("%1/osm/10").arg(cacheDirectory), manager, parser.value("extension"));
+ mapTiles.setInputFile(inputFileName);
+ mapTiles.setBoundingBox(boundingBox);
+ mapTiles.createTiles();
typedef QMap<QString, QVector<TileId> > Tiles;
Tiles tiles;
@@ -228,7 +188,7 @@ int main(int argc, char *argv[])
// @todo FIXME Assumes placemark ownership
//WayConcatenator concatenator(tagsFilter.accepted(), QStringList() << "highway=*", false);
- TileIterator iter(boundingBox(inputFileName), zoomLevel);
+ TileIterator iter(mapTiles.boundingBox(), zoomLevel);
total += iter.total();
foreach(auto const &tileId, iter) {
auto const tile = TileId(QString(), zoomLevel, tileId.x(), tileId.y());
@@ -250,7 +210,7 @@ int main(int argc, char *argv[])
GeoDataDocument* tile1 = mapTiles.clip(zoomLevel, tileId.x(), tileId.y());
GeoDataDocument* tile2 = loader.clip(zoomLevel, tileId.x(), tileId.y());
GeoDataDocument* combined = mergeDocuments(tile1, tile2);
- QSharedPointer<NodeReducer> reducer = QSharedPointer<NodeReducer>(keepAllNodes ? nullptr : new NodeReducer(combined, zoomLevel));
+ NodeReducer nodeReducer(combined, zoomLevel);
if (!writeTile(combined, filename)) {
return 4;
}
@@ -259,10 +219,8 @@ int main(int argc, char *argv[])
std::cout << loader.name().toStdString() << " + map ";
std::cout << mapTiles.name().toStdString() << " ~> ";
std::cout << combined->name().toStdString() << ") done.";
- if (reducer) {
- double const reduction = reducer->removedNodes() / qMax(1.0, double(reducer->remainingNodes() + reducer->removedNodes()));
- std::cout << " Node reduction: " << qRound(reduction * 100.0) << "%";
- }
+ double const reduction = nodeReducer.removedNodes() / qMax(1.0, double(nodeReducer.remainingNodes() + nodeReducer.removedNodes()));
+ std::cout << " Node reduction: " << qRound(reduction * 100.0) << "%";
std::cout << " \r";
std::cout.flush();
delete combined;