Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "TerrainTile.h"
#include "JsonHelper.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
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)
, _isValid(false)
{
}
TerrainTile::~TerrainTile()
{
}
TerrainTile::TerrainTile(QJsonDocument doc)
: _minElevation(-1.0)
, _maxElevation(-1.0)
, _avgElevation(-1.0)
, _isValid(false)
{
if (!doc.isObject()) {
qCDebug(TerrainTileLog) << "Terrain tile json doc is no object";
return;
}
QJsonObject rootObject = doc.object();
QString errorString;
QList<JsonHelper::KeyValidateInfo> rootVersionKeyInfoList = {
{ _jsonStatusKey, QJsonValue::String, true },
{ _jsonDataKey, QJsonValue::String, true },
};
if (!JsonHelper::validateKeys(rootObject, rootVersionKeyInfoList, errorString)) {
qCDebug(TerrainTileLog) << "Error in reading json: " << errorString;
return false;
}
if (rootObject[_jsonStatusKey].toString() != "success") {
qCDebug(TerrainTileLog) << "Invalid terrain tile.";
return;
}
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;
return false;
}
// 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;
return false;
}
const QJsonArray& swArray = boundsObject[_jsonSouthWestKey].toArray();
const QJsonArray& neArray = boundsObject[_jsonNorthEastKey].toArray();
if (swArray.count() < 2 || neArray.count() < 2 ) {
qCDebug(TerrainTileLog) << "Incomplete bounding location";
return;
}
_southWest.setLatitude(swArray[0].toDouble());
_southWest.setLongitude(swArray[1].toDouble());
_northEast.setLatitude(neArray[0].toDouble());
_northEast.setLongitude(neArray[1].toDouble());
// Stats
const QJsonObject& statsObject = dataObject[_jsonBoundsKey].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;
return false;
}
_maxElevation = statsObject[_jsonMaxElevationKey].toInt();
_minElevation = statsObject[_jsonMinElevationKey].toInt();
_avgElevation = statsObject[_jsonAvgElevationKey].toInt();
// Carpet
const QJsonArray& carpetArray = dataObject[_jsonCarpetKey].toArray();
if (carpetArray.count() != _gridSize) {
qCDebug(TerrainTileLog) << "Expected array of " << _gridSize << ", instead got " << carpetArray.count();
return;
}
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();
return;
}
for (int j = 0; j < _gridSize; j++) {
_data[i][j] = row[j].toDouble();
}
}
_isValid = true;
}
bool TerrainTile::isIn(QGeoCoordinate coord)
{
if (!_isValid) {
qCDebug(TerrainTileLog) << "isIn requested, but tile not valid";
return false;
}
bool ret = coord.latitude() >= _southWest.longitude() && coord.longitude() >= _southWest.longitude() &&
coord.latitude() <= _northEast.longitude() && coord.longitude() <= _northEast.longitude();
qCDebug(TerrainTileLog) << "Checking isIn: " << coord << " , in sw " << _southWest << " , ne " << _northEast << ": " << ret;
return ret;
}
float TerrainTile::elevation(const QGeoCoordinate& coord)
{
if (_isValid) {
qCDebug << "elevation: " << coord << " , in sw " << _southWest << " , ne " << _northEast;
// Get the index at resolution of 1 arc second
int indexLat = std::round((coord.latitude() - _southWest.latitude()) / _srtm1Increment);
int indexLon = std::round((coord.longitude() - _southWest.longitude()) / _srtm1Increment);
qCDebug << "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(indexLon >= 0);
Q_ASSERT(indexLon < _gridSize);
qCDebug << "elevation" << _data[indexLat][indexLon];
return _data[indexLat][indexLon];
} else {
qCDebug(TerrainTileLog) << "Asking for elevation, but no valid data.";
return -1.0;
}
}