Commit 8b7553b5 authored by Andreas Bircher's avatar Andreas Bircher

download tiles when downloading offline map

parent 17fe7893
...@@ -157,6 +157,8 @@ QGCMapEngineManager::startDownload(const QString& name, const QString& mapType) ...@@ -157,6 +157,8 @@ QGCMapEngineManager::startDownload(const QString& name, const QString& mapType)
} else { } else {
qWarning() << "QGCMapEngineManager::startDownload() No Tiles to save"; qWarning() << "QGCMapEngineManager::startDownload() No Tiles to save";
} }
// TODO: this could also get some feedback
_elevationProvider.cacheTerrainTiles(QGeoCoordinate(_bottomRightLat, _topleftLon), QGeoCoordinate(_topleftLat, _bottomRightLon));
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "QGCLoggingCategory.h" #include "QGCLoggingCategory.h"
#include "QGCMapEngine.h" #include "QGCMapEngine.h"
#include "QGCMapTileSet.h" #include "QGCMapTileSet.h"
#include "Terrain.h"
Q_DECLARE_LOGGING_CATEGORY(QGCMapEngineManagerLog) Q_DECLARE_LOGGING_CATEGORY(QGCMapEngineManagerLog)
...@@ -152,6 +153,8 @@ private: ...@@ -152,6 +153,8 @@ private:
int _actionProgress; int _actionProgress;
ImportAction _importAction; ImportAction _importAction;
bool _importReplace; bool _importReplace;
ElevationProvider _elevationProvider;
}; };
#endif #endif
...@@ -95,6 +95,37 @@ bool ElevationProvider::queryTerrainData(const QList<QGeoCoordinate>& coordinate ...@@ -95,6 +95,37 @@ bool ElevationProvider::queryTerrainData(const QList<QGeoCoordinate>& coordinate
return true; return true;
} }
bool ElevationProvider::cacheTerrainTiles(const QGeoCoordinate& southWest, const QGeoCoordinate& northEast)
{
qCDebug(TerrainLog) << "Cache terrain tiles southWest:northEast" << southWest << northEast;
// Correct corners of the tile to fixed grid
QGeoCoordinate southWestCorrected;
southWestCorrected.setLatitude(floor(southWest.latitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
southWestCorrected.setLongitude(floor(southWest.longitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
QGeoCoordinate northEastCorrected;
northEastCorrected.setLatitude(ceil(northEast.latitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
northEastCorrected.setLongitude(ceil(northEast.longitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
// Add all tiles to download queue
for (double lat = southWestCorrected.latitude() + TerrainTile::srtm1TileSize / 2.0; lat < northEastCorrected.latitude(); lat += TerrainTile::srtm1TileSize) {
for (double lon = southWestCorrected.longitude() + TerrainTile::srtm1TileSize / 2.0; lon < northEastCorrected.longitude(); lon += TerrainTile::srtm1TileSize) {
QString uniqueTileId = _uniqueTileId(QGeoCoordinate(lat, lon));
_tilesMutex.lock();
if (_downloadQueue.contains(uniqueTileId) || _tiles.contains(uniqueTileId)) {
_tilesMutex.unlock();
continue;
}
_downloadQueue.append(uniqueTileId.replace("_", ","));
_tilesMutex.unlock();
qCDebug(TerrainLog) << "Adding tile to download queue: " << uniqueTileId;
}
}
_downloadTiles();
return true;
}
bool ElevationProvider::cacheTerrainTiles(const QList<QGeoCoordinate>& coordinates) bool ElevationProvider::cacheTerrainTiles(const QList<QGeoCoordinate>& coordinates)
{ {
if (coordinates.length() == 0) { if (coordinates.length() == 0) {
...@@ -105,9 +136,10 @@ bool ElevationProvider::cacheTerrainTiles(const QList<QGeoCoordinate>& coordinat ...@@ -105,9 +136,10 @@ bool ElevationProvider::cacheTerrainTiles(const QList<QGeoCoordinate>& coordinat
QString uniqueTileId = _uniqueTileId(coordinate); QString uniqueTileId = _uniqueTileId(coordinate);
_tilesMutex.lock(); _tilesMutex.lock();
if (_downloadQueue.contains(uniqueTileId) || _tiles.contains(uniqueTileId)) { if (_downloadQueue.contains(uniqueTileId) || _tiles.contains(uniqueTileId)) {
_tilesMutex.unlock();
continue; continue;
} }
_downloadQueue.append(uniqueTileId.replace("-", ",")); _downloadQueue.append(uniqueTileId.replace("_", ","));
_tilesMutex.unlock(); _tilesMutex.unlock();
qCDebug(TerrainLog) << "Adding tile to download queue: " << uniqueTileId; qCDebug(TerrainLog) << "Adding tile to download queue: " << uniqueTileId;
} }
...@@ -166,7 +198,8 @@ void ElevationProvider::_requestFinishedTile() ...@@ -166,7 +198,8 @@ void ElevationProvider::_requestFinishedTile()
QJsonParseError parseError; QJsonParseError parseError;
QJsonDocument responseJson = QJsonDocument::fromJson(responseBytes, &parseError); QJsonDocument responseJson = QJsonDocument::fromJson(responseBytes, &parseError);
qCDebug(TerrainLog) << "ERROR: Received " << responseJson; qCDebug(TerrainLog) << "ERROR: Received " << responseJson;
// TODO: Handle error in downloading data // TODO (birchera): Handle error in downloading data
_downloadTiles();
return; return;
} }
...@@ -175,7 +208,8 @@ void ElevationProvider::_requestFinishedTile() ...@@ -175,7 +208,8 @@ void ElevationProvider::_requestFinishedTile()
QJsonParseError parseError; QJsonParseError parseError;
QJsonDocument responseJson = QJsonDocument::fromJson(responseBytes, &parseError); QJsonDocument responseJson = QJsonDocument::fromJson(responseBytes, &parseError);
if (parseError.error != QJsonParseError::NoError) { if (parseError.error != QJsonParseError::NoError) {
// TODO: Handle error in downloading data // TODO (birchera): Handle error in downloading data
_downloadTiles();
return; return;
} }
...@@ -187,7 +221,7 @@ void ElevationProvider::_requestFinishedTile() ...@@ -187,7 +221,7 @@ void ElevationProvider::_requestFinishedTile()
} else { } else {
delete tile; delete tile;
} }
_tilesMutex.lock(); _tilesMutex.unlock();
} }
_downloadTiles(); _downloadTiles();
...@@ -202,7 +236,7 @@ void ElevationProvider::_downloadTiles(void) ...@@ -202,7 +236,7 @@ void ElevationProvider::_downloadTiles(void)
query.addQueryItem(QStringLiteral("points"), _downloadQueue.first()); query.addQueryItem(QStringLiteral("points"), _downloadQueue.first());
_downloadQueue.pop_front(); _downloadQueue.pop_front();
_tilesMutex.unlock(); _tilesMutex.unlock();
QUrl url(QStringLiteral("https://api.airmap.com/elevation/stage/srtm1/carpet")); QUrl url(QStringLiteral("https://api.airmap.com/elevation/stage/srtm1/ele/carpet"));
url.setQuery(query); url.setQuery(query);
QNetworkRequest request(url); QNetworkRequest request(url);
...@@ -224,15 +258,17 @@ void ElevationProvider::_downloadTiles(void) ...@@ -224,15 +258,17 @@ void ElevationProvider::_downloadTiles(void)
QString ElevationProvider::_uniqueTileId(const QGeoCoordinate& coordinate) QString ElevationProvider::_uniqueTileId(const QGeoCoordinate& coordinate)
{ {
QGeoCoordinate southEast; // Compute corners of the tile
southEast.setLatitude(floor(coordinate.latitude()*40.0)/40.0); QGeoCoordinate southWest;
southEast.setLongitude(floor(coordinate.longitude()*40.0)/40.0); southWest.setLatitude(floor(coordinate.latitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
southWest.setLongitude(floor(coordinate.longitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
QGeoCoordinate northEast; QGeoCoordinate northEast;
northEast.setLatitude(ceil(coordinate.latitude()*40.0)/40.0); northEast.setLatitude(ceil(coordinate.latitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
northEast.setLongitude(ceil(coordinate.longitude()*40.0)/40.0); northEast.setLongitude(ceil(coordinate.longitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
QString ret = QString::number(southEast.latitude(), 'f', 6) + "-" + QString::number(southEast.longitude(), 'f', 6) + "-" + // Generate uniquely identifying string
QString::number(northEast.latitude(), 'f', 6) + "-" + QString::number(northEast.longitude(), 'f', 6); QString ret = QString::number(southWest.latitude(), 'f', 6) + "_" + QString::number(southWest.longitude(), 'f', 6) + "_" +
QString::number(northEast.latitude(), 'f', 6) + "_" + QString::number(northEast.longitude(), 'f', 6);
qCDebug(TerrainLog) << "Computing unique tile id for " << coordinate << ret; qCDebug(TerrainLog) << "Computing unique tile id for " << coordinate << ret;
return ret; return ret;
......
...@@ -44,13 +44,22 @@ public: ...@@ -44,13 +44,22 @@ public:
*/ */
bool queryTerrainData(const QList<QGeoCoordinate>& coordinates); bool queryTerrainData(const QList<QGeoCoordinate>& coordinates);
/**
* Cache all data in rectangular region given by list of coordinates.
*
* @param coordinates
* @return true on successful scheduling for download
*/
bool cacheTerrainTiles(const QList<QGeoCoordinate>& coordinates);
/** /**
* Cache all data in rectangular region given by south west and north east corner. * Cache all data in rectangular region given by south west and north east corner.
* *
* @param southWest * @param southWest
* @param northEast * @param northEast
* @return true on successful scheduling for download
*/ */
bool cacheTerrainTiles(const QList<QGeoCoordinate>& coordinates); bool cacheTerrainTiles(const QGeoCoordinate& southWest, const QGeoCoordinate& northEast);
signals: signals:
void terrainData(bool success, QList<float> altitudes); void terrainData(bool success, QList<float> altitudes);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
QGC_LOGGING_CATEGORY(TerrainTileLog, "TerrainTileLog") QGC_LOGGING_CATEGORY(TerrainTileLog, "TerrainTileLog")
const double TerrainTile::_srtm1TileSize = 0.025; const double TerrainTile::srtm1TileSize = 0.025;
const char* TerrainTile::_jsonStatusKey = "status"; const char* TerrainTile::_jsonStatusKey = "status";
const char* TerrainTile::_jsonDataKey = "data"; const char* TerrainTile::_jsonDataKey = "data";
const char* TerrainTile::_jsonBoundsKey = "bounds"; const char* TerrainTile::_jsonBoundsKey = "bounds";
...@@ -47,7 +47,7 @@ TerrainTile::TerrainTile(QJsonDocument document) ...@@ -47,7 +47,7 @@ TerrainTile::TerrainTile(QJsonDocument document)
QString errorString; QString errorString;
QList<JsonHelper::KeyValidateInfo> rootVersionKeyInfoList = { QList<JsonHelper::KeyValidateInfo> rootVersionKeyInfoList = {
{ _jsonStatusKey, QJsonValue::String, true }, { _jsonStatusKey, QJsonValue::String, true },
{ _jsonDataKey, QJsonValue::String, true }, { _jsonDataKey, QJsonValue::Object, true },
}; };
if (!JsonHelper::validateKeys(rootObject, rootVersionKeyInfoList, errorString)) { if (!JsonHelper::validateKeys(rootObject, rootVersionKeyInfoList, errorString)) {
qCDebug(TerrainTileLog) << "Error in reading json: " << errorString; qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
...@@ -91,7 +91,7 @@ TerrainTile::TerrainTile(QJsonDocument document) ...@@ -91,7 +91,7 @@ TerrainTile::TerrainTile(QJsonDocument document)
_northEast.setLongitude(neArray[1].toDouble()); _northEast.setLongitude(neArray[1].toDouble());
// Stats // Stats
const QJsonObject& statsObject = dataObject[_jsonBoundsKey].toObject(); const QJsonObject& statsObject = dataObject[_jsonStatsKey].toObject();
QList<JsonHelper::KeyValidateInfo> statsVersionKeyInfoList = { QList<JsonHelper::KeyValidateInfo> statsVersionKeyInfoList = {
{ _jsonMaxElevationKey, QJsonValue::Double, true }, { _jsonMaxElevationKey, QJsonValue::Double, true },
{ _jsonMinElevationKey, QJsonValue::Double, true }, { _jsonMinElevationKey, QJsonValue::Double, true },
...@@ -107,17 +107,17 @@ TerrainTile::TerrainTile(QJsonDocument document) ...@@ -107,17 +107,17 @@ TerrainTile::TerrainTile(QJsonDocument document)
// Carpet // Carpet
const QJsonArray& carpetArray = dataObject[_jsonCarpetKey].toArray(); const QJsonArray& carpetArray = dataObject[_jsonCarpetKey].toArray();
if (carpetArray.count() != _gridSize) { if (carpetArray.count() < gridSize) { // TODO (birchera): We always get 91x91 points, figure out why and where the exact location of the elev values are.
qCDebug(TerrainTileLog) << "Expected array of " << _gridSize << ", instead got " << carpetArray.count(); qCDebug(TerrainTileLog) << "Expected array of " << gridSize << ", instead got " << carpetArray.count();
return; return;
} }
for (int i = 0; i < _gridSize; i++) { for (int i = 0; i < gridSize; i++) {
const QJsonArray& row = carpetArray[i].toArray(); const QJsonArray& row = carpetArray[i].toArray();
if (row.count() != _gridSize) { if (row.count() < gridSize) { // TODO (birchera): the same as above
qCDebug(TerrainTileLog) << "Expected row array of " << _gridSize << ", instead got " << row.count(); qCDebug(TerrainTileLog) << "Expected row array of " << gridSize << ", instead got " << row.count();
return; return;
} }
for (int j = 0; j < _gridSize; j++) { for (int j = 0; j < gridSize; j++) {
_data[i][j] = row[j].toDouble(); _data[i][j] = row[j].toDouble();
} }
} }
...@@ -130,8 +130,8 @@ bool TerrainTile::isIn(const QGeoCoordinate& coordinate) const ...@@ -130,8 +130,8 @@ bool TerrainTile::isIn(const QGeoCoordinate& coordinate) const
qCDebug(TerrainTileLog) << "isIn requested, but tile not valid"; qCDebug(TerrainTileLog) << "isIn requested, but tile not valid";
return false; return false;
} }
bool ret = coordinate.latitude() >= _southWest.longitude() && coordinate.longitude() >= _southWest.longitude() && bool ret = coordinate.latitude() >= _southWest.latitude() && coordinate.longitude() >= _southWest.longitude() &&
coordinate.latitude() <= _northEast.longitude() && coordinate.longitude() <= _northEast.longitude(); coordinate.latitude() <= _northEast.latitude() && coordinate.longitude() <= _northEast.longitude();
qCDebug(TerrainTileLog) << "Checking isIn: " << coordinate << " , in sw " << _southWest << " , ne " << _northEast << ": " << ret; qCDebug(TerrainTileLog) << "Checking isIn: " << coordinate << " , in sw " << _southWest << " , ne " << _northEast << ": " << ret;
return ret; return ret;
} }
...@@ -141,13 +141,13 @@ float TerrainTile::elevation(const QGeoCoordinate& coordinate) const ...@@ -141,13 +141,13 @@ float TerrainTile::elevation(const QGeoCoordinate& coordinate) const
if (_isValid) { if (_isValid) {
qCDebug(TerrainTileLog) << "elevation: " << coordinate << " , in sw " << _southWest << " , ne " << _northEast; qCDebug(TerrainTileLog) << "elevation: " << coordinate << " , in sw " << _southWest << " , ne " << _northEast;
// Get the index at resolution of 1 arc second // Get the index at resolution of 1 arc second
int indexLat = std::round((coordinate.latitude() - _southWest.latitude()) * _gridSize / _srtm1TileSize); int indexLat = std::round((coordinate.latitude() - _southWest.latitude()) * gridSize / srtm1TileSize);
int indexLon = std::round((coordinate.longitude() - _southWest.longitude()) * _gridSize / _srtm1TileSize); int indexLon = std::round((coordinate.longitude() - _southWest.longitude()) * gridSize / srtm1TileSize);
qCDebug(TerrainTileLog) << "indexLat:indexLon" << indexLat << indexLon; // TODO (birchera): Move this down to the next debug output, once this is all properly working. qCDebug(TerrainTileLog) << "indexLat:indexLon" << indexLat << indexLon; // TODO (birchera): Move this down to the next debug output, once this is all properly working.
Q_ASSERT(indexLat >= 0); Q_ASSERT(indexLat >= 0);
Q_ASSERT(indexLat < _gridSize); Q_ASSERT(indexLat < gridSize);
Q_ASSERT(indexLon >= 0); Q_ASSERT(indexLon >= 0);
Q_ASSERT(indexLon < _gridSize); Q_ASSERT(indexLon < gridSize);
qCDebug(TerrainTileLog) << "elevation" << _data[indexLat][indexLon]; qCDebug(TerrainTileLog) << "elevation" << _data[indexLat][indexLon];
return _data[indexLat][indexLon]; return _data[indexLat][indexLon];
} else { } else {
......
...@@ -74,10 +74,10 @@ public: ...@@ -74,10 +74,10 @@ public:
QGeoCoordinate centerCoordinate(void) const; QGeoCoordinate centerCoordinate(void) const;
/// tile grid size in lat and lon /// tile grid size in lat and lon
static const int _gridSize = TERRAIN_TILE_SIZE; static const int gridSize = TERRAIN_TILE_SIZE;
/// size of a tile in degree /// size of a tile in degree
static const double _srtm1TileSize; static const double srtm1TileSize;
private: private:
QGeoCoordinate _southWest; /// South west corner of the tile QGeoCoordinate _southWest; /// South west corner of the tile
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment