Commit 6bb01ff3 authored by Andreas Bircher's avatar Andreas Bircher

make offline caching working serialized as well

parent 5c72de31
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "QGCMapEngine.h" #include "QGCMapEngine.h"
#include "QGCMapTileSet.h" #include "QGCMapTileSet.h"
#include "QGCMapEngineManager.h" #include "QGCMapEngineManager.h"
#include "TerrainTile.h"
#include <QSettings> #include <QSettings>
#include <math.h> #include <math.h>
...@@ -282,6 +283,9 @@ QGCCachedTileSet::_networkReplyFinished() ...@@ -282,6 +283,9 @@ QGCCachedTileSet::_networkReplyFinished()
qCDebug(QGCCachedTileSetLog) << "Tile fetched" << hash; qCDebug(QGCCachedTileSetLog) << "Tile fetched" << hash;
QByteArray image = reply->readAll(); QByteArray image = reply->readAll();
UrlFactory::MapType type = getQGCMapEngine()->hashToType(hash); UrlFactory::MapType type = getQGCMapEngine()->hashToType(hash);
if (type == UrlFactory::MapType::AirmapElevation) {
image = TerrainTile::serialize(image);
}
QString format = getQGCMapEngine()->urlFactory()->getImageFormat(type, image); QString format = getQGCMapEngine()->urlFactory()->getImageFormat(type, image);
if(!format.isEmpty()) { if(!format.isEmpty()) {
//-- Cache tile //-- Cache tile
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
static const unsigned char pngSignature[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00}; static const unsigned char pngSignature[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00};
static const unsigned char jpegSignature[] = {0xFF, 0xD8, 0xFF, 0x00}; static const unsigned char jpegSignature[] = {0xFF, 0xD8, 0xFF, 0x00};
static const unsigned char gifSignature[] = {0x47, 0x49, 0x46, 0x38, 0x00}; static const unsigned char gifSignature[] = {0x47, 0x49, 0x46, 0x38, 0x00};
static const unsigned char jsonSignature[] = {0x7B, 0x22, 0x00}; // two characters '{"'
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
UrlFactory::UrlFactory() UrlFactory::UrlFactory()
...@@ -86,8 +85,6 @@ UrlFactory::getImageFormat(MapType type, const QByteArray& image) ...@@ -86,8 +85,6 @@ UrlFactory::getImageFormat(MapType type, const QByteArray& image)
format = "jpg"; format = "jpg";
else if (image.startsWith(reinterpret_cast<const char*>(gifSignature))) else if (image.startsWith(reinterpret_cast<const char*>(gifSignature)))
format = "gif"; format = "gif";
else if (image.startsWith(reinterpret_cast<const char*>(jsonSignature)))
format = "json";
else { else {
switch (type) { switch (type) {
case GoogleMap: case GoogleMap:
...@@ -126,7 +123,7 @@ UrlFactory::getImageFormat(MapType type, const QByteArray& image) ...@@ -126,7 +123,7 @@ UrlFactory::getImageFormat(MapType type, const QByteArray& image)
format = "jpg"; format = "jpg";
break; break;
case AirmapElevation: case AirmapElevation:
format = "json"; format = "bin";
break; break;
default: default:
qWarning("UrlFactory::getImageFormat() Unknown map id %d", type); qWarning("UrlFactory::getImageFormat() Unknown map id %d", type);
...@@ -563,7 +560,7 @@ UrlFactory::_tryCorrectGoogleVersions(QNetworkAccessManager* networkManager) ...@@ -563,7 +560,7 @@ UrlFactory::_tryCorrectGoogleVersions(QNetworkAccessManager* networkManager)
#define AVERAGE_MAPBOX_SAT_MAP 15739 #define AVERAGE_MAPBOX_SAT_MAP 15739
#define AVERAGE_MAPBOX_STREET_MAP 5648 #define AVERAGE_MAPBOX_STREET_MAP 5648
#define AVERAGE_TILE_SIZE 13652 #define AVERAGE_TILE_SIZE 13652
#define AVERAGE_AIRMAP_ELEV_SIZE 5360 #define AVERAGE_AIRMAP_ELEV_SIZE 2786
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
quint32 quint32
......
...@@ -398,6 +398,8 @@ void TerrainTileManager::_fetchedTile() ...@@ -398,6 +398,8 @@ void TerrainTileManager::_fetchedTile()
// parse received data and insert into hash table // parse received data and insert into hash table
QByteArray responseBytes = reply->mapImageData(); QByteArray responseBytes = reply->mapImageData();
qWarning() << "Received some bytes of terrain data: " << responseBytes.size();
TerrainTile* terrainTile = new TerrainTile(responseBytes); TerrainTile* terrainTile = new TerrainTile(responseBytes);
if (terrainTile->isValid()) { if (terrainTile->isValid()) {
_tilesMutex.lock(); _tilesMutex.lock();
......
...@@ -87,7 +87,7 @@ private: ...@@ -87,7 +87,7 @@ private:
bool _carpetStatsOnly; bool _carpetStatsOnly;
}; };
/// AirMap online implementation of terrain queries /// AirMap offline cachable implementation of terrain queries
class TerrainOfflineAirMapQuery : public TerrainQueryInterface { class TerrainOfflineAirMapQuery : public TerrainQueryInterface {
Q_OBJECT Q_OBJECT
...@@ -99,12 +99,10 @@ public: ...@@ -99,12 +99,10 @@ public:
void requestPathHeights(const QGeoCoordinate& fromCoord, const QGeoCoordinate& toCoord) final; void requestPathHeights(const QGeoCoordinate& fromCoord, const QGeoCoordinate& toCoord) final;
void requestCarpetHeights(const QGeoCoordinate& swCoord, const QGeoCoordinate& neCoord, bool statsOnly) final; void requestCarpetHeights(const QGeoCoordinate& swCoord, const QGeoCoordinate& neCoord, bool statsOnly) final;
// Internal method // Internal methods
void _signalCoordinateHeights(bool success, QList<double> heights); void _signalCoordinateHeights(bool success, QList<double> heights);
void _signalPathHeights(bool success, double latStep, double lonStep, const QList<double>& heights); void _signalPathHeights(bool success, double latStep, double lonStep, const QList<double>& heights);
void _signalCarpetHeights(bool success, double minHeight, double maxHeight, const QList<QList<double>>& carpet); void _signalCarpetHeights(bool success, double minHeight, double maxHeight, const QList<QList<double>>& carpet);
bool _carpetStatsOnly;
}; };
/// Used internally by TerrainOfflineAirMapQuery to manage terrain tiles /// Used internally by TerrainOfflineAirMapQuery to manage terrain tiles
......
...@@ -55,31 +55,38 @@ TerrainTile::TerrainTile(QByteArray byteArray) ...@@ -55,31 +55,38 @@ TerrainTile::TerrainTile(QByteArray byteArray)
{ {
QDataStream stream(byteArray); QDataStream stream(byteArray);
double lat,lon; float lat,lon;
stream >> lat stream >> lat
>> lon; >> lon;
_southWest.setLatitude(lat); _southWest.setLatitude(lat);
_southWest.setLongitude(lon); _southWest.setLongitude(lon);
stream >> lat stream >> lat
>> lon; >> lon;
_northEast.setLatitude(lat); _northEast.setLatitude(lat);
_northEast.setLongitude(lon); _northEast.setLongitude(lon);
stream >> _minElevation stream >> _minElevation
>> _maxElevation >> _maxElevation
>> _avgElevation >> _avgElevation
>> _gridSizeLat >> _gridSizeLat
>> _gridSizeLon; >> _gridSizeLon;
qCDebug(TerrainTileLog) << "Loading terrain tile: " << _southWest << " - " << _northEast;
qCDebug(TerrainTileLog) << "min:max:avg:sizeLat:sizeLon" << _minElevation << _maxElevation << _avgElevation << _gridSizeLat << _gridSizeLon;
for (int i = 0; i < _gridSizeLat; i++) { for (int i = 0; i < _gridSizeLat; i++) {
if (i == 0) { if (i == 0) {
_data = new double*[_gridSizeLat]; _data = new int16_t*[_gridSizeLat];
for (int k = 0; k < _gridSizeLat; k++) { for (int k = 0; k < _gridSizeLat; k++) {
_data[k] = new double[_gridSizeLon]; _data[k] = new int16_t[_gridSizeLon];
} }
} }
for (int j = 0; j < _gridSizeLon; j++) { for (int j = 0; j < _gridSizeLon; j++) {
if (stream.atEnd()) {
qWarning() << "Terrain tile binary data does not contain all data";
return;
}
stream >> _data[i][j]; stream >> _data[i][j];
} }
} }
...@@ -108,7 +115,7 @@ double TerrainTile::elevation(const QGeoCoordinate& coordinate) const ...@@ -108,7 +115,7 @@ double TerrainTile::elevation(const QGeoCoordinate& coordinate) const
int indexLat = _latToDataIndex(coordinate.latitude()); int indexLat = _latToDataIndex(coordinate.latitude());
int indexLon = _lonToDataIndex(coordinate.longitude()); int indexLon = _lonToDataIndex(coordinate.longitude());
qCDebug(TerrainTileLog) << "indexLat:indexLon" << indexLat << indexLon << "elevation" << _data[indexLat][indexLon]; qCDebug(TerrainTileLog) << "indexLat:indexLon" << indexLat << indexLon << "elevation" << _data[indexLat][indexLon];
return _data[indexLat][indexLon]; return static_cast<double>(_data[indexLat][indexLon]);
} else { } else {
qCDebug(TerrainTileLog) << "Asking for elevation, but no valid data."; qCDebug(TerrainTileLog) << "Asking for elevation, but no valid data.";
return -1.0; return -1.0;
...@@ -141,7 +148,7 @@ QByteArray TerrainTile::serialize(QByteArray input) ...@@ -141,7 +148,7 @@ QByteArray TerrainTile::serialize(QByteArray input)
QString errorString; QString errorString;
QList<JsonHelper::KeyValidateInfo> rootVersionKeyInfoList = { QList<JsonHelper::KeyValidateInfo> rootVersionKeyInfoList = {
{ _jsonStatusKey, QJsonValue::String, true }, { _jsonStatusKey, QJsonValue::String, true },
{ _jsonDataKey, QJsonValue::Object, 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;
...@@ -157,7 +164,7 @@ QByteArray TerrainTile::serialize(QByteArray input) ...@@ -157,7 +164,7 @@ QByteArray TerrainTile::serialize(QByteArray input)
const QJsonObject& dataObject = rootObject[_jsonDataKey].toObject(); const QJsonObject& dataObject = rootObject[_jsonDataKey].toObject();
QList<JsonHelper::KeyValidateInfo> dataVersionKeyInfoList = { QList<JsonHelper::KeyValidateInfo> dataVersionKeyInfoList = {
{ _jsonBoundsKey, QJsonValue::Object, true }, { _jsonBoundsKey, QJsonValue::Object, true },
{ _jsonStatsKey, QJsonValue::Object, true }, { _jsonStatsKey, QJsonValue::Object, true },
{ _jsonCarpetKey, QJsonValue::Array, true }, { _jsonCarpetKey, QJsonValue::Array, true },
}; };
if (!JsonHelper::validateKeys(dataObject, dataVersionKeyInfoList, errorString)) { if (!JsonHelper::validateKeys(dataObject, dataVersionKeyInfoList, errorString)) {
...@@ -184,16 +191,16 @@ QByteArray TerrainTile::serialize(QByteArray input) ...@@ -184,16 +191,16 @@ QByteArray TerrainTile::serialize(QByteArray input)
QByteArray emptyArray; QByteArray emptyArray;
return emptyArray; return emptyArray;
} }
stream << swArray[0].toDouble(); stream << static_cast<float>(swArray[0].toDouble());
stream << swArray[1].toDouble(); stream << static_cast<float>(swArray[1].toDouble());
stream << neArray[0].toDouble(); stream << static_cast<float>(neArray[0].toDouble());
stream << neArray[1].toDouble(); stream << static_cast<float>(neArray[1].toDouble());
// Stats // Stats
const QJsonObject& statsObject = dataObject[_jsonStatsKey].toObject(); const QJsonObject& statsObject = dataObject[_jsonStatsKey].toObject();
QList<JsonHelper::KeyValidateInfo> statsVersionKeyInfoList = { QList<JsonHelper::KeyValidateInfo> statsVersionKeyInfoList = {
{ _jsonMaxElevationKey, QJsonValue::Double, true },
{ _jsonMinElevationKey, QJsonValue::Double, true }, { _jsonMinElevationKey, QJsonValue::Double, true },
{ _jsonMaxElevationKey, QJsonValue::Double, true },
{ _jsonAvgElevationKey, QJsonValue::Double, true }, { _jsonAvgElevationKey, QJsonValue::Double, true },
}; };
if (!JsonHelper::validateKeys(statsObject, statsVersionKeyInfoList, errorString)) { if (!JsonHelper::validateKeys(statsObject, statsVersionKeyInfoList, errorString)) {
...@@ -201,21 +208,21 @@ QByteArray TerrainTile::serialize(QByteArray input) ...@@ -201,21 +208,21 @@ QByteArray TerrainTile::serialize(QByteArray input)
QByteArray emptyArray; QByteArray emptyArray;
return emptyArray; return emptyArray;
} }
stream << statsObject[_jsonMaxElevationKey].toInt(); stream << static_cast<int16_t>(statsObject[_jsonMinElevationKey].toInt());
stream << statsObject[_jsonMinElevationKey].toInt(); stream << static_cast<int16_t>(statsObject[_jsonMaxElevationKey].toInt());
stream << statsObject[_jsonAvgElevationKey].toDouble(); stream << static_cast<float>(statsObject[_jsonAvgElevationKey].toDouble());
// Carpet // Carpet
const QJsonArray& carpetArray = dataObject[_jsonCarpetKey].toArray(); const QJsonArray& carpetArray = dataObject[_jsonCarpetKey].toArray();
int gridSizeLat = carpetArray.count(); int gridSizeLat = carpetArray.count();
stream << gridSizeLat; stream << static_cast<int16_t>(gridSizeLat);
int gridSizeLon = 0; int gridSizeLon = 0;
qCDebug(TerrainTileLog) << "Received tile has size in latitude direction: " << carpetArray.count(); qCDebug(TerrainTileLog) << "Received tile has size in latitude direction: " << carpetArray.count();
for (int i = 0; i < gridSizeLat; i++) { for (int i = 0; i < gridSizeLat; i++) {
const QJsonArray& row = carpetArray[i].toArray(); const QJsonArray& row = carpetArray[i].toArray();
if (i == 0) { if (i == 0) {
gridSizeLon = row.count(); gridSizeLon = row.count();
stream << gridSizeLon; stream << static_cast<int16_t>(gridSizeLon);
qCDebug(TerrainTileLog) << "Received tile has size in longitued direction: " << row.count(); qCDebug(TerrainTileLog) << "Received tile has size in longitued direction: " << row.count();
} }
if (row.count() < gridSizeLon) { if (row.count() < gridSizeLon) {
...@@ -224,7 +231,7 @@ QByteArray TerrainTile::serialize(QByteArray input) ...@@ -224,7 +231,7 @@ QByteArray TerrainTile::serialize(QByteArray input)
return emptyArray; return emptyArray;
} }
for (int j = 0; j < gridSizeLon; j++) { for (int j = 0; j < gridSizeLon; j++) {
stream << row[j].toDouble(); stream << static_cast<int16_t>(row[j].toDouble());
} }
} }
......
...@@ -101,13 +101,13 @@ private: ...@@ -101,13 +101,13 @@ private:
QGeoCoordinate _southWest; /// South west corner of the tile QGeoCoordinate _southWest; /// South west corner of the tile
QGeoCoordinate _northEast; /// North east corner of the tile QGeoCoordinate _northEast; /// North east corner of the tile
int _minElevation; /// Minimum elevation in tile int16_t _minElevation; /// Minimum elevation in tile
int _maxElevation; /// Maximum elevation in tile int16_t _maxElevation; /// Maximum elevation in tile
double _avgElevation; /// Average elevation of the tile float _avgElevation; /// Average elevation of the tile
double** _data; /// 2D elevation data array int16_t** _data; /// 2D elevation data array
int _gridSizeLat; /// data grid size in latitude direction int16_t _gridSizeLat; /// data grid size in latitude direction
int _gridSizeLon; /// data grid size in longitude direction int16_t _gridSizeLon; /// data grid size in longitude direction
bool _isValid; /// data loaded is valid bool _isValid; /// data loaded is valid
// Json keys // Json keys
......
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