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)
} else {
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 @@
#include "QGCLoggingCategory.h"
#include "QGCMapEngine.h"
#include "QGCMapTileSet.h"
#include "Terrain.h"
Q_DECLARE_LOGGING_CATEGORY(QGCMapEngineManagerLog)
......@@ -152,6 +153,8 @@ private:
int _actionProgress;
ImportAction _importAction;
bool _importReplace;
ElevationProvider _elevationProvider;
};
#endif
......@@ -95,6 +95,37 @@ bool ElevationProvider::queryTerrainData(const QList<QGeoCoordinate>& coordinate
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)
{
if (coordinates.length() == 0) {
......@@ -105,9 +136,10 @@ bool ElevationProvider::cacheTerrainTiles(const QList<QGeoCoordinate>& coordinat
QString uniqueTileId = _uniqueTileId(coordinate);
_tilesMutex.lock();
if (_downloadQueue.contains(uniqueTileId) || _tiles.contains(uniqueTileId)) {
_tilesMutex.unlock();
continue;
}
_downloadQueue.append(uniqueTileId.replace("-", ","));
_downloadQueue.append(uniqueTileId.replace("_", ","));
_tilesMutex.unlock();
qCDebug(TerrainLog) << "Adding tile to download queue: " << uniqueTileId;
}
......@@ -166,7 +198,8 @@ void ElevationProvider::_requestFinishedTile()
QJsonParseError parseError;
QJsonDocument responseJson = QJsonDocument::fromJson(responseBytes, &parseError);
qCDebug(TerrainLog) << "ERROR: Received " << responseJson;
// TODO: Handle error in downloading data
// TODO (birchera): Handle error in downloading data
_downloadTiles();
return;
}
......@@ -175,7 +208,8 @@ void ElevationProvider::_requestFinishedTile()
QJsonParseError parseError;
QJsonDocument responseJson = QJsonDocument::fromJson(responseBytes, &parseError);
if (parseError.error != QJsonParseError::NoError) {
// TODO: Handle error in downloading data
// TODO (birchera): Handle error in downloading data
_downloadTiles();
return;
}
......@@ -187,7 +221,7 @@ void ElevationProvider::_requestFinishedTile()
} else {
delete tile;
}
_tilesMutex.lock();
_tilesMutex.unlock();
}
_downloadTiles();
......@@ -202,7 +236,7 @@ void ElevationProvider::_downloadTiles(void)
query.addQueryItem(QStringLiteral("points"), _downloadQueue.first());
_downloadQueue.pop_front();
_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);
QNetworkRequest request(url);
......@@ -224,15 +258,17 @@ void ElevationProvider::_downloadTiles(void)
QString ElevationProvider::_uniqueTileId(const QGeoCoordinate& coordinate)
{
QGeoCoordinate southEast;
southEast.setLatitude(floor(coordinate.latitude()*40.0)/40.0);
southEast.setLongitude(floor(coordinate.longitude()*40.0)/40.0);
// Compute corners of the tile
QGeoCoordinate southWest;
southWest.setLatitude(floor(coordinate.latitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
southWest.setLongitude(floor(coordinate.longitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
QGeoCoordinate northEast;
northEast.setLatitude(ceil(coordinate.latitude()*40.0)/40.0);
northEast.setLongitude(ceil(coordinate.longitude()*40.0)/40.0);
northEast.setLatitude(ceil(coordinate.latitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
northEast.setLongitude(ceil(coordinate.longitude()/TerrainTile::srtm1TileSize)*TerrainTile::srtm1TileSize);
QString ret = QString::number(southEast.latitude(), 'f', 6) + "-" + QString::number(southEast.longitude(), 'f', 6) + "-" +
QString::number(northEast.latitude(), 'f', 6) + "-" + QString::number(northEast.longitude(), 'f', 6);
// Generate uniquely identifying string
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;
return ret;
......
......@@ -44,13 +44,22 @@ public:
*/
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.
*
* @param southWest
* @param northEast
* @return true on successful scheduling for download
*/
bool cacheTerrainTiles(const QList<QGeoCoordinate>& coordinates);
bool cacheTerrainTiles(const QGeoCoordinate& southWest, const QGeoCoordinate& northEast);
signals:
void terrainData(bool success, QList<float> altitudes);
......
......@@ -7,7 +7,7 @@
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::_jsonDataKey = "data";
const char* TerrainTile::_jsonBoundsKey = "bounds";
......@@ -47,7 +47,7 @@ TerrainTile::TerrainTile(QJsonDocument document)
QString errorString;
QList<JsonHelper::KeyValidateInfo> rootVersionKeyInfoList = {
{ _jsonStatusKey, QJsonValue::String, true },
{ _jsonDataKey, QJsonValue::String, true },
{ _jsonDataKey, QJsonValue::Object, true },
};
if (!JsonHelper::validateKeys(rootObject, rootVersionKeyInfoList, errorString)) {
qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
......@@ -91,7 +91,7 @@ TerrainTile::TerrainTile(QJsonDocument document)
_northEast.setLongitude(neArray[1].toDouble());
// Stats
const QJsonObject& statsObject = dataObject[_jsonBoundsKey].toObject();
const QJsonObject& statsObject = dataObject[_jsonStatsKey].toObject();
QList<JsonHelper::KeyValidateInfo> statsVersionKeyInfoList = {
{ _jsonMaxElevationKey, QJsonValue::Double, true },
{ _jsonMinElevationKey, QJsonValue::Double, true },
......@@ -107,17 +107,17 @@ TerrainTile::TerrainTile(QJsonDocument document)
// Carpet
const QJsonArray& carpetArray = dataObject[_jsonCarpetKey].toArray();
if (carpetArray.count() != _gridSize) {
qCDebug(TerrainTileLog) << "Expected array of " << _gridSize << ", instead got " << carpetArray.count();
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();
return;
}
for (int i = 0; i < _gridSize; i++) {
for (int i = 0; i < gridSize; i++) {
const QJsonArray& row = carpetArray[i].toArray();
if (row.count() != _gridSize) {
qCDebug(TerrainTileLog) << "Expected row array of " << _gridSize << ", instead got " << row.count();
if (row.count() < gridSize) { // TODO (birchera): the same as above
qCDebug(TerrainTileLog) << "Expected row array of " << gridSize << ", instead got " << row.count();
return;
}
for (int j = 0; j < _gridSize; j++) {
for (int j = 0; j < gridSize; j++) {
_data[i][j] = row[j].toDouble();
}
}
......@@ -130,8 +130,8 @@ bool TerrainTile::isIn(const QGeoCoordinate& coordinate) const
qCDebug(TerrainTileLog) << "isIn requested, but tile not valid";
return false;
}
bool ret = coordinate.latitude() >= _southWest.longitude() && coordinate.longitude() >= _southWest.longitude() &&
coordinate.latitude() <= _northEast.longitude() && coordinate.longitude() <= _northEast.longitude();
bool ret = coordinate.latitude() >= _southWest.latitude() && coordinate.longitude() >= _southWest.longitude() &&
coordinate.latitude() <= _northEast.latitude() && coordinate.longitude() <= _northEast.longitude();
qCDebug(TerrainTileLog) << "Checking isIn: " << coordinate << " , in sw " << _southWest << " , ne " << _northEast << ": " << ret;
return ret;
}
......@@ -141,13 +141,13 @@ float TerrainTile::elevation(const QGeoCoordinate& coordinate) const
if (_isValid) {
qCDebug(TerrainTileLog) << "elevation: " << coordinate << " , in sw " << _southWest << " , ne " << _northEast;
// Get the index at resolution of 1 arc second
int indexLat = std::round((coordinate.latitude() - _southWest.latitude()) * _gridSize / _srtm1TileSize);
int indexLon = std::round((coordinate.longitude() - _southWest.longitude()) * _gridSize / _srtm1TileSize);
int indexLat = std::round((coordinate.latitude() - _southWest.latitude()) * 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.
Q_ASSERT(indexLat >= 0);
Q_ASSERT(indexLat < _gridSize);
Q_ASSERT(indexLat < gridSize);
Q_ASSERT(indexLon >= 0);
Q_ASSERT(indexLon < _gridSize);
Q_ASSERT(indexLon < gridSize);
qCDebug(TerrainTileLog) << "elevation" << _data[indexLat][indexLon];
return _data[indexLat][indexLon];
} else {
......
......@@ -74,10 +74,10 @@ public:
QGeoCoordinate centerCoordinate(void) const;
/// 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
static const double _srtm1TileSize;
static const double srtm1TileSize;
private:
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