Newer
Older
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDataStream>
QGC_LOGGING_CATEGORY(TerrainTileLog, "TerrainTileLog")
const char* TerrainTile::_jsonStatusKey = "status";
const char* TerrainTile::_jsonDataKey = "data";
const char* TerrainTile::_jsonBoundsKey = "bounds";
const char* TerrainTile::_jsonSouthWestKey = "sw";
const char* TerrainTile::_jsonNorthEastKey = "ne";
const char* TerrainTile::_jsonStatsKey = "stats";
const char* TerrainTile::_jsonMaxElevationKey = "max";
const char* TerrainTile::_jsonMinElevationKey = "min";
const char* TerrainTile::_jsonAvgElevationKey = "avg";
const char* TerrainTile::_jsonCarpetKey = "carpet";
TerrainTile::TerrainTile()
: _minElevation(-1.0)
, _maxElevation(-1.0)
, _avgElevation(-1.0)
, _data(NULL)
, _gridSizeLat(-1)
, _gridSizeLon(-1)
, _isValid(false)
{
}
TerrainTile::~TerrainTile()
{
if (_data) {
for (int i = 0; i < _gridSizeLat; i++) {
delete _data[i];
}
TerrainTile::TerrainTile(QByteArray byteArray)
: _minElevation(-1.0)
, _maxElevation(-1.0)
, _avgElevation(-1.0)
, _data(NULL)
, _gridSizeLat(-1)
, _gridSizeLon(-1)
QDataStream stream(byteArray);
double lat,lon;
stream >> lat
>> lon;
_southWest.setLatitude(lat);
_southWest.setLongitude(lon);
stream >> lat
>> lon;
_northEast.setLatitude(lat);
_northEast.setLongitude(lon);
stream >> _minElevation
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
>> _maxElevation
>> _avgElevation
>> _gridSizeLat
>> _gridSizeLon;
for (int i = 0; i < _gridSizeLat; i++) {
if (i == 0) {
_data = new double*[_gridSizeLat];
for (int k = 0; k < _gridSizeLat; k++) {
_data[k] = new double[_gridSizeLon];
}
}
for (int j = 0; j < _gridSizeLon; j++) {
stream >> _data[i][j];
}
}
_isValid = true;
}
bool TerrainTile::isIn(const QGeoCoordinate& coordinate) const
{
if (!_isValid) {
qCDebug(TerrainTileLog) << "isIn requested, but tile not valid";
return false;
}
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;
}
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 = _latToDataIndex(coordinate.latitude());
int indexLon = _lonToDataIndex(coordinate.longitude());
qCDebug(TerrainTileLog) << "indexLat:indexLon" << indexLat << indexLon << "elevation" << _data[indexLat][indexLon];
return _data[indexLat][indexLon];
} else {
qCDebug(TerrainTileLog) << "Asking for elevation, but no valid data.";
return -1.0;
}
}
QGeoCoordinate TerrainTile::centerCoordinate(void) const
{
return _southWest.atDistanceAndAzimuth(_southWest.distanceTo(_northEast) / 2.0, _southWest.azimuthTo(_northEast));
}
QByteArray TerrainTile::serialize(QByteArray input)
QJsonParseError parseError;
QJsonDocument document = QJsonDocument::fromJson(input, &parseError);
if (parseError.error != QJsonParseError::NoError) {
QByteArray emptyArray;
return emptyArray;
}
QByteArray byteArray;
QDataStream stream(&byteArray, QIODevice::WriteOnly);
qCDebug(TerrainTileLog) << "Terrain tile json doc is no object";
QByteArray emptyArray;
return emptyArray;
QString errorString;
QList<JsonHelper::KeyValidateInfo> rootVersionKeyInfoList = {
{ _jsonStatusKey, QJsonValue::String, true },
{ _jsonDataKey, QJsonValue::Object, true },
};
if (!JsonHelper::validateKeys(rootObject, rootVersionKeyInfoList, errorString)) {
qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
QByteArray emptyArray;
return emptyArray;
}
if (rootObject[_jsonStatusKey].toString() != "success") {
qCDebug(TerrainTileLog) << "Invalid terrain tile.";
QByteArray emptyArray;
return emptyArray;
}
const QJsonObject& dataObject = rootObject[_jsonDataKey].toObject();
QList<JsonHelper::KeyValidateInfo> dataVersionKeyInfoList = {
{ _jsonBoundsKey, QJsonValue::Object, true },
{ _jsonStatsKey, QJsonValue::Object, true },
{ _jsonCarpetKey, QJsonValue::Array, true },
};
if (!JsonHelper::validateKeys(dataObject, dataVersionKeyInfoList, errorString)) {
qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
QByteArray emptyArray;
return emptyArray;
}
// Bounds
const QJsonObject& boundsObject = dataObject[_jsonBoundsKey].toObject();
QList<JsonHelper::KeyValidateInfo> boundsVersionKeyInfoList = {
{ _jsonSouthWestKey, QJsonValue::Array, true },
{ _jsonNorthEastKey, QJsonValue::Array, true },
};
if (!JsonHelper::validateKeys(boundsObject, boundsVersionKeyInfoList, errorString)) {
qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
QByteArray emptyArray;
return emptyArray;
}
const QJsonArray& swArray = boundsObject[_jsonSouthWestKey].toArray();
const QJsonArray& neArray = boundsObject[_jsonNorthEastKey].toArray();
if (swArray.count() < 2 || neArray.count() < 2 ) {
qCDebug(TerrainTileLog) << "Incomplete bounding location";
QByteArray emptyArray;
return emptyArray;
stream << swArray[0].toDouble();
stream << swArray[1].toDouble();
stream << neArray[0].toDouble();
stream << neArray[1].toDouble();
const QJsonObject& statsObject = dataObject[_jsonStatsKey].toObject();
QList<JsonHelper::KeyValidateInfo> statsVersionKeyInfoList = {
{ _jsonMaxElevationKey, QJsonValue::Double, true },
{ _jsonMinElevationKey, QJsonValue::Double, true },
{ _jsonAvgElevationKey, QJsonValue::Double, true },
};
if (!JsonHelper::validateKeys(statsObject, statsVersionKeyInfoList, errorString)) {
qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
QByteArray emptyArray;
return emptyArray;
stream << statsObject[_jsonMaxElevationKey].toInt();
stream << statsObject[_jsonMinElevationKey].toInt();
stream << statsObject[_jsonAvgElevationKey].toDouble();
// Carpet
const QJsonArray& carpetArray = dataObject[_jsonCarpetKey].toArray();
int gridSizeLat = carpetArray.count();
stream << gridSizeLat;
int gridSizeLon = 0;
qCDebug(TerrainTileLog) << "Received tile has size in latitude direction: " << carpetArray.count();
for (int i = 0; i < gridSizeLat; i++) {
gridSizeLon = row.count();
stream << gridSizeLon;
qCDebug(TerrainTileLog) << "Received tile has size in longitued direction: " << row.count();
}
if (row.count() < gridSizeLon) {
qCDebug(TerrainTileLog) << "Expected row array of " << gridSizeLon << ", instead got " << row.count();
QByteArray emptyArray;
return emptyArray;
for (int j = 0; j < gridSizeLon; j++) {
stream << row[j].toDouble();
return byteArray;
int TerrainTile::_latToDataIndex(double latitude) const
{
if (isValid() && _southWest.isValid() && _northEast.isValid()) {
return qRound((latitude - _southWest.latitude()) / (_northEast.latitude() - _southWest.latitude()) * (_gridSizeLat - 1));
} else {
return -1;
}
}
int TerrainTile::_lonToDataIndex(double longitude) const
{
if (isValid() && _southWest.isValid() && _northEast.isValid()) {
return qRound((longitude - _southWest.longitude()) / (_northEast.longitude() - _southWest.longitude()) * (_gridSizeLon - 1));
} else {
return -1;
}
}