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
/****************************************************************************
*
* (c) 2017 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "QGCLoggingCategory.h"
#include <QObject>
#include <QGeoCoordinate>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTimer>
Q_DECLARE_LOGGING_CATEGORY(TerrainQueryLog)
class TerrainAtCoordinateQuery;
// Base class for all terrain query objects
class TerrainQuery : public QObject {
Q_OBJECT
public:
TerrainQuery(QObject* parent = NULL);
protected:
// Send a query to AirMap terrain servers. Data and errors are returned back from super class virtual implementations.
// @param path Additional path to add to url
// @param urlQuery Query to send
void _sendQuery(const QString& path, const QUrlQuery& urlQuery);
virtual void _getNetworkReplyFailed (void) = 0; ///< QNetworkManager::get failed to return QNetworkReplay object
virtual void _requestFailed (QNetworkReply::NetworkError error) = 0; ///< QNetworkReply::finished returned error
virtual void _requestJsonParseFailed (const QString& errorString) = 0; ///< Parsing of returned json failed
virtual void _requestAirmapStatusFailed (const QString& status) = 0; ///< AirMap status was not "success"
virtual void _requestSucess (const QJsonValue& dataJsonValue) = 0; ///< Successful reqest, data returned
private slots:
void _requestFinished(void);
private:
QNetworkAccessManager _networkManager;
};
/// Used internally by TerrainAtCoordinateQuery to batch coordinate requests together
class TerrainAtCoordinateBatchManager : public TerrainQuery {
Q_OBJECT
public:
TerrainAtCoordinateBatchManager(void);
void addQuery(TerrainAtCoordinateQuery* terrainAtCoordinateQuery, const QList<QGeoCoordinate>& coordinates);
protected:
void _getNetworkReplyFailed (void) final;
void _requestFailed (QNetworkReply::NetworkError error) final;
void _requestJsonParseFailed (const QString& errorString) final;
void _requestAirmapStatusFailed (const QString& status) final;
void _requestSucess (const QJsonValue& dataJsonValue) final;
private slots:
void _sendNextBatch (void);
void _queryObjectDestroyed (QObject* elevationProvider);
private:
typedef struct {
TerrainAtCoordinateQuery* terrainAtCoordinateQuery;
QList<QGeoCoordinate> coordinates;
} QueuedRequestInfo_t;
typedef struct {
TerrainAtCoordinateQuery* terrainAtCoordinateQuery;
bool queryObjectDestroyed;
int cCoord;
} SentRequestInfo_t;
enum class State {
Idle,
Downloading,
};
void _batchFailed(void);
QString _stateToString(State state);
QList<QueuedRequestInfo_t> _requestQueue;
QList<SentRequestInfo_t> _sentRequests;
State _state = State::Idle;
const int _batchTimeout = 500;
QTimer _batchTimer;
};
/// NOTE: TerrainAtCoordinateQuery is not thread safe. All instances/calls to ElevationProvider must be on main thread.
class TerrainAtCoordinateQuery : public QObject
{
Q_OBJECT
public:
TerrainAtCoordinateQuery(QObject* parent = NULL);
/// Async terrain query for a list of lon,lat coordinates. When the query is done, the terrainData() signal
/// is emitted.
/// @param coordinates to query
void requestData(const QList<QGeoCoordinate>& coordinates);
// Internal method
void _signalTerrainData(bool success, QList<float>& altitudes);
signals:
void terrainData(bool success, QList<float> altitudes);
};
class TerrainPathQuery : public TerrainQuery
{
Q_OBJECT
public:
TerrainPathQuery(QObject* parent = NULL);
/// Async terrain query for terrain heights between two lat/lon coordinates. When the query is done, the terrainData() signal
/// is emitted.
/// @param coordinates to query
void requestData(const QGeoCoordinate& fromCoord, const QGeoCoordinate& toCoord);
typedef struct {
double latStep; ///< Amount of latitudinal distance between each returned height
double lonStep; ///< Amount of longitudinal distance between each returned height
QList<double> rgHeight; ///< Terrain heights along path
} PathHeightInfo_t;
signals:
/// Signalled when terrain data comes back from server
void terrainData(bool success, const PathHeightInfo_t& pathHeightInfo);
protected:
void _getNetworkReplyFailed (void) final;
void _requestFailed (QNetworkReply::NetworkError error) final;
void _requestJsonParseFailed (const QString& errorString) final;
void _requestAirmapStatusFailed (const QString& status) final;
void _requestSucess (const QJsonValue& dataJsonValue) final;
};
Q_DECLARE_METATYPE(TerrainPathQuery::PathHeightInfo_t)
class TerrainPolyPathQuery : public QObject
{
Q_OBJECT
public:
TerrainPolyPathQuery(QObject* parent = NULL);
/// Async terrain query for terrain heights for the paths between each specified QGeoCoordinate.
/// When the query is done, the terrainData() signal is emitted.
/// @param polyPath List of QGeoCoordinate
void requestData(const QVariantList& polyPath);
void requestData(const QList<QGeoCoordinate>& polyPath);
signals:
/// Signalled when terrain data comes back from server
void terrainData(bool success, const QList<TerrainPathQuery::PathHeightInfo_t>& rgPathHeightInfo);
private slots:
void _terrainDataReceived(bool success, const TerrainPathQuery::PathHeightInfo_t& pathHeightInfo);
private:
int _curIndex;
QList<QGeoCoordinate> _rgCoords;
QList<TerrainPathQuery::PathHeightInfo_t> _rgPathHeightInfo;
TerrainPathQuery _pathQuery;