Commit 7c2e38fd authored by Don Gagne's avatar Don Gagne

Persist tile info as doubles. This prevent float/double precision match errors at the edge of tiles.
parent 67244fdd
...@@ -53,81 +53,50 @@ TerrainTile::TerrainTile(QByteArray byteArray) ...@@ -53,81 +53,50 @@ TerrainTile::TerrainTile(QByteArray byteArray)
, _gridSizeLon(-1) , _gridSizeLon(-1)
, _isValid(false) , _isValid(false)
{ {
QDataStream stream(byteArray); int cTileHeaderBytes = static_cast<int>(sizeof(TileInfo_t));
int cTileBytesAvailable = byteArray.size();
float lat,lon; if (cTileBytesAvailable < cTileHeaderBytes) {
if (stream.atEnd()) { qWarning() << "Terrain tile binary data too small for TileInfo_s header";
qWarning() << "Terrain tile binary data does not contain all data";
return; return;
} }
stream >> lat;
if (stream.atEnd()) {
qWarning() << "Terrain tile binary data does not contain all data";
return;
}
stream >> lon;
_southWest.setLatitude(lat);
_southWest.setLongitude(lon);
if (stream.atEnd()) { const TileInfo_t* tileInfo = reinterpret_cast<const TileInfo_t*>(byteArray.constData());
qWarning() << "Terrain tile binary data does not contain all data"; _southWest.setLatitude(tileInfo->swLat);
return; _southWest.setLongitude(tileInfo->swLon);
} _northEast.setLatitude(tileInfo->neLat);
stream >> lat; _northEast.setLongitude(tileInfo->neLon);
if (stream.atEnd()) { _minElevation = tileInfo->minElevation;
qWarning() << "Terrain tile binary data does not contain all data"; _maxElevation = tileInfo->maxElevation;
return; _avgElevation = tileInfo->avgElevation;
} _gridSizeLat = tileInfo->gridSizeLat;
stream >> lon; _gridSizeLon = tileInfo->gridSizeLon;
_northEast.setLatitude(lat);
_northEast.setLongitude(lon);
if (stream.atEnd()) { qCDebug(TerrainTileLog) << "Loading terrain tile: " << _southWest << " - " << _northEast;
qWarning() << "Terrain tile binary data does not contain all data"; qCDebug(TerrainTileLog) << "min:max:avg:sizeLat:sizeLon" << _minElevation << _maxElevation << _avgElevation << _gridSizeLat << _gridSizeLon;
return;
} int cTileDataBytes = static_cast<int>(sizeof(int16_t)) * _gridSizeLat * _gridSizeLon;
stream >> _minElevation; if (cTileBytesAvailable < cTileHeaderBytes + cTileDataBytes) {
if (stream.atEnd()) { qWarning() << "Terrain tile binary data too small for tile data";
qWarning() << "Terrain tile binary data does not contain all data";
return;
}
stream >> _maxElevation;
if (stream.atEnd()) {
qWarning() << "Terrain tile binary data does not contain all data";
return;
}
stream >> _avgElevation;
if (stream.atEnd()) {
qWarning() << "Terrain tile binary data does not contain all data";
return;
}
stream >> _gridSizeLat;
if (stream.atEnd()) {
qWarning() << "Terrain tile binary data does not contain all data";
return; return;
} }
stream >> _gridSizeLon;
qCDebug(TerrainTileLog) << "Loading terrain tile: " << _southWest << " - " << _northEast; _data = new int16_t*[_gridSizeLat];
qCDebug(TerrainTileLog) << "min:max:avg:sizeLat:sizeLon" << _minElevation << _maxElevation << _avgElevation << _gridSizeLat << _gridSizeLon; for (int k = 0; k < _gridSizeLat; k++) {
_data[k] = new int16_t[_gridSizeLon];
}
int valueIndex = 0;
const int16_t* pTileData = reinterpret_cast<const int16_t*>(&reinterpret_cast<const uint8_t*>(byteArray.constData())[cTileHeaderBytes]);
for (int i = 0; i < _gridSizeLat; i++) { for (int i = 0; i < _gridSizeLat; i++) {
if (i == 0) {
_data = new int16_t*[_gridSizeLat];
for (int k = 0; k < _gridSizeLat; k++) {
_data[k] = new int16_t[_gridSizeLon];
}
}
for (int j = 0; j < _gridSizeLon; j++) { for (int j = 0; j < _gridSizeLon; j++) {
if (stream.atEnd()) { _data[i][j] = pTileData[valueIndex++];
qWarning() << "Terrain tile binary data does not contain all data";
return;
}
stream >> _data[i][j];
} }
} }
_isValid = true; _isValid = true;
return;
} }
...@@ -176,8 +145,6 @@ QByteArray TerrainTile::serialize(QByteArray input) ...@@ -176,8 +145,6 @@ QByteArray TerrainTile::serialize(QByteArray input)
return emptyArray; return emptyArray;
} }
QByteArray byteArray;
QDataStream stream(&byteArray, QIODevice::WriteOnly);
if (!document.isObject()) { if (!document.isObject()) {
qCDebug(TerrainTileLog) << "Terrain tile json doc is no object"; qCDebug(TerrainTileLog) << "Terrain tile json doc is no object";
QByteArray emptyArray; QByteArray emptyArray;
...@@ -231,10 +198,6 @@ QByteArray TerrainTile::serialize(QByteArray input) ...@@ -231,10 +198,6 @@ QByteArray TerrainTile::serialize(QByteArray input)
QByteArray emptyArray; QByteArray emptyArray;
return emptyArray; return emptyArray;
} }
stream << static_cast<float>(swArray[0].toDouble());
stream << static_cast<float>(swArray[1].toDouble());
stream << static_cast<float>(neArray[0].toDouble());
stream << static_cast<float>(neArray[1].toDouble());
// Stats // Stats
const QJsonObject& statsObject = dataObject[_jsonStatsKey].toObject(); const QJsonObject& statsObject = dataObject[_jsonStatsKey].toObject();
...@@ -248,30 +211,46 @@ QByteArray TerrainTile::serialize(QByteArray input) ...@@ -248,30 +211,46 @@ QByteArray TerrainTile::serialize(QByteArray input)
QByteArray emptyArray; QByteArray emptyArray;
return emptyArray; return emptyArray;
} }
stream << static_cast<int16_t>(statsObject[_jsonMinElevationKey].toInt());
stream << static_cast<int16_t>(statsObject[_jsonMaxElevationKey].toInt());
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 << static_cast<int16_t>(gridSizeLat); int gridSizeLon = carpetArray[0].toArray().count();
int gridSizeLon = 0; qCDebug(TerrainTileLog) << "Received tile has size in latitude direction: " << gridSizeLat;
qCDebug(TerrainTileLog) << "Received tile has size in latitude direction: " << carpetArray.count(); qCDebug(TerrainTileLog) << "Received tile has size in longitued direction: " << gridSizeLon;
TileInfo_t tileInfo;
tileInfo.swLat = swArray[0].toDouble();
tileInfo.swLon = swArray[1].toDouble();
tileInfo.neLat = neArray[0].toDouble();
tileInfo.neLon = neArray[1].toDouble();
tileInfo.minElevation = static_cast<int16_t>(statsObject[_jsonMinElevationKey].toInt());
tileInfo.maxElevation = static_cast<int16_t>(statsObject[_jsonMaxElevationKey].toInt());
tileInfo.avgElevation = statsObject[_jsonAvgElevationKey].toDouble();
tileInfo.gridSizeLat = static_cast<int16_t>(gridSizeLat);
tileInfo.gridSizeLon = static_cast<int16_t>(gridSizeLon);
int cTileHeaderBytes = static_cast<int>(sizeof(TileInfo_t));
int cTileDataBytes = static_cast<int>(sizeof(int16_t)) * gridSizeLat * gridSizeLon;
QByteArray byteArray(cTileHeaderBytes + cTileDataBytes, 0);
TileInfo_t* pTileInfo = reinterpret_cast<TileInfo_t*>(byteArray.data());
int16_t* pTileData = reinterpret_cast<int16_t*>(&reinterpret_cast<uint8_t*>(byteArray.data())[cTileHeaderBytes]);
*pTileInfo = tileInfo;
int valueIndex = 0;
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) {
gridSizeLon = row.count();
stream << static_cast<int16_t>(gridSizeLon);
qCDebug(TerrainTileLog) << "Received tile has size in longitued direction: " << row.count();
}
if (row.count() < gridSizeLon) { if (row.count() < gridSizeLon) {
qCDebug(TerrainTileLog) << "Expected row array of " << gridSizeLon << ", instead got " << row.count(); qCDebug(TerrainTileLog) << "Expected row array of " << gridSizeLon << ", instead got " << row.count();
QByteArray emptyArray; QByteArray emptyArray;
return emptyArray; return emptyArray;
} }
for (int j = 0; j < gridSizeLon; j++) { for (int j = 0; j < gridSizeLon; j++) {
stream << static_cast<int16_t>(row[j].toDouble()); pTileData[valueIndex++] = static_cast<int16_t>(row[j].toDouble());
} }
} }
......
...@@ -95,6 +95,15 @@ public: ...@@ -95,6 +95,15 @@ public:
static constexpr double terrainAltitudeSpacing = 30.0; static constexpr double terrainAltitudeSpacing = 30.0;
private: private:
typedef struct {
double swLat,swLon, neLat, neLon;
int16_t minElevation;
int16_t maxElevation;
double avgElevation;
int16_t gridSizeLat;
int16_t gridSizeLon;
} TileInfo_t;
inline int _latToDataIndex(double latitude) const; inline int _latToDataIndex(double latitude) const;
inline int _lonToDataIndex(double longitude) const; inline int _lonToDataIndex(double longitude) const;
...@@ -103,7 +112,7 @@ private: ...@@ -103,7 +112,7 @@ private:
int16_t _minElevation; /// Minimum elevation in tile int16_t _minElevation; /// Minimum elevation in tile
int16_t _maxElevation; /// Maximum elevation in tile int16_t _maxElevation; /// Maximum elevation in tile
float _avgElevation; /// Average elevation of the tile double _avgElevation; /// Average elevation of the tile
int16_t** _data; /// 2D elevation data array int16_t** _data; /// 2D elevation data array
int16_t _gridSizeLat; /// data grid size in latitude direction int16_t _gridSizeLat; /// data grid size in latitude direction
......
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